[BACK]Return to if_sip.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/pci/if_sip.c between version 1.113 and 1.113.8.3

version 1.113, 2007/07/09 21:00:55 version 1.113.8.3, 2008/03/23 02:04:48
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      if_sip.c,v 1.113.8.2 2008/01/09 01:53:49 matt Exp       */
   
 /*-  /*-
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.   * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
Line 80 
Line 80 
  */   */
   
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "if_sip.c,v 1.113.8.2 2008/01/09 01:53:49 matt Exp");
   
 #include "bpfilter.h"  #include "bpfilter.h"
 #include "rnd.h"  #include "rnd.h"
Line 112  __KERNEL_RCSID(0, "$NetBSD$");
Line 112  __KERNEL_RCSID(0, "$NetBSD$");
 #include <net/bpf.h>  #include <net/bpf.h>
 #endif  #endif
   
 #include <machine/bus.h>  #include <sys/bus.h>
 #include <machine/intr.h>  #include <sys/intr.h>
 #include <machine/endian.h>  #include <machine/endian.h>
   
 #include <dev/mii/mii.h>  #include <dev/mii/mii.h>
Line 126  __KERNEL_RCSID(0, "$NetBSD$");
Line 126  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <dev/pci/if_sipreg.h>  #include <dev/pci/if_sipreg.h>
   
 #ifdef DP83820          /* DP83820 Gigabit Ethernet */  
 #define SIP_DECL(x)     __CONCAT(gsip_,x)  
 #else                   /* SiS900 and DP83815 */  
 #define SIP_DECL(x)     __CONCAT(sip_,x)  
 #endif  
   
 #define SIP_STR(x)      __STRING(SIP_DECL(x))  
   
 /*  /*
  * Transmit descriptor list size.  This is arbitrary, but allocate   * Transmit descriptor list size.  This is arbitrary, but allocate
  * enough descriptors for 128 pending transmissions, and 8 segments   * enough descriptors for 128 pending transmissions, and 8 segments
Line 141  __KERNEL_RCSID(0, "$NetBSD$");
Line 133  __KERNEL_RCSID(0, "$NetBSD$");
  *   *
  * This MUST work out to a power of 2.   * This MUST work out to a power of 2.
  */   */
 #ifdef DP83820  #define GSIP_NTXSEGS_ALLOC 16
 #define SIP_NTXSEGS             64  #define SIP_NTXSEGS_ALLOC 8
 #define SIP_NTXSEGS_ALLOC       16  
 #else  
 #define SIP_NTXSEGS             16  
 #define SIP_NTXSEGS_ALLOC       8  
 #endif  
   
 #define SIP_TXQUEUELEN          256  #define SIP_TXQUEUELEN          256
 #define SIP_NTXDESC             (SIP_TXQUEUELEN * SIP_NTXSEGS_ALLOC)  #define MAX_SIP_NTXDESC \
 #define SIP_NTXDESC_MASK        (SIP_NTXDESC - 1)      (SIP_TXQUEUELEN * MAX(SIP_NTXSEGS_ALLOC, GSIP_NTXSEGS_ALLOC))
 #define SIP_NEXTTX(x)           (((x) + 1) & SIP_NTXDESC_MASK)  
   
 #if defined(DP83820)  
 #define TX_DMAMAP_SIZE          ETHER_MAX_LEN_JUMBO  
 #else  
 #define TX_DMAMAP_SIZE          MCLBYTES  
 #endif  
   
 /*  /*
  * Receive descriptor list size.  We have one Rx buffer per incoming   * Receive descriptor list size.  We have one Rx buffer per incoming
Line 170  __KERNEL_RCSID(0, "$NetBSD$");
Line 150  __KERNEL_RCSID(0, "$NetBSD$");
  * mbuf cluster).  256 receive buffers is only 51 maximum size packets,   * mbuf cluster).  256 receive buffers is only 51 maximum size packets,
  * so we'd better be quick about handling receive interrupts.   * so we'd better be quick about handling receive interrupts.
  */   */
 #if defined(DP83820)  #define GSIP_NRXDESC            256
 #define SIP_NRXDESC             256  
 #else  
 #define SIP_NRXDESC             128  #define SIP_NRXDESC             128
 #endif /* DP83820 */  
 #define SIP_NRXDESC_MASK        (SIP_NRXDESC - 1)  #define MAX_SIP_NRXDESC MAX(GSIP_NRXDESC, SIP_NRXDESC)
 #define SIP_NEXTRX(x)           (((x) + 1) & SIP_NRXDESC_MASK)  
   
 /*  /*
  * Control structures are DMA'd to the SiS900 chip.  We allocate them in   * Control structures are DMA'd to the SiS900 chip.  We allocate them in
Line 187  struct sip_control_data {
Line 164  struct sip_control_data {
         /*          /*
          * The transmit descriptors.           * The transmit descriptors.
          */           */
         struct sip_desc scd_txdescs[SIP_NTXDESC];          struct sip_desc scd_txdescs[MAX_SIP_NTXDESC];
   
         /*          /*
          * The receive descriptors.           * The receive descriptors.
          */           */
         struct sip_desc scd_rxdescs[SIP_NRXDESC];          struct sip_desc scd_rxdescs[MAX_SIP_NRXDESC];
 };  };
   
 #define SIP_CDOFF(x)    offsetof(struct sip_control_data, x)  #define SIP_CDOFF(x)    offsetof(struct sip_control_data, x)
Line 220  struct sip_rxsoft {
Line 197  struct sip_rxsoft {
         bus_dmamap_t rxs_dmamap;        /* our DMA map */          bus_dmamap_t rxs_dmamap;        /* our DMA map */
 };  };
   
   enum sip_attach_stage {
             SIP_ATTACH_FIN = 0
           , SIP_ATTACH_CREATE_RXMAP
           , SIP_ATTACH_CREATE_TXMAP
           , SIP_ATTACH_LOAD_MAP
           , SIP_ATTACH_CREATE_MAP
           , SIP_ATTACH_MAP_MEM
           , SIP_ATTACH_ALLOC_MEM
           , SIP_ATTACH_INTR
           , SIP_ATTACH_MAP
   };
   
 /*  /*
  * Software state per device.   * Software state per device.
  */   */
Line 227  struct sip_softc {
Line 216  struct sip_softc {
         struct device sc_dev;           /* generic device information */          struct device sc_dev;           /* generic device information */
         bus_space_tag_t sc_st;          /* bus space tag */          bus_space_tag_t sc_st;          /* bus space tag */
         bus_space_handle_t sc_sh;       /* bus space handle */          bus_space_handle_t sc_sh;       /* bus space handle */
           bus_size_t sc_sz;               /* bus space size */
         bus_dma_tag_t sc_dmat;          /* bus DMA tag */          bus_dma_tag_t sc_dmat;          /* bus DMA tag */
           pci_chipset_tag_t sc_pc;
           bus_dma_segment_t sc_seg;
         struct ethercom sc_ethercom;    /* ethernet common data */          struct ethercom sc_ethercom;    /* ethernet common data */
         void *sc_sdhook;                /* shutdown hook */  
   
         const struct sip_product *sc_model; /* which model are we? */          const struct sip_product *sc_model; /* which model are we? */
           int sc_gigabit;                 /* 1: 83820, 0: other */
         int sc_rev;                     /* chip revision */          int sc_rev;                     /* chip revision */
   
         void *sc_ih;                    /* interrupt cookie */          void *sc_ih;                    /* interrupt cookie */
Line 247  struct sip_softc {
Line 239  struct sip_softc {
          * Software state for transmit and receive descriptors.           * Software state for transmit and receive descriptors.
          */           */
         struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];          struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
         struct sip_rxsoft sc_rxsoft[SIP_NRXDESC];          struct sip_rxsoft sc_rxsoft[MAX_SIP_NRXDESC];
   
         /*          /*
          * Control data structures.           * Control data structures.
Line 268  struct sip_softc {
Line 260  struct sip_softc {
         struct evcnt sc_ev_rxintr;      /* Rx interrupts */          struct evcnt sc_ev_rxintr;      /* Rx interrupts */
         struct evcnt sc_ev_hiberr;      /* HIBERR interrupts */          struct evcnt sc_ev_hiberr;      /* HIBERR interrupts */
         struct evcnt sc_ev_rxpause;     /* PAUSE received */          struct evcnt sc_ev_rxpause;     /* PAUSE received */
 #ifdef DP83820          /* DP83820 only */
         struct evcnt sc_ev_txpause;     /* PAUSE transmitted */          struct evcnt sc_ev_txpause;     /* PAUSE transmitted */
         struct evcnt sc_ev_rxipsum;     /* IP checksums checked in-bound */          struct evcnt sc_ev_rxipsum;     /* IP checksums checked in-bound */
         struct evcnt sc_ev_rxtcpsum;    /* TCP checksums checked in-bound */          struct evcnt sc_ev_rxtcpsum;    /* TCP checksums checked in-bound */
Line 276  struct sip_softc {
Line 268  struct sip_softc {
         struct evcnt sc_ev_txipsum;     /* IP checksums comp. out-bound */          struct evcnt sc_ev_txipsum;     /* IP checksums comp. out-bound */
         struct evcnt sc_ev_txtcpsum;    /* TCP checksums comp. out-bound */          struct evcnt sc_ev_txtcpsum;    /* TCP checksums comp. out-bound */
         struct evcnt sc_ev_txudpsum;    /* UDP checksums comp. out-bound */          struct evcnt sc_ev_txudpsum;    /* UDP checksums comp. out-bound */
 #endif /* DP83820 */  
 #endif /* SIP_EVENT_COUNTERS */  #endif /* SIP_EVENT_COUNTERS */
   
         u_int32_t sc_txcfg;             /* prototype TXCFG register */          u_int32_t sc_txcfg;             /* prototype TXCFG register */
Line 286  struct sip_softc {
Line 277  struct sip_softc {
   
         u_int32_t sc_cfg;               /* prototype CFG register */          u_int32_t sc_cfg;               /* prototype CFG register */
   
 #ifdef DP83820  
         u_int32_t sc_gpior;             /* prototype GPIOR register */          u_int32_t sc_gpior;             /* prototype GPIOR register */
 #endif /* DP83820 */  
   
         u_int32_t sc_tx_fill_thresh;    /* transmit fill threshold */          u_int32_t sc_tx_fill_thresh;    /* transmit fill threshold */
         u_int32_t sc_tx_drain_thresh;   /* transmit drain threshold */          u_int32_t sc_tx_drain_thresh;   /* transmit drain threshold */
Line 296  struct sip_softc {
Line 285  struct sip_softc {
         u_int32_t sc_rx_drain_thresh;   /* receive drain threshold */          u_int32_t sc_rx_drain_thresh;   /* receive drain threshold */
   
         int     sc_flowflags;           /* 802.3x flow control flags */          int     sc_flowflags;           /* 802.3x flow control flags */
 #ifdef DP83820  
         int     sc_rx_flow_thresh;      /* Rx FIFO threshold for flow control */          int     sc_rx_flow_thresh;      /* Rx FIFO threshold for flow control */
 #else  
         int     sc_paused;              /* paused indication */          int     sc_paused;              /* paused indication */
 #endif  
   
         int     sc_txfree;              /* number of free Tx descriptors */          int     sc_txfree;              /* number of free Tx descriptors */
         int     sc_txnext;              /* next ready Tx descriptor */          int     sc_txnext;              /* next ready Tx descriptor */
Line 322  struct sip_softc {
Line 308  struct sip_softc {
         short   sc_if_flags;          short   sc_if_flags;
   
         int     sc_rxptr;               /* next ready Rx descriptor/descsoft */          int     sc_rxptr;               /* next ready Rx descriptor/descsoft */
 #if defined(DP83820)  
         int     sc_rxdiscard;          int     sc_rxdiscard;
         int     sc_rxlen;          int     sc_rxlen;
         struct mbuf *sc_rxhead;          struct mbuf *sc_rxhead;
         struct mbuf *sc_rxtail;          struct mbuf *sc_rxtail;
         struct mbuf **sc_rxtailp;          struct mbuf **sc_rxtailp;
 #endif /* DP83820 */  
           int sc_ntxdesc;
           int sc_ntxdesc_mask;
   
           int sc_nrxdesc_mask;
   
           const struct sip_parm {
                   const struct sip_regs {
                           int r_rxcfg;
                           int r_txcfg;
                   } p_regs;
   
                   const struct sip_bits {
                           uint32_t b_txcfg_mxdma_8;
                           uint32_t b_txcfg_mxdma_16;
                           uint32_t b_txcfg_mxdma_32;
                           uint32_t b_txcfg_mxdma_64;
                           uint32_t b_txcfg_mxdma_128;
                           uint32_t b_txcfg_mxdma_256;
                           uint32_t b_txcfg_mxdma_512;
                           uint32_t b_txcfg_flth_mask;
                           uint32_t b_txcfg_drth_mask;
   
                           uint32_t b_rxcfg_mxdma_8;
                           uint32_t b_rxcfg_mxdma_16;
                           uint32_t b_rxcfg_mxdma_32;
                           uint32_t b_rxcfg_mxdma_64;
                           uint32_t b_rxcfg_mxdma_128;
                           uint32_t b_rxcfg_mxdma_256;
                           uint32_t b_rxcfg_mxdma_512;
   
                           uint32_t b_isr_txrcmp;
                           uint32_t b_isr_rxrcmp;
                           uint32_t b_isr_dperr;
                           uint32_t b_isr_sserr;
                           uint32_t b_isr_rmabt;
                           uint32_t b_isr_rtabt;
   
                           uint32_t b_cmdsts_size_mask;
                   } p_bits;
                   int             p_filtmem;
                   int             p_rxbuf_len;
                   bus_size_t      p_tx_dmamap_size;
                   int             p_ntxsegs;
                   int             p_ntxsegs_alloc;
                   int             p_nrxdesc;
           } *sc_parm;
   
           void (*sc_rxintr)(struct sip_softc *);
   
 #if NRND > 0  #if NRND > 0
         rndsource_element_t rnd_source; /* random source */          rndsource_element_t rnd_source; /* random source */
 #endif  #endif
 };  };
   
 #ifdef DP83820  #define sc_bits sc_parm->p_bits
 #define SIP_RXCHAIN_RESET(sc)                                           \  #define sc_regs sc_parm->p_regs
 do {                                                                    \  
         (sc)->sc_rxtailp = &(sc)->sc_rxhead;                            \  static const struct sip_parm sip_parm = {
         *(sc)->sc_rxtailp = NULL;                                       \            .p_filtmem = OTHER_RFCR_NS_RFADDR_FILTMEM
         (sc)->sc_rxlen = 0;                                             \          , .p_rxbuf_len = MCLBYTES - 1   /* field width */
 } while (/*CONSTCOND*/0)          , .p_tx_dmamap_size = MCLBYTES
           , .p_ntxsegs = 16
 #define SIP_RXCHAIN_LINK(sc, m)                                         \          , .p_ntxsegs_alloc = SIP_NTXSEGS_ALLOC
 do {                                                                    \          , .p_nrxdesc = SIP_NRXDESC
         *(sc)->sc_rxtailp = (sc)->sc_rxtail = (m);                      \          , .p_bits = {
         (sc)->sc_rxtailp = &(m)->m_next;                                \                    .b_txcfg_mxdma_8      = 0x00200000    /*       8 bytes */
 } while (/*CONSTCOND*/0)                  , .b_txcfg_mxdma_16     = 0x00300000    /*      16 bytes */
 #endif /* DP83820 */                  , .b_txcfg_mxdma_32     = 0x00400000    /*      32 bytes */
                   , .b_txcfg_mxdma_64     = 0x00500000    /*      64 bytes */
                   , .b_txcfg_mxdma_128    = 0x00600000    /*     128 bytes */
                   , .b_txcfg_mxdma_256    = 0x00700000    /*     256 bytes */
                   , .b_txcfg_mxdma_512    = 0x00000000    /*     512 bytes */
                   , .b_txcfg_flth_mask    = 0x00003f00    /* Tx fill threshold */
                   , .b_txcfg_drth_mask    = 0x0000003f    /* Tx drain threshold */
   
                   , .b_rxcfg_mxdma_8      = 0x00200000    /*       8 bytes */
                   , .b_rxcfg_mxdma_16     = 0x00300000    /*      16 bytes */
                   , .b_rxcfg_mxdma_32     = 0x00400000    /*      32 bytes */
                   , .b_rxcfg_mxdma_64     = 0x00500000    /*      64 bytes */
                   , .b_rxcfg_mxdma_128    = 0x00600000    /*     128 bytes */
                   , .b_rxcfg_mxdma_256    = 0x00700000    /*     256 bytes */
                   , .b_rxcfg_mxdma_512    = 0x00000000    /*     512 bytes */
   
                   , .b_isr_txrcmp = 0x02000000    /* transmit reset complete */
                   , .b_isr_rxrcmp = 0x01000000    /* receive reset complete */
                   , .b_isr_dperr  = 0x00800000    /* detected parity error */
                   , .b_isr_sserr  = 0x00400000    /* signalled system error */
                   , .b_isr_rmabt  = 0x00200000    /* received master abort */
                   , .b_isr_rtabt  = 0x00100000    /* received target abort */
                   , .b_cmdsts_size_mask = OTHER_CMDSTS_SIZE_MASK
           }
           , .p_regs = {
                   .r_rxcfg = OTHER_SIP_RXCFG,
                   .r_txcfg = OTHER_SIP_TXCFG
           }
   }, gsip_parm = {
             .p_filtmem = DP83820_RFCR_NS_RFADDR_FILTMEM
           , .p_rxbuf_len = MCLBYTES - 8
           , .p_tx_dmamap_size = ETHER_MAX_LEN_JUMBO
           , .p_ntxsegs = 64
           , .p_ntxsegs_alloc = GSIP_NTXSEGS_ALLOC
           , .p_nrxdesc = GSIP_NRXDESC
           , .p_bits = {
                     .b_txcfg_mxdma_8      = 0x00100000    /*       8 bytes */
                   , .b_txcfg_mxdma_16     = 0x00200000    /*      16 bytes */
                   , .b_txcfg_mxdma_32     = 0x00300000    /*      32 bytes */
                   , .b_txcfg_mxdma_64     = 0x00400000    /*      64 bytes */
                   , .b_txcfg_mxdma_128    = 0x00500000    /*     128 bytes */
                   , .b_txcfg_mxdma_256    = 0x00600000    /*     256 bytes */
                   , .b_txcfg_mxdma_512    = 0x00700000    /*     512 bytes */
                   , .b_txcfg_flth_mask    = 0x0000ff00    /* Fx fill threshold */
                   , .b_txcfg_drth_mask    = 0x000000ff    /* Tx drain threshold */
   
                   , .b_rxcfg_mxdma_8      = 0x00100000    /*       8 bytes */
                   , .b_rxcfg_mxdma_16     = 0x00200000    /*      16 bytes */
                   , .b_rxcfg_mxdma_32     = 0x00300000    /*      32 bytes */
                   , .b_rxcfg_mxdma_64     = 0x00400000    /*      64 bytes */
                   , .b_rxcfg_mxdma_128    = 0x00500000    /*     128 bytes */
                   , .b_rxcfg_mxdma_256    = 0x00600000    /*     256 bytes */
                   , .b_rxcfg_mxdma_512    = 0x00700000    /*     512 bytes */
   
                   , .b_isr_txrcmp = 0x00400000    /* transmit reset complete */
                   , .b_isr_rxrcmp = 0x00200000    /* receive reset complete */
                   , .b_isr_dperr  = 0x00100000    /* detected parity error */
                   , .b_isr_sserr  = 0x00080000    /* signalled system error */
                   , .b_isr_rmabt  = 0x00040000    /* received master abort */
                   , .b_isr_rtabt  = 0x00020000    /* received target abort */
                   , .b_cmdsts_size_mask = DP83820_CMDSTS_SIZE_MASK
           }
           , .p_regs = {
                   .r_rxcfg = DP83820_SIP_RXCFG,
                   .r_txcfg = DP83820_SIP_TXCFG
           }
   };
   
   static inline int
   sip_nexttx(const struct sip_softc *sc, int x)
   {
           return (x + 1) & sc->sc_ntxdesc_mask;
   }
   
   static inline int
   sip_nextrx(const struct sip_softc *sc, int x)
   {
           return (x + 1) & sc->sc_nrxdesc_mask;
   }
   
   /* 83820 only */
   static inline void
   sip_rxchain_reset(struct sip_softc *sc)
   {
           sc->sc_rxtailp = &sc->sc_rxhead;
           *sc->sc_rxtailp = NULL;
           sc->sc_rxlen = 0;
   }
   
   /* 83820 only */
   static inline void
   sip_rxchain_link(struct sip_softc *sc, struct mbuf *m)
   {
           *sc->sc_rxtailp = sc->sc_rxtail = m;
           sc->sc_rxtailp = &m->m_next;
   }
   
 #ifdef SIP_EVENT_COUNTERS  #ifdef SIP_EVENT_COUNTERS
 #define SIP_EVCNT_INCR(ev)      (ev)->ev_count++  #define SIP_EVCNT_INCR(ev)      (ev)->ev_count++
Line 359  do {         \
Line 487  do {         \
 #define SIP_CDTXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDTXOFF((x)))  #define SIP_CDTXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDTXOFF((x)))
 #define SIP_CDRXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDRXOFF((x)))  #define SIP_CDRXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDRXOFF((x)))
   
 #define SIP_CDTXSYNC(sc, x, n, ops)                                     \  static inline void
 do {                                                                    \  sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops)
         int __x, __n;                                                   \  {
                                                                         \          int x, n;
         __x = (x);                                                      \  
         __n = (n);                                                      \          x = x0;
                                                                         \          n = n0;
         /* If it will wrap around, sync to the end of the ring. */      \  
         if ((__x + __n) > SIP_NTXDESC) {                                \          /* If it will wrap around, sync to the end of the ring. */
                 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,       \          if (x + n > sc->sc_ntxdesc) {
                     SIP_CDTXOFF(__x), sizeof(struct sip_desc) *         \                  bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
                     (SIP_NTXDESC - __x), (ops));                        \                      SIP_CDTXOFF(x), sizeof(struct sip_desc) *
                 __n -= (SIP_NTXDESC - __x);                             \                      (sc->sc_ntxdesc - x), ops);
                 __x = 0;                                                \                  n -= (sc->sc_ntxdesc - x);
         }                                                               \                  x = 0;
                                                                         \          }
         /* Now sync whatever is left. */                                \  
         bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \          /* Now sync whatever is left. */
             SIP_CDTXOFF(__x), sizeof(struct sip_desc) * __n, (ops));    \          bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
 } while (0)              SIP_CDTXOFF(x), sizeof(struct sip_desc) * n, ops);
   }
 #define SIP_CDRXSYNC(sc, x, ops)                                        \  
         bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \  
             SIP_CDRXOFF((x)), sizeof(struct sip_desc), (ops))  
   
   static inline void
   sip_cdrxsync(struct sip_softc *sc, int x, int ops)
   {
           bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap,
               SIP_CDRXOFF(x), sizeof(struct sip_desc), ops);
   }
   
   #if 0
 #ifdef DP83820  #ifdef DP83820
 #define SIP_INIT_RXDESC_EXTSTS  __sipd->sipd_extsts = 0;          u_int32_t       sipd_bufptr;    /* pointer to DMA segment */
 #define SIP_RXBUF_LEN           (MCLBYTES - 8)          u_int32_t       sipd_cmdsts;    /* command/status word */
 #else  #else
 #define SIP_INIT_RXDESC_EXTSTS  /* nothing */          u_int32_t       sipd_cmdsts;    /* command/status word */
 #define SIP_RXBUF_LEN           (MCLBYTES - 1)  /* field width */          u_int32_t       sipd_bufptr;    /* pointer to DMA segment */
 #endif  #endif /* DP83820 */
 #define SIP_INIT_RXDESC(sc, x)                                          \  #endif /* 0 */
 do {                                                                    \  
         struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)];               \  static inline volatile uint32_t *
         struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)];               \  sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd)
                                                                         \  {
         __sipd->sipd_link =                                             \          return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0];
             htole32(SIP_CDRXADDR((sc), SIP_NEXTRX((x))));               \  }
         __sipd->sipd_bufptr =                                           \  
             htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr);             \  static inline volatile uint32_t *
         __sipd->sipd_cmdsts = htole32(CMDSTS_INTR |                     \  sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd)
             (SIP_RXBUF_LEN & CMDSTS_SIZE_MASK));                        \  {
         SIP_INIT_RXDESC_EXTSTS                                          \          return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1];
         SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \  }
 } while (0)  
   static inline void
   sip_init_rxdesc(struct sip_softc *sc, int x)
   {
           struct sip_rxsoft *rxs = &sc->sc_rxsoft[x];
           struct sip_desc *sipd = &sc->sc_rxdescs[x];
   
           sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x)));
           *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr);
           *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR |
               (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask));
           sipd->sipd_extsts = 0;
           sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   }
   
 #define SIP_CHIP_VERS(sc, v, p, r)                                      \  #define SIP_CHIP_VERS(sc, v, p, r)                                      \
         ((sc)->sc_model->sip_vendor == (v) &&                           \          ((sc)->sc_model->sip_vendor == (v) &&                           \
Line 415  do {         \
Line 561  do {         \
         ((sc)->sc_model->sip_vendor == (v) &&                           \          ((sc)->sc_model->sip_vendor == (v) &&                           \
          (sc)->sc_model->sip_product == (p))           (sc)->sc_model->sip_product == (p))
   
 #if !defined(DP83820)  
 #define SIP_SIS900_REV(sc, rev)                                         \  #define SIP_SIS900_REV(sc, rev)                                         \
         SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev))          SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev))
 #endif  
   
 #define SIP_TIMEOUT 1000  #define SIP_TIMEOUT 1000
   
 static void     SIP_DECL(start)(struct ifnet *);  static void     sipcom_start(struct ifnet *);
 static void     SIP_DECL(watchdog)(struct ifnet *);  static void     sipcom_watchdog(struct ifnet *);
 static int      SIP_DECL(ioctl)(struct ifnet *, u_long, void *);  static int      sipcom_ioctl(struct ifnet *, u_long, void *);
 static int      SIP_DECL(init)(struct ifnet *);  static int      sipcom_init(struct ifnet *);
 static void     SIP_DECL(stop)(struct ifnet *, int);  static void     sipcom_stop(struct ifnet *, int);
   
 static void     SIP_DECL(shutdown)(void *);  static bool     sipcom_reset(struct sip_softc *);
   static void     sipcom_rxdrain(struct sip_softc *);
 static void     SIP_DECL(reset)(struct sip_softc *);  static int      sipcom_add_rxbuf(struct sip_softc *, int);
 static void     SIP_DECL(rxdrain)(struct sip_softc *);  static void     sipcom_read_eeprom(struct sip_softc *, int, int,
 static int      SIP_DECL(add_rxbuf)(struct sip_softc *, int);  
 static void     SIP_DECL(read_eeprom)(struct sip_softc *, int, int,  
                                       u_int16_t *);                                        u_int16_t *);
 static void     SIP_DECL(tick)(void *);  static void     sipcom_tick(void *);
   
 #if !defined(DP83820)  static void     sipcom_sis900_set_filter(struct sip_softc *);
 static void     SIP_DECL(sis900_set_filter)(struct sip_softc *);  static void     sipcom_dp83815_set_filter(struct sip_softc *);
 #endif /* ! DP83820 */  
 static void     SIP_DECL(dp83815_set_filter)(struct sip_softc *);  
   
 #if defined(DP83820)  static void     sipcom_dp83820_read_macaddr(struct sip_softc *,
 static void     SIP_DECL(dp83820_read_macaddr)(struct sip_softc *,  
                     const struct pci_attach_args *, u_int8_t *);                      const struct pci_attach_args *, u_int8_t *);
 #else  static void     sipcom_sis900_eeprom_delay(struct sip_softc *sc);
 static void     SIP_DECL(sis900_eeprom_delay)(struct sip_softc *sc);  static void     sipcom_sis900_read_macaddr(struct sip_softc *,
 static void     SIP_DECL(sis900_read_macaddr)(struct sip_softc *,  
                     const struct pci_attach_args *, u_int8_t *);                      const struct pci_attach_args *, u_int8_t *);
 static void     SIP_DECL(dp83815_read_macaddr)(struct sip_softc *,  static void     sipcom_dp83815_read_macaddr(struct sip_softc *,
                     const struct pci_attach_args *, u_int8_t *);                      const struct pci_attach_args *, u_int8_t *);
 #endif /* DP83820 */  
   
 static int      SIP_DECL(intr)(void *);  static int      sipcom_intr(void *);
 static void     SIP_DECL(txintr)(struct sip_softc *);  static void     sipcom_txintr(struct sip_softc *);
 static void     SIP_DECL(rxintr)(struct sip_softc *);  static void     sip_rxintr(struct sip_softc *);
   static void     gsip_rxintr(struct sip_softc *);
 #if defined(DP83820)  
 static int      SIP_DECL(dp83820_mii_readreg)(struct device *, int, int);  static int      sipcom_dp83820_mii_readreg(device_t, int, int);
 static void     SIP_DECL(dp83820_mii_writereg)(struct device *, int, int, int);  static void     sipcom_dp83820_mii_writereg(device_t, int, int, int);
 static void     SIP_DECL(dp83820_mii_statchg)(struct device *);  static void     sipcom_dp83820_mii_statchg(device_t);
 #else  
 static int      SIP_DECL(sis900_mii_readreg)(struct device *, int, int);  static int      sipcom_sis900_mii_readreg(device_t, int, int);
 static void     SIP_DECL(sis900_mii_writereg)(struct device *, int, int, int);  static void     sipcom_sis900_mii_writereg(device_t, int, int, int);
 static void     SIP_DECL(sis900_mii_statchg)(struct device *);  static void     sipcom_sis900_mii_statchg(device_t);
   
 static int      SIP_DECL(dp83815_mii_readreg)(struct device *, int, int);  static int      sipcom_dp83815_mii_readreg(device_t, int, int);
 static void     SIP_DECL(dp83815_mii_writereg)(struct device *, int, int, int);  static void     sipcom_dp83815_mii_writereg(device_t, int, int, int);
 static void     SIP_DECL(dp83815_mii_statchg)(struct device *);  static void     sipcom_dp83815_mii_statchg(device_t);
 #endif /* DP83820 */  
   static void     sipcom_mediastatus(struct ifnet *, struct ifmediareq *);
 static int      SIP_DECL(mediachange)(struct ifnet *);  
 static void     SIP_DECL(mediastatus)(struct ifnet *, struct ifmediareq *);  static int      sipcom_match(device_t, struct cfdata *, void *);
   static void     sipcom_attach(device_t, device_t, void *);
   static void     sipcom_do_detach(device_t, enum sip_attach_stage);
   static int      sipcom_detach(device_t, int);
   static bool     sipcom_resume(device_t PMF_FN_PROTO);
   static bool     sipcom_suspend(device_t PMF_FN_PROTO);
   
 static int      SIP_DECL(match)(struct device *, struct cfdata *, void *);  int     gsip_copy_small = 0;
 static void     SIP_DECL(attach)(struct device *, struct device *, void *);  int     sip_copy_small = 0;
   
 int     SIP_DECL(copy_small) = 0;  
   
 #ifdef DP83820  
 CFATTACH_DECL(gsip, sizeof(struct sip_softc),  CFATTACH_DECL(gsip, sizeof(struct sip_softc),
     gsip_match, gsip_attach, NULL, NULL);      sipcom_match, sipcom_attach, sipcom_detach, NULL);
 #else  
 CFATTACH_DECL(sip, sizeof(struct sip_softc),  CFATTACH_DECL(sip, sizeof(struct sip_softc),
     sip_match, sip_attach, NULL, NULL);      sipcom_match, sipcom_attach, sipcom_detach, NULL);
 #endif  
   
 /*  /*
  * Descriptions of the variants of the SiS900.   * Descriptions of the variants of the SiS900.
  */   */
 struct sip_variant {  struct sip_variant {
         int     (*sipv_mii_readreg)(struct device *, int, int);          int     (*sipv_mii_readreg)(device_t, int, int);
         void    (*sipv_mii_writereg)(struct device *, int, int, int);          void    (*sipv_mii_writereg)(device_t, int, int, int);
         void    (*sipv_mii_statchg)(struct device *);          void    (*sipv_mii_statchg)(device_t);
         void    (*sipv_set_filter)(struct sip_softc *);          void    (*sipv_set_filter)(struct sip_softc *);
         void    (*sipv_read_macaddr)(struct sip_softc *,          void    (*sipv_read_macaddr)(struct sip_softc *,
                     const struct pci_attach_args *, u_int8_t *);                      const struct pci_attach_args *, u_int8_t *);
 };  };
   
 static u_int32_t SIP_DECL(mii_bitbang_read)(struct device *);  static u_int32_t sipcom_mii_bitbang_read(device_t);
 static void     SIP_DECL(mii_bitbang_write)(struct device *, u_int32_t);  static void     sipcom_mii_bitbang_write(device_t, u_int32_t);
   
 static const struct mii_bitbang_ops SIP_DECL(mii_bitbang_ops) = {  static const struct mii_bitbang_ops sipcom_mii_bitbang_ops = {
         SIP_DECL(mii_bitbang_read),          sipcom_mii_bitbang_read,
         SIP_DECL(mii_bitbang_write),          sipcom_mii_bitbang_write,
         {          {
                 EROMAR_MDIO,            /* MII_BIT_MDO */                  EROMAR_MDIO,            /* MII_BIT_MDO */
                 EROMAR_MDIO,            /* MII_BIT_MDI */                  EROMAR_MDIO,            /* MII_BIT_MDI */
Line 514  static const struct mii_bitbang_ops SIP_
Line 651  static const struct mii_bitbang_ops SIP_
         }          }
 };  };
   
 #if defined(DP83820)  static const struct sip_variant sipcom_variant_dp83820 = {
 static const struct sip_variant SIP_DECL(variant_dp83820) = {          sipcom_dp83820_mii_readreg,
         SIP_DECL(dp83820_mii_readreg),          sipcom_dp83820_mii_writereg,
         SIP_DECL(dp83820_mii_writereg),          sipcom_dp83820_mii_statchg,
         SIP_DECL(dp83820_mii_statchg),          sipcom_dp83815_set_filter,
         SIP_DECL(dp83815_set_filter),          sipcom_dp83820_read_macaddr,
         SIP_DECL(dp83820_read_macaddr),  
 };  };
 #else  
 static const struct sip_variant SIP_DECL(variant_sis900) = {  static const struct sip_variant sipcom_variant_sis900 = {
         SIP_DECL(sis900_mii_readreg),          sipcom_sis900_mii_readreg,
         SIP_DECL(sis900_mii_writereg),          sipcom_sis900_mii_writereg,
         SIP_DECL(sis900_mii_statchg),          sipcom_sis900_mii_statchg,
         SIP_DECL(sis900_set_filter),          sipcom_sis900_set_filter,
         SIP_DECL(sis900_read_macaddr),          sipcom_sis900_read_macaddr,
 };  };
   
 static const struct sip_variant SIP_DECL(variant_dp83815) = {  static const struct sip_variant sipcom_variant_dp83815 = {
         SIP_DECL(dp83815_mii_readreg),          sipcom_dp83815_mii_readreg,
         SIP_DECL(dp83815_mii_writereg),          sipcom_dp83815_mii_writereg,
         SIP_DECL(dp83815_mii_statchg),          sipcom_dp83815_mii_statchg,
         SIP_DECL(dp83815_set_filter),          sipcom_dp83815_set_filter,
         SIP_DECL(dp83815_read_macaddr),          sipcom_dp83815_read_macaddr,
 };  };
 #endif /* DP83820 */  
   
 /*  /*
  * Devices supported by this driver.   * Devices supported by this driver.
Line 548  static const struct sip_product {
Line 684  static const struct sip_product {
         pci_product_id_t        sip_product;          pci_product_id_t        sip_product;
         const char              *sip_name;          const char              *sip_name;
         const struct sip_variant *sip_variant;          const struct sip_variant *sip_variant;
 } SIP_DECL(products)[] = {          int                     sip_gigabit;
 #if defined(DP83820)  } sipcom_products[] = {
         { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83820,          { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83820,
           "NatSemi DP83820 Gigabit Ethernet",            "NatSemi DP83820 Gigabit Ethernet",
           &SIP_DECL(variant_dp83820) },            &sipcom_variant_dp83820, 1 },
 #else  
         { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_900,          { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_900,
           "SiS 900 10/100 Ethernet",            "SiS 900 10/100 Ethernet",
           &SIP_DECL(variant_sis900) },            &sipcom_variant_sis900, 0 },
         { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7016,          { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_7016,
           "SiS 7016 10/100 Ethernet",            "SiS 7016 10/100 Ethernet",
           &SIP_DECL(variant_sis900) },            &sipcom_variant_sis900, 0 },
   
         { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83815,          { PCI_VENDOR_NS,        PCI_PRODUCT_NS_DP83815,
           "NatSemi DP83815 10/100 Ethernet",            "NatSemi DP83815 10/100 Ethernet",
           &SIP_DECL(variant_dp83815) },            &sipcom_variant_dp83815, 0 },
 #endif /* DP83820 */  
   
         { 0,                    0,          { 0,                    0,
           NULL,            NULL,
           NULL },            NULL, 0 },
 };  };
   
 static const struct sip_product *  static const struct sip_product *
 SIP_DECL(lookup)(const struct pci_attach_args *pa)  sipcom_lookup(const struct pci_attach_args *pa, bool gigabit)
 {  {
         const struct sip_product *sip;          const struct sip_product *sip;
   
         for (sip = SIP_DECL(products); sip->sip_name != NULL; sip++) {          for (sip = sipcom_products; sip->sip_name != NULL; sip++) {
                 if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&                  if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&
                     PCI_PRODUCT(pa->pa_id) == sip->sip_product)                      PCI_PRODUCT(pa->pa_id) == sip->sip_product &&
                         return (sip);                      sip->sip_gigabit == gigabit)
                           return sip;
         }          }
         return (NULL);          return NULL;
 }  }
   
 #ifdef DP83820  
 /*  /*
  * I really hate stupid hardware vendors.  There's a bit in the EEPROM   * I really hate stupid hardware vendors.  There's a bit in the EEPROM
  * which indicates if the card can do 64-bit data transfers.  Unfortunately,   * which indicates if the card can do 64-bit data transfers.  Unfortunately,
Line 601  SIP_DECL(lookup)(const struct pci_attach
Line 735  SIP_DECL(lookup)(const struct pci_attach
  *         June 30, 2002   *         June 30, 2002
  */   */
 static int  static int
 SIP_DECL(check_64bit)(const struct pci_attach_args *pa)  sipcom_check_64bit(const struct pci_attach_args *pa)
 {  {
         static const struct {          static const struct {
                 pci_vendor_id_t c64_vendor;                  pci_vendor_id_t c64_vendor;
Line 634  SIP_DECL(check_64bit)(const struct pci_a
Line 768  SIP_DECL(check_64bit)(const struct pci_a
   
         return (0);          return (0);
 }  }
 #endif /* DP83820 */  
   
 static int  static int
 SIP_DECL(match)(struct device *parent, struct cfdata *cf,  sipcom_match(device_t parent, struct cfdata *cf, void *aux)
     void *aux)  
 {  {
         struct pci_attach_args *pa = aux;          struct pci_attach_args *pa = aux;
   
         if (SIP_DECL(lookup)(pa) != NULL)          if (sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0) != NULL)
                 return (1);                  return 1;
   
         return (0);          return 0;
 }  }
   
 static void  static void
 SIP_DECL(attach)(struct device *parent, struct device *self, void *aux)  sipcom_dp83820_attach(struct sip_softc *sc, struct pci_attach_args *pa)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          u_int32_t reg;
           int i;
   
           /*
            * Cause the chip to load configuration data from the EEPROM.
            */
           bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN);
           for (i = 0; i < 10000; i++) {
                   delay(10);
                   if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
                       PTSCR_EELOAD_EN) == 0)
                           break;
           }
           if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &
               PTSCR_EELOAD_EN) {
                   printf("%s: timeout loading configuration from EEPROM\n",
                       sc->sc_dev.dv_xname);
                   return;
           }
   
           sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR);
   
           reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG);
           if (reg & CFG_PCI64_DET) {
                   printf("%s: 64-bit PCI slot detected", sc->sc_dev.dv_xname);
                   /*
                    * Check to see if this card is 64-bit.  If so, enable 64-bit
                    * data transfers.
                    *
                    * We can't use the DATA64_EN bit in the EEPROM, because
                    * vendors of 32-bit cards fail to clear that bit in many
                    * cases (yet the card still detects that it's in a 64-bit
                    * slot; go figure).
                    */
                   if (sipcom_check_64bit(pa)) {
                           sc->sc_cfg |= CFG_DATA64_EN;
                           printf(", using 64-bit data transfers");
                   }
                   printf("\n");
           }
   
           /*
            * XXX Need some PCI flags indicating support for
            * XXX 64-bit addressing.
            */
   #if 0
           if (reg & CFG_M64ADDR)
                   sc->sc_cfg |= CFG_M64ADDR;
           if (reg & CFG_T64ADDR)
                   sc->sc_cfg |= CFG_T64ADDR;
   #endif
   
           if (reg & (CFG_TBI_EN|CFG_EXT_125)) {
                   const char *sep = "";
                   printf("%s: using ", sc->sc_dev.dv_xname);
                   if (reg & CFG_EXT_125) {
                           sc->sc_cfg |= CFG_EXT_125;
                           printf("%s125MHz clock", sep);
                           sep = ", ";
                   }
                   if (reg & CFG_TBI_EN) {
                           sc->sc_cfg |= CFG_TBI_EN;
                           printf("%sten-bit interface", sep);
                           sep = ", ";
                   }
                   printf("\n");
           }
           if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 ||
               (reg & CFG_MRM_DIS) != 0)
                   sc->sc_cfg |= CFG_MRM_DIS;
           if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 ||
               (reg & CFG_MWI_DIS) != 0)
                   sc->sc_cfg |= CFG_MWI_DIS;
   
           /*
            * Use the extended descriptor format on the DP83820.  This
            * gives us an interface to VLAN tagging and IPv4/TCP/UDP
            * checksumming.
            */
           sc->sc_cfg |= CFG_EXTSTS_EN;
   }
   
   static int
   sipcom_detach(device_t self, int flags)
   {
           int s;
   
           s = splnet();
           sipcom_do_detach(self, SIP_ATTACH_FIN);
           splx(s);
   
           return 0;
   }
   
   static void
   sipcom_do_detach(device_t self, enum sip_attach_stage stage)
   {
           int i;
           struct sip_softc *sc = device_private(self);
           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   
           /*
            * Free any resources we've allocated during attach.
            * Do this in reverse order and fall through.
            */
           switch (stage) {
           case SIP_ATTACH_FIN:
                   sipcom_stop(ifp, 1);
                   pmf_device_deregister(self);
   #ifdef SIP_EVENT_COUNTERS
                   /*
                    * Attach event counters.
                    */
                   evcnt_detach(&sc->sc_ev_txforceintr);
                   evcnt_detach(&sc->sc_ev_txdstall);
                   evcnt_detach(&sc->sc_ev_txsstall);
                   evcnt_detach(&sc->sc_ev_hiberr);
                   evcnt_detach(&sc->sc_ev_rxintr);
                   evcnt_detach(&sc->sc_ev_txiintr);
                   evcnt_detach(&sc->sc_ev_txdintr);
                   if (!sc->sc_gigabit) {
                           evcnt_detach(&sc->sc_ev_rxpause);
                   } else {
                           evcnt_detach(&sc->sc_ev_txudpsum);
                           evcnt_detach(&sc->sc_ev_txtcpsum);
                           evcnt_detach(&sc->sc_ev_txipsum);
                           evcnt_detach(&sc->sc_ev_rxudpsum);
                           evcnt_detach(&sc->sc_ev_rxtcpsum);
                           evcnt_detach(&sc->sc_ev_rxipsum);
                           evcnt_detach(&sc->sc_ev_txpause);
                           evcnt_detach(&sc->sc_ev_rxpause);
                   }
   #endif /* SIP_EVENT_COUNTERS */
   
   #if NRND > 0
                   rnd_detach_source(&sc->rnd_source);
   #endif
   
                   ether_ifdetach(ifp);
                   if_detach(ifp);
                   mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
   
                   /*FALLTHROUGH*/
           case SIP_ATTACH_CREATE_RXMAP:
                   for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
                           if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
                                   bus_dmamap_destroy(sc->sc_dmat,
                                       sc->sc_rxsoft[i].rxs_dmamap);
                   }
                   /*FALLTHROUGH*/
           case SIP_ATTACH_CREATE_TXMAP:
                   for (i = 0; i < SIP_TXQUEUELEN; i++) {
                           if (sc->sc_txsoft[i].txs_dmamap != NULL)
                                   bus_dmamap_destroy(sc->sc_dmat,
                                       sc->sc_txsoft[i].txs_dmamap);
                   }
                   /*FALLTHROUGH*/
           case SIP_ATTACH_LOAD_MAP:
                   bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
                   /*FALLTHROUGH*/
           case SIP_ATTACH_CREATE_MAP:
                   bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
                   /*FALLTHROUGH*/
           case SIP_ATTACH_MAP_MEM:
                   bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,
                       sizeof(struct sip_control_data));
                   /*FALLTHROUGH*/
           case SIP_ATTACH_ALLOC_MEM:
                   bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, 1);
                   /* FALLTHROUGH*/
           case SIP_ATTACH_INTR:
                   pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
                   /* FALLTHROUGH*/
           case SIP_ATTACH_MAP:
                   bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
                   break;
           default:
                   break;
           }
           return;
   }
   
   static bool
   sipcom_resume(device_t self PMF_FN_ARGS)
   {
           struct sip_softc *sc = device_private(self);
   
           return sipcom_reset(sc);
   }
   
   static bool
   sipcom_suspend(device_t self PMF_FN_ARGS)
   {
           struct sip_softc *sc = device_private(self);
   
           sipcom_rxdrain(sc);
           return true;
   }
   
   static void
   sipcom_attach(device_t parent, device_t self, void *aux)
   {
           struct sip_softc *sc = device_private(self);
         struct pci_attach_args *pa = aux;          struct pci_attach_args *pa = aux;
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         pci_chipset_tag_t pc = pa->pa_pc;          pci_chipset_tag_t pc = pa->pa_pc;
Line 659  SIP_DECL(attach)(struct device *parent, 
Line 993  SIP_DECL(attach)(struct device *parent, 
         const char *intrstr = NULL;          const char *intrstr = NULL;
         bus_space_tag_t iot, memt;          bus_space_tag_t iot, memt;
         bus_space_handle_t ioh, memh;          bus_space_handle_t ioh, memh;
         bus_dma_segment_t seg;          bus_size_t iosz, memsz;
         int ioh_valid, memh_valid;          int ioh_valid, memh_valid;
         int i, rseg, error;          int i, rseg, error;
         const struct sip_product *sip;          const struct sip_product *sip;
         u_int8_t enaddr[ETHER_ADDR_LEN];          u_int8_t enaddr[ETHER_ADDR_LEN];
         pcireg_t pmreg;          pcireg_t pmreg;
 #ifdef DP83820  
         pcireg_t memtype;          pcireg_t memtype;
         u_int32_t reg;          bus_size_t tx_dmamap_size;
 #endif /* DP83820 */          int ntxsegs_alloc;
           cfdata_t cf = device_cfdata(self);
   
         callout_init(&sc->sc_tick_ch, 0);          callout_init(&sc->sc_tick_ch, 0);
   
         sip = SIP_DECL(lookup)(pa);          sip = sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0);
         if (sip == NULL) {          if (sip == NULL) {
                 printf("\n");                  printf("\n");
                 panic(SIP_STR(attach) ": impossible");                  panic("%s: impossible", __func__);
           }
           sc->sc_gigabit = sip->sip_gigabit;
   
           sc->sc_pc = pc;
   
           if (sc->sc_gigabit) {
                   sc->sc_rxintr = gsip_rxintr;
                   sc->sc_parm = &gsip_parm;
           } else {
                   sc->sc_rxintr = sip_rxintr;
                   sc->sc_parm = &sip_parm;
         }          }
           tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size;
           ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc;
           sc->sc_ntxdesc = SIP_TXQUEUELEN * ntxsegs_alloc;
           sc->sc_ntxdesc_mask = sc->sc_ntxdesc - 1;
           sc->sc_nrxdesc_mask = sc->sc_parm->p_nrxdesc - 1;
   
         sc->sc_rev = PCI_REVISION(pa->pa_class);          sc->sc_rev = PCI_REVISION(pa->pa_class);
   
         printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev);          printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev);
Line 699  SIP_DECL(attach)(struct device *parent, 
Line 1050  SIP_DECL(attach)(struct device *parent, 
          */           */
         ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,          ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,
             PCI_MAPREG_TYPE_IO, 0,              PCI_MAPREG_TYPE_IO, 0,
             &iot, &ioh, NULL, NULL) == 0);              &iot, &ioh, NULL, &iosz) == 0);
 #ifdef DP83820          if (sc->sc_gigabit) {
         memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA);                  memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA);
         switch (memtype) {                  switch (memtype) {
         case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:                  case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
         case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:                  case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
                           memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
                               memtype, 0, &memt, &memh, NULL, &memsz) == 0);
                           break;
                   default:
                           memh_valid = 0;
                   }
           } else {
                 memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,                  memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
                     memtype, 0, &memt, &memh, NULL, NULL) == 0);                      PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
                 break;                      &memt, &memh, NULL, &memsz) == 0);
         default:  
                 memh_valid = 0;  
         }          }
 #else  
         memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,  
             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,  
             &memt, &memh, NULL, NULL) == 0);  
 #endif /* DP83820 */  
   
         if (memh_valid) {          if (memh_valid) {
                 sc->sc_st = memt;                  sc->sc_st = memt;
                 sc->sc_sh = memh;                  sc->sc_sh = memh;
                   sc->sc_sz = memsz;
         } else if (ioh_valid) {          } else if (ioh_valid) {
                 sc->sc_st = iot;                  sc->sc_st = iot;
                 sc->sc_sh = ioh;                  sc->sc_sh = ioh;
                   sc->sc_sz = iosz;
         } else {          } else {
                 printf("%s: unable to map device registers\n",                  printf("%s: unable to map device registers\n",
                     sc->sc_dev.dv_xname);                      sc->sc_dev.dv_xname);
Line 742  SIP_DECL(attach)(struct device *parent, 
Line 1095  SIP_DECL(attach)(struct device *parent, 
             pmreg | PCI_COMMAND_MASTER_ENABLE);              pmreg | PCI_COMMAND_MASTER_ENABLE);
   
         /* power up chip */          /* power up chip */
         if ((error = pci_activate(pa->pa_pc, pa->pa_tag, sc,          if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, NULL)) &&
             NULL)) && error != EOPNOTSUPP) {              error != EOPNOTSUPP) {
                 aprint_error("%s: cannot activate %d\n", sc->sc_dev.dv_xname,                  aprint_error("%s: cannot activate %d\n", sc->sc_dev.dv_xname,
                     error);                      error);
                 return;                  return;
Line 757  SIP_DECL(attach)(struct device *parent, 
Line 1110  SIP_DECL(attach)(struct device *parent, 
                 return;                  return;
         }          }
         intrstr = pci_intr_string(pc, ih);          intrstr = pci_intr_string(pc, ih);
         sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, SIP_DECL(intr), sc);          sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sipcom_intr, sc);
         if (sc->sc_ih == NULL) {          if (sc->sc_ih == NULL) {
                 printf("%s: unable to establish interrupt",                  printf("%s: unable to establish interrupt",
                     sc->sc_dev.dv_xname);                      sc->sc_dev.dv_xname);
                 if (intrstr != NULL)                  if (intrstr != NULL)
                         printf(" at %s", intrstr);                          printf(" at %s", intrstr);
                 printf("\n");                  printf("\n");
                 return;                  return sipcom_do_detach(self, SIP_ATTACH_MAP);
         }          }
         printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);          printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
   
Line 776  SIP_DECL(attach)(struct device *parent, 
Line 1129  SIP_DECL(attach)(struct device *parent, 
          * DMA map for it.           * DMA map for it.
          */           */
         if ((error = bus_dmamem_alloc(sc->sc_dmat,          if ((error = bus_dmamem_alloc(sc->sc_dmat,
             sizeof(struct sip_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,              sizeof(struct sip_control_data), PAGE_SIZE, 0, &sc->sc_seg, 1,
             0)) != 0) {              &rseg, 0)) != 0) {
                 printf("%s: unable to allocate control data, error = %d\n",                  printf("%s: unable to allocate control data, error = %d\n",
                     sc->sc_dev.dv_xname, error);                      sc->sc_dev.dv_xname, error);
                 goto fail_0;                  return sipcom_do_detach(self, SIP_ATTACH_INTR);
         }          }
   
         if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,          if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, rseg,
             sizeof(struct sip_control_data), (void **)&sc->sc_control_data,              sizeof(struct sip_control_data), (void **)&sc->sc_control_data,
             BUS_DMA_COHERENT)) != 0) {              BUS_DMA_COHERENT|BUS_DMA_NOCACHE)) != 0) {
                 printf("%s: unable to map control data, error = %d\n",                  printf("%s: unable to map control data, error = %d\n",
                     sc->sc_dev.dv_xname, error);                      sc->sc_dev.dv_xname, error);
                 goto fail_1;                  sipcom_do_detach(self, SIP_ATTACH_ALLOC_MEM);
         }          }
   
         if ((error = bus_dmamap_create(sc->sc_dmat,          if ((error = bus_dmamap_create(sc->sc_dmat,
Line 796  SIP_DECL(attach)(struct device *parent, 
Line 1149  SIP_DECL(attach)(struct device *parent, 
             sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {              sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
                 printf("%s: unable to create control data DMA map, "                  printf("%s: unable to create control data DMA map, "
                     "error = %d\n", sc->sc_dev.dv_xname, error);                      "error = %d\n", sc->sc_dev.dv_xname, error);
                 goto fail_2;                  sipcom_do_detach(self, SIP_ATTACH_MAP_MEM);
         }          }
   
         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,          if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
Line 804  SIP_DECL(attach)(struct device *parent, 
Line 1157  SIP_DECL(attach)(struct device *parent, 
             0)) != 0) {              0)) != 0) {
                 printf("%s: unable to load control data DMA map, error = %d\n",                  printf("%s: unable to load control data DMA map, error = %d\n",
                     sc->sc_dev.dv_xname, error);                      sc->sc_dev.dv_xname, error);
                 goto fail_3;                  sipcom_do_detach(self, SIP_ATTACH_CREATE_MAP);
         }          }
   
         /*          /*
          * Create the transmit buffer DMA maps.           * Create the transmit buffer DMA maps.
          */           */
         for (i = 0; i < SIP_TXQUEUELEN; i++) {          for (i = 0; i < SIP_TXQUEUELEN; i++) {
                 if ((error = bus_dmamap_create(sc->sc_dmat, TX_DMAMAP_SIZE,                  if ((error = bus_dmamap_create(sc->sc_dmat, tx_dmamap_size,
                     SIP_NTXSEGS, MCLBYTES, 0, 0,                      sc->sc_parm->p_ntxsegs, MCLBYTES, 0, 0,
                     &sc->sc_txsoft[i].txs_dmamap)) != 0) {                      &sc->sc_txsoft[i].txs_dmamap)) != 0) {
                         printf("%s: unable to create tx DMA map %d, "                          printf("%s: unable to create tx DMA map %d, "
                             "error = %d\n", sc->sc_dev.dv_xname, i, error);                              "error = %d\n", sc->sc_dev.dv_xname, i, error);
                         goto fail_4;                          sipcom_do_detach(self, SIP_ATTACH_CREATE_TXMAP);
                 }                  }
         }          }
   
         /*          /*
          * Create the receive buffer DMA maps.           * Create the receive buffer DMA maps.
          */           */
         for (i = 0; i < SIP_NRXDESC; i++) {          for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
                 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,                  if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
                     MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {                      MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
                         printf("%s: unable to create rx DMA map %d, "                          printf("%s: unable to create rx DMA map %d, "
                             "error = %d\n", sc->sc_dev.dv_xname, i, error);                              "error = %d\n", sc->sc_dev.dv_xname, i, error);
                         goto fail_5;                          sipcom_do_detach(self, SIP_ATTACH_CREATE_RXMAP);
                 }                  }
                 sc->sc_rxsoft[i].rxs_mbuf = NULL;                  sc->sc_rxsoft[i].rxs_mbuf = NULL;
         }          }
Line 836  SIP_DECL(attach)(struct device *parent, 
Line 1189  SIP_DECL(attach)(struct device *parent, 
         /*          /*
          * Reset the chip to a known state.           * Reset the chip to a known state.
          */           */
         SIP_DECL(reset)(sc);          sipcom_reset(sc);
   
         /*          /*
          * Read the Ethernet address from the EEPROM.  This might           * Read the Ethernet address from the EEPROM.  This might
Line 844  SIP_DECL(attach)(struct device *parent, 
Line 1197  SIP_DECL(attach)(struct device *parent, 
          * in the softc.           * in the softc.
          */           */
         sc->sc_cfg = 0;          sc->sc_cfg = 0;
 #if !defined(DP83820)          if (!sc->sc_gigabit) {
         if (SIP_SIS900_REV(sc,SIS_REV_635) ||                  if (SIP_SIS900_REV(sc,SIS_REV_635) ||
             SIP_SIS900_REV(sc,SIS_REV_900B))                      SIP_SIS900_REV(sc,SIS_REV_900B))
                 sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT);                          sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT);
   
         if (SIP_SIS900_REV(sc,SIS_REV_635) ||                  if (SIP_SIS900_REV(sc,SIS_REV_635) ||
             SIP_SIS900_REV(sc,SIS_REV_960) ||                      SIP_SIS900_REV(sc,SIS_REV_960) ||
             SIP_SIS900_REV(sc,SIS_REV_900B))                      SIP_SIS900_REV(sc,SIS_REV_900B))
                 sc->sc_cfg |= (bus_space_read_4(sc->sc_st, sc->sc_sh,                          sc->sc_cfg |=
                                                 SIP_CFG) & CFG_EDBMASTEN);                              (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) &
 #endif                               CFG_EDBMASTEN);
           }
   
         (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr);          (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr);
   
Line 869  SIP_DECL(attach)(struct device *parent, 
Line 1223  SIP_DECL(attach)(struct device *parent, 
          * NOTE: "Big endian mode" is useless on the SiS900 and           * NOTE: "Big endian mode" is useless on the SiS900 and
          * friends -- it affects packet data, not descriptors.           * friends -- it affects packet data, not descriptors.
          */           */
 #ifdef DP83820          if (sc->sc_gigabit)
         /*                  sipcom_dp83820_attach(sc, pa);
          * Cause the chip to load configuration data from the EEPROM.  
          */  
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN);  
         for (i = 0; i < 10000; i++) {  
                 delay(10);  
                 if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &  
                     PTSCR_EELOAD_EN) == 0)  
                         break;  
         }  
         if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) &  
             PTSCR_EELOAD_EN) {  
                 printf("%s: timeout loading configuration from EEPROM\n",  
                     sc->sc_dev.dv_xname);  
                 return;  
         }  
   
         sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR);  
   
         reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG);  
         if (reg & CFG_PCI64_DET) {  
                 printf("%s: 64-bit PCI slot detected", sc->sc_dev.dv_xname);  
                 /*  
                  * Check to see if this card is 64-bit.  If so, enable 64-bit  
                  * data transfers.  
                  *  
                  * We can't use the DATA64_EN bit in the EEPROM, because  
                  * vendors of 32-bit cards fail to clear that bit in many  
                  * cases (yet the card still detects that it's in a 64-bit  
                  * slot; go figure).  
                  */  
                 if (SIP_DECL(check_64bit)(pa)) {  
                         sc->sc_cfg |= CFG_DATA64_EN;  
                         printf(", using 64-bit data transfers");  
                 }  
                 printf("\n");  
         }  
   
         /*  
          * XXX Need some PCI flags indicating support for  
          * XXX 64-bit addressing.  
          */  
 #if 0  
         if (reg & CFG_M64ADDR)  
                 sc->sc_cfg |= CFG_M64ADDR;  
         if (reg & CFG_T64ADDR)  
                 sc->sc_cfg |= CFG_T64ADDR;  
 #endif  
   
         if (reg & (CFG_TBI_EN|CFG_EXT_125)) {  
                 const char *sep = "";  
                 printf("%s: using ", sc->sc_dev.dv_xname);  
                 if (reg & CFG_EXT_125) {  
                         sc->sc_cfg |= CFG_EXT_125;  
                         printf("%s125MHz clock", sep);  
                         sep = ", ";  
                 }  
                 if (reg & CFG_TBI_EN) {  
                         sc->sc_cfg |= CFG_TBI_EN;  
                         printf("%sten-bit interface", sep);  
                         sep = ", ";  
                 }  
                 printf("\n");  
         }  
         if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 ||  
             (reg & CFG_MRM_DIS) != 0)  
                 sc->sc_cfg |= CFG_MRM_DIS;  
         if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 ||  
             (reg & CFG_MWI_DIS) != 0)  
                 sc->sc_cfg |= CFG_MWI_DIS;  
   
         /*  
          * Use the extended descriptor format on the DP83820.  This  
          * gives us an interface to VLAN tagging and IPv4/TCP/UDP  
          * checksumming.  
          */  
         sc->sc_cfg |= CFG_EXTSTS_EN;  
 #endif /* DP83820 */  
   
         /*          /*
          * Initialize our media structures and probe the MII.           * Initialize our media structures and probe the MII.
Line 956  SIP_DECL(attach)(struct device *parent, 
Line 1233  SIP_DECL(attach)(struct device *parent, 
         sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg;          sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg;
         sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg;          sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg;
         sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg;          sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg;
         ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, SIP_DECL(mediachange),          sc->sc_ethercom.ec_mii = &sc->sc_mii;
             SIP_DECL(mediastatus));          ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, ether_mediachange,
               sipcom_mediastatus);
   
         /*          /*
          * XXX We cannot handle flow control on the DP83815.           * XXX We cannot handle flow control on the DP83815.
Line 979  SIP_DECL(attach)(struct device *parent, 
Line 1257  SIP_DECL(attach)(struct device *parent, 
         ifp->if_softc = sc;          ifp->if_softc = sc;
         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;          ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
         sc->sc_if_flags = ifp->if_flags;          sc->sc_if_flags = ifp->if_flags;
         ifp->if_ioctl = SIP_DECL(ioctl);          ifp->if_ioctl = sipcom_ioctl;
         ifp->if_start = SIP_DECL(start);          ifp->if_start = sipcom_start;
         ifp->if_watchdog = SIP_DECL(watchdog);          ifp->if_watchdog = sipcom_watchdog;
         ifp->if_init = SIP_DECL(init);          ifp->if_init = sipcom_init;
         ifp->if_stop = SIP_DECL(stop);          ifp->if_stop = sipcom_stop;
         IFQ_SET_READY(&ifp->if_snd);          IFQ_SET_READY(&ifp->if_snd);
   
         /*          /*
Line 991  SIP_DECL(attach)(struct device *parent, 
Line 1269  SIP_DECL(attach)(struct device *parent, 
          */           */
         sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;          sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
   
 #ifdef DP83820          if (sc->sc_gigabit) {
         /*                  /*
          * And the DP83820 can do VLAN tagging in hardware, and                   * And the DP83820 can do VLAN tagging in hardware, and
          * support the jumbo Ethernet MTU.                   * support the jumbo Ethernet MTU.
          */                   */
         sc->sc_ethercom.ec_capabilities |=                  sc->sc_ethercom.ec_capabilities |=
             ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;                      ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
   
         /*                  /*
          * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums                   * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums
          * in hardware.                   * in hardware.
          */                   */
         ifp->if_capabilities |=                  ifp->if_capabilities |=
             IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |                      IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
             IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |                      IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
             IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;                      IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx;
 #endif /* DP83820 */          }
   
         /*          /*
          * Attach the interface.           * Attach the interface.
Line 1039  SIP_DECL(attach)(struct device *parent, 
Line 1317  SIP_DECL(attach)(struct device *parent, 
          * may trash the first few outgoing packets if the           * may trash the first few outgoing packets if the
          * PCI bus is saturated.           * PCI bus is saturated.
          */           */
 #ifdef DP83820          if (sc->sc_gigabit)
         sc->sc_tx_drain_thresh = 6400 / 32;     /* from FreeBSD nge(4) */                  sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */
 #else          else
         sc->sc_tx_drain_thresh = 1504 / 32;                  sc->sc_tx_drain_thresh = 1504 / 32;
 #endif  
   
         /*          /*
          * Initialize the Rx FIFO drain threshold.           * Initialize the Rx FIFO drain threshold.
Line 1073  SIP_DECL(attach)(struct device *parent, 
Line 1350  SIP_DECL(attach)(struct device *parent, 
             NULL, sc->sc_dev.dv_xname, "rxintr");              NULL, sc->sc_dev.dv_xname, "rxintr");
         evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR,          evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR,
             NULL, sc->sc_dev.dv_xname, "hiberr");              NULL, sc->sc_dev.dv_xname, "hiberr");
 #ifndef DP83820          if (!sc->sc_gigabit) {
         evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR,                  evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR,
             NULL, sc->sc_dev.dv_xname, "rxpause");                      NULL, sc->sc_dev.dv_xname, "rxpause");
 #endif /* !DP83820 */          } else {
 #ifdef DP83820                  evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "rxpause");
             NULL, sc->sc_dev.dv_xname, "rxpause");                  evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "txpause");
             NULL, sc->sc_dev.dv_xname, "txpause");                  evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "rxipsum");
             NULL, sc->sc_dev.dv_xname, "rxipsum");                  evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "rxtcpsum");
             NULL, sc->sc_dev.dv_xname, "rxtcpsum");                  evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "rxudpsum");
             NULL, sc->sc_dev.dv_xname, "rxudpsum");                  evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "txipsum");
             NULL, sc->sc_dev.dv_xname, "txipsum");                  evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "txtcpsum");
             NULL, sc->sc_dev.dv_xname, "txtcpsum");                  evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC,
         evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC,                      NULL, sc->sc_dev.dv_xname, "txudpsum");
             NULL, sc->sc_dev.dv_xname, "txudpsum");          }
 #endif /* DP83820 */  
 #endif /* SIP_EVENT_COUNTERS */  #endif /* SIP_EVENT_COUNTERS */
   
           if (!pmf_device_register(self, sipcom_suspend, sipcom_resume))
                   aprint_error_dev(self, "couldn't establish power handler\n");
           else
                   pmf_class_network_register(self, ifp);
   }
   
   static inline void
   sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0,
       uint64_t capenable)
   {
           struct m_tag *mtag;
           u_int32_t extsts;
   #ifdef DEBUG
           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   #endif
         /*          /*
          * Make sure the interface is shutdown during reboot.           * If VLANs are enabled and the packet has a VLAN tag, set
            * up the descriptor to encapsulate the packet for us.
            *
            * This apparently has to be on the last descriptor of
            * the packet.
          */           */
         sc->sc_sdhook = shutdownhook_establish(SIP_DECL(shutdown), sc);  
         if (sc->sc_sdhook == NULL)  
                 printf("%s: WARNING: unable to establish shutdown hook\n",  
                     sc->sc_dev.dv_xname);  
         return;  
   
         /*          /*
          * Free any resources we've allocated during the failed attach           * Byte swapping is tricky. We need to provide the tag
          * attempt.  Do this in reverse order and fall through.           * in a network byte order. On a big-endian machine,
            * the byteorder is correct, but we need to swap it
            * anyway, because this will be undone by the outside
            * htole32(). That's why there must be an
            * unconditional swap instead of htons() inside.
          */           */
  fail_5:          if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) {
         for (i = 0; i < SIP_NRXDESC; i++) {                  sc->sc_txdescs[lasttx].sipd_extsts |=
                 if (sc->sc_rxsoft[i].rxs_dmamap != NULL)                      htole32(EXTSTS_VPKT |
                         bus_dmamap_destroy(sc->sc_dmat,                                  (bswap16(VLAN_TAG_VALUE(mtag)) &
                             sc->sc_rxsoft[i].rxs_dmamap);                                   EXTSTS_VTCI));
         }          }
  fail_4:  
         for (i = 0; i < SIP_TXQUEUELEN; i++) {  
                 if (sc->sc_txsoft[i].txs_dmamap != NULL)  
                         bus_dmamap_destroy(sc->sc_dmat,  
                             sc->sc_txsoft[i].txs_dmamap);  
         }  
         bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);  
  fail_3:  
         bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);  
  fail_2:  
         bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data,  
             sizeof(struct sip_control_data));  
  fail_1:  
         bus_dmamem_free(sc->sc_dmat, &seg, rseg);  
  fail_0:  
         return;  
 }  
   
 /*  
  * sip_shutdown:  
  *  
  *      Make sure the interface is stopped at reboot time.  
  */  
 static void  
 SIP_DECL(shutdown)(void *arg)  
 {  
         struct sip_softc *sc = arg;  
   
         SIP_DECL(stop)(&sc->sc_ethercom.ec_if, 1);          /*
            * If the upper-layer has requested IPv4/TCPv4/UDPv4
            * checksumming, set up the descriptor to do this work
            * for us.
            *
            * This apparently has to be on the first descriptor of
            * the packet.
            *
            * Byte-swap constants so the compiler can optimize.
            */
           extsts = 0;
           if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {
                   KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx);
                   SIP_EVCNT_INCR(&sc->sc_ev_txipsum);
                   extsts |= htole32(EXTSTS_IPPKT);
           }
           if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) {
                   KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx);
                   SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum);
                   extsts |= htole32(EXTSTS_TCPPKT);
           } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) {
                   KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx);
                   SIP_EVCNT_INCR(&sc->sc_ev_txudpsum);
                   extsts |= htole32(EXTSTS_UDPPKT);
           }
           sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts;
 }  }
   
 /*  /*
Line 1153  SIP_DECL(shutdown)(void *arg)
Line 1445  SIP_DECL(shutdown)(void *arg)
  *      Start packet transmission on the interface.   *      Start packet transmission on the interface.
  */   */
 static void  static void
 SIP_DECL(start)(struct ifnet *ifp)  sipcom_start(struct ifnet *ifp)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
         struct mbuf *m0;          struct mbuf *m0;
 #ifndef DP83820  
         struct mbuf *m;          struct mbuf *m;
 #endif  
         struct sip_txsoft *txs;          struct sip_txsoft *txs;
         bus_dmamap_t dmamap;          bus_dmamap_t dmamap;
         int error, nexttx, lasttx, seg;          int error, nexttx, lasttx, seg;
Line 1167  SIP_DECL(start)(struct ifnet *ifp)
Line 1457  SIP_DECL(start)(struct ifnet *ifp)
 #if 0  #if 0
         int firsttx = sc->sc_txnext;          int firsttx = sc->sc_txnext;
 #endif  #endif
 #ifdef DP83820  
         struct m_tag *mtag;  
         u_int32_t extsts;  
 #endif  
   
 #ifndef DP83820  
         /*          /*
          * If we've been told to pause, don't transmit any more packets.           * If we've been told to pause, don't transmit any more packets.
          */           */
         if (sc->sc_paused)          if (!sc->sc_gigabit && sc->sc_paused)
                 ifp->if_flags |= IFF_OACTIVE;                  ifp->if_flags |= IFF_OACTIVE;
 #endif  
   
         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)          if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
                 return;                  return;
Line 1201  SIP_DECL(start)(struct ifnet *ifp)
Line 1485  SIP_DECL(start)(struct ifnet *ifp)
                 IFQ_POLL(&ifp->if_snd, m0);                  IFQ_POLL(&ifp->if_snd, m0);
                 if (m0 == NULL)                  if (m0 == NULL)
                         break;                          break;
 #ifndef DP83820  
                 m = NULL;                  m = NULL;
 #endif  
   
                 dmamap = txs->txs_dmamap;                  dmamap = txs->txs_dmamap;
   
 #ifdef DP83820  
                 /*                  /*
                  * Load the DMA map.  If this fails, the packet either                   * Load the DMA map.  If this fails, the packet either
                  * didn't fit in the allotted number of segments, or we                   * didn't fit in the alloted number of segments, or we
                  * were short on resources.  For the too-many-segments                   * were short on resources.
                  * case, we simply report an error and drop the packet,  
                  * since we can't sanely copy a jumbo packet to a single  
                  * buffer.  
                  */                   */
                 error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,                  error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
                     BUS_DMA_WRITE|BUS_DMA_NOWAIT);                      BUS_DMA_WRITE|BUS_DMA_NOWAIT);
                 if (error) {                  /* In the non-gigabit case, we'll copy and try again. */
                         if (error == EFBIG) {                  if (error != 0 && !sc->sc_gigabit) {
                                 printf("%s: Tx packet consumes too many "  
                                     "DMA segments, dropping...\n",  
                                     sc->sc_dev.dv_xname);  
                                 IFQ_DEQUEUE(&ifp->if_snd, m0);  
                                 m_freem(m0);  
                                 continue;  
                         }  
                         /*  
                          * Short on resources, just stop for now.  
                          */  
                         break;  
                 }  
 #else /* DP83820 */  
                 /*  
                  * Load the DMA map.  If this fails, the packet either  
                  * didn't fit in the alloted number of segments, or we  
                  * were short on resources.  In this case, we'll copy  
                  * and try again.  
                  */  
                 if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,  
                     BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {  
                         MGETHDR(m, M_DONTWAIT, MT_DATA);                          MGETHDR(m, M_DONTWAIT, MT_DATA);
                         if (m == NULL) {                          if (m == NULL) {
                                 printf("%s: unable to allocate Tx mbuf\n",                                  printf("%s: unable to allocate Tx mbuf\n",
Line 1266  SIP_DECL(start)(struct ifnet *ifp)
Line 1523  SIP_DECL(start)(struct ifnet *ifp)
                                     "error = %d\n", sc->sc_dev.dv_xname, error);                                      "error = %d\n", sc->sc_dev.dv_xname, error);
                                 break;                                  break;
                         }                          }
                   } else if (error == EFBIG) {
                           /*
                            * For the too-many-segments case, we simply
                            * report an error and drop the packet,
                            * since we can't sanely copy a jumbo packet
                            * to a single buffer.
                            */
                           printf("%s: Tx packet consumes too many "
                               "DMA segments, dropping...\n", sc->sc_dev.dv_xname);
                           IFQ_DEQUEUE(&ifp->if_snd, m0);
                           m_freem(m0);
                           continue;
                   } else if (error != 0) {
                           /*
                            * Short on resources, just stop for now.
                            */
                           break;
                 }                  }
 #endif /* DP83820 */  
   
                 /*                  /*
                  * Ensure we have enough descriptors free to describe                   * Ensure we have enough descriptors free to describe
Line 1288  SIP_DECL(start)(struct ifnet *ifp)
Line 1561  SIP_DECL(start)(struct ifnet *ifp)
                          */                           */
                         ifp->if_flags |= IFF_OACTIVE;                          ifp->if_flags |= IFF_OACTIVE;
                         bus_dmamap_unload(sc->sc_dmat, dmamap);                          bus_dmamap_unload(sc->sc_dmat, dmamap);
 #ifndef DP83820  
                         if (m != NULL)                          if (m != NULL)
                                 m_freem(m);                                  m_freem(m);
 #endif  
                         SIP_EVCNT_INCR(&sc->sc_ev_txdstall);                          SIP_EVCNT_INCR(&sc->sc_ev_txdstall);
                         break;                          break;
                 }                  }
   
                 IFQ_DEQUEUE(&ifp->if_snd, m0);                  IFQ_DEQUEUE(&ifp->if_snd, m0);
 #ifndef DP83820  
                 if (m != NULL) {                  if (m != NULL) {
                         m_freem(m0);                          m_freem(m0);
                         m0 = m;                          m0 = m;
                 }                  }
 #endif  
   
                 /*                  /*
                  * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.                   * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
Line 1317  SIP_DECL(start)(struct ifnet *ifp)
Line 1586  SIP_DECL(start)(struct ifnet *ifp)
                  */                   */
                 for (nexttx = lasttx = sc->sc_txnext, seg = 0;                  for (nexttx = lasttx = sc->sc_txnext, seg = 0;
                      seg < dmamap->dm_nsegs;                       seg < dmamap->dm_nsegs;
                      seg++, nexttx = SIP_NEXTTX(nexttx)) {                       seg++, nexttx = sip_nexttx(sc, nexttx)) {
                         /*                          /*
                          * If this is the first descriptor we're                           * If this is the first descriptor we're
                          * enqueueing, don't set the OWN bit just                           * enqueueing, don't set the OWN bit just
                          * yet.  That could cause a race condition.                           * yet.  That could cause a race condition.
                          * We'll do it below.                           * We'll do it below.
                          */                           */
                         sc->sc_txdescs[nexttx].sipd_bufptr =                          *sipd_bufptr(sc, &sc->sc_txdescs[nexttx]) =
                             htole32(dmamap->dm_segs[seg].ds_addr);                              htole32(dmamap->dm_segs[seg].ds_addr);
                         sc->sc_txdescs[nexttx].sipd_cmdsts =                          *sipd_cmdsts(sc, &sc->sc_txdescs[nexttx]) =
                             htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) |                              htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) |
                             CMDSTS_MORE | dmamap->dm_segs[seg].ds_len);                              CMDSTS_MORE | dmamap->dm_segs[seg].ds_len);
 #ifdef DP83820  
                         sc->sc_txdescs[nexttx].sipd_extsts = 0;                          sc->sc_txdescs[nexttx].sipd_extsts = 0;
 #endif /* DP83820 */  
                         lasttx = nexttx;                          lasttx = nexttx;
                 }                  }
   
                 /* Clear the MORE bit on the last segment. */                  /* Clear the MORE bit on the last segment. */
                 sc->sc_txdescs[lasttx].sipd_cmdsts &= htole32(~CMDSTS_MORE);                  *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) &=
                       htole32(~CMDSTS_MORE);
   
                 /*                  /*
                  * If we're in the interrupt delay window, delay the                   * If we're in the interrupt delay window, delay the
Line 1344  SIP_DECL(start)(struct ifnet *ifp)
Line 1612  SIP_DECL(start)(struct ifnet *ifp)
                  */                   */
                 if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) {                  if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) {
                         SIP_EVCNT_INCR(&sc->sc_ev_txforceintr);                          SIP_EVCNT_INCR(&sc->sc_ev_txforceintr);
                         sc->sc_txdescs[lasttx].sipd_cmdsts |=                          *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) |=
                             htole32(CMDSTS_INTR);                              htole32(CMDSTS_INTR);
                         sc->sc_txwin = 0;                          sc->sc_txwin = 0;
                 }                  }
   
 #ifdef DP83820                  if (sc->sc_gigabit)
                 /*                          sipcom_set_extsts(sc, lasttx, m0, ifp->if_capenable);
                  * If VLANs are enabled and the packet has a VLAN tag, set  
                  * up the descriptor to encapsulate the packet for us.  
                  *  
                  * This apparently has to be on the last descriptor of  
                  * the packet.  
                  */  
   
                 /*  
                  * Byte swapping is tricky. We need to provide the tag  
                  * in a network byte order. On a big-endian machine,  
                  * the byteorder is correct, but we need to swap it  
                  * anyway, because this will be undone by the outside  
                  * htole32(). That's why there must be an  
                  * unconditional swap instead of htons() inside.  
                  */  
                 if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) {  
                         sc->sc_txdescs[lasttx].sipd_extsts |=  
                             htole32(EXTSTS_VPKT |  
                                         (bswap16(VLAN_TAG_VALUE(mtag)) &  
                                          EXTSTS_VTCI));  
                 }  
   
                 /*  
                  * If the upper-layer has requested IPv4/TCPv4/UDPv4  
                  * checksumming, set up the descriptor to do this work  
                  * for us.  
                  *  
                  * This apparently has to be on the first descriptor of  
                  * the packet.  
                  *  
                  * Byte-swap constants so the compiler can optimize.  
                  */  
                 extsts = 0;  
                 if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) {  
                         KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx);  
                         SIP_EVCNT_INCR(&sc->sc_ev_txipsum);  
                         extsts |= htole32(EXTSTS_IPPKT);  
                 }  
                 if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) {  
                         KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx);  
                         SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum);  
                         extsts |= htole32(EXTSTS_TCPPKT);  
                 } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) {  
                         KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx);  
                         SIP_EVCNT_INCR(&sc->sc_ev_txudpsum);  
                         extsts |= htole32(EXTSTS_UDPPKT);  
                 }  
                 sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts;  
 #endif /* DP83820 */  
   
                 /* Sync the descriptors we're using. */                  /* Sync the descriptors we're using. */
                 SIP_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,                  sip_cdtxsync(sc, sc->sc_txnext, dmamap->dm_nsegs,
                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);                      BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   
                 /*                  /*
                  * The entire packet is set up.  Give the first descrptor                   * The entire packet is set up.  Give the first descrptor
                  * to the chip now.                   * to the chip now.
                  */                   */
                 sc->sc_txdescs[sc->sc_txnext].sipd_cmdsts |=                  *sipd_cmdsts(sc, &sc->sc_txdescs[sc->sc_txnext]) |=
                     htole32(CMDSTS_OWN);                      htole32(CMDSTS_OWN);
                 SIP_CDTXSYNC(sc, sc->sc_txnext, 1,                  sip_cdtxsync(sc, sc->sc_txnext, 1,
                     BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);                      BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   
                 /*                  /*
Line 1472  SIP_DECL(start)(struct ifnet *ifp)
Line 1691  SIP_DECL(start)(struct ifnet *ifp)
 #endif  #endif
   
                 /* Set a watchdog timer in case the chip flakes out. */                  /* Set a watchdog timer in case the chip flakes out. */
 #ifdef DP83820  
                 /* Gigabit autonegotiation takes 5 seconds. */                  /* Gigabit autonegotiation takes 5 seconds. */
                 ifp->if_timer = 10;                  ifp->if_timer = (sc->sc_gigabit) ? 10 : 5;
 #else  
                 ifp->if_timer = 5;  
 #endif  
         }          }
 }  }
   
Line 1487  SIP_DECL(start)(struct ifnet *ifp)
Line 1702  SIP_DECL(start)(struct ifnet *ifp)
  *      Watchdog timer handler.   *      Watchdog timer handler.
  */   */
 static void  static void
 SIP_DECL(watchdog)(struct ifnet *ifp)  sipcom_watchdog(struct ifnet *ifp)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
   
Line 1497  SIP_DECL(watchdog)(struct ifnet *ifp)
Line 1712  SIP_DECL(watchdog)(struct ifnet *ifp)
          * If we manage to sweep them all up, ignore the lack of           * If we manage to sweep them all up, ignore the lack of
          * interrupt.           * interrupt.
          */           */
         SIP_DECL(txintr)(sc);          sipcom_txintr(sc);
   
         if (sc->sc_txfree != SIP_NTXDESC) {          if (sc->sc_txfree != sc->sc_ntxdesc) {
                 printf("%s: device timeout\n", sc->sc_dev.dv_xname);                  printf("%s: device timeout\n", sc->sc_dev.dv_xname);
                 ifp->if_oerrors++;                  ifp->if_oerrors++;
   
                 /* Reset the interface. */                  /* Reset the interface. */
                 (void) SIP_DECL(init)(ifp);                  (void) sipcom_init(ifp);
         } else if (ifp->if_flags & IFF_DEBUG)          } else if (ifp->if_flags & IFF_DEBUG)
                 printf("%s: recovered from device timeout\n",                  printf("%s: recovered from device timeout\n",
                     sc->sc_dev.dv_xname);                      sc->sc_dev.dv_xname);
   
         /* Try to get more packets going. */          /* Try to get more packets going. */
         SIP_DECL(start)(ifp);          sipcom_start(ifp);
 }  }
   
 /*  /*
Line 1519  SIP_DECL(watchdog)(struct ifnet *ifp)
Line 1734  SIP_DECL(watchdog)(struct ifnet *ifp)
  *      Handle control requests from the operator.   *      Handle control requests from the operator.
  */   */
 static int  static int
 SIP_DECL(ioctl)(struct ifnet *ifp, u_long cmd, void *data)  sipcom_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
         struct ifreq *ifr = (struct ifreq *)data;          struct ifreq *ifr = (struct ifreq *)data;
Line 1533  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
Line 1748  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
                 if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||                  if (IFM_SUBTYPE(ifr->ifr_media) == IFM_AUTO ||
                     (ifr->ifr_media & IFM_FDX) == 0)                      (ifr->ifr_media & IFM_FDX) == 0)
                         ifr->ifr_media &= ~IFM_ETH_FMASK;                          ifr->ifr_media &= ~IFM_ETH_FMASK;
 #ifdef DP83820  
                 if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {  
                         if ((ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {  
                                 /* We can do both TXPAUSE and RXPAUSE. */  
                                 ifr->ifr_media |=  
                                     IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;  
                         }  
                         sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK;  
                 }  
 #else  
                 /* XXX */                  /* XXX */
                 if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))                  if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815))
                         ifr->ifr_media &= ~IFM_ETH_FMASK;                          ifr->ifr_media &= ~IFM_ETH_FMASK;
   
                 if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {                  if (IFM_SUBTYPE(ifr->ifr_media) != IFM_AUTO) {
                         if (ifr->ifr_media & IFM_FLOW) {                          if (sc->sc_gigabit &&
                               (ifr->ifr_media & IFM_ETH_FMASK) == IFM_FLOW) {
                                   /* We can do both TXPAUSE and RXPAUSE. */
                                   ifr->ifr_media |=
                                       IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE;
                           } else if (ifr->ifr_media & IFM_FLOW) {
                                 /*                                  /*
                                  * Both TXPAUSE and RXPAUSE must be set.                                   * Both TXPAUSE and RXPAUSE must be set.
                                  * (SiS900 and DP83815 don't have PAUSE_ASYM                                   * (SiS900 and DP83815 don't have PAUSE_ASYM
Line 1561  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
Line 1771  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
                         }                          }
                         sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK;                          sc->sc_flowflags = ifr->ifr_media & IFM_ETH_FMASK;
                 }                  }
 #endif                  goto ethioctl;
                 /* FALLTHROUGH */  
         case SIOCGIFMEDIA:  
                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);  
                 break;  
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 /* If the interface is up and running, only modify the receive                  /* If the interface is up and running, only modify the receive
                  * filter when setting promiscuous or debug mode.  Otherwise                   * filter when setting promiscuous or debug mode.  Otherwise
Line 1592  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
Line 1798  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
 #undef RESETIGN  #undef RESETIGN
                 }                  }
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
           ethioctl:
         default:          default:
                 error = ether_ioctl(ifp, cmd, data);                  if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
                 if (error == ENETRESET) {                          break;
   
                   error = 0;
   
                   if (cmd == SIOCSIFCAP)
                           error = (*ifp->if_init)(ifp);
                   else if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
                           ;
                   else if (ifp->if_flags & IFF_RUNNING) {
                         /*                          /*
                          * Multicast list has changed; set the hardware filter                           * Multicast list has changed; set the hardware filter
                          * accordingly.                           * accordingly.
                          */                           */
                         if (ifp->if_flags & IFF_RUNNING)                          (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
                             (*sc->sc_model->sip_variant->sipv_set_filter)(sc);  
                         error = 0;  
                 }                  }
                 break;                  break;
         }          }
   
         /* Try to get more packets going. */          /* Try to get more packets going. */
         SIP_DECL(start)(ifp);          sipcom_start(ifp);
   
         sc->sc_if_flags = ifp->if_flags;          sc->sc_if_flags = ifp->if_flags;
         splx(s);          splx(s);
Line 1620  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
Line 1833  SIP_DECL(ioctl)(struct ifnet *ifp, u_lon
  *      Interrupt service routine.   *      Interrupt service routine.
  */   */
 static int  static int
 SIP_DECL(intr)(void *arg)  sipcom_intr(void *arg)
 {  {
         struct sip_softc *sc = arg;          struct sip_softc *sc = arg;
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
Line 1647  SIP_DECL(intr)(void *arg)
Line 1860  SIP_DECL(intr)(void *arg)
                         SIP_EVCNT_INCR(&sc->sc_ev_rxintr);                          SIP_EVCNT_INCR(&sc->sc_ev_rxintr);
   
                         /* Grab any new packets. */                          /* Grab any new packets. */
                         SIP_DECL(rxintr)(sc);                          (*sc->sc_rxintr)(sc);
   
                         if (isr & ISR_RXORN) {                          if (isr & ISR_RXORN) {
                                 printf("%s: receive FIFO overrun\n",                                  printf("%s: receive FIFO overrun\n",
Line 1677  SIP_DECL(intr)(void *arg)
Line 1890  SIP_DECL(intr)(void *arg)
 #endif  #endif
   
                         /* Sweep up transmit descriptors. */                          /* Sweep up transmit descriptors. */
                         SIP_DECL(txintr)(sc);                          sipcom_txintr(sc);
   
                         if (isr & ISR_TXURN) {                          if (isr & ISR_TXURN) {
                                 u_int32_t thresh;                                  u_int32_t thresh;
                                   int txfifo_size = (sc->sc_gigabit)
                                       ? DP83820_SIP_TXFIFO_SIZE
                                       : OTHER_SIP_TXFIFO_SIZE;
   
                                 printf("%s: transmit FIFO underrun",                                  printf("%s: transmit FIFO underrun",
                                     sc->sc_dev.dv_xname);                                      sc->sc_dev.dv_xname);
   
                                 thresh = sc->sc_tx_drain_thresh + 1;                                  thresh = sc->sc_tx_drain_thresh + 1;
                                 if (thresh <= TXCFG_DRTH &&                                  if (thresh <= __SHIFTOUT_MASK(sc->sc_bits.b_txcfg_drth_mask)
                                     (thresh * 32) <= (SIP_TXFIFO_SIZE -                                  && (thresh * 32) <= (txfifo_size -
                                      (sc->sc_tx_fill_thresh * 32))) {                                       (sc->sc_tx_fill_thresh * 32))) {
                                         printf("; increasing Tx drain "                                          printf("; increasing Tx drain "
                                             "threshold to %u bytes\n",                                              "threshold to %u bytes\n",
                                             thresh * 32);                                              thresh * 32);
                                         sc->sc_tx_drain_thresh = thresh;                                          sc->sc_tx_drain_thresh = thresh;
                                         (void) SIP_DECL(init)(ifp);                                          (void) sipcom_init(ifp);
                                 } else {                                  } else {
                                         (void) SIP_DECL(init)(ifp);                                          (void) sipcom_init(ifp);
                                         printf("\n");                                          printf("\n");
                                 }                                  }
                         }                          }
                 }                  }
   
 #if !defined(DP83820)  
                 if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {                  if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {
                         if (isr & ISR_PAUSE_ST) {                          if (isr & ISR_PAUSE_ST) {
                                 sc->sc_paused = 1;                                  sc->sc_paused = 1;
Line 1713  SIP_DECL(intr)(void *arg)
Line 1927  SIP_DECL(intr)(void *arg)
                                 ifp->if_flags &= ~IFF_OACTIVE;                                  ifp->if_flags &= ~IFF_OACTIVE;
                         }                          }
                 }                  }
 #endif /* ! DP83820 */  
   
                 if (isr & ISR_HIBERR) {                  if (isr & ISR_HIBERR) {
                         int want_init = 0;                          int want_init = 0;
Line 1730  SIP_DECL(intr)(void *arg)
Line 1943  SIP_DECL(intr)(void *arg)
                                 }                                       \                                  }                                       \
                         } while (/*CONSTCOND*/0)                          } while (/*CONSTCOND*/0)
   
                         PRINTERR(ISR_DPERR, "parity error");                          PRINTERR(sc->sc_bits.b_isr_dperr, "parity error");
                         PRINTERR(ISR_SSERR, "system error");                          PRINTERR(sc->sc_bits.b_isr_sserr, "system error");
                         PRINTERR(ISR_RMABT, "master abort");                          PRINTERR(sc->sc_bits.b_isr_rmabt, "master abort");
                         PRINTERR(ISR_RTABT, "target abort");                          PRINTERR(sc->sc_bits.b_isr_rtabt, "target abort");
                         PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");                          PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
                         /*                          /*
                          * Ignore:                           * Ignore:
Line 1741  SIP_DECL(intr)(void *arg)
Line 1954  SIP_DECL(intr)(void *arg)
                          *      Rx reset complete                           *      Rx reset complete
                          */                           */
                         if (want_init)                          if (want_init)
                                 (void) SIP_DECL(init)(ifp);                                  (void) sipcom_init(ifp);
 #undef PRINTERR  #undef PRINTERR
                 }                  }
         }          }
Line 1750  SIP_DECL(intr)(void *arg)
Line 1963  SIP_DECL(intr)(void *arg)
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, IER_IE);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IER, IER_IE);
   
         /* Try to get more packets going. */          /* Try to get more packets going. */
         SIP_DECL(start)(ifp);          sipcom_start(ifp);
   
         return (handled);          return (handled);
 }  }
Line 1761  SIP_DECL(intr)(void *arg)
Line 1974  SIP_DECL(intr)(void *arg)
  *      Helper; handle transmit interrupts.   *      Helper; handle transmit interrupts.
  */   */
 static void  static void
 SIP_DECL(txintr)(struct sip_softc *sc)  sipcom_txintr(struct sip_softc *sc)
 {  {
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         struct sip_txsoft *txs;          struct sip_txsoft *txs;
         u_int32_t cmdsts;          u_int32_t cmdsts;
   
 #ifndef DP83820  
         if (sc->sc_paused == 0)          if (sc->sc_paused == 0)
 #endif  
                 ifp->if_flags &= ~IFF_OACTIVE;                  ifp->if_flags &= ~IFF_OACTIVE;
   
         /*          /*
Line 1777  SIP_DECL(txintr)(struct sip_softc *sc)
Line 1988  SIP_DECL(txintr)(struct sip_softc *sc)
          * frames which have been transmitted.           * frames which have been transmitted.
          */           */
         while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {          while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
                 SIP_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,                  sip_cdtxsync(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
                     BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);                      BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   
                 cmdsts = le32toh(sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts);                  cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
                 if (cmdsts & CMDSTS_OWN)                  if (cmdsts & CMDSTS_OWN)
                         break;                          break;
   
Line 1829  SIP_DECL(txintr)(struct sip_softc *sc)
Line 2040  SIP_DECL(txintr)(struct sip_softc *sc)
         }          }
 }  }
   
 #if defined(DP83820)  
 /*  /*
  * sip_rxintr:   * gsip_rxintr:
  *   *
  *      Helper; handle receive interrupts.   *      Helper; handle receive interrupts on gigabit parts.
  */   */
 static void  static void
 SIP_DECL(rxintr)(struct sip_softc *sc)  gsip_rxintr(struct sip_softc *sc)
 {  {
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         struct sip_rxsoft *rxs;          struct sip_rxsoft *rxs;
Line 1844  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2054  SIP_DECL(rxintr)(struct sip_softc *sc)
         u_int32_t cmdsts, extsts;          u_int32_t cmdsts, extsts;
         int i, len;          int i, len;
   
         for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {          for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
                 rxs = &sc->sc_rxsoft[i];                  rxs = &sc->sc_rxsoft[i];
   
                 SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);                  sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   
                 cmdsts = le32toh(sc->sc_rxdescs[i].sipd_cmdsts);                  cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
                 extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);                  extsts = le32toh(sc->sc_rxdescs[i].sipd_extsts);
                 len = CMDSTS_SIZE(cmdsts);                  len = CMDSTS_SIZE(sc, cmdsts);
   
                 /*                  /*
                  * NOTE: OWN is set if owned by _consumer_.  We're the                   * NOTE: OWN is set if owned by _consumer_.  We're the
Line 1866  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2076  SIP_DECL(rxintr)(struct sip_softc *sc)
                 }                  }
   
                 if (__predict_false(sc->sc_rxdiscard)) {                  if (__predict_false(sc->sc_rxdiscard)) {
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
                         if ((cmdsts & CMDSTS_MORE) == 0) {                          if ((cmdsts & CMDSTS_MORE) == 0) {
                                 /* Reset our state. */                                  /* Reset our state. */
                                 sc->sc_rxdiscard = 0;                                  sc->sc_rxdiscard = 0;
Line 1882  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2092  SIP_DECL(rxintr)(struct sip_softc *sc)
                 /*                  /*
                  * Add a new receive buffer to the ring.                   * Add a new receive buffer to the ring.
                  */                   */
                 if (SIP_DECL(add_rxbuf)(sc, i) != 0) {                  if (sipcom_add_rxbuf(sc, i) != 0) {
                         /*                          /*
                          * Failed, throw away what we've done so                           * Failed, throw away what we've done so
                          * far, and discard the rest of the packet.                           * far, and discard the rest of the packet.
Line 1890  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2100  SIP_DECL(rxintr)(struct sip_softc *sc)
                         ifp->if_ierrors++;                          ifp->if_ierrors++;
                         bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,                          bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                             rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);                              rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
                         if (cmdsts & CMDSTS_MORE)                          if (cmdsts & CMDSTS_MORE)
                                 sc->sc_rxdiscard = 1;                                  sc->sc_rxdiscard = 1;
                         if (sc->sc_rxhead != NULL)                          if (sc->sc_rxhead != NULL)
                                 m_freem(sc->sc_rxhead);                                  m_freem(sc->sc_rxhead);
                         SIP_RXCHAIN_RESET(sc);                          sip_rxchain_reset(sc);
                         continue;                          continue;
                 }                  }
   
                 SIP_RXCHAIN_LINK(sc, m);                  sip_rxchain_link(sc, m);
   
                 m->m_len = len;                  m->m_len = len;
   
Line 1922  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2132  SIP_DECL(rxintr)(struct sip_softc *sc)
                 len = m->m_len + sc->sc_rxlen;                  len = m->m_len + sc->sc_rxlen;
                 m = sc->sc_rxhead;                  m = sc->sc_rxhead;
   
                 SIP_RXCHAIN_RESET(sc);                  sip_rxchain_reset(sc);
   
                 /*                  /*
                  * If an error occurred, update stats and drop the packet.                   * If an error occurred, update stats and drop the packet.
Line 1956  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2166  SIP_DECL(rxintr)(struct sip_softc *sc)
                  * memory consumption when we receive lots                   * memory consumption when we receive lots
                  * of small packets.                   * of small packets.
                  */                   */
                 if (SIP_DECL(copy_small) != 0 && len <= (MHLEN - 2)) {                  if (gsip_copy_small != 0 && len <= (MHLEN - 2)) {
                         struct mbuf *nm;                          struct mbuf *nm;
                         MGETHDR(nm, M_DONTWAIT, MT_DATA);                          MGETHDR(nm, M_DONTWAIT, MT_DATA);
                         if (nm == NULL) {                          if (nm == NULL) {
Line 2052  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2262  SIP_DECL(rxintr)(struct sip_softc *sc)
         /* Update the receive pointer. */          /* Update the receive pointer. */
         sc->sc_rxptr = i;          sc->sc_rxptr = i;
 }  }
 #else /* ! DP83820 */  
 /*  /*
  * sip_rxintr:   * sip_rxintr:
  *   *
  *      Helper; handle receive interrupts.   *      Helper; handle receive interrupts on 10/100 parts.
  */   */
 static void  static void
 SIP_DECL(rxintr)(struct sip_softc *sc)  sip_rxintr(struct sip_softc *sc)
 {  {
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         struct sip_rxsoft *rxs;          struct sip_rxsoft *rxs;
Line 2067  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2277  SIP_DECL(rxintr)(struct sip_softc *sc)
         u_int32_t cmdsts;          u_int32_t cmdsts;
         int i, len;          int i, len;
   
         for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {          for (i = sc->sc_rxptr;; i = sip_nextrx(sc, i)) {
                 rxs = &sc->sc_rxsoft[i];                  rxs = &sc->sc_rxsoft[i];
   
                 SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);                  sip_cdrxsync(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   
                 cmdsts = le32toh(sc->sc_rxdescs[i].sipd_cmdsts);                  cmdsts = le32toh(*sipd_cmdsts(sc, &sc->sc_rxdescs[i]));
   
                 /*                  /*
                  * NOTE: OWN is set if owned by _consumer_.  We're the                   * NOTE: OWN is set if owned by _consumer_.  We're the
Line 2115  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2325  SIP_DECL(rxintr)(struct sip_softc *sc)
                         PRINTERR(CMDSTS_Rx_CRCE, "CRC error");                          PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
                         PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");                          PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
 #undef PRINTERR  #undef PRINTERR
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
                         continue;                          continue;
                 }                  }
   
Line 2126  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2336  SIP_DECL(rxintr)(struct sip_softc *sc)
                  * No errors; receive the packet.  Note, the SiS 900                   * No errors; receive the packet.  Note, the SiS 900
                  * includes the CRC with every packet.                   * includes the CRC with every packet.
                  */                   */
                 len = CMDSTS_SIZE(cmdsts) - ETHER_CRC_LEN;                  len = CMDSTS_SIZE(sc, cmdsts) - ETHER_CRC_LEN;
   
 #ifdef __NO_STRICT_ALIGNMENT  #ifdef __NO_STRICT_ALIGNMENT
                 /*                  /*
Line 2140  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2350  SIP_DECL(rxintr)(struct sip_softc *sc)
                  * chain.  If this fails, we drop the packet and                   * chain.  If this fails, we drop the packet and
                  * recycle the old buffer.                   * recycle the old buffer.
                  */                   */
                 if (SIP_DECL(copy_small) != 0 && len <= MHLEN) {                  if (sip_copy_small != 0 && len <= MHLEN) {
                         MGETHDR(m, M_DONTWAIT, MT_DATA);                          MGETHDR(m, M_DONTWAIT, MT_DATA);
                         if (m == NULL)                          if (m == NULL)
                                 goto dropit;                                  goto dropit;
                         MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);                          MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner);
                         memcpy(mtod(m, void *),                          memcpy(mtod(m, void *),
                             mtod(rxs->rxs_mbuf, void *), len);                              mtod(rxs->rxs_mbuf, void *), len);
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
                         bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,                          bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                             rxs->rxs_dmamap->dm_mapsize,                              rxs->rxs_dmamap->dm_mapsize,
                             BUS_DMASYNC_PREREAD);                              BUS_DMASYNC_PREREAD);
                 } else {                  } else {
                         m = rxs->rxs_mbuf;                          m = rxs->rxs_mbuf;
                         if (SIP_DECL(add_rxbuf)(sc, i) != 0) {                          if (sipcom_add_rxbuf(sc, i) != 0) {
  dropit:   dropit:
                                 ifp->if_ierrors++;                                  ifp->if_ierrors++;
                                 SIP_INIT_RXDESC(sc, i);                                  sip_init_rxdesc(sc, i);
                                 bus_dmamap_sync(sc->sc_dmat,                                  bus_dmamap_sync(sc->sc_dmat,
                                     rxs->rxs_dmamap, 0,                                      rxs->rxs_dmamap, 0,
                                     rxs->rxs_dmamap->dm_mapsize,                                      rxs->rxs_dmamap->dm_mapsize,
Line 2175  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2385  SIP_DECL(rxintr)(struct sip_softc *sc)
                 if (m == NULL) {                  if (m == NULL) {
  dropit:   dropit:
                         ifp->if_ierrors++;                          ifp->if_ierrors++;
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
                         bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,                          bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                             rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);                              rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
                         continue;                          continue;
Line 2197  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2407  SIP_DECL(rxintr)(struct sip_softc *sc)
                 memcpy(mtod(m, void *), mtod(rxs->rxs_mbuf, void *), len);                  memcpy(mtod(m, void *), mtod(rxs->rxs_mbuf, void *), len);
   
                 /* Allow the receive descriptor to continue using its mbuf. */                  /* Allow the receive descriptor to continue using its mbuf. */
                 SIP_INIT_RXDESC(sc, i);                  sip_init_rxdesc(sc, i);
                 bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,                  bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
                     rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);                      rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
 #endif /* __NO_STRICT_ALIGNMENT */  #endif /* __NO_STRICT_ALIGNMENT */
Line 2222  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2432  SIP_DECL(rxintr)(struct sip_softc *sc)
         /* Update the receive pointer. */          /* Update the receive pointer. */
         sc->sc_rxptr = i;          sc->sc_rxptr = i;
 }  }
 #endif /* DP83820 */  
   
 /*  /*
  * sip_tick:   * sip_tick:
Line 2230  SIP_DECL(rxintr)(struct sip_softc *sc)
Line 2439  SIP_DECL(rxintr)(struct sip_softc *sc)
  *      One second timer, used to tick the MII.   *      One second timer, used to tick the MII.
  */   */
 static void  static void
 SIP_DECL(tick)(void *arg)  sipcom_tick(void *arg)
 {  {
         struct sip_softc *sc = arg;          struct sip_softc *sc = arg;
         int s;          int s;
   
         s = splnet();          s = splnet();
 #ifdef DP83820  
 #ifdef SIP_EVENT_COUNTERS  #ifdef SIP_EVENT_COUNTERS
         /* Read PAUSE related counts from MIB registers. */          if (sc->sc_gigabit) {
         sc->sc_ev_rxpause.ev_count +=                  /* Read PAUSE related counts from MIB registers. */
             bus_space_read_4(sc->sc_st, sc->sc_sh,                  sc->sc_ev_rxpause.ev_count +=
                              SIP_NS_MIB(MIB_RXPauseFrames)) & 0xffff;                      bus_space_read_4(sc->sc_st, sc->sc_sh,
         sc->sc_ev_txpause.ev_count +=                                       SIP_NS_MIB(MIB_RXPauseFrames)) & 0xffff;
             bus_space_read_4(sc->sc_st, sc->sc_sh,                  sc->sc_ev_txpause.ev_count +=
                              SIP_NS_MIB(MIB_TXPauseFrames)) & 0xffff;                      bus_space_read_4(sc->sc_st, sc->sc_sh,
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_MIBC, MIBC_ACLR);                                       SIP_NS_MIB(MIB_TXPauseFrames)) & 0xffff;
                   bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_MIBC, MIBC_ACLR);
           }
 #endif /* SIP_EVENT_COUNTERS */  #endif /* SIP_EVENT_COUNTERS */
 #endif /* DP83820 */  
         mii_tick(&sc->sc_mii);          mii_tick(&sc->sc_mii);
         splx(s);          splx(s);
   
         callout_reset(&sc->sc_tick_ch, hz, SIP_DECL(tick), sc);          callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
 }  }
   
 /*  /*
Line 2259  SIP_DECL(tick)(void *arg)
Line 2468  SIP_DECL(tick)(void *arg)
  *   *
  *      Perform a soft reset on the SiS 900.   *      Perform a soft reset on the SiS 900.
  */   */
 static void  static bool
 SIP_DECL(reset)(struct sip_softc *sc)  sipcom_reset(struct sip_softc *sc)
 {  {
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
         bus_space_handle_t sh = sc->sc_sh;          bus_space_handle_t sh = sc->sc_sh;
Line 2277  SIP_DECL(reset)(struct sip_softc *sc)
Line 2486  SIP_DECL(reset)(struct sip_softc *sc)
                 delay(2);                  delay(2);
         }          }
   
         if (i == SIP_TIMEOUT)          if (i == SIP_TIMEOUT) {
                 printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);                  printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
                   return false;
           }
   
         delay(1000);          delay(1000);
   
 #ifdef DP83820          if (sc->sc_gigabit) {
                   /*
                    * Set the general purpose I/O bits.  Do it here in case we
                    * need to have GPIO set up to talk to the media interface.
                    */
                   bus_space_write_4(st, sh, SIP_GPIOR, sc->sc_gpior);
                   delay(1000);
           }
           return true;
   }
   
   static void
   sipcom_dp83820_init(struct sip_softc *sc, uint64_t capenable)
   {
           u_int32_t reg;
           bus_space_tag_t st = sc->sc_st;
           bus_space_handle_t sh = sc->sc_sh;
         /*          /*
          * Set the general purpose I/O bits.  Do it here in case we           * Initialize the VLAN/IP receive control register.
          * need to have GPIO set up to talk to the media interface.           * We enable checksum computation on all incoming
            * packets, and do not reject packets w/ bad checksums.
          */           */
         bus_space_write_4(st, sh, SIP_GPIOR, sc->sc_gpior);          reg = 0;
         delay(1000);          if (capenable &
 #endif /* DP83820 */              (IFCAP_CSUM_IPv4_Rx|IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx))
                   reg |= VRCR_IPEN;
           if (VLAN_ATTACHED(&sc->sc_ethercom))
                   reg |= VRCR_VTDEN|VRCR_VTREN;
           bus_space_write_4(st, sh, SIP_VRCR, reg);
   
           /*
            * Initialize the VLAN/IP transmit control register.
            * We enable outgoing checksum computation on a
            * per-packet basis.
            */
           reg = 0;
           if (capenable &
               (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_UDPv4_Tx))
                   reg |= VTCR_PPCHK;
           if (VLAN_ATTACHED(&sc->sc_ethercom))
                   reg |= VTCR_VPPTI;
           bus_space_write_4(st, sh, SIP_VTCR, reg);
   
           /*
            * If we're using VLANs, initialize the VLAN data register.
            * To understand why we bswap the VLAN Ethertype, see section
            * 4.2.36 of the DP83820 manual.
            */
           if (VLAN_ATTACHED(&sc->sc_ethercom))
                   bus_space_write_4(st, sh, SIP_VDR, bswap16(ETHERTYPE_VLAN));
 }  }
   
 /*  /*
Line 2298  SIP_DECL(reset)(struct sip_softc *sc)
Line 2551  SIP_DECL(reset)(struct sip_softc *sc)
  *      Initialize the interface.  Must be called at splnet().   *      Initialize the interface.  Must be called at splnet().
  */   */
 static int  static int
 SIP_DECL(init)(struct ifnet *ifp)  sipcom_init(struct ifnet *ifp)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
Line 2306  SIP_DECL(init)(struct ifnet *ifp)
Line 2559  SIP_DECL(init)(struct ifnet *ifp)
         struct sip_txsoft *txs;          struct sip_txsoft *txs;
         struct sip_rxsoft *rxs;          struct sip_rxsoft *rxs;
         struct sip_desc *sipd;          struct sip_desc *sipd;
 #if defined(DP83820)  
         u_int32_t reg;  
 #endif  
         int i, error = 0;          int i, error = 0;
   
         /*          if (device_is_active(&sc->sc_dev)) {
          * Cancel any pending I/O.                  /*
          */                   * Cancel any pending I/O.
         SIP_DECL(stop)(ifp, 0);                   */
                   sipcom_stop(ifp, 0);
           } else if (!pmf_device_resume_self(&sc->sc_dev))
                   return 0;
   
         /*          /*
          * Reset the chip to a known state.           * Reset the chip to a known state.
          */           */
         SIP_DECL(reset)(sc);          if (!sipcom_reset(sc))
                   return EBUSY;
   
 #if !defined(DP83820)  
         if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) {          if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) {
                 /*                  /*
                  * DP83815 manual, page 78:                   * DP83815 manual, page 78:
Line 2350  SIP_DECL(init)(struct ifnet *ifp)
Line 2603  SIP_DECL(init)(struct ifnet *ifp)
   
                 bus_space_write_4(st, sh, 0x00cc, 0x0000);                  bus_space_write_4(st, sh, 0x00cc, 0x0000);
         }          }
 #endif /* ! DP83820 */  
   
         /*          /*
          * Initialize the transmit descriptor ring.           * Initialize the transmit descriptor ring.
          */           */
         for (i = 0; i < SIP_NTXDESC; i++) {          for (i = 0; i < sc->sc_ntxdesc; i++) {
                 sipd = &sc->sc_txdescs[i];                  sipd = &sc->sc_txdescs[i];
                 memset(sipd, 0, sizeof(struct sip_desc));                  memset(sipd, 0, sizeof(struct sip_desc));
                 sipd->sipd_link = htole32(SIP_CDTXADDR(sc, SIP_NEXTTX(i)));                  sipd->sipd_link = htole32(SIP_CDTXADDR(sc, sip_nexttx(sc, i)));
         }          }
         SIP_CDTXSYNC(sc, 0, SIP_NTXDESC,          sip_cdtxsync(sc, 0, sc->sc_ntxdesc,
             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);              BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
         sc->sc_txfree = SIP_NTXDESC;          sc->sc_txfree = sc->sc_ntxdesc;
         sc->sc_txnext = 0;          sc->sc_txnext = 0;
         sc->sc_txwin = 0;          sc->sc_txwin = 0;
   
Line 2381  SIP_DECL(init)(struct ifnet *ifp)
Line 2633  SIP_DECL(init)(struct ifnet *ifp)
          * Initialize the receive descriptor and receive job           * Initialize the receive descriptor and receive job
          * descriptor rings.           * descriptor rings.
          */           */
         for (i = 0; i < SIP_NRXDESC; i++) {          for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
                 rxs = &sc->sc_rxsoft[i];                  rxs = &sc->sc_rxsoft[i];
                 if (rxs->rxs_mbuf == NULL) {                  if (rxs->rxs_mbuf == NULL) {
                         if ((error = SIP_DECL(add_rxbuf)(sc, i)) != 0) {                          if ((error = sipcom_add_rxbuf(sc, i)) != 0) {
                                 printf("%s: unable to allocate or map rx "                                  printf("%s: unable to allocate or map rx "
                                     "buffer %d, error = %d\n",                                      "buffer %d, error = %d\n",
                                     sc->sc_dev.dv_xname, i, error);                                      sc->sc_dev.dv_xname, i, error);
Line 2392  SIP_DECL(init)(struct ifnet *ifp)
Line 2644  SIP_DECL(init)(struct ifnet *ifp)
                                  * XXX Should attempt to run with fewer receive                                   * XXX Should attempt to run with fewer receive
                                  * XXX buffers instead of just failing.                                   * XXX buffers instead of just failing.
                                  */                                   */
                                 SIP_DECL(rxdrain)(sc);                                  sipcom_rxdrain(sc);
                                 goto out;                                  goto out;
                         }                          }
                 } else                  } else
                         SIP_INIT_RXDESC(sc, i);                          sip_init_rxdesc(sc, i);
         }          }
         sc->sc_rxptr = 0;          sc->sc_rxptr = 0;
 #ifdef DP83820  
         sc->sc_rxdiscard = 0;          sc->sc_rxdiscard = 0;
         SIP_RXCHAIN_RESET(sc);          sip_rxchain_reset(sc);
 #endif /* DP83820 */  
   
         /*          /*
          * Set the configuration register; it's already initialized           * Set the configuration register; it's already initialized
Line 2413  SIP_DECL(init)(struct ifnet *ifp)
Line 2663  SIP_DECL(init)(struct ifnet *ifp)
         /*          /*
          * Initialize the prototype TXCFG register.           * Initialize the prototype TXCFG register.
          */           */
 #if defined(DP83820)          if (sc->sc_gigabit) {
         sc->sc_txcfg = TXCFG_MXDMA_512;                  sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
         sc->sc_rxcfg = RXCFG_MXDMA_512;                  sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
 #else          } else if ((SIP_SIS900_REV(sc, SIS_REV_635) ||
         if ((SIP_SIS900_REV(sc, SIS_REV_635) ||  
              SIP_SIS900_REV(sc, SIS_REV_960) ||               SIP_SIS900_REV(sc, SIS_REV_960) ||
              SIP_SIS900_REV(sc, SIS_REV_900B)) &&               SIP_SIS900_REV(sc, SIS_REV_900B)) &&
             (sc->sc_cfg & CFG_EDBMASTEN)) {              (sc->sc_cfg & CFG_EDBMASTEN)) {
                 sc->sc_txcfg = TXCFG_MXDMA_64;                  sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_64;
                 sc->sc_rxcfg = RXCFG_MXDMA_64;                  sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_64;
         } else {          } else {
                 sc->sc_txcfg = TXCFG_MXDMA_512;                  sc->sc_txcfg = sc->sc_bits.b_txcfg_mxdma_512;
                 sc->sc_rxcfg = RXCFG_MXDMA_512;                  sc->sc_rxcfg = sc->sc_bits.b_rxcfg_mxdma_512;
         }          }
 #endif /* DP83820 */  
   
         sc->sc_txcfg |= TXCFG_ATP |          sc->sc_txcfg |= TXCFG_ATP |
             (sc->sc_tx_fill_thresh << TXCFG_FLTH_SHIFT) |              __SHIFTIN(sc->sc_tx_fill_thresh, sc->sc_bits.b_txcfg_flth_mask) |
             sc->sc_tx_drain_thresh;              sc->sc_tx_drain_thresh;
         bus_space_write_4(st, sh, SIP_TXCFG, sc->sc_txcfg);          bus_space_write_4(st, sh, sc->sc_regs.r_txcfg, sc->sc_txcfg);
   
         /*          /*
          * Initialize the receive drain threshold if we have never           * Initialize the receive drain threshold if we have never
Line 2446  SIP_DECL(init)(struct ifnet *ifp)
Line 2694  SIP_DECL(init)(struct ifnet *ifp)
                  * set this value lower than 2; 14 bytes are required to                   * set this value lower than 2; 14 bytes are required to
                  * filter the packet).                   * filter the packet).
                  */                   */
                 sc->sc_rx_drain_thresh = RXCFG_DRTH >> RXCFG_DRTH_SHIFT;                  sc->sc_rx_drain_thresh = __SHIFTOUT_MASK(RXCFG_DRTH_MASK);
         }          }
   
         /*          /*
          * Initialize the prototype RXCFG register.           * Initialize the prototype RXCFG register.
          */           */
         sc->sc_rxcfg |= (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);          sc->sc_rxcfg |= __SHIFTIN(sc->sc_rx_drain_thresh, RXCFG_DRTH_MASK);
 #ifdef DP83820  
         /*          /*
          * Accept long packets (including FCS) so we can handle           * Accept long packets (including FCS) so we can handle
          * 802.1q-tagged frames and jumbo frames properly.           * 802.1q-tagged frames and jumbo frames properly.
          */           */
         if (ifp->if_mtu > ETHERMTU ||          if ((sc->sc_gigabit && ifp->if_mtu > ETHERMTU) ||
             (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU))              (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU))
                 sc->sc_rxcfg |= RXCFG_ALP;                  sc->sc_rxcfg |= RXCFG_ALP;
   
Line 2468  SIP_DECL(init)(struct ifnet *ifp)
Line 2715  SIP_DECL(init)(struct ifnet *ifp)
          * evidence that >8109 does not work on some boards, such as the           * evidence that >8109 does not work on some boards, such as the
          * Planex GN-1000TE).           * Planex GN-1000TE).
          */           */
         if (ifp->if_mtu > 8109 &&          if (sc->sc_gigabit && ifp->if_mtu > 8109 &&
             (ifp->if_capenable &              (ifp->if_capenable &
              (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|               (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx|
               IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|                IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx|
Line 2482  SIP_DECL(init)(struct ifnet *ifp)
Line 2729  SIP_DECL(init)(struct ifnet *ifp)
                 ifp->if_csum_flags_tx = 0;                  ifp->if_csum_flags_tx = 0;
                 ifp->if_csum_flags_rx = 0;                  ifp->if_csum_flags_rx = 0;
         }          }
 #else  
         /*  
          * Accept packets >1518 bytes (including FCS) so we can handle  
          * 802.1q-tagged frames properly.  
          */  
         if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU)  
                 sc->sc_rxcfg |= RXCFG_ALP;  
 #endif  
         bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);  
   
 #ifdef DP83820  
         /*  
          * Initialize the VLAN/IP receive control register.  
          * We enable checksum computation on all incoming  
          * packets, and do not reject packets w/ bad checksums.  
          */  
         reg = 0;  
         if (ifp->if_capenable &  
             (IFCAP_CSUM_IPv4_Rx|IFCAP_CSUM_TCPv4_Rx|IFCAP_CSUM_UDPv4_Rx))  
                 reg |= VRCR_IPEN;  
         if (VLAN_ATTACHED(&sc->sc_ethercom))  
                 reg |= VRCR_VTDEN|VRCR_VTREN;  
         bus_space_write_4(st, sh, SIP_VRCR, reg);  
   
         /*          bus_space_write_4(st, sh, sc->sc_regs.r_rxcfg, sc->sc_rxcfg);
          * Initialize the VLAN/IP transmit control register.  
          * We enable outgoing checksum computation on a  
          * per-packet basis.  
          */  
         reg = 0;  
         if (ifp->if_capenable &  
             (IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_UDPv4_Tx))  
                 reg |= VTCR_PPCHK;  
         if (VLAN_ATTACHED(&sc->sc_ethercom))  
                 reg |= VTCR_VPPTI;  
         bus_space_write_4(st, sh, SIP_VTCR, reg);  
   
         /*          if (sc->sc_gigabit)
          * If we're using VLANs, initialize the VLAN data register.                  sipcom_dp83820_init(sc, ifp->if_capenable);
          * To understand why we bswap the VLAN Ethertype, see section  
          * 4.2.36 of the DP83820 manual.  
          */  
         if (VLAN_ATTACHED(&sc->sc_ethercom))  
                 bus_space_write_4(st, sh, SIP_VDR, bswap16(ETHERTYPE_VLAN));  
 #endif /* DP83820 */  
   
         /*          /*
          * Give the transmit and receive rings to the chip.           * Give the transmit and receive rings to the chip.
Line 2537  SIP_DECL(init)(struct ifnet *ifp)
Line 2744  SIP_DECL(init)(struct ifnet *ifp)
         /*          /*
          * Initialize the interrupt mask.           * Initialize the interrupt mask.
          */           */
         sc->sc_imr = ISR_DPERR|ISR_SSERR|ISR_RMABT|ISR_RTABT|ISR_RXSOVR|          sc->sc_imr = sc->sc_bits.b_isr_dperr |
                        sc->sc_bits.b_isr_sserr |
                        sc->sc_bits.b_isr_rmabt |
                        sc->sc_bits.b_isr_rtabt | ISR_RXSOVR |
             ISR_TXURN|ISR_TXDESC|ISR_TXIDLE|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;              ISR_TXURN|ISR_TXDESC|ISR_TXIDLE|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
         bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);          bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
   
         /* Set up the receive filter. */          /* Set up the receive filter. */
         (*sc->sc_model->sip_variant->sipv_set_filter)(sc);          (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
   
 #ifdef DP83820  
         /*          /*
          * Tune sc_rx_flow_thresh.           * Tune sc_rx_flow_thresh.
          * XXX "More than 8KB" is too short for jumbo frames.           * XXX "More than 8KB" is too short for jumbo frames.
Line 2553  SIP_DECL(init)(struct ifnet *ifp)
Line 2762  SIP_DECL(init)(struct ifnet *ifp)
         sc->sc_rx_flow_thresh = (PCR_PS_STHI_8 | PCR_PS_STLO_4 |          sc->sc_rx_flow_thresh = (PCR_PS_STHI_8 | PCR_PS_STLO_4 |
                                  PCR_PS_FFHI_8 | PCR_PS_FFLO_4 |                                   PCR_PS_FFHI_8 | PCR_PS_FFLO_4 |
                                  (PCR_PAUSE_CNT & PCR_PAUSE_CNT_MASK));                                   (PCR_PAUSE_CNT & PCR_PAUSE_CNT_MASK));
 #endif  
   
         /*          /*
          * Set the current media.  Do this after initializing the prototype           * Set the current media.  Do this after initializing the prototype
          * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow           * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
          * control.           * control.
          */           */
         mii_mediachg(&sc->sc_mii);          if ((error = ether_mediachange(ifp)) != 0)
                   goto out;
   
 #ifdef DP83820  
         /*          /*
          * Set the interrupt hold-off timer to 100us.           * Set the interrupt hold-off timer to 100us.
          */           */
         bus_space_write_4(st, sh, SIP_IHR, 0x01);          if (sc->sc_gigabit)
 #endif                  bus_space_write_4(st, sh, SIP_IHR, 0x01);
   
         /*          /*
          * Enable interrupts.           * Enable interrupts.
Line 2582  SIP_DECL(init)(struct ifnet *ifp)
Line 2790  SIP_DECL(init)(struct ifnet *ifp)
         /*          /*
          * Start the one second MII clock.           * Start the one second MII clock.
          */           */
         callout_reset(&sc->sc_tick_ch, hz, SIP_DECL(tick), sc);          callout_reset(&sc->sc_tick_ch, hz, sipcom_tick, sc);
   
         /*          /*
          * ...all done!           * ...all done!
Line 2606  SIP_DECL(init)(struct ifnet *ifp)
Line 2814  SIP_DECL(init)(struct ifnet *ifp)
  *      Drain the receive queue.   *      Drain the receive queue.
  */   */
 static void  static void
 SIP_DECL(rxdrain)(struct sip_softc *sc)  sipcom_rxdrain(struct sip_softc *sc)
 {  {
         struct sip_rxsoft *rxs;          struct sip_rxsoft *rxs;
         int i;          int i;
   
         for (i = 0; i < SIP_NRXDESC; i++) {          for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) {
                 rxs = &sc->sc_rxsoft[i];                  rxs = &sc->sc_rxsoft[i];
                 if (rxs->rxs_mbuf != NULL) {                  if (rxs->rxs_mbuf != NULL) {
                         bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);                          bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
Line 2627  SIP_DECL(rxdrain)(struct sip_softc *sc)
Line 2835  SIP_DECL(rxdrain)(struct sip_softc *sc)
  *      Stop transmission on the interface.   *      Stop transmission on the interface.
  */   */
 static void  static void
 SIP_DECL(stop)(struct ifnet *ifp, int disable)  sipcom_stop(struct ifnet *ifp, int disable)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
Line 2659  SIP_DECL(stop)(struct ifnet *ifp, int di
Line 2867  SIP_DECL(stop)(struct ifnet *ifp, int di
         while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {          while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
                 if ((ifp->if_flags & IFF_DEBUG) != 0 &&                  if ((ifp->if_flags & IFF_DEBUG) != 0 &&
                     SIMPLEQ_NEXT(txs, txs_q) == NULL &&                      SIMPLEQ_NEXT(txs, txs_q) == NULL &&
                     (le32toh(sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts) &                      (le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc])) &
                      CMDSTS_INTR) == 0)                       CMDSTS_INTR) == 0)
                         printf("%s: sip_stop: last descriptor does not "                          printf("%s: sip_stop: last descriptor does not "
                             "have INTR bit set\n", sc->sc_dev.dv_xname);                              "have INTR bit set\n", sc->sc_dev.dv_xname);
Line 2672  SIP_DECL(stop)(struct ifnet *ifp, int di
Line 2880  SIP_DECL(stop)(struct ifnet *ifp, int di
                 }                  }
 #endif  #endif
                 cmdsts |=               /* DEBUG */                  cmdsts |=               /* DEBUG */
                     le32toh(sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts);                      le32toh(*sipd_cmdsts(sc, &sc->sc_txdescs[txs->txs_lastdesc]));
                 bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);                  bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
                 m_freem(txs->txs_mbuf);                  m_freem(txs->txs_mbuf);
                 txs->txs_mbuf = NULL;                  txs->txs_mbuf = NULL;
                 SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);                  SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
         }          }
   
         if (disable)  
                 SIP_DECL(rxdrain)(sc);  
   
         /*          /*
          * Mark the interface down and cancel the watchdog timer.           * Mark the interface down and cancel the watchdog timer.
          */           */
         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);          ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
         ifp->if_timer = 0;          ifp->if_timer = 0;
   
           if (disable)
                   pmf_device_suspend_self(&sc->sc_dev);
   
         if ((ifp->if_flags & IFF_DEBUG) != 0 &&          if ((ifp->if_flags & IFF_DEBUG) != 0 &&
             (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != SIP_NTXDESC)              (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != sc->sc_ntxdesc)
                 printf("%s: sip_stop: no INTR bits set in dirty tx "                  printf("%s: sip_stop: no INTR bits set in dirty tx "
                     "descriptors\n", sc->sc_dev.dv_xname);                      "descriptors\n", sc->sc_dev.dv_xname);
 }  }
Line 2700  SIP_DECL(stop)(struct ifnet *ifp, int di
Line 2908  SIP_DECL(stop)(struct ifnet *ifp, int di
  *      Read data from the serial EEPROM.   *      Read data from the serial EEPROM.
  */   */
 static void  static void
 SIP_DECL(read_eeprom)(struct sip_softc *sc, int word, int wordcnt,  sipcom_read_eeprom(struct sip_softc *sc, int word, int wordcnt,
     u_int16_t *data)      u_int16_t *data)
 {  {
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
Line 2761  SIP_DECL(read_eeprom)(struct sip_softc *
Line 2969  SIP_DECL(read_eeprom)(struct sip_softc *
 }  }
   
 /*  /*
  * sip_add_rxbuf:   * sipcom_add_rxbuf:
  *   *
  *      Add a receive buffer to the indicated descriptor.   *      Add a receive buffer to the indicated descriptor.
  */   */
 static int  static int
 SIP_DECL(add_rxbuf)(struct sip_softc *sc, int idx)  sipcom_add_rxbuf(struct sip_softc *sc, int idx)
 {  {
         struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];          struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];
         struct mbuf *m;          struct mbuf *m;
Line 2783  SIP_DECL(add_rxbuf)(struct sip_softc *sc
Line 2991  SIP_DECL(add_rxbuf)(struct sip_softc *sc
                 return (ENOBUFS);                  return (ENOBUFS);
         }          }
   
 #if defined(DP83820)          /* XXX I don't believe this is necessary. --dyoung */
         m->m_len = SIP_RXBUF_LEN;          if (sc->sc_gigabit)
 #endif /* DP83820 */                  m->m_len = sc->sc_parm->p_rxbuf_len;
   
         if (rxs->rxs_mbuf != NULL)          if (rxs->rxs_mbuf != NULL)
                 bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);                  bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
Line 2798  SIP_DECL(add_rxbuf)(struct sip_softc *sc
Line 3006  SIP_DECL(add_rxbuf)(struct sip_softc *sc
         if (error) {          if (error) {
                 printf("%s: can't load rx DMA map %d, error = %d\n",                  printf("%s: can't load rx DMA map %d, error = %d\n",
                     sc->sc_dev.dv_xname, idx, error);                      sc->sc_dev.dv_xname, idx, error);
                 panic("sip_add_rxbuf");         /* XXX */                  panic("%s", __func__);          /* XXX */
         }          }
   
         bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,          bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
             rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);              rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   
         SIP_INIT_RXDESC(sc, idx);          sip_init_rxdesc(sc, idx);
   
         return (0);          return (0);
 }  }
   
 #if !defined(DP83820)  
 /*  /*
  * sip_sis900_set_filter:   * sip_sis900_set_filter:
  *   *
  *      Set up the receive filter.   *      Set up the receive filter.
  */   */
 static void  static void
 SIP_DECL(sis900_set_filter)(struct sip_softc *sc)  sipcom_sis900_set_filter(struct sip_softc *sc)
 {  {
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
         bus_space_handle_t sh = sc->sc_sh;          bus_space_handle_t sh = sc->sc_sh;
         struct ethercom *ec = &sc->sc_ethercom;          struct ethercom *ec = &sc->sc_ethercom;
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         struct ether_multi *enm;          struct ether_multi *enm;
         u_int8_t *cp;          const u_int8_t *cp;
         struct ether_multistep step;          struct ether_multistep step;
         u_int32_t crc, mchash[16];          u_int32_t crc, mchash[16];
   
Line 2917  SIP_DECL(sis900_set_filter)(struct sip_s
Line 3124  SIP_DECL(sis900_set_filter)(struct sip_s
         /*          /*
          * Disable receive filter, and program the node address.           * Disable receive filter, and program the node address.
          */           */
         cp = LLADDR(ifp->if_sadl);          cp = CLLADDR(ifp->if_sadl);
         FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);          FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);
         FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);          FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);
         FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);          FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);
Line 2954  SIP_DECL(sis900_set_filter)(struct sip_s
Line 3161  SIP_DECL(sis900_set_filter)(struct sip_s
          */           */
         bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);          bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
 }  }
 #endif /* ! DP83820 */  
   
 /*  /*
  * sip_dp83815_set_filter:   * sip_dp83815_set_filter:
Line 2962  SIP_DECL(sis900_set_filter)(struct sip_s
Line 3168  SIP_DECL(sis900_set_filter)(struct sip_s
  *      Set up the receive filter.   *      Set up the receive filter.
  */   */
 static void  static void
 SIP_DECL(dp83815_set_filter)(struct sip_softc *sc)  sipcom_dp83815_set_filter(struct sip_softc *sc)
 {  {
         bus_space_tag_t st = sc->sc_st;          bus_space_tag_t st = sc->sc_st;
         bus_space_handle_t sh = sc->sc_sh;          bus_space_handle_t sh = sc->sc_sh;
         struct ethercom *ec = &sc->sc_ethercom;          struct ethercom *ec = &sc->sc_ethercom;
         struct ifnet *ifp = &sc->sc_ethercom.ec_if;          struct ifnet *ifp = &sc->sc_ethercom.ec_if;
         struct ether_multi *enm;          struct ether_multi *enm;
         u_int8_t *cp;          const u_int8_t *cp;
         struct ether_multistep step;          struct ether_multistep step;
         u_int32_t crc, hash, slot, bit;          u_int32_t crc, hash, slot, bit;
 #ifdef DP83820  #define MCHASH_NWORDS_83820     128
 #define MCHASH_NWORDS   128  #define MCHASH_NWORDS_83815     32
 #else  #define MCHASH_NWORDS   MAX(MCHASH_NWORDS_83820, MCHASH_NWORDS_83815)
 #define MCHASH_NWORDS   32  
 #endif /* DP83820 */  
         u_int16_t mchash[MCHASH_NWORDS];          u_int16_t mchash[MCHASH_NWORDS];
         int i;          int i;
   
Line 2996  SIP_DECL(dp83815_set_filter)(struct sip_
Line 3200  SIP_DECL(dp83815_set_filter)(struct sip_
                 goto allmulti;                  goto allmulti;
         }          }
   
 #ifdef DP83820  
         /*          /*
          * Set up the DP83820 multicast address filter by passing all multicast           * Set up the DP83820/DP83815 multicast address filter by
          * addresses through a CRC generator, and then using the high-order           * passing all multicast addresses through a CRC generator,
          * 11 bits as an index into the 2048 bit multicast hash table.  The           * and then using the high-order 11/9 bits as an index into
          * high-order 7 bits select the slot, while the low-order 4 bits           * the 2048/512 bit multicast hash table.  The high-order
          * select the bit within the slot.  Note that only the low 16-bits           * 7/5 bits select the slot, while the low-order 4 bits
          * of each filter word are used, and there are 128 filter words.           * select the bit within the slot.  Note that only the low
          */           * 16-bits of each filter word are used, and there are
 #else           * 128/32 filter words.
         /*  
          * Set up the DP83815 multicast address filter by passing all multicast  
          * addresses through a CRC generator, and then using the high-order  
          * 9 bits as an index into the 512 bit multicast hash table.  The  
          * high-order 5 bits select the slot, while the low-order 4 bits  
          * select the bit within the slot.  Note that only the low 16-bits  
          * of each filter word are used, and there are 32 filter words.  
          */           */
 #endif /* DP83820 */  
   
         memset(mchash, 0, sizeof(mchash));          memset(mchash, 0, sizeof(mchash));
   
Line 3037  SIP_DECL(dp83815_set_filter)(struct sip_
Line 3232  SIP_DECL(dp83815_set_filter)(struct sip_
   
                 crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);                  crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
   
 #ifdef DP83820                  if (sc->sc_gigabit) {
                 /* Just want the 11 most significant bits. */                          /* Just want the 11 most significant bits. */
                 hash = crc >> 21;                          hash = crc >> 21;
 #else                  } else {
                 /* Just want the 9 most significant bits. */                          /* Just want the 9 most significant bits. */
                 hash = crc >> 23;                          hash = crc >> 23;
 #endif /* DP83820 */                  }
   
                 slot = hash >> 4;                  slot = hash >> 4;
                 bit = hash & 0xf;                  bit = hash & 0xf;
Line 3070  SIP_DECL(dp83815_set_filter)(struct sip_
Line 3265  SIP_DECL(dp83815_set_filter)(struct sip_
         /*          /*
          * Disable receive filter, and program the node address.           * Disable receive filter, and program the node address.
          */           */
         cp = LLADDR(ifp->if_sadl);          cp = CLLADDR(ifp->if_sadl);
         FILTER_EMIT(RFCR_NS_RFADDR_PMATCH0, (cp[1] << 8) | cp[0]);          FILTER_EMIT(RFCR_NS_RFADDR_PMATCH0, (cp[1] << 8) | cp[0]);
         FILTER_EMIT(RFCR_NS_RFADDR_PMATCH2, (cp[3] << 8) | cp[2]);          FILTER_EMIT(RFCR_NS_RFADDR_PMATCH2, (cp[3] << 8) | cp[2]);
         FILTER_EMIT(RFCR_NS_RFADDR_PMATCH4, (cp[5] << 8) | cp[4]);          FILTER_EMIT(RFCR_NS_RFADDR_PMATCH4, (cp[5] << 8) | cp[4]);
   
         if ((ifp->if_flags & IFF_ALLMULTI) == 0) {          if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
                   int nwords =
                       sc->sc_gigabit ? MCHASH_NWORDS_83820 : MCHASH_NWORDS_83815;
                 /*                  /*
                  * Program the multicast hash table.                   * Program the multicast hash table.
                  */                   */
                 for (i = 0; i < MCHASH_NWORDS; i++) {                  for (i = 0; i < nwords; i++) {
                         FILTER_EMIT(RFCR_NS_RFADDR_FILTMEM + (i * 2),                          FILTER_EMIT(sc->sc_parm->p_filtmem + (i * 2), mchash[i]);
                             mchash[i]);  
                 }                  }
         }          }
 #undef FILTER_EMIT  #undef FILTER_EMIT
 #undef MCHASH_NWORDS  #undef MCHASH_NWORDS
   #undef MCHASH_NWORDS_83815
   #undef MCHASH_NWORDS_83820
   
         /*          /*
          * Re-enable the receiver filter.           * Re-enable the receiver filter.
Line 3093  SIP_DECL(dp83815_set_filter)(struct sip_
Line 3291  SIP_DECL(dp83815_set_filter)(struct sip_
         bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);          bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
 }  }
   
 #if defined(DP83820)  
 /*  /*
  * sip_dp83820_mii_readreg:     [mii interface function]   * sip_dp83820_mii_readreg:     [mii interface function]
  *   *
  *      Read a PHY register on the MII of the DP83820.   *      Read a PHY register on the MII of the DP83820.
  */   */
 static int  static int
 SIP_DECL(dp83820_mii_readreg)(struct device *self, int phy, int reg)  sipcom_dp83820_mii_readreg(device_t self, int phy, int reg)
 {  {
         struct sip_softc *sc = (void *) self;          struct sip_softc *sc = device_private(self);
   
         if (sc->sc_cfg & CFG_TBI_EN) {          if (sc->sc_cfg & CFG_TBI_EN) {
                 bus_addr_t tbireg;                  bus_addr_t tbireg;
Line 3155  SIP_DECL(dp83820_mii_readreg)(struct dev
Line 3352  SIP_DECL(dp83820_mii_readreg)(struct dev
                 return (rv);                  return (rv);
         }          }
   
         return (mii_bitbang_readreg(self, &SIP_DECL(mii_bitbang_ops),          return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops, phy, reg);
             phy, reg));  
 }  }
   
 /*  /*
Line 3165  SIP_DECL(dp83820_mii_readreg)(struct dev
Line 3361  SIP_DECL(dp83820_mii_readreg)(struct dev
  *      Write a PHY register on the MII of the DP83820.   *      Write a PHY register on the MII of the DP83820.
  */   */
 static void  static void
 SIP_DECL(dp83820_mii_writereg)(struct device *self, int phy, int reg, int val)  sipcom_dp83820_mii_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct sip_softc *sc = (void *) self;          struct sip_softc *sc = device_private(self);
   
         if (sc->sc_cfg & CFG_TBI_EN) {          if (sc->sc_cfg & CFG_TBI_EN) {
                 bus_addr_t tbireg;                  bus_addr_t tbireg;
Line 3187  SIP_DECL(dp83820_mii_writereg)(struct de
Line 3383  SIP_DECL(dp83820_mii_writereg)(struct de
                 return;                  return;
         }          }
   
         mii_bitbang_writereg(self, &SIP_DECL(mii_bitbang_ops),          mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops, phy, reg, val);
             phy, reg, val);  
 }  }
   
 /*  /*
Line 3197  SIP_DECL(dp83820_mii_writereg)(struct de
Line 3392  SIP_DECL(dp83820_mii_writereg)(struct de
  *      Callback from MII layer when media changes.   *      Callback from MII layer when media changes.
  */   */
 static void  static void
 SIP_DECL(dp83820_mii_statchg)(struct device *self)  sipcom_dp83820_mii_statchg(device_t self)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
         struct mii_data *mii = &sc->sc_mii;          struct mii_data *mii = &sc->sc_mii;
         u_int32_t cfg, pcr;          u_int32_t cfg, pcr;
   
Line 3249  SIP_DECL(dp83820_mii_statchg)(struct dev
Line 3444  SIP_DECL(dp83820_mii_statchg)(struct dev
         }          }
   
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CFG, cfg);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CFG, cfg);
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);          bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);              sc->sc_txcfg);
           bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
               sc->sc_rxcfg);
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PCR, pcr);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_NS_PCR, pcr);
 }  }
 #endif /* ! DP83820 */  
   
 /*  /*
  * sip_mii_bitbang_read: [mii bit-bang interface function]   * sip_mii_bitbang_read: [mii bit-bang interface function]
Line 3261  SIP_DECL(dp83820_mii_statchg)(struct dev
Line 3457  SIP_DECL(dp83820_mii_statchg)(struct dev
  *      Read the MII serial port for the MII bit-bang module.   *      Read the MII serial port for the MII bit-bang module.
  */   */
 static u_int32_t  static u_int32_t
 SIP_DECL(mii_bitbang_read)(struct device *self)  sipcom_mii_bitbang_read(device_t self)
 {  {
         struct sip_softc *sc = (void *) self;          struct sip_softc *sc = device_private(self);
   
         return (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR));          return (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR));
 }  }
Line 3274  SIP_DECL(mii_bitbang_read)(struct device
Line 3470  SIP_DECL(mii_bitbang_read)(struct device
  *      Write the MII serial port for the MII bit-bang module.   *      Write the MII serial port for the MII bit-bang module.
  */   */
 static void  static void
 SIP_DECL(mii_bitbang_write)(struct device *self, u_int32_t val)  sipcom_mii_bitbang_write(device_t self, u_int32_t val)
 {  {
         struct sip_softc *sc = (void *) self;          struct sip_softc *sc = device_private(self);
   
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);
 }  }
   
 #ifndef DP83820  
 /*  /*
  * sip_sis900_mii_readreg:      [mii interface function]   * sip_sis900_mii_readreg:      [mii interface function]
  *   *
  *      Read a PHY register on the MII.   *      Read a PHY register on the MII.
  */   */
 static int  static int
 SIP_DECL(sis900_mii_readreg)(struct device *self, int phy, int reg)  sipcom_sis900_mii_readreg(device_t self, int phy, int reg)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
         u_int32_t enphy;          u_int32_t enphy;
   
         /*          /*
Line 3298  SIP_DECL(sis900_mii_readreg)(struct devi
Line 3493  SIP_DECL(sis900_mii_readreg)(struct devi
          * operations.           * operations.
          */           */
         if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900)          if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900)
                 return (mii_bitbang_readreg(self, &SIP_DECL(mii_bitbang_ops),                  return mii_bitbang_readreg(self, &sipcom_mii_bitbang_ops,
                     phy, reg));                      phy, reg);
   
 #ifndef SIS900_MII_RESTRICT  #ifndef SIS900_MII_RESTRICT
         /*          /*
Line 3325  SIP_DECL(sis900_mii_readreg)(struct devi
Line 3520  SIP_DECL(sis900_mii_readreg)(struct devi
  *      Write a PHY register on the MII.   *      Write a PHY register on the MII.
  */   */
 static void  static void
 SIP_DECL(sis900_mii_writereg)(struct device *self, int phy, int reg, int val)  sipcom_sis900_mii_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
         u_int32_t enphy;          u_int32_t enphy;
   
         if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900) {          if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900) {
                 mii_bitbang_writereg(self, &SIP_DECL(mii_bitbang_ops),                  mii_bitbang_writereg(self, &sipcom_mii_bitbang_ops,
                     phy, reg, val);                      phy, reg, val);
                 return;                  return;
         }          }
Line 3359  SIP_DECL(sis900_mii_writereg)(struct dev
Line 3554  SIP_DECL(sis900_mii_writereg)(struct dev
  *      Callback from MII layer when media changes.   *      Callback from MII layer when media changes.
  */   */
 static void  static void
 SIP_DECL(sis900_mii_statchg)(struct device *self)  sipcom_sis900_mii_statchg(device_t self)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
         struct mii_data *mii = &sc->sc_mii;          struct mii_data *mii = &sc->sc_mii;
         u_int32_t flowctl;          u_int32_t flowctl;
   
Line 3402  SIP_DECL(sis900_mii_statchg)(struct devi
Line 3597  SIP_DECL(sis900_mii_statchg)(struct devi
                 flowctl = 0;                  flowctl = 0;
         }          }
   
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);          bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);              sc->sc_txcfg);
           bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
               sc->sc_rxcfg);
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);          bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
 }  }
Line 3414  SIP_DECL(sis900_mii_statchg)(struct devi
Line 3611  SIP_DECL(sis900_mii_statchg)(struct devi
  *      Read a PHY register on the MII.   *      Read a PHY register on the MII.
  */   */
 static int  static int
 SIP_DECL(dp83815_mii_readreg)(struct device *self, int phy, int reg)  sipcom_dp83815_mii_readreg(device_t self, int phy, int reg)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
         u_int32_t val;          u_int32_t val;
   
         /*          /*
Line 3449  SIP_DECL(dp83815_mii_readreg)(struct dev
Line 3646  SIP_DECL(dp83815_mii_readreg)(struct dev
  *      Write a PHY register to the MII.   *      Write a PHY register to the MII.
  */   */
 static void  static void
 SIP_DECL(dp83815_mii_writereg)(struct device *self, int phy, int reg, int val)  sipcom_dp83815_mii_writereg(device_t self, int phy, int reg, int val)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
   
         /*          /*
          * The DP83815 only has an internal PHY.  Only allow           * The DP83815 only has an internal PHY.  Only allow
Line 3469  SIP_DECL(dp83815_mii_writereg)(struct de
Line 3666  SIP_DECL(dp83815_mii_writereg)(struct de
  *      Callback from MII layer when media changes.   *      Callback from MII layer when media changes.
  */   */
 static void  static void
 SIP_DECL(dp83815_mii_statchg)(struct device *self)  sipcom_dp83815_mii_statchg(device_t self)
 {  {
         struct sip_softc *sc = (struct sip_softc *) self;          struct sip_softc *sc = device_private(self);
   
         /*          /*
          * Update TXCFG for full-duplex operation.           * Update TXCFG for full-duplex operation.
Line 3494  SIP_DECL(dp83815_mii_statchg)(struct dev
Line 3691  SIP_DECL(dp83815_mii_statchg)(struct dev
          * XXX 802.3x flow control.           * XXX 802.3x flow control.
          */           */
   
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);          bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_txcfg,
         bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);              sc->sc_txcfg);
           bus_space_write_4(sc->sc_st, sc->sc_sh, sc->sc_regs.r_rxcfg,
               sc->sc_rxcfg);
   
         /*          /*
          * Some DP83815s experience problems when used with short           * Some DP83815s experience problems when used with short
Line 3525  SIP_DECL(dp83815_mii_statchg)(struct dev
Line 3724  SIP_DECL(dp83815_mii_statchg)(struct dev
                 bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0);                  bus_space_write_4(sc->sc_st, sc->sc_sh, 0x00cc, 0);
         }          }
 }  }
 #endif /* DP83820 */  
   
 #if defined(DP83820)  
 static void  static void
 SIP_DECL(dp83820_read_macaddr)(struct sip_softc *sc,  sipcom_dp83820_read_macaddr(struct sip_softc *sc,
     const struct pci_attach_args *pa, u_int8_t *enaddr)      const struct pci_attach_args *pa, u_int8_t *enaddr)
 {  {
         u_int16_t eeprom_data[SIP_DP83820_EEPROM_LENGTH / 2];          u_int16_t eeprom_data[SIP_DP83820_EEPROM_LENGTH / 2];
Line 3541  SIP_DECL(dp83820_read_macaddr)(struct si
Line 3738  SIP_DECL(dp83820_read_macaddr)(struct si
          * the DP83820 manual, section 4.2.4.           * the DP83820 manual, section 4.2.4.
          */           */
   
         SIP_DECL(read_eeprom)(sc, 0,          sipcom_read_eeprom(sc, 0, __arraycount(eeprom_data), eeprom_data);
             sizeof(eeprom_data) / sizeof(eeprom_data[0]), eeprom_data);  
   
         match = eeprom_data[SIP_DP83820_EEPROM_CHECKSUM / 2] >> 8;          match = eeprom_data[SIP_DP83820_EEPROM_CHECKSUM / 2] >> 8;
         match = ~(match - 1);          match = ~(match - 1);
Line 3563  SIP_DECL(dp83820_read_macaddr)(struct si
Line 3759  SIP_DECL(dp83820_read_macaddr)(struct si
         enaddr[4] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] & 0xff;          enaddr[4] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] & 0xff;
         enaddr[5] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] >> 8;          enaddr[5] = eeprom_data[SIP_DP83820_EEPROM_PMATCH0 / 2] >> 8;
 }  }
 #else /* ! DP83820 */  
 static void  static void
 SIP_DECL(sis900_eeprom_delay)(struct sip_softc *sc)  sipcom_sis900_eeprom_delay(struct sip_softc *sc)
 {  {
         int i;          int i;
   
Line 3578  SIP_DECL(sis900_eeprom_delay)(struct sip
Line 3774  SIP_DECL(sis900_eeprom_delay)(struct sip
 }  }
   
 static void  static void
 SIP_DECL(sis900_read_macaddr)(struct sip_softc *sc,  sipcom_sis900_read_macaddr(struct sip_softc *sc,
     const struct pci_attach_args *pa, u_int8_t *enaddr)      const struct pci_attach_args *pa, u_int8_t *enaddr)
 {  {
         u_int16_t myea[ETHER_ADDR_LEN / 2];          u_int16_t myea[ETHER_ADDR_LEN / 2];
Line 3636  SIP_DECL(sis900_read_macaddr)(struct sip
Line 3832  SIP_DECL(sis900_read_macaddr)(struct sip
                                  * XXX-cube This is ugly.  I'll look for docs about it.                                   * XXX-cube This is ugly.  I'll look for docs about it.
                                  */                                   */
                                 SIS_SET_EROMAR(sc, EROMAR_EECS);                                  SIS_SET_EROMAR(sc, EROMAR_EECS);
                                 SIP_DECL(sis900_eeprom_delay)(sc);                                  sipcom_sis900_eeprom_delay(sc);
                                 for (i = 0; i <= 25; i++) { /* Yes, 26 times. */                                  for (i = 0; i <= 25; i++) { /* Yes, 26 times. */
                                         SIS_SET_EROMAR(sc, EROMAR_EESK);                                          SIS_SET_EROMAR(sc, EROMAR_EESK);
                                         SIP_DECL(sis900_eeprom_delay)(sc);                                          sipcom_sis900_eeprom_delay(sc);
                                         SIS_CLR_EROMAR(sc, EROMAR_EESK);                                          SIS_CLR_EROMAR(sc, EROMAR_EESK);
                                         SIP_DECL(sis900_eeprom_delay)(sc);                                          sipcom_sis900_eeprom_delay(sc);
                                 }                                  }
                                 SIS_CLR_EROMAR(sc, EROMAR_EECS);                                  SIS_CLR_EROMAR(sc, EROMAR_EECS);
                                 SIP_DECL(sis900_eeprom_delay)(sc);                                  sipcom_sis900_eeprom_delay(sc);
                                 bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, 0);                                  bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, 0);
   
                                 if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR) & EROMAR_GNT) {                                  if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_EROMAR) & EROMAR_GNT) {
                                         SIP_DECL(read_eeprom)(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,                                          sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
                                             sizeof(myea) / sizeof(myea[0]), myea);                                              sizeof(myea) / sizeof(myea[0]), myea);
                                         break;                                          break;
                                 }                                  }
Line 3666  SIP_DECL(sis900_read_macaddr)(struct sip
Line 3862  SIP_DECL(sis900_read_macaddr)(struct sip
                 } break;                  } break;
   
         default:          default:
                 SIP_DECL(read_eeprom)(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,                  sipcom_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
                     sizeof(myea) / sizeof(myea[0]), myea);                      sizeof(myea) / sizeof(myea[0]), myea);
         }          }
   
Line 3683  static const u_int8_t bbr4[] = {0,8,4,12
Line 3879  static const u_int8_t bbr4[] = {0,8,4,12
 #define bbr(v)  ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])  #define bbr(v)  ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
   
 static void  static void
 SIP_DECL(dp83815_read_macaddr)(struct sip_softc *sc,  sipcom_dp83815_read_macaddr(struct sip_softc *sc,
     const struct pci_attach_args *pa, u_int8_t *enaddr)      const struct pci_attach_args *pa, u_int8_t *enaddr)
 {  {
         u_int16_t eeprom_data[SIP_DP83815_EEPROM_LENGTH / 2], *ea;          u_int16_t eeprom_data[SIP_DP83815_EEPROM_LENGTH / 2], *ea;
         u_int8_t cksum, *e, match;          u_int8_t cksum, *e, match;
         int i;          int i;
   
         SIP_DECL(read_eeprom)(sc, 0, sizeof(eeprom_data) /          sipcom_read_eeprom(sc, 0, sizeof(eeprom_data) /
             sizeof(eeprom_data[0]), eeprom_data);              sizeof(eeprom_data[0]), eeprom_data);
   
         match = eeprom_data[SIP_DP83815_EEPROM_CHECKSUM/2] >> 8;          match = eeprom_data[SIP_DP83815_EEPROM_CHECKSUM/2] >> 8;
Line 3735  SIP_DECL(dp83815_read_macaddr)(struct si
Line 3931  SIP_DECL(dp83815_read_macaddr)(struct si
         for (i = 0; i < 6 ;i++)          for (i = 0; i < 6 ;i++)
                 enaddr[i] = bbr(enaddr[i]);                  enaddr[i] = bbr(enaddr[i]);
 }  }
 #endif /* DP83820 */  
   
 /*  /*
  * sip_mediastatus:     [ifmedia interface function]   * sip_mediastatus:     [ifmedia interface function]
Line 3743  SIP_DECL(dp83815_read_macaddr)(struct si
Line 3938  SIP_DECL(dp83815_read_macaddr)(struct si
  *      Get the current interface media status.   *      Get the current interface media status.
  */   */
 static void  static void
 SIP_DECL(mediastatus)(struct ifnet *ifp, struct ifmediareq *ifmr)  sipcom_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
 {  {
         struct sip_softc *sc = ifp->if_softc;          struct sip_softc *sc = ifp->if_softc;
   
         mii_pollstat(&sc->sc_mii);          ether_mediastatus(ifp, ifmr);
         ifmr->ifm_status = sc->sc_mii.mii_media_status;          ifmr->ifm_active = (ifmr->ifm_active & ~IFM_ETH_FMASK) |
         ifmr->ifm_active = (sc->sc_mii.mii_media_active & ~IFM_ETH_FMASK) |  
                            sc->sc_flowflags;                             sc->sc_flowflags;
 }  }
   
 /*  
  * sip_mediachange:     [ifmedia interface function]  
  *  
  *      Set hardware to newly-selected media.  
  */  
 static int  
 SIP_DECL(mediachange)(struct ifnet *ifp)  
 {  
         struct sip_softc *sc = ifp->if_softc;  
   
         if (ifp->if_flags & IFF_UP)  
                 mii_mediachg(&sc->sc_mii);  
         return (0);  
 }  

Legend:
Removed from v.1.113  
changed lines
  Added in v.1.113.8.3

CVSweb <webmaster@jp.NetBSD.org>