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

          Line data    Source code
       1             : /*      $OpenBSD: if_sis.c,v 1.135 2017/01/22 10:17:38 dlg Exp $ */
       2             : /*
       3             :  * Copyright (c) 1997, 1998, 1999
       4             :  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  * 1. Redistributions of source code must retain the above copyright
      10             :  *    notice, this list of conditions and the following disclaimer.
      11             :  * 2. Redistributions in binary form must reproduce the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer in the
      13             :  *    documentation and/or other materials provided with the distribution.
      14             :  * 3. All advertising materials mentioning features or use of this software
      15             :  *    must display the following acknowledgement:
      16             :  *      This product includes software developed by Bill Paul.
      17             :  * 4. Neither the name of the author nor the names of any co-contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
      25             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      26             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      27             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      29             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      30             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      31             :  * THE POSSIBILITY OF SUCH DAMAGE.
      32             :  *
      33             :  * $FreeBSD: src/sys/pci/if_sis.c,v 1.30 2001/02/06 10:11:47 phk Exp $
      34             :  */
      35             : 
      36             : /*
      37             :  * SiS 900/SiS 7016 fast ethernet PCI NIC driver. Datasheets are
      38             :  * available from http://www.sis.com.tw.
      39             :  *
      40             :  * This driver also supports the NatSemi DP83815. Datasheets are
      41             :  * available from http://www.national.com.
      42             :  *
      43             :  * Written by Bill Paul <wpaul@ee.columbia.edu>
      44             :  * Electrical Engineering Department
      45             :  * Columbia University, New York City
      46             :  */
      47             : 
      48             : /*
      49             :  * The SiS 900 is a fairly simple chip. It uses bus master DMA with
      50             :  * simple TX and RX descriptors of 3 longwords in size. The receiver
      51             :  * has a single perfect filter entry for the station address and a
      52             :  * 128-bit multicast hash table. The SiS 900 has a built-in MII-based
      53             :  * transceiver while the 7016 requires an external transceiver chip.
      54             :  * Both chips offer the standard bit-bang MII interface as well as
      55             :  * an enchanced PHY interface which simplifies accessing MII registers.
      56             :  *
      57             :  * The only downside to this chipset is that RX descriptors must be
      58             :  * longword aligned.
      59             :  */
      60             : 
      61             : #include "bpfilter.h"
      62             : 
      63             : #include <sys/param.h>
      64             : #include <sys/systm.h>
      65             : #include <sys/mbuf.h>
      66             : #include <sys/protosw.h>
      67             : #include <sys/socket.h>
      68             : #include <sys/ioctl.h>
      69             : #include <sys/errno.h>
      70             : #include <sys/malloc.h>
      71             : #include <sys/kernel.h>
      72             : #include <sys/timeout.h>
      73             : 
      74             : #include <net/if.h>
      75             : 
      76             : #include <netinet/in.h>
      77             : #include <netinet/if_ether.h>
      78             : 
      79             : #include <net/if_media.h>
      80             : 
      81             : #if NBPFILTER > 0
      82             : #include <net/bpf.h>
      83             : #endif
      84             : 
      85             : #include <sys/device.h>
      86             : 
      87             : #include <dev/mii/miivar.h>
      88             : 
      89             : #include <dev/pci/pcireg.h>
      90             : #include <dev/pci/pcivar.h>
      91             : #include <dev/pci/pcidevs.h>
      92             : 
      93             : #define SIS_USEIOSPACE
      94             : 
      95             : #include <dev/pci/if_sisreg.h>
      96             : 
      97             : int sis_probe(struct device *, void *, void *);
      98             : void sis_attach(struct device *, struct device *, void *);
      99             : int sis_activate(struct device *, int);
     100             : 
     101             : struct cfattach sis_ca = {
     102             :         sizeof(struct sis_softc), sis_probe, sis_attach, NULL,
     103             :         sis_activate
     104             : };
     105             : 
     106             : struct cfdriver sis_cd = {
     107             :         NULL, "sis", DV_IFNET
     108             : };
     109             : 
     110             : int sis_intr(void *);
     111             : void sis_fill_rx_ring(struct sis_softc *);
     112             : int sis_newbuf(struct sis_softc *, struct sis_desc *);
     113             : int sis_encap(struct sis_softc *, struct mbuf *, u_int32_t *);
     114             : void sis_rxeof(struct sis_softc *);
     115             : void sis_txeof(struct sis_softc *);
     116             : void sis_tick(void *);
     117             : void sis_start(struct ifnet *);
     118             : int sis_ioctl(struct ifnet *, u_long, caddr_t);
     119             : void sis_init(void *);
     120             : void sis_stop(struct sis_softc *);
     121             : void sis_watchdog(struct ifnet *);
     122             : int sis_ifmedia_upd(struct ifnet *);
     123             : void sis_ifmedia_sts(struct ifnet *, struct ifmediareq *);
     124             : 
     125             : u_int16_t sis_reverse(u_int16_t);
     126             : void sis_delay(struct sis_softc *);
     127             : void sis_eeprom_idle(struct sis_softc *);
     128             : void sis_eeprom_putbyte(struct sis_softc *, int);
     129             : void sis_eeprom_getword(struct sis_softc *, int, u_int16_t *);
     130             : #if defined(__amd64__) || defined(__i386__)
     131             : void sis_read_cmos(struct sis_softc *, struct pci_attach_args *, caddr_t, int, int);
     132             : #endif
     133             : void sis_read_mac(struct sis_softc *, struct pci_attach_args *);
     134             : void sis_read_eeprom(struct sis_softc *, caddr_t, int, int, int);
     135             : void sis_read96x_mac(struct sis_softc *);
     136             : 
     137             : void sis_mii_sync(struct sis_softc *);
     138             : void sis_mii_send(struct sis_softc *, u_int32_t, int);
     139             : int sis_mii_readreg(struct sis_softc *, struct sis_mii_frame *);
     140             : int sis_mii_writereg(struct sis_softc *, struct sis_mii_frame *);
     141             : int sis_miibus_readreg(struct device *, int, int);
     142             : void sis_miibus_writereg(struct device *, int, int, int);
     143             : void sis_miibus_statchg(struct device *);
     144             : 
     145             : u_int32_t sis_mchash(struct sis_softc *, const uint8_t *);
     146             : void sis_iff(struct sis_softc *);
     147             : void sis_iff_ns(struct sis_softc *);
     148             : void sis_iff_sis(struct sis_softc *);
     149             : void sis_reset(struct sis_softc *);
     150             : int sis_ring_init(struct sis_softc *);
     151             : 
     152             : #define SIS_SETBIT(sc, reg, x)                          \
     153             :         CSR_WRITE_4(sc, reg,                            \
     154             :                 CSR_READ_4(sc, reg) | (x))
     155             : 
     156             : #define SIS_CLRBIT(sc, reg, x)                          \
     157             :         CSR_WRITE_4(sc, reg,                            \
     158             :                 CSR_READ_4(sc, reg) & ~(x))
     159             : 
     160             : #define SIO_SET(x)                                      \
     161             :         CSR_WRITE_4(sc, SIS_EECTL, CSR_READ_4(sc, SIS_EECTL) | x)
     162             : 
     163             : #define SIO_CLR(x)                                      \
     164             :         CSR_WRITE_4(sc, SIS_EECTL, CSR_READ_4(sc, SIS_EECTL) & ~x)
     165             : 
     166             : const struct pci_matchid sis_devices[] = {
     167             :         { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900 },
     168             :         { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016 },
     169             :         { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815 }
     170             : };
     171             : 
     172             : /*
     173             :  * Routine to reverse the bits in a word. Stolen almost
     174             :  * verbatim from /usr/games/fortune.
     175             :  */
     176             : u_int16_t
     177           0 : sis_reverse(u_int16_t n)
     178             : {
     179           0 :         n = ((n >>  1) & 0x5555) | ((n <<  1) & 0xaaaa);
     180           0 :         n = ((n >>  2) & 0x3333) | ((n <<  2) & 0xcccc);
     181           0 :         n = ((n >>  4) & 0x0f0f) | ((n <<  4) & 0xf0f0);
     182           0 :         n = ((n >>  8) & 0x00ff) | ((n <<  8) & 0xff00);
     183             : 
     184           0 :         return (n);
     185             : }
     186             : 
     187             : void
     188           0 : sis_delay(struct sis_softc *sc)
     189             : {
     190             :         int                     idx;
     191             : 
     192           0 :         for (idx = (300 / 33) + 1; idx > 0; idx--)
     193           0 :                 CSR_READ_4(sc, SIS_CSR);
     194           0 : }
     195             : 
     196             : void
     197           0 : sis_eeprom_idle(struct sis_softc *sc)
     198             : {
     199             :         int                     i;
     200             : 
     201           0 :         SIO_SET(SIS_EECTL_CSEL);
     202           0 :         sis_delay(sc);
     203           0 :         SIO_SET(SIS_EECTL_CLK);
     204           0 :         sis_delay(sc);
     205             : 
     206           0 :         for (i = 0; i < 25; i++) {
     207             :                 SIO_CLR(SIS_EECTL_CLK);
     208             :                 sis_delay(sc);
     209           0 :                 SIO_SET(SIS_EECTL_CLK);
     210           0 :                 sis_delay(sc);
     211             :         }
     212             : 
     213             :         SIO_CLR(SIS_EECTL_CLK);
     214             :         sis_delay(sc);
     215           0 :         SIO_CLR(SIS_EECTL_CSEL);
     216           0 :         sis_delay(sc);
     217           0 :         CSR_WRITE_4(sc, SIS_EECTL, 0x00000000);
     218           0 : }
     219             : 
     220             : /*
     221             :  * Send a read command and address to the EEPROM, check for ACK.
     222             :  */
     223             : void
     224           0 : sis_eeprom_putbyte(struct sis_softc *sc, int addr)
     225             : {
     226             :         int                     d, i;
     227             : 
     228           0 :         d = addr | SIS_EECMD_READ;
     229             : 
     230             :         /*
     231             :          * Feed in each bit and strobe the clock.
     232             :          */
     233           0 :         for (i = 0x400; i; i >>= 1) {
     234           0 :                 if (d & i)
     235           0 :                         SIO_SET(SIS_EECTL_DIN);
     236             :                 else
     237           0 :                         SIO_CLR(SIS_EECTL_DIN);
     238           0 :                 sis_delay(sc);
     239           0 :                 SIO_SET(SIS_EECTL_CLK);
     240           0 :                 sis_delay(sc);
     241           0 :                 SIO_CLR(SIS_EECTL_CLK);
     242           0 :                 sis_delay(sc);
     243             :         }
     244           0 : }
     245             : 
     246             : /*
     247             :  * Read a word of data stored in the EEPROM at address 'addr.'
     248             :  */
     249             : void
     250           0 : sis_eeprom_getword(struct sis_softc *sc, int addr, u_int16_t *dest)
     251             : {
     252             :         int                     i;
     253             :         u_int16_t               word = 0;
     254             : 
     255             :         /* Force EEPROM to idle state. */
     256           0 :         sis_eeprom_idle(sc);
     257             : 
     258             :         /* Enter EEPROM access mode. */
     259           0 :         sis_delay(sc);
     260           0 :         SIO_CLR(SIS_EECTL_CLK);
     261           0 :         sis_delay(sc);
     262           0 :         SIO_SET(SIS_EECTL_CSEL);
     263           0 :         sis_delay(sc);
     264             : 
     265             :         /*
     266             :          * Send address of word we want to read.
     267             :          */
     268           0 :         sis_eeprom_putbyte(sc, addr);
     269             : 
     270             :         /*
     271             :          * Start reading bits from EEPROM.
     272             :          */
     273           0 :         for (i = 0x8000; i; i >>= 1) {
     274           0 :                 SIO_SET(SIS_EECTL_CLK);
     275           0 :                 sis_delay(sc);
     276           0 :                 if (CSR_READ_4(sc, SIS_EECTL) & SIS_EECTL_DOUT)
     277           0 :                         word |= i;
     278           0 :                 sis_delay(sc);
     279           0 :                 SIO_CLR(SIS_EECTL_CLK);
     280           0 :                 sis_delay(sc);
     281             :         }
     282             : 
     283             :         /* Turn off EEPROM access mode. */
     284           0 :         sis_eeprom_idle(sc);
     285             : 
     286           0 :         *dest = word;
     287           0 : }
     288             : 
     289             : /*
     290             :  * Read a sequence of words from the EEPROM.
     291             :  */
     292             : void
     293           0 : sis_read_eeprom(struct sis_softc *sc, caddr_t dest,
     294             :     int off, int cnt, int swap)
     295             : {
     296             :         int                     i;
     297           0 :         u_int16_t               word = 0, *ptr;
     298             : 
     299           0 :         for (i = 0; i < cnt; i++) {
     300           0 :                 sis_eeprom_getword(sc, off + i, &word);
     301           0 :                 ptr = (u_int16_t *)(dest + (i * 2));
     302             :                 if (swap)
     303             :                         *ptr = letoh16(word);
     304             :                 else
     305             :                         *ptr = word;
     306             :         }
     307           0 : }
     308             : 
     309             : #if defined(__amd64__) || defined(__i386__)
     310             : void
     311           0 : sis_read_cmos(struct sis_softc *sc, struct pci_attach_args *pa,
     312             :     caddr_t dest, int off, int cnt)
     313             : {
     314             :         u_int32_t reg;
     315             :         int i;
     316             : 
     317           0 :         reg = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x48);
     318           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, 0x48, reg | 0x40);
     319             : 
     320           0 :         for (i = 0; i < cnt; i++) {
     321           0 :                 bus_space_write_1(pa->pa_iot, 0x0, 0x70, i + off);
     322           0 :                 *(dest + i) = bus_space_read_1(pa->pa_iot, 0x0, 0x71);
     323             :         }
     324             : 
     325           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, 0x48, reg & ~0x40);
     326           0 : }
     327             : #endif
     328             : 
     329             : void
     330           0 : sis_read_mac(struct sis_softc *sc, struct pci_attach_args *pa)
     331             : {
     332             :         uint32_t rxfilt, csrsave;
     333           0 :         u_int16_t *enaddr = (u_int16_t *) &sc->arpcom.ac_enaddr;
     334             : 
     335           0 :         rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
     336           0 :         csrsave = CSR_READ_4(sc, SIS_CSR);
     337             : 
     338           0 :         CSR_WRITE_4(sc, SIS_CSR, SIS_CSR_RELOAD | csrsave);
     339           0 :         CSR_WRITE_4(sc, SIS_CSR, 0);
     340             : 
     341           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt & ~SIS_RXFILTCTL_ENABLE);
     342             : 
     343           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
     344           0 :         enaddr[0] = letoh16(CSR_READ_4(sc, SIS_RXFILT_DATA) & 0xffff);
     345           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR1);
     346           0 :         enaddr[1] = letoh16(CSR_READ_4(sc, SIS_RXFILT_DATA) & 0xffff);
     347           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
     348           0 :         enaddr[2] = letoh16(CSR_READ_4(sc, SIS_RXFILT_DATA) & 0xffff);
     349             : 
     350           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
     351           0 :         CSR_WRITE_4(sc, SIS_CSR, csrsave);
     352           0 : }
     353             : 
     354             : void
     355           0 : sis_read96x_mac(struct sis_softc *sc)
     356             : {
     357             :         int i;
     358             : 
     359           0 :         SIO_SET(SIS96x_EECTL_REQ);
     360             : 
     361           0 :         for (i = 0; i < 2000; i++) {
     362           0 :                 if ((CSR_READ_4(sc, SIS_EECTL) & SIS96x_EECTL_GNT)) {
     363           0 :                         sis_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr,
     364             :                             SIS_EE_NODEADDR, 3, 1);
     365           0 :                         break;
     366             :                 } else
     367           0 :                         DELAY(1);
     368             :         }
     369             : 
     370           0 :         SIO_SET(SIS96x_EECTL_DONE);
     371           0 : }
     372             : 
     373             : /*
     374             :  * Sync the PHYs by setting data bit and strobing the clock 32 times.
     375             :  */
     376             : void
     377           0 : sis_mii_sync(struct sis_softc *sc)
     378             : {
     379             :         int                     i;
     380             :  
     381           0 :         SIO_SET(SIS_MII_DIR|SIS_MII_DATA);
     382             :  
     383           0 :         for (i = 0; i < 32; i++) {
     384           0 :                 SIO_SET(SIS_MII_CLK);
     385           0 :                 DELAY(1);
     386           0 :                 SIO_CLR(SIS_MII_CLK);
     387           0 :                 DELAY(1);
     388             :         }
     389           0 : }
     390             :  
     391             : /*
     392             :  * Clock a series of bits through the MII.
     393             :  */
     394             : void
     395           0 : sis_mii_send(struct sis_softc *sc, u_int32_t bits, int cnt)
     396             : {
     397             :         int                     i;
     398             :  
     399           0 :         SIO_CLR(SIS_MII_CLK);
     400             :  
     401           0 :         for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
     402           0 :                 if (bits & i)
     403           0 :                         SIO_SET(SIS_MII_DATA);
     404             :                 else
     405           0 :                         SIO_CLR(SIS_MII_DATA);
     406           0 :                 DELAY(1);
     407           0 :                 SIO_CLR(SIS_MII_CLK);
     408           0 :                 DELAY(1);
     409           0 :                 SIO_SET(SIS_MII_CLK);
     410             :         }
     411           0 : }
     412             :  
     413             : /*
     414             :  * Read an PHY register through the MII.
     415             :  */
     416             : int
     417           0 : sis_mii_readreg(struct sis_softc *sc, struct sis_mii_frame *frame)
     418             : {
     419             :         int                     i, ack, s;
     420             :  
     421           0 :         s = splnet();
     422             :  
     423             :         /*
     424             :          * Set up frame for RX.
     425             :          */
     426           0 :         frame->mii_stdelim = SIS_MII_STARTDELIM;
     427           0 :         frame->mii_opcode = SIS_MII_READOP;
     428           0 :         frame->mii_turnaround = 0;
     429           0 :         frame->mii_data = 0;
     430             :         
     431             :         /*
     432             :          * Turn on data xmit.
     433             :          */
     434           0 :         SIO_SET(SIS_MII_DIR);
     435             : 
     436           0 :         sis_mii_sync(sc);
     437             :  
     438             :         /*
     439             :          * Send command/address info.
     440             :          */
     441           0 :         sis_mii_send(sc, frame->mii_stdelim, 2);
     442           0 :         sis_mii_send(sc, frame->mii_opcode, 2);
     443           0 :         sis_mii_send(sc, frame->mii_phyaddr, 5);
     444           0 :         sis_mii_send(sc, frame->mii_regaddr, 5);
     445             :  
     446             :         /* Idle bit */
     447           0 :         SIO_CLR((SIS_MII_CLK|SIS_MII_DATA));
     448           0 :         DELAY(1);
     449           0 :         SIO_SET(SIS_MII_CLK);
     450           0 :         DELAY(1);
     451             :  
     452             :         /* Turn off xmit. */
     453           0 :         SIO_CLR(SIS_MII_DIR);
     454             :  
     455             :         /* Check for ack */
     456           0 :         SIO_CLR(SIS_MII_CLK);
     457           0 :         DELAY(1);
     458           0 :         ack = CSR_READ_4(sc, SIS_EECTL) & SIS_MII_DATA;
     459           0 :         SIO_SET(SIS_MII_CLK);
     460           0 :         DELAY(1);
     461             :  
     462             :         /*
     463             :          * Now try reading data bits. If the ack failed, we still
     464             :          * need to clock through 16 cycles to keep the PHY(s) in sync.
     465             :          */
     466           0 :         if (ack) {
     467           0 :                 for(i = 0; i < 16; i++) {
     468           0 :                         SIO_CLR(SIS_MII_CLK);
     469           0 :                         DELAY(1);
     470           0 :                         SIO_SET(SIS_MII_CLK);
     471           0 :                         DELAY(1);
     472             :                 }
     473             :                 goto fail;
     474             :         }
     475             :  
     476           0 :         for (i = 0x8000; i; i >>= 1) {
     477           0 :                 SIO_CLR(SIS_MII_CLK);
     478           0 :                 DELAY(1);
     479           0 :                 if (!ack) {
     480           0 :                         if (CSR_READ_4(sc, SIS_EECTL) & SIS_MII_DATA)
     481           0 :                                 frame->mii_data |= i;
     482           0 :                         DELAY(1);
     483           0 :                 }
     484           0 :                 SIO_SET(SIS_MII_CLK);
     485           0 :                 DELAY(1);
     486             :         }
     487             : 
     488             : fail:
     489             : 
     490           0 :         SIO_CLR(SIS_MII_CLK);
     491           0 :         DELAY(1);
     492           0 :         SIO_SET(SIS_MII_CLK);
     493           0 :         DELAY(1);
     494             : 
     495           0 :         splx(s);
     496             : 
     497           0 :         if (ack)
     498           0 :                 return (1);
     499           0 :         return (0);
     500           0 : }
     501             :  
     502             : /*
     503             :  * Write to a PHY register through the MII.
     504             :  */
     505             : int
     506           0 : sis_mii_writereg(struct sis_softc *sc, struct sis_mii_frame *frame)
     507             : {
     508             :         int                     s;
     509             :  
     510           0 :         s = splnet();
     511             :         /*
     512             :          * Set up frame for TX.
     513             :          */
     514             :  
     515           0 :         frame->mii_stdelim = SIS_MII_STARTDELIM;
     516           0 :         frame->mii_opcode = SIS_MII_WRITEOP;
     517           0 :         frame->mii_turnaround = SIS_MII_TURNAROUND;
     518             :         
     519             :         /*
     520             :          * Turn on data output.
     521             :          */
     522           0 :         SIO_SET(SIS_MII_DIR);
     523             :  
     524           0 :         sis_mii_sync(sc);
     525             :  
     526           0 :         sis_mii_send(sc, frame->mii_stdelim, 2);
     527           0 :         sis_mii_send(sc, frame->mii_opcode, 2);
     528           0 :         sis_mii_send(sc, frame->mii_phyaddr, 5);
     529           0 :         sis_mii_send(sc, frame->mii_regaddr, 5);
     530           0 :         sis_mii_send(sc, frame->mii_turnaround, 2);
     531           0 :         sis_mii_send(sc, frame->mii_data, 16);
     532             :  
     533             :         /* Idle bit. */
     534           0 :         SIO_SET(SIS_MII_CLK);
     535           0 :         DELAY(1);
     536           0 :         SIO_CLR(SIS_MII_CLK);
     537           0 :         DELAY(1);
     538             :  
     539             :         /*
     540             :          * Turn off xmit.
     541             :          */
     542           0 :         SIO_CLR(SIS_MII_DIR);
     543             :  
     544           0 :         splx(s);
     545             :  
     546           0 :         return (0);
     547             : }
     548             : 
     549             : int
     550           0 : sis_miibus_readreg(struct device *self, int phy, int reg)
     551             : {
     552           0 :         struct sis_softc        *sc = (struct sis_softc *)self;
     553           0 :         struct sis_mii_frame    frame;
     554             : 
     555           0 :         if (sc->sis_type == SIS_TYPE_83815) {
     556           0 :                 if (phy != 0)
     557           0 :                         return (0);
     558             :                 /*
     559             :                  * The NatSemi chip can take a while after
     560             :                  * a reset to come ready, during which the BMSR
     561             :                  * returns a value of 0. This is *never* supposed
     562             :                  * to happen: some of the BMSR bits are meant to
     563             :                  * be hardwired in the on position, and this can
     564             :                  * confuse the miibus code a bit during the probe
     565             :                  * and attach phase. So we make an effort to check
     566             :                  * for this condition and wait for it to clear.
     567             :                  */
     568           0 :                 if (!CSR_READ_4(sc, NS_BMSR))
     569           0 :                         DELAY(1000);
     570           0 :                 return CSR_READ_4(sc, NS_BMCR + (reg * 4));
     571             :         }
     572             : 
     573             :         /*
     574             :          * Chipsets < SIS_635 seem not to be able to read/write
     575             :          * through mdio. Use the enhanced PHY access register
     576             :          * again for them.
     577             :          */
     578           0 :         if (sc->sis_type == SIS_TYPE_900 &&
     579           0 :             sc->sis_rev < SIS_REV_635) {
     580             :                 int i, val = 0;
     581             : 
     582           0 :                 if (phy != 0)
     583           0 :                         return (0);
     584             : 
     585           0 :                 CSR_WRITE_4(sc, SIS_PHYCTL,
     586             :                     (phy << 11) | (reg << 6) | SIS_PHYOP_READ);
     587           0 :                 SIS_SETBIT(sc, SIS_PHYCTL, SIS_PHYCTL_ACCESS);
     588             : 
     589           0 :                 for (i = 0; i < SIS_TIMEOUT; i++) {
     590           0 :                         if (!(CSR_READ_4(sc, SIS_PHYCTL) & SIS_PHYCTL_ACCESS))
     591             :                                 break;
     592             :                 }
     593             : 
     594           0 :                 if (i == SIS_TIMEOUT) {
     595           0 :                         printf("%s: PHY failed to come ready\n",
     596           0 :                             sc->sc_dev.dv_xname);
     597           0 :                         return (0);
     598             :                 }
     599             : 
     600           0 :                 val = (CSR_READ_4(sc, SIS_PHYCTL) >> 16) & 0xFFFF;
     601             : 
     602           0 :                 if (val == 0xFFFF)
     603           0 :                         return (0);
     604             : 
     605           0 :                 return (val);
     606             :         } else {
     607           0 :                 bzero(&frame, sizeof(frame));
     608             : 
     609           0 :                 frame.mii_phyaddr = phy;
     610           0 :                 frame.mii_regaddr = reg;
     611           0 :                 sis_mii_readreg(sc, &frame);
     612             : 
     613           0 :                 return (frame.mii_data);
     614             :         }
     615           0 : }
     616             : 
     617             : void
     618           0 : sis_miibus_writereg(struct device *self, int phy, int reg, int data)
     619             : {
     620           0 :         struct sis_softc        *sc = (struct sis_softc *)self;
     621           0 :         struct sis_mii_frame    frame;
     622             : 
     623           0 :         if (sc->sis_type == SIS_TYPE_83815) {
     624           0 :                 if (phy != 0)
     625           0 :                         return;
     626           0 :                 CSR_WRITE_4(sc, NS_BMCR + (reg * 4), data);
     627           0 :                 return;
     628             :         }
     629             : 
     630             :         /*
     631             :          * Chipsets < SIS_635 seem not to be able to read/write
     632             :          * through mdio. Use the enhanced PHY access register
     633             :          * again for them.
     634             :          */
     635           0 :         if (sc->sis_type == SIS_TYPE_900 &&
     636           0 :             sc->sis_rev < SIS_REV_635) {
     637             :                 int i;
     638             : 
     639           0 :                 if (phy != 0)
     640           0 :                         return;
     641             : 
     642           0 :                 CSR_WRITE_4(sc, SIS_PHYCTL, (data << 16) | (phy << 11) |
     643             :                     (reg << 6) | SIS_PHYOP_WRITE);
     644           0 :                 SIS_SETBIT(sc, SIS_PHYCTL, SIS_PHYCTL_ACCESS);
     645             : 
     646           0 :                 for (i = 0; i < SIS_TIMEOUT; i++) {
     647           0 :                         if (!(CSR_READ_4(sc, SIS_PHYCTL) & SIS_PHYCTL_ACCESS))
     648             :                                 break;
     649             :                 }
     650             : 
     651           0 :                 if (i == SIS_TIMEOUT)
     652           0 :                         printf("%s: PHY failed to come ready\n",
     653           0 :                             sc->sc_dev.dv_xname);
     654           0 :         } else {
     655           0 :                 bzero(&frame, sizeof(frame));
     656             : 
     657           0 :                 frame.mii_phyaddr = phy;
     658           0 :                 frame.mii_regaddr = reg;
     659           0 :                 frame.mii_data = data;
     660           0 :                 sis_mii_writereg(sc, &frame);
     661             :         }
     662           0 : }
     663             : 
     664             : void
     665           0 : sis_miibus_statchg(struct device *self)
     666             : {
     667           0 :         struct sis_softc        *sc = (struct sis_softc *)self;
     668           0 :         struct ifnet            *ifp = &sc->arpcom.ac_if;
     669           0 :         struct mii_data         *mii = &sc->sc_mii;
     670             : 
     671           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
     672           0 :                 return;
     673             : 
     674           0 :         sc->sis_link = 0;
     675           0 :         if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
     676             :             (IFM_ACTIVE | IFM_AVALID)) {
     677           0 :                 switch (IFM_SUBTYPE(mii->mii_media_active)) {
     678             :                 case IFM_10_T:
     679           0 :                         CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_10);
     680           0 :                         sc->sis_link++;
     681           0 :                         break;
     682             :                 case IFM_100_TX:
     683           0 :                         CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100);
     684           0 :                         sc->sis_link++;
     685           0 :                         break;
     686             :                 default:
     687             :                         break;
     688             :                 }
     689             :         }
     690             : 
     691           0 :         if (!sc->sis_link) {
     692             :                 /*
     693             :                  * Stopping MACs seem to reset SIS_TX_LISTPTR and
     694             :                  * SIS_RX_LISTPTR which in turn requires resetting
     695             :                  * TX/RX buffers.  So just don't do anything for
     696             :                  * lost link.
     697             :                  */
     698           0 :                 return;
     699             :         }
     700             : 
     701             :         /* Set full/half duplex mode. */
     702           0 :         if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
     703           0 :                 SIS_SETBIT(sc, SIS_TX_CFG,
     704             :                     (SIS_TXCFG_IGN_HBEAT | SIS_TXCFG_IGN_CARR));
     705           0 :                 SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS);
     706           0 :         } else {
     707           0 :                 SIS_CLRBIT(sc, SIS_TX_CFG,
     708             :                     (SIS_TXCFG_IGN_HBEAT | SIS_TXCFG_IGN_CARR));
     709           0 :                 SIS_CLRBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS);
     710             :         }
     711             : 
     712           0 :         if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr >= NS_SRR_16A) {
     713             :                 /*
     714             :                  * MPII03.D: Half Duplex Excessive Collisions.
     715             :                  * Also page 49 in 83816 manual
     716             :                  */
     717           0 :                 SIS_SETBIT(sc, SIS_TX_CFG, SIS_TXCFG_MPII03D);
     718           0 :         }
     719             : 
     720             :         /*
     721             :          * Some DP83815s experience problems when used with short
     722             :          * (< 30m/100ft) Ethernet cables in 100baseTX mode.  This
     723             :          * sequence adjusts the DSP's signal attenuation to fix the
     724             :          * problem.
     725             :          */
     726           0 :         if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr < NS_SRR_16A &&
     727           0 :             IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
     728             :                 uint32_t reg;
     729             : 
     730           0 :                 CSR_WRITE_4(sc, NS_PHY_PAGE, 0x0001);
     731           0 :                 reg = CSR_READ_4(sc, NS_PHY_DSPCFG) & 0xfff;
     732           0 :                 CSR_WRITE_4(sc, NS_PHY_DSPCFG, reg | 0x1000);
     733           0 :                 DELAY(100);
     734           0 :                 reg = CSR_READ_4(sc, NS_PHY_TDATA) & 0xff;
     735           0 :                 if ((reg & 0x0080) == 0 || (reg > 0xd8 && reg <= 0xff)) {
     736             : #ifdef DEBUG
     737             :                         printf("%s: Applying short cable fix (reg=%x)\n",
     738             :                             sc->sc_dev.dv_xname, reg);
     739             : #endif
     740           0 :                         CSR_WRITE_4(sc, NS_PHY_TDATA, 0x00e8);
     741           0 :                         SIS_SETBIT(sc, NS_PHY_DSPCFG, 0x20);
     742           0 :                 }
     743           0 :                 CSR_WRITE_4(sc, NS_PHY_PAGE, 0);
     744           0 :         }
     745             :         /* Enable TX/RX MACs. */
     746           0 :         SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE | SIS_CSR_RX_DISABLE);
     747           0 :         SIS_SETBIT(sc, SIS_CSR, SIS_CSR_TX_ENABLE | SIS_CSR_RX_ENABLE);
     748           0 : }
     749             : 
     750             : u_int32_t
     751           0 : sis_mchash(struct sis_softc *sc, const uint8_t *addr)
     752             : {
     753             :         uint32_t                crc;
     754             : 
     755             :         /* Compute CRC for the address value. */
     756           0 :         crc = ether_crc32_be(addr, ETHER_ADDR_LEN);
     757             : 
     758             :         /*
     759             :          * return the filter bit position
     760             :          *
     761             :          * The NatSemi chip has a 512-bit filter, which is
     762             :          * different than the SiS, so we special-case it.
     763             :          */
     764           0 :         if (sc->sis_type == SIS_TYPE_83815)
     765           0 :                 return (crc >> 23);
     766           0 :         else if (sc->sis_rev >= SIS_REV_635 ||
     767           0 :             sc->sis_rev == SIS_REV_900B)
     768           0 :                 return (crc >> 24);
     769             :         else
     770           0 :                 return (crc >> 25);
     771           0 : }
     772             : 
     773             : void
     774           0 : sis_iff(struct sis_softc *sc)
     775             : {
     776           0 :         if (sc->sis_type == SIS_TYPE_83815)
     777           0 :                 sis_iff_ns(sc);
     778             :         else
     779           0 :                 sis_iff_sis(sc);
     780           0 : }
     781             : 
     782             : void
     783           0 : sis_iff_ns(struct sis_softc *sc)
     784             : {
     785           0 :         struct ifnet            *ifp = &sc->arpcom.ac_if;
     786             :         struct arpcom           *ac = &sc->arpcom;
     787             :         struct ether_multi      *enm;
     788             :         struct ether_multistep  step;
     789             :         u_int32_t               h = 0, i, rxfilt;
     790             :         int                     bit, index;
     791             : 
     792           0 :         rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
     793           0 :         if (rxfilt & SIS_RXFILTCTL_ENABLE) {
     794             :                 /*
     795             :                  * Filter should be disabled to program other bits.
     796             :                  */
     797           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt & ~SIS_RXFILTCTL_ENABLE);
     798           0 :                 CSR_READ_4(sc, SIS_RXFILT_CTL);
     799           0 :         }
     800           0 :         rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
     801             :             NS_RXFILTCTL_ARP | SIS_RXFILTCTL_BROAD | NS_RXFILTCTL_MCHASH |
     802             :             NS_RXFILTCTL_PERFECT);
     803           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
     804             : 
     805             :         /*
     806             :          * Always accept ARP frames.
     807             :          * Always accept broadcast frames.
     808             :          * Always accept frames destined to our station address.
     809             :          */
     810           0 :         rxfilt |= NS_RXFILTCTL_ARP | SIS_RXFILTCTL_BROAD |
     811             :             NS_RXFILTCTL_PERFECT;
     812             : 
     813           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
     814           0 :                 ifp->if_flags |= IFF_ALLMULTI;
     815           0 :                 rxfilt |= SIS_RXFILTCTL_ALLMULTI;
     816           0 :                 if (ifp->if_flags & IFF_PROMISC)
     817           0 :                         rxfilt |= SIS_RXFILTCTL_ALLPHYS;
     818             :         } else {
     819             :                 /*
     820             :                  * We have to explicitly enable the multicast hash table
     821             :                  * on the NatSemi chip if we want to use it, which we do.
     822             :                  */
     823           0 :                 rxfilt |= NS_RXFILTCTL_MCHASH;
     824             : 
     825             :                 /* first, zot all the existing hash bits */
     826           0 :                 for (i = 0; i < 32; i++) {
     827           0 :                         CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + (i * 2));
     828           0 :                         CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
     829             :                 }
     830             : 
     831           0 :                 ETHER_FIRST_MULTI(step, ac, enm);
     832           0 :                 while (enm != NULL) {
     833           0 :                         h = sis_mchash(sc, enm->enm_addrlo);
     834             : 
     835           0 :                         index = h >> 3;
     836           0 :                         bit = h & 0x1F;
     837             : 
     838           0 :                         CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + index);
     839             : 
     840           0 :                         if (bit > 0xF)
     841           0 :                                 bit -= 0x10;
     842             : 
     843           0 :                         SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
     844             : 
     845           0 :                         ETHER_NEXT_MULTI(step, enm);
     846             :                 }
     847             :         }
     848             : 
     849           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
     850             :         /* Turn the receive filter on. */
     851           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt | SIS_RXFILTCTL_ENABLE);
     852           0 :         CSR_READ_4(sc, SIS_RXFILT_CTL);
     853           0 : }
     854             : 
     855             : void
     856           0 : sis_iff_sis(struct sis_softc *sc)
     857             : {
     858           0 :         struct ifnet            *ifp = &sc->arpcom.ac_if;
     859             :         struct arpcom           *ac = &sc->arpcom;
     860             :         struct ether_multi      *enm;
     861             :         struct ether_multistep  step;
     862             :         u_int32_t               h, i, maxmulti, rxfilt;
     863           0 :         u_int16_t               hashes[16];
     864             : 
     865             :         /* hash table size */
     866           0 :         if (sc->sis_rev >= SIS_REV_635 ||
     867           0 :             sc->sis_rev == SIS_REV_900B)
     868           0 :                 maxmulti = 16;
     869             :         else
     870             :                 maxmulti = 8;
     871             : 
     872           0 :         rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
     873           0 :         if (rxfilt & SIS_RXFILTCTL_ENABLE) {
     874             :                 /*
     875             :                  * Filter should be disabled to program other bits.
     876             :                  */
     877           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt & ~SIS_RXFILTCTL_ENABLE);
     878           0 :                 CSR_READ_4(sc, SIS_RXFILT_CTL);
     879           0 :         }
     880           0 :         rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
     881             :             SIS_RXFILTCTL_BROAD);
     882           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
     883             : 
     884             :         /*
     885             :          * Always accept broadcast frames.
     886             :          */
     887           0 :         rxfilt |= SIS_RXFILTCTL_BROAD;
     888             : 
     889           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 ||
     890           0 :             ac->ac_multicnt > maxmulti) {
     891           0 :                 ifp->if_flags |= IFF_ALLMULTI;
     892           0 :                 rxfilt |= SIS_RXFILTCTL_ALLMULTI;
     893           0 :                 if (ifp->if_flags & IFF_PROMISC)
     894           0 :                         rxfilt |= SIS_RXFILTCTL_ALLPHYS;
     895             : 
     896           0 :                 for (i = 0; i < maxmulti; i++)
     897           0 :                         hashes[i] = ~0;
     898             :         } else {
     899           0 :                 for (i = 0; i < maxmulti; i++)
     900           0 :                         hashes[i] = 0;
     901             : 
     902           0 :                 ETHER_FIRST_MULTI(step, ac, enm);
     903           0 :                 while (enm != NULL) {
     904           0 :                         h = sis_mchash(sc, enm->enm_addrlo);
     905             : 
     906           0 :                         hashes[h >> 4] |= 1 << (h & 0xf);
     907             : 
     908           0 :                         ETHER_NEXT_MULTI(step, enm);
     909             :                 }
     910             :         }
     911             : 
     912           0 :         for (i = 0; i < maxmulti; i++) {
     913           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, (4 + i) << 16);
     914           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA, hashes[i]);
     915             :         }
     916             : 
     917           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
     918             :         /* Turn the receive filter on. */
     919           0 :         CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt | SIS_RXFILTCTL_ENABLE);
     920           0 :         CSR_READ_4(sc, SIS_RXFILT_CTL);
     921           0 : }
     922             : 
     923             : void
     924           0 : sis_reset(struct sis_softc *sc)
     925             : {
     926             :         int                     i;
     927             : 
     928           0 :         SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RESET);
     929             : 
     930           0 :         for (i = 0; i < SIS_TIMEOUT; i++) {
     931           0 :                 if (!(CSR_READ_4(sc, SIS_CSR) & SIS_CSR_RESET))
     932             :                         break;
     933             :         }
     934             : 
     935           0 :         if (i == SIS_TIMEOUT)
     936           0 :                 printf("%s: reset never completed\n", sc->sc_dev.dv_xname);
     937             : 
     938             :         /* Wait a little while for the chip to get its brains in order. */
     939           0 :         DELAY(1000);
     940             : 
     941             :         /*
     942             :          * If this is a NetSemi chip, make sure to clear
     943             :          * PME mode.
     944             :          */
     945           0 :         if (sc->sis_type == SIS_TYPE_83815) {
     946           0 :                 CSR_WRITE_4(sc, NS_CLKRUN, NS_CLKRUN_PMESTS);
     947           0 :                 CSR_WRITE_4(sc, NS_CLKRUN, 0);
     948           0 :         }
     949           0 : }
     950             : 
     951             : /*
     952             :  * Probe for an SiS chip. Check the PCI vendor and device
     953             :  * IDs against our list and return a device name if we find a match.
     954             :  */
     955             : int
     956           0 : sis_probe(struct device *parent, void *match, void *aux)
     957             : {
     958           0 :         return (pci_matchbyid((struct pci_attach_args *)aux, sis_devices,
     959             :             nitems(sis_devices)));
     960             : }
     961             : 
     962             : /*
     963             :  * Attach the interface. Allocate softc structures, do ifmedia
     964             :  * setup and ethernet/BPF attach.
     965             :  */
     966             : void
     967           0 : sis_attach(struct device *parent, struct device *self, void *aux)
     968             : {
     969             :         int                     i;
     970             :         const char              *intrstr = NULL;
     971           0 :         struct sis_softc        *sc = (struct sis_softc *)self;
     972           0 :         struct pci_attach_args  *pa = aux;
     973           0 :         pci_chipset_tag_t       pc = pa->pa_pc;
     974           0 :         pci_intr_handle_t       ih;
     975             :         struct ifnet            *ifp;
     976           0 :         bus_size_t              size;
     977             : 
     978           0 :         sc->sis_stopped = 1;
     979             : 
     980           0 :         pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
     981             : 
     982             :         /*
     983             :          * Map control/status registers.
     984             :          */
     985             : 
     986             : #ifdef SIS_USEIOSPACE
     987           0 :         if (pci_mapreg_map(pa, SIS_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
     988           0 :             &sc->sis_btag, &sc->sis_bhandle, NULL, &size, 0)) {
     989           0 :                 printf(": can't map i/o space\n");
     990           0 :                 return;
     991             :         }
     992             : #else
     993             :         if (pci_mapreg_map(pa, SIS_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
     994             :             &sc->sis_btag, &sc->sis_bhandle, NULL, &size, 0)) {
     995             :                 printf(": can't map mem space\n");
     996             :                 return;
     997             :         }
     998             : #endif
     999             : 
    1000             :         /* Allocate interrupt */
    1001           0 :         if (pci_intr_map(pa, &ih)) {
    1002           0 :                 printf(": couldn't map interrupt\n");
    1003           0 :                 goto fail_1;
    1004             :         }
    1005           0 :         intrstr = pci_intr_string(pc, ih);
    1006           0 :         sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sis_intr, sc,
    1007           0 :             self->dv_xname);
    1008           0 :         if (sc->sc_ih == NULL) {
    1009           0 :                 printf(": couldn't establish interrupt");
    1010           0 :                 if (intrstr != NULL)
    1011           0 :                         printf(" at %s", intrstr);
    1012           0 :                 printf("\n");
    1013           0 :                 goto fail_1;
    1014             :         }
    1015             : 
    1016           0 :         switch (PCI_PRODUCT(pa->pa_id)) {
    1017             :         case PCI_PRODUCT_SIS_900:
    1018           0 :                 sc->sis_type = SIS_TYPE_900;
    1019           0 :                 break;
    1020             :         case PCI_PRODUCT_SIS_7016:
    1021           0 :                 sc->sis_type = SIS_TYPE_7016;
    1022           0 :                 break;
    1023             :         case PCI_PRODUCT_NS_DP83815:
    1024           0 :                 sc->sis_type = SIS_TYPE_83815;
    1025           0 :                 break;
    1026             :         default:
    1027             :                 break;
    1028             :         }
    1029           0 :         sc->sis_rev = PCI_REVISION(pa->pa_class);
    1030             : 
    1031             :         /* Reset the adapter. */
    1032           0 :         sis_reset(sc);
    1033             : 
    1034           0 :         if (sc->sis_type == SIS_TYPE_900 &&
    1035           0 :            (sc->sis_rev == SIS_REV_635 ||
    1036           0 :             sc->sis_rev == SIS_REV_900B)) {
    1037           0 :                 SIO_SET(SIS_CFG_RND_CNT);
    1038           0 :                 SIO_SET(SIS_CFG_PERR_DETECT);
    1039           0 :         }
    1040             : 
    1041             :         /*
    1042             :          * Get station address from the EEPROM.
    1043             :          */
    1044           0 :         switch (PCI_VENDOR(pa->pa_id)) {
    1045             :         case PCI_VENDOR_NS:
    1046           0 :                 sc->sis_srr = CSR_READ_4(sc, NS_SRR);
    1047             : 
    1048           0 :                 if (sc->sis_srr == NS_SRR_15C)
    1049           0 :                         printf(", DP83815C");
    1050           0 :                 else if (sc->sis_srr == NS_SRR_15D)
    1051           0 :                         printf(", DP83815D");
    1052           0 :                 else if (sc->sis_srr == NS_SRR_16A)
    1053           0 :                         printf(", DP83816A");
    1054             :                 else
    1055           0 :                         printf(", srr %x", sc->sis_srr);
    1056             : 
    1057             :                 /*
    1058             :                  * Reading the MAC address out of the EEPROM on
    1059             :                  * the NatSemi chip takes a bit more work than
    1060             :                  * you'd expect. The address spans 4 16-bit words,
    1061             :                  * with the first word containing only a single bit.
    1062             :                  * You have to shift everything over one bit to
    1063             :                  * get it aligned properly. Also, the bits are
    1064             :                  * stored backwards (the LSB is really the MSB,
    1065             :                  * and so on) so you have to reverse them in order
    1066             :                  * to get the MAC address into the form we want.
    1067             :                  * Why? Who the hell knows.
    1068             :                  */
    1069             :                 {
    1070           0 :                         u_int16_t               tmp[4];
    1071             : 
    1072           0 :                         sis_read_eeprom(sc, (caddr_t)&tmp, NS_EE_NODEADDR,
    1073             :                             4, 0);
    1074             : 
    1075             :                         /* Shift everything over one bit. */
    1076           0 :                         tmp[3] = tmp[3] >> 1;
    1077           0 :                         tmp[3] |= tmp[2] << 15;
    1078           0 :                         tmp[2] = tmp[2] >> 1;
    1079           0 :                         tmp[2] |= tmp[1] << 15;
    1080           0 :                         tmp[1] = tmp[1] >> 1;
    1081           0 :                         tmp[1] |= tmp[0] << 15;
    1082             : 
    1083             :                         /* Now reverse all the bits. */
    1084           0 :                         tmp[3] = letoh16(sis_reverse(tmp[3]));
    1085           0 :                         tmp[2] = letoh16(sis_reverse(tmp[2]));
    1086           0 :                         tmp[1] = letoh16(sis_reverse(tmp[1]));
    1087             : 
    1088           0 :                         bcopy(&tmp[1], sc->arpcom.ac_enaddr,
    1089             :                             ETHER_ADDR_LEN);
    1090           0 :                 }
    1091           0 :                 break;
    1092             :         case PCI_VENDOR_SIS:
    1093             :         default:
    1094             : #if defined(__amd64__) || defined(__i386__)
    1095             :                 /*
    1096             :                  * If this is a SiS 630E chipset with an embedded
    1097             :                  * SiS 900 controller, we have to read the MAC address
    1098             :                  * from the APC CMOS RAM. Our method for doing this
    1099             :                  * is very ugly since we have to reach out and grab
    1100             :                  * ahold of hardware for which we cannot properly
    1101             :                  * allocate resources. This code is only compiled on
    1102             :                  * the i386 architecture since the SiS 630E chipset
    1103             :                  * is for x86 motherboards only. Note that there are
    1104             :                  * a lot of magic numbers in this hack. These are
    1105             :                  * taken from SiS's Linux driver. I'd like to replace
    1106             :                  * them with proper symbolic definitions, but that
    1107             :                  * requires some datasheets that I don't have access
    1108             :                  * to at the moment.
    1109             :                  */
    1110           0 :                 if (sc->sis_rev == SIS_REV_630S ||
    1111           0 :                     sc->sis_rev == SIS_REV_630E)
    1112           0 :                         sis_read_cmos(sc, pa, (caddr_t)&sc->arpcom.ac_enaddr,
    1113             :                             0x9, 6);
    1114             :                 else
    1115             : #endif
    1116           0 :                 if (sc->sis_rev == SIS_REV_96x)
    1117           0 :                         sis_read96x_mac(sc);
    1118           0 :                 else if (sc->sis_rev == SIS_REV_635 ||
    1119           0 :                     sc->sis_rev == SIS_REV_630ET ||
    1120           0 :                     sc->sis_rev == SIS_REV_630EA1)
    1121           0 :                         sis_read_mac(sc, pa);
    1122             :                 else
    1123           0 :                         sis_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr,
    1124             :                             SIS_EE_NODEADDR, 3, 1);
    1125             :                 break;
    1126             :         }
    1127             : 
    1128           0 :         printf(": %s, address %s\n", intrstr,
    1129           0 :             ether_sprintf(sc->arpcom.ac_enaddr));
    1130             : 
    1131           0 :         sc->sc_dmat = pa->pa_dmat;
    1132             : 
    1133           0 :         if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sis_list_data),
    1134             :             PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
    1135           0 :             BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) {
    1136           0 :                 printf(": can't alloc list mem\n");
    1137           0 :                 goto fail_2;
    1138             :         }
    1139           0 :         if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
    1140             :             sizeof(struct sis_list_data), &sc->sc_listkva,
    1141           0 :             BUS_DMA_NOWAIT) != 0) {
    1142           0 :                 printf(": can't map list mem\n");
    1143           0 :                 goto fail_2;
    1144             :         }
    1145           0 :         if (bus_dmamap_create(sc->sc_dmat, sizeof(struct sis_list_data), 1,
    1146             :             sizeof(struct sis_list_data), 0, BUS_DMA_NOWAIT,
    1147           0 :             &sc->sc_listmap) != 0) {
    1148           0 :                 printf(": can't alloc list map\n");
    1149           0 :                 goto fail_2;
    1150             :         }
    1151           0 :         if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
    1152           0 :             sizeof(struct sis_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
    1153           0 :                 printf(": can't load list map\n");
    1154           0 :                 goto fail_2;
    1155             :         }
    1156           0 :         sc->sis_ldata = (struct sis_list_data *)sc->sc_listkva;
    1157             : 
    1158           0 :         for (i = 0; i < SIS_RX_LIST_CNT; i++) {
    1159           0 :                 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
    1160           0 :                     BUS_DMA_NOWAIT, &sc->sis_ldata->sis_rx_list[i].map) != 0) {
    1161           0 :                         printf(": can't create rx map\n");
    1162           0 :                         goto fail_2;
    1163             :                 }
    1164             :         }
    1165             : 
    1166           0 :         for (i = 0; i < SIS_TX_LIST_CNT; i++) {
    1167           0 :                 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    1168             :                     SIS_MAXTXSEGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
    1169           0 :                     &sc->sis_ldata->sis_tx_list[i].map) != 0) {
    1170           0 :                         printf(": can't create tx map\n");
    1171           0 :                         goto fail_2;
    1172             :                 }
    1173             :         }
    1174           0 :         if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, SIS_MAXTXSEGS,
    1175           0 :             MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
    1176           0 :                 printf(": can't create tx spare map\n");
    1177           0 :                 goto fail_2;
    1178             :         }
    1179             : 
    1180           0 :         timeout_set(&sc->sis_timeout, sis_tick, sc);
    1181             : 
    1182           0 :         ifp = &sc->arpcom.ac_if;
    1183           0 :         ifp->if_softc = sc;
    1184           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    1185           0 :         ifp->if_ioctl = sis_ioctl;
    1186           0 :         ifp->if_start = sis_start;
    1187           0 :         ifp->if_watchdog = sis_watchdog;
    1188           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, SIS_TX_LIST_CNT - 1);
    1189           0 :         bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
    1190           0 :         ifp->if_hardmtu = 1518; /* determined experimentally on DP83815 */
    1191             : 
    1192           0 :         ifp->if_capabilities = IFCAP_VLAN_MTU;
    1193             : 
    1194           0 :         sc->sc_mii.mii_ifp = ifp;
    1195           0 :         sc->sc_mii.mii_readreg = sis_miibus_readreg;
    1196           0 :         sc->sc_mii.mii_writereg = sis_miibus_writereg;
    1197           0 :         sc->sc_mii.mii_statchg = sis_miibus_statchg;
    1198           0 :         ifmedia_init(&sc->sc_mii.mii_media, 0, sis_ifmedia_upd,sis_ifmedia_sts);
    1199           0 :         mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
    1200             :             0);
    1201           0 :         if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
    1202           0 :                 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
    1203           0 :                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
    1204           0 :         } else
    1205           0 :                 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
    1206             : 
    1207             :         /*
    1208             :          * Call MI attach routines.
    1209             :          */
    1210           0 :         if_attach(ifp);
    1211           0 :         ether_ifattach(ifp);
    1212           0 :         return;
    1213             : 
    1214             : fail_2:
    1215           0 :         pci_intr_disestablish(pc, sc->sc_ih);
    1216             : 
    1217             : fail_1:
    1218           0 :         bus_space_unmap(sc->sis_btag, sc->sis_bhandle, size);
    1219           0 : }
    1220             : 
    1221             : int
    1222           0 : sis_activate(struct device *self, int act)
    1223             : {
    1224           0 :         struct sis_softc *sc = (struct sis_softc *)self;
    1225           0 :         struct ifnet *ifp = &sc->arpcom.ac_if;
    1226             :         int rv = 0;
    1227             : 
    1228           0 :         switch (act) {
    1229             :         case DVACT_SUSPEND:
    1230           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1231           0 :                         sis_stop(sc);
    1232           0 :                 rv = config_activate_children(self, act);
    1233           0 :                 break;
    1234             :         case DVACT_RESUME:
    1235           0 :                 if (ifp->if_flags & IFF_UP)
    1236           0 :                         sis_init(sc);
    1237             :                 break;
    1238             :         default:
    1239           0 :                 rv = config_activate_children(self, act);
    1240           0 :                 break;
    1241             :         }
    1242           0 :         return (rv);
    1243             : }
    1244             : 
    1245             : /*
    1246             :  * Initialize the TX and RX descriptors and allocate mbufs for them. Note that
    1247             :  * we arrange the descriptors in a closed ring, so that the last descriptor
    1248             :  * points back to the first.
    1249             :  */
    1250             : int
    1251           0 : sis_ring_init(struct sis_softc *sc)
    1252             : {
    1253             :         struct sis_list_data    *ld;
    1254             :         struct sis_ring_data    *cd;
    1255             :         int                     i, nexti;
    1256             : 
    1257           0 :         cd = &sc->sis_cdata;
    1258           0 :         ld = sc->sis_ldata;
    1259             : 
    1260           0 :         for (i = 0; i < SIS_TX_LIST_CNT; i++) {
    1261           0 :                 if (i == (SIS_TX_LIST_CNT - 1))
    1262           0 :                         nexti = 0;
    1263             :                 else
    1264           0 :                         nexti = i + 1;
    1265           0 :                 ld->sis_tx_list[i].sis_nextdesc = &ld->sis_tx_list[nexti];
    1266           0 :                 ld->sis_tx_list[i].sis_next =
    1267           0 :                     htole32(sc->sc_listmap->dm_segs[0].ds_addr +
    1268             :                       offsetof(struct sis_list_data, sis_tx_list[nexti]));
    1269           0 :                 ld->sis_tx_list[i].sis_mbuf = NULL;
    1270           0 :                 ld->sis_tx_list[i].sis_ptr = 0;
    1271           0 :                 ld->sis_tx_list[i].sis_ctl = 0;
    1272             :         }
    1273             : 
    1274           0 :         cd->sis_tx_prod = cd->sis_tx_cons = cd->sis_tx_cnt = 0;
    1275             : 
    1276           0 :         for (i = 0; i < SIS_RX_LIST_CNT; i++) {
    1277           0 :                 if (i == SIS_RX_LIST_CNT - 1)
    1278           0 :                         nexti = 0;
    1279             :                 else
    1280           0 :                         nexti = i + 1;
    1281           0 :                 ld->sis_rx_list[i].sis_nextdesc = &ld->sis_rx_list[nexti];
    1282           0 :                 ld->sis_rx_list[i].sis_next =
    1283           0 :                     htole32(sc->sc_listmap->dm_segs[0].ds_addr +
    1284             :                       offsetof(struct sis_list_data, sis_rx_list[nexti]));
    1285           0 :                 ld->sis_rx_list[i].sis_ctl = 0;
    1286             :         }
    1287             : 
    1288           0 :         cd->sis_rx_prod = cd->sis_rx_cons;
    1289           0 :         if_rxr_init(&cd->sis_rx_ring, 2, SIS_RX_LIST_CNT - 1);
    1290           0 :         sis_fill_rx_ring(sc);
    1291             : 
    1292           0 :         return (0);
    1293             : }
    1294             : 
    1295             : void
    1296           0 : sis_fill_rx_ring(struct sis_softc *sc)
    1297             : {
    1298             :         struct sis_list_data    *ld;
    1299             :         struct sis_ring_data    *cd;
    1300             :         u_int                   slots;
    1301             : 
    1302           0 :         cd = &sc->sis_cdata;
    1303           0 :         ld = sc->sis_ldata;
    1304             : 
    1305           0 :         for (slots = if_rxr_get(&cd->sis_rx_ring, SIS_RX_LIST_CNT);
    1306           0 :             slots > 0; slots--) {
    1307           0 :                 if (sis_newbuf(sc, &ld->sis_rx_list[cd->sis_rx_prod]))
    1308             :                         break;
    1309             : 
    1310           0 :                 SIS_INC(cd->sis_rx_prod, SIS_RX_LIST_CNT);
    1311             :         }
    1312           0 :         if_rxr_put(&cd->sis_rx_ring, slots);
    1313           0 : }
    1314             : 
    1315             : /*
    1316             :  * Initialize an RX descriptor and attach an MBUF cluster.
    1317             :  */
    1318             : int
    1319           0 : sis_newbuf(struct sis_softc *sc, struct sis_desc *c)
    1320             : {
    1321             :         struct mbuf             *m_new = NULL;
    1322             : 
    1323           0 :         if (c == NULL)
    1324           0 :                 return (EINVAL);
    1325             : 
    1326           0 :         m_new = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
    1327           0 :         if (!m_new)
    1328           0 :                 return (ENOBUFS);
    1329             : 
    1330           0 :         m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    1331             : 
    1332           0 :         if (bus_dmamap_load_mbuf(sc->sc_dmat, c->map, m_new,
    1333             :             BUS_DMA_NOWAIT)) {
    1334           0 :                 m_free(m_new);
    1335           0 :                 return (ENOBUFS);
    1336             :         }
    1337             : 
    1338           0 :         bus_dmamap_sync(sc->sc_dmat, c->map, 0, c->map->dm_mapsize,
    1339             :             BUS_DMASYNC_PREREAD);
    1340             : 
    1341           0 :         c->sis_mbuf = m_new;
    1342           0 :         c->sis_ptr = htole32(c->map->dm_segs[0].ds_addr);
    1343             : 
    1344           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
    1345             :             ((caddr_t)c - sc->sc_listkva), sizeof(struct sis_desc),
    1346             :             BUS_DMASYNC_PREWRITE);
    1347             : 
    1348           0 :         c->sis_ctl = htole32(ETHER_MAX_DIX_LEN);
    1349             : 
    1350           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
    1351             :             ((caddr_t)c - sc->sc_listkva), sizeof(struct sis_desc),
    1352             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1353             : 
    1354           0 :         return (0);
    1355           0 : }
    1356             : 
    1357             : /*
    1358             :  * A frame has been uploaded: pass the resulting mbuf chain up to
    1359             :  * the higher level protocols.
    1360             :  */
    1361             : void
    1362           0 : sis_rxeof(struct sis_softc *sc)
    1363             : {
    1364           0 :         struct mbuf_list        ml = MBUF_LIST_INITIALIZER();
    1365             :         struct mbuf             *m;
    1366             :         struct ifnet            *ifp;
    1367             :         struct sis_desc         *cur_rx;
    1368             :         int                     total_len = 0;
    1369             :         u_int32_t               rxstat;
    1370             : 
    1371           0 :         ifp = &sc->arpcom.ac_if;
    1372             : 
    1373           0 :         while (if_rxr_inuse(&sc->sis_cdata.sis_rx_ring) > 0) {
    1374           0 :                 cur_rx = &sc->sis_ldata->sis_rx_list[sc->sis_cdata.sis_rx_cons];
    1375           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
    1376             :                     ((caddr_t)cur_rx - sc->sc_listkva),
    1377             :                     sizeof(struct sis_desc),
    1378             :                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    1379           0 :                 if (!SIS_OWNDESC(cur_rx))
    1380             :                         break;
    1381             : 
    1382             :                 rxstat = letoh32(cur_rx->sis_rxstat);
    1383           0 :                 m = cur_rx->sis_mbuf;
    1384           0 :                 cur_rx->sis_mbuf = NULL;
    1385           0 :                 total_len = SIS_RXBYTES(cur_rx);
    1386             :                 /* from here on the buffer is consumed */
    1387           0 :                 SIS_INC(sc->sis_cdata.sis_rx_cons, SIS_RX_LIST_CNT);
    1388           0 :                 if_rxr_put(&sc->sis_cdata.sis_rx_ring, 1);
    1389             : 
    1390             :                 /*
    1391             :                  * DP83816A sometimes produces zero-length packets
    1392             :                  * shortly after initialisation.
    1393             :                  */
    1394           0 :                 if (total_len == 0) {
    1395           0 :                         m_freem(m);
    1396           0 :                         continue;
    1397             :                 }
    1398             : 
    1399             :                 /* The ethernet CRC is always included */
    1400           0 :                 total_len -= ETHER_CRC_LEN;
    1401             : 
    1402             :                 /*
    1403             :                  * If an error occurs, update stats, clear the
    1404             :                  * status word and leave the mbuf cluster in place:
    1405             :                  * it should simply get re-used next time this descriptor
    1406             :                  * comes up in the ring. However, don't report long
    1407             :                  * frames as errors since they could be VLANs.
    1408             :                  */
    1409           0 :                 if (rxstat & SIS_RXSTAT_GIANT &&
    1410           0 :                     total_len <= (ETHER_MAX_DIX_LEN - ETHER_CRC_LEN))
    1411           0 :                         rxstat &= ~SIS_RXSTAT_GIANT;
    1412           0 :                 if (SIS_RXSTAT_ERROR(rxstat)) {
    1413           0 :                         ifp->if_ierrors++;
    1414           0 :                         if (rxstat & SIS_RXSTAT_COLL)
    1415           0 :                                 ifp->if_collisions++;
    1416           0 :                         m_freem(m);
    1417           0 :                         continue;
    1418             :                 }
    1419             : 
    1420             :                 /* No errors; receive the packet. */
    1421           0 :                 bus_dmamap_sync(sc->sc_dmat, cur_rx->map, 0,
    1422             :                     cur_rx->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
    1423             : #ifdef __STRICT_ALIGNMENT
    1424             :                 /*
    1425             :                  * On some architectures, we do not have alignment problems,
    1426             :                  * so try to allocate a new buffer for the receive ring, and
    1427             :                  * pass up the one where the packet is already, saving the
    1428             :                  * expensive copy done in m_devget().
    1429             :                  * If we are on an architecture with alignment problems, or
    1430             :                  * if the allocation fails, then use m_devget and leave the
    1431             :                  * existing buffer in the receive ring.
    1432             :                  */
    1433             :                 {
    1434             :                         struct mbuf *m0;
    1435             :                         m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN);
    1436             :                         m_freem(m);
    1437             :                         if (m0 == NULL) {
    1438             :                                 ifp->if_ierrors++;
    1439             :                                 continue;
    1440             :                         }
    1441             :                         m = m0;
    1442             :                 }
    1443             : #else
    1444           0 :                 m->m_pkthdr.len = m->m_len = total_len;
    1445             : #endif
    1446             : 
    1447           0 :                 ml_enqueue(&ml, m);
    1448             :         }
    1449             : 
    1450           0 :         if_input(ifp, &ml);
    1451             : 
    1452           0 :         sis_fill_rx_ring(sc);
    1453           0 : }
    1454             : 
    1455             : /*
    1456             :  * A frame was downloaded to the chip. It's safe for us to clean up
    1457             :  * the list buffers.
    1458             :  */
    1459             : 
    1460             : void
    1461           0 : sis_txeof(struct sis_softc *sc)
    1462             : {
    1463             :         struct ifnet            *ifp;
    1464             :         u_int32_t               idx, ctl, txstat;
    1465             : 
    1466           0 :         ifp = &sc->arpcom.ac_if;
    1467             : 
    1468             :         /*
    1469             :          * Go through our tx list and free mbufs for those
    1470             :          * frames that have been transmitted.
    1471             :          */
    1472           0 :         for (idx = sc->sis_cdata.sis_tx_cons; sc->sis_cdata.sis_tx_cnt > 0;
    1473           0 :             sc->sis_cdata.sis_tx_cnt--, SIS_INC(idx, SIS_TX_LIST_CNT)) {
    1474           0 :                 struct sis_desc *cur_tx = &sc->sis_ldata->sis_tx_list[idx];
    1475             : 
    1476           0 :                 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
    1477             :                     ((caddr_t)cur_tx - sc->sc_listkva),
    1478             :                     sizeof(struct sis_desc),
    1479             :                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    1480             : 
    1481           0 :                 if (SIS_OWNDESC(cur_tx))
    1482           0 :                         break;
    1483             : 
    1484             :                 ctl = letoh32(cur_tx->sis_ctl);
    1485             : 
    1486           0 :                 if (ctl & SIS_CMDSTS_MORE)
    1487           0 :                         continue;
    1488             : 
    1489             :                 txstat = letoh32(cur_tx->sis_txstat);
    1490             : 
    1491           0 :                 if (!(ctl & SIS_CMDSTS_PKT_OK)) {
    1492           0 :                         ifp->if_oerrors++;
    1493           0 :                         if (txstat & SIS_TXSTAT_EXCESSCOLLS)
    1494           0 :                                 ifp->if_collisions++;
    1495           0 :                         if (txstat & SIS_TXSTAT_OUTOFWINCOLL)
    1496           0 :                                 ifp->if_collisions++;
    1497             :                 }
    1498             : 
    1499           0 :                 ifp->if_collisions += (txstat & SIS_TXSTAT_COLLCNT) >> 16;
    1500             : 
    1501           0 :                 if (cur_tx->map->dm_nsegs != 0) {
    1502             :                         bus_dmamap_t map = cur_tx->map;
    1503             : 
    1504           0 :                         bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    1505             :                             BUS_DMASYNC_POSTWRITE);
    1506           0 :                         bus_dmamap_unload(sc->sc_dmat, map);
    1507           0 :                 }
    1508           0 :                 if (cur_tx->sis_mbuf != NULL) {
    1509           0 :                         m_freem(cur_tx->sis_mbuf);
    1510           0 :                         cur_tx->sis_mbuf = NULL;
    1511           0 :                 }
    1512           0 :         }
    1513             : 
    1514           0 :         if (idx != sc->sis_cdata.sis_tx_cons) {
    1515             :                 /* we freed up some buffers */
    1516           0 :                 sc->sis_cdata.sis_tx_cons = idx;
    1517           0 :                 ifq_clr_oactive(&ifp->if_snd);
    1518           0 :         }
    1519             : 
    1520           0 :         ifp->if_timer = (sc->sis_cdata.sis_tx_cnt == 0) ? 0 : 5;
    1521           0 : }
    1522             : 
    1523             : void
    1524           0 : sis_tick(void *xsc)
    1525             : {
    1526           0 :         struct sis_softc        *sc = (struct sis_softc *)xsc;
    1527             :         struct mii_data         *mii;
    1528             :         int                     s;
    1529             : 
    1530           0 :         s = splnet();
    1531             : 
    1532           0 :         mii = &sc->sc_mii;
    1533           0 :         mii_tick(mii);
    1534             : 
    1535           0 :         if (!sc->sis_link)
    1536           0 :                 sis_miibus_statchg(&sc->sc_dev);
    1537             :         
    1538           0 :         timeout_add_sec(&sc->sis_timeout, 1);
    1539             : 
    1540           0 :         splx(s);
    1541           0 : }
    1542             : 
    1543             : int
    1544           0 : sis_intr(void *arg)
    1545             : {
    1546           0 :         struct sis_softc        *sc = arg;
    1547           0 :         struct ifnet            *ifp = &sc->arpcom.ac_if;
    1548             :         u_int32_t               status;
    1549             : 
    1550           0 :         if (sc->sis_stopped) /* Most likely shared interrupt */
    1551           0 :                 return (0);
    1552             : 
    1553             :         /* Reading the ISR register clears all interrupts. */
    1554           0 :         status = CSR_READ_4(sc, SIS_ISR);
    1555           0 :         if ((status & SIS_INTRS) == 0)
    1556           0 :                 return (0);
    1557             : 
    1558           0 :         if (status &
    1559             :             (SIS_ISR_TX_DESC_OK | SIS_ISR_TX_ERR |
    1560             :              SIS_ISR_TX_OK | SIS_ISR_TX_IDLE))
    1561           0 :                 sis_txeof(sc);
    1562             : 
    1563           0 :         if (status &
    1564             :             (SIS_ISR_RX_DESC_OK | SIS_ISR_RX_OK |
    1565             :              SIS_ISR_RX_ERR | SIS_ISR_RX_IDLE))
    1566           0 :                 sis_rxeof(sc);
    1567             : 
    1568           0 :         if (status & (SIS_ISR_RX_IDLE)) {
    1569             :                 /* consume what's there so that sis_rx_cons points
    1570             :                  * to the first HW owned descriptor. */
    1571           0 :                 sis_rxeof(sc);
    1572             :                 /* reprogram the RX listptr */
    1573           0 :                 CSR_WRITE_4(sc, SIS_RX_LISTPTR,
    1574             :                     sc->sc_listmap->dm_segs[0].ds_addr +
    1575             :                     offsetof(struct sis_list_data,
    1576             :                     sis_rx_list[sc->sis_cdata.sis_rx_cons]));
    1577           0 :         }
    1578             : 
    1579           0 :         if (status & SIS_ISR_SYSERR)
    1580           0 :                 sis_init(sc);
    1581             : 
    1582             :         /*
    1583             :          * XXX: Re-enable RX engine every time otherwise it occasionally
    1584             :          * stops under unknown circumstances.
    1585             :          */
    1586           0 :         SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_ENABLE);
    1587             : 
    1588           0 :         if (!IFQ_IS_EMPTY(&ifp->if_snd))
    1589           0 :                 sis_start(ifp);
    1590             : 
    1591           0 :         return (1);
    1592           0 : }
    1593             : 
    1594             : /*
    1595             :  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
    1596             :  * pointers to the fragment pointers.
    1597             :  */
    1598             : int
    1599           0 : sis_encap(struct sis_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
    1600             : {
    1601             :         struct sis_desc         *f = NULL;
    1602             :         bus_dmamap_t            map;
    1603             :         int                     frag, cur, i, error;
    1604             : 
    1605           0 :         map = sc->sc_tx_sparemap;
    1606             : 
    1607           0 :         error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m_head,
    1608             :             BUS_DMA_NOWAIT);
    1609           0 :         switch (error) {
    1610             :         case 0:
    1611             :                 break;
    1612             : 
    1613             :         case EFBIG:
    1614           0 :                 if (m_defrag(m_head, M_DONTWAIT) == 0 &&
    1615           0 :                     bus_dmamap_load_mbuf(sc->sc_dmat, map, m_head,
    1616           0 :                     BUS_DMA_NOWAIT) == 0)
    1617             :                         break;
    1618             : 
    1619             :                 /* FALLTHROUGH */
    1620             :         default:
    1621           0 :                 return (ENOBUFS);
    1622             :         }
    1623             : 
    1624           0 :         if ((SIS_TX_LIST_CNT - (sc->sis_cdata.sis_tx_cnt + map->dm_nsegs)) < 2) {
    1625           0 :                 bus_dmamap_unload(sc->sc_dmat, map);
    1626           0 :                 return (ENOBUFS);
    1627             :         }
    1628             : 
    1629             :         /*
    1630             :          * Start packing the mbufs in this chain into
    1631             :          * the fragment pointers. Stop when we run out
    1632             :          * of fragments or hit the end of the mbuf chain.
    1633             :          */
    1634           0 :         cur = frag = *txidx;
    1635             : 
    1636           0 :         for (i = 0; i < map->dm_nsegs; i++) {
    1637           0 :                 f = &sc->sis_ldata->sis_tx_list[frag];
    1638           0 :                 f->sis_ctl = htole32(SIS_CMDSTS_MORE | map->dm_segs[i].ds_len);
    1639           0 :                 f->sis_ptr = htole32(map->dm_segs[i].ds_addr);
    1640           0 :                 if (i != 0)
    1641           0 :                         f->sis_ctl |= htole32(SIS_CMDSTS_OWN);
    1642             :                 cur = frag;
    1643           0 :                 SIS_INC(frag, SIS_TX_LIST_CNT);
    1644             :         }
    1645             : 
    1646           0 :         bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    1647             :             BUS_DMASYNC_PREWRITE);
    1648             : 
    1649           0 :         sc->sis_ldata->sis_tx_list[cur].sis_mbuf = m_head;
    1650           0 :         sc->sis_ldata->sis_tx_list[cur].sis_ctl &= ~htole32(SIS_CMDSTS_MORE);
    1651           0 :         sc->sis_ldata->sis_tx_list[*txidx].sis_ctl |= htole32(SIS_CMDSTS_OWN);
    1652           0 :         sc->sis_cdata.sis_tx_cnt += map->dm_nsegs;
    1653           0 :         *txidx = frag;
    1654             : 
    1655           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
    1656             :             offsetof(struct sis_list_data, sis_tx_list[0]),
    1657             :             sizeof(struct sis_desc) * SIS_TX_LIST_CNT,  
    1658             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1659             : 
    1660           0 :         return (0);
    1661           0 : }
    1662             : 
    1663             : /*
    1664             :  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
    1665             :  * to the mbuf data regions directly in the transmit lists. We also save a
    1666             :  * copy of the pointers since the transmit list fragment pointers are
    1667             :  * physical addresses.
    1668             :  */
    1669             : 
    1670             : void
    1671           0 : sis_start(struct ifnet *ifp)
    1672             : {
    1673             :         struct sis_softc        *sc;
    1674             :         struct mbuf             *m_head = NULL;
    1675           0 :         u_int32_t               idx, queued = 0;
    1676             : 
    1677           0 :         sc = ifp->if_softc;
    1678             : 
    1679           0 :         if (!sc->sis_link)
    1680           0 :                 return;
    1681             : 
    1682           0 :         idx = sc->sis_cdata.sis_tx_prod;
    1683             : 
    1684           0 :         if (ifq_is_oactive(&ifp->if_snd))
    1685           0 :                 return;
    1686             : 
    1687           0 :         while(sc->sis_ldata->sis_tx_list[idx].sis_mbuf == NULL) {
    1688           0 :                 m_head = ifq_deq_begin(&ifp->if_snd);
    1689           0 :                 if (m_head == NULL)
    1690             :                         break;
    1691             : 
    1692           0 :                 if (sis_encap(sc, m_head, &idx)) {
    1693           0 :                         ifq_deq_rollback(&ifp->if_snd, m_head);
    1694           0 :                         ifq_set_oactive(&ifp->if_snd);
    1695           0 :                         break;
    1696             :                 }
    1697             : 
    1698             :                 /* now we are committed to transmit the packet */
    1699           0 :                 ifq_deq_commit(&ifp->if_snd, m_head);
    1700             : 
    1701           0 :                 queued++;
    1702             : 
    1703             :                 /*
    1704             :                  * If there's a BPF listener, bounce a copy of this frame
    1705             :                  * to him.
    1706             :                  */
    1707             : #if NBPFILTER > 0
    1708           0 :                 if (ifp->if_bpf)
    1709           0 :                         bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
    1710             : #endif
    1711             :         }
    1712             : 
    1713           0 :         if (queued) {
    1714             :                 /* Transmit */
    1715           0 :                 sc->sis_cdata.sis_tx_prod = idx;
    1716           0 :                 SIS_SETBIT(sc, SIS_CSR, SIS_CSR_TX_ENABLE);
    1717             : 
    1718             :                 /*
    1719             :                  * Set a timeout in case the chip goes out to lunch.
    1720             :                  */
    1721           0 :                 ifp->if_timer = 5;
    1722           0 :         }
    1723           0 : }
    1724             : 
    1725             : void
    1726           0 : sis_init(void *xsc)
    1727             : {
    1728           0 :         struct sis_softc        *sc = (struct sis_softc *)xsc;
    1729           0 :         struct ifnet            *ifp = &sc->arpcom.ac_if;
    1730             :         struct mii_data         *mii;
    1731             :         int                     s;
    1732             : 
    1733           0 :         s = splnet();
    1734             : 
    1735             :         /*
    1736             :          * Cancel pending I/O and free all RX/TX buffers.
    1737             :          */
    1738           0 :         sis_stop(sc);
    1739             : 
    1740             :         /*
    1741             :          * Reset the chip to a known state.
    1742             :          */
    1743           0 :         sis_reset(sc);
    1744             : 
    1745             : #if NS_IHR_DELAY > 0
    1746             :         /* Configure interrupt holdoff register. */
    1747           0 :         if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr == NS_SRR_16A)
    1748           0 :                 CSR_WRITE_4(sc, NS_IHR, NS_IHR_VALUE);
    1749             : #endif
    1750             : 
    1751           0 :         mii = &sc->sc_mii;
    1752             : 
    1753             :         /* Set MAC address */
    1754           0 :         if (sc->sis_type == SIS_TYPE_83815) {
    1755             :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR0);
    1756             :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1757             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[0]));
    1758           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR1);
    1759           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1760             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[1]));
    1761           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR2);
    1762           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1763             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[2]));
    1764           0 :         } else {
    1765             :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
    1766             :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1767             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[0]));
    1768           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR1);
    1769           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1770             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[1]));
    1771           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
    1772           0 :                 CSR_WRITE_4(sc, SIS_RXFILT_DATA,
    1773             :                     htole16(((u_int16_t *)sc->arpcom.ac_enaddr)[2]));
    1774             :         }
    1775             : 
    1776             :         /* Init circular TX/RX lists. */
    1777           0 :         if (sis_ring_init(sc) != 0) {
    1778           0 :                 printf("%s: initialization failed: no memory for rx buffers\n",
    1779           0 :                     sc->sc_dev.dv_xname);
    1780           0 :                 sis_stop(sc);
    1781           0 :                 splx(s);
    1782           0 :                 return;
    1783             :         }
    1784             : 
    1785             :         /*
    1786             :          * Page 78 of the DP83815 data sheet (september 2002 version)
    1787             :          * recommends the following register settings "for optimum
    1788             :          * performance." for rev 15C.  The driver from NS also sets
    1789             :          * the PHY_CR register for later versions.
    1790             :          *
    1791             :          * This resolves an issue with tons of errors in AcceptPerfectMatch
    1792             :          * (non-IFF_PROMISC) mode.
    1793             :          */
    1794           0 :          if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr <= NS_SRR_15D) {
    1795           0 :                 CSR_WRITE_4(sc, NS_PHY_PAGE, 0x0001);
    1796           0 :                 CSR_WRITE_4(sc, NS_PHY_CR, 0x189C);
    1797             :                 /* set val for c2 */
    1798           0 :                 CSR_WRITE_4(sc, NS_PHY_TDATA, 0x0000);
    1799             :                 /* load/kill c2 */
    1800           0 :                 CSR_WRITE_4(sc, NS_PHY_DSPCFG, 0x5040);
    1801             :                 /* raise SD off, from 4 to c */
    1802           0 :                 CSR_WRITE_4(sc, NS_PHY_SDCFG, 0x008C);
    1803           0 :                 CSR_WRITE_4(sc, NS_PHY_PAGE, 0);
    1804           0 :         }
    1805             : 
    1806             :         /*
    1807             :          * Program promiscuous mode and multicast filters.
    1808             :          */
    1809           0 :         sis_iff(sc);
    1810             : 
    1811             :         /*
    1812             :          * Load the address of the RX and TX lists.
    1813             :          */
    1814           0 :         CSR_WRITE_4(sc, SIS_RX_LISTPTR, sc->sc_listmap->dm_segs[0].ds_addr +
    1815             :             offsetof(struct sis_list_data, sis_rx_list[0]));
    1816           0 :         CSR_WRITE_4(sc, SIS_TX_LISTPTR, sc->sc_listmap->dm_segs[0].ds_addr +
    1817             :             offsetof(struct sis_list_data, sis_tx_list[0]));
    1818             : 
    1819             :         /* SIS_CFG_EDB_MASTER_EN indicates the EDB bus is used instead of
    1820             :          * the PCI bus. When this bit is set, the Max DMA Burst Size
    1821             :          * for TX/RX DMA should be no larger than 16 double words.
    1822             :          */
    1823           0 :         if (CSR_READ_4(sc, SIS_CFG) & SIS_CFG_EDB_MASTER_EN)
    1824           0 :                 CSR_WRITE_4(sc, SIS_RX_CFG, SIS_RXCFG64);
    1825             :         else
    1826           0 :                 CSR_WRITE_4(sc, SIS_RX_CFG, SIS_RXCFG256);
    1827             : 
    1828             :         /* Accept Long Packets for VLAN support */
    1829           0 :         SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_JABBER);
    1830             : 
    1831             :         /*
    1832             :          * Assume 100Mbps link, actual MAC configuration is done
    1833             :          * after getting a valid link.
    1834             :          */
    1835           0 :         CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100);
    1836             : 
    1837             :         /*
    1838             :          * Enable interrupts.
    1839             :          */
    1840           0 :         CSR_WRITE_4(sc, SIS_IMR, SIS_INTRS);
    1841           0 :         CSR_WRITE_4(sc, SIS_IER, 1);
    1842             : 
    1843             :         /* Clear MAC disable. */
    1844           0 :         SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE | SIS_CSR_RX_DISABLE);
    1845             : 
    1846           0 :         sc->sis_link = 0;
    1847           0 :         mii_mediachg(mii);
    1848             : 
    1849           0 :         sc->sis_stopped = 0;
    1850           0 :         ifp->if_flags |= IFF_RUNNING;
    1851           0 :         ifq_clr_oactive(&ifp->if_snd);
    1852             : 
    1853           0 :         splx(s);
    1854             : 
    1855           0 :         timeout_add_sec(&sc->sis_timeout, 1);
    1856           0 : }
    1857             : 
    1858             : /*
    1859             :  * Set media options.
    1860             :  */
    1861             : int
    1862           0 : sis_ifmedia_upd(struct ifnet *ifp)
    1863             : {
    1864             :         struct sis_softc        *sc;
    1865             :         struct mii_data         *mii;
    1866             : 
    1867           0 :         sc = ifp->if_softc;
    1868             : 
    1869           0 :         mii = &sc->sc_mii;
    1870           0 :         if (mii->mii_instance) {
    1871             :                 struct mii_softc        *miisc;
    1872           0 :                 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
    1873           0 :                         mii_phy_reset(miisc);
    1874           0 :         }
    1875           0 :         mii_mediachg(mii);
    1876             : 
    1877           0 :         return (0);
    1878             : }
    1879             : 
    1880             : /*
    1881             :  * Report current media status.
    1882             :  */
    1883             : void
    1884           0 : sis_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
    1885             : {
    1886             :         struct sis_softc        *sc;
    1887             :         struct mii_data         *mii;
    1888             : 
    1889           0 :         sc = ifp->if_softc;
    1890             : 
    1891           0 :         mii = &sc->sc_mii;
    1892           0 :         mii_pollstat(mii);
    1893           0 :         ifmr->ifm_active = mii->mii_media_active;
    1894           0 :         ifmr->ifm_status = mii->mii_media_status;
    1895           0 : }
    1896             : 
    1897             : int
    1898           0 : sis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
    1899             : {
    1900           0 :         struct sis_softc        *sc = ifp->if_softc;
    1901           0 :         struct ifreq            *ifr = (struct ifreq *) data;
    1902             :         struct mii_data         *mii;
    1903             :         int                     s, error = 0;
    1904             : 
    1905           0 :         s = splnet();
    1906             : 
    1907           0 :         switch(command) {
    1908             :         case SIOCSIFADDR:
    1909           0 :                 ifp->if_flags |= IFF_UP;
    1910           0 :                 if (!(ifp->if_flags & IFF_RUNNING))
    1911           0 :                         sis_init(sc);
    1912             :                 break;
    1913             : 
    1914             :         case SIOCSIFFLAGS:
    1915           0 :                 if (ifp->if_flags & IFF_UP) {
    1916           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1917           0 :                                 error = ENETRESET;
    1918             :                         else
    1919           0 :                                 sis_init(sc);
    1920             :                 } else {
    1921           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1922           0 :                                 sis_stop(sc);
    1923             :                 }
    1924             :                 break;
    1925             : 
    1926             :         case SIOCGIFMEDIA:
    1927             :         case SIOCSIFMEDIA:
    1928           0 :                 mii = &sc->sc_mii;
    1929           0 :                 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
    1930           0 :                 break;
    1931             : 
    1932             :         case SIOCGIFRXR:
    1933           0 :                 error = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data,
    1934           0 :                     NULL, MCLBYTES, &sc->sis_cdata.sis_rx_ring);
    1935           0 :                 break;
    1936             : 
    1937             :         default:
    1938           0 :                 error = ether_ioctl(ifp, &sc->arpcom, command, data);
    1939           0 :         }
    1940             : 
    1941           0 :         if (error == ENETRESET) {
    1942           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1943           0 :                         sis_iff(sc);
    1944             :                 error = 0;
    1945           0 :         }
    1946             : 
    1947           0 :         splx(s);
    1948           0 :         return(error);
    1949             : }
    1950             : 
    1951             : void
    1952           0 : sis_watchdog(struct ifnet *ifp)
    1953             : {
    1954             :         struct sis_softc        *sc;
    1955             :         int                     s;
    1956             : 
    1957           0 :         sc = ifp->if_softc;
    1958             : 
    1959           0 :         if (sc->sis_stopped)
    1960           0 :                 return;
    1961             : 
    1962           0 :         ifp->if_oerrors++;
    1963           0 :         printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
    1964             : 
    1965           0 :         s = splnet();
    1966           0 :         sis_init(sc);
    1967             : 
    1968           0 :         if (!IFQ_IS_EMPTY(&ifp->if_snd))
    1969           0 :                 sis_start(ifp);
    1970             : 
    1971           0 :         splx(s);
    1972           0 : }
    1973             : 
    1974             : /*
    1975             :  * Stop the adapter and free any mbufs allocated to the
    1976             :  * RX and TX lists.
    1977             :  */
    1978             : void
    1979           0 : sis_stop(struct sis_softc *sc)
    1980             : {
    1981             :         int                     i;
    1982             :         struct ifnet            *ifp;
    1983             : 
    1984           0 :         if (sc->sis_stopped)
    1985           0 :                 return;
    1986             : 
    1987           0 :         ifp = &sc->arpcom.ac_if;
    1988           0 :         ifp->if_timer = 0;
    1989             : 
    1990           0 :         timeout_del(&sc->sis_timeout);
    1991             : 
    1992           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1993           0 :         ifq_clr_oactive(&ifp->if_snd);
    1994           0 :         sc->sis_stopped = 1;
    1995             : 
    1996           0 :         CSR_WRITE_4(sc, SIS_IER, 0);
    1997           0 :         CSR_WRITE_4(sc, SIS_IMR, 0);
    1998           0 :         CSR_READ_4(sc, SIS_ISR); /* clear any interrupts already pending */
    1999           0 :         SIS_SETBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE | SIS_CSR_RX_DISABLE);
    2000           0 :         DELAY(1000);
    2001           0 :         CSR_WRITE_4(sc, SIS_TX_LISTPTR, 0);
    2002           0 :         CSR_WRITE_4(sc, SIS_RX_LISTPTR, 0);
    2003             : 
    2004           0 :         sc->sis_link = 0;
    2005             : 
    2006             :         /*
    2007             :          * Free data in the RX lists.
    2008             :          */
    2009           0 :         for (i = 0; i < SIS_RX_LIST_CNT; i++) {
    2010           0 :                 if (sc->sis_ldata->sis_rx_list[i].map->dm_nsegs != 0) {
    2011             :                         bus_dmamap_t map = sc->sis_ldata->sis_rx_list[i].map;
    2012             : 
    2013           0 :                         bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    2014             :                             BUS_DMASYNC_POSTREAD);
    2015           0 :                         bus_dmamap_unload(sc->sc_dmat, map);
    2016           0 :                 }
    2017           0 :                 if (sc->sis_ldata->sis_rx_list[i].sis_mbuf != NULL) {
    2018           0 :                         m_freem(sc->sis_ldata->sis_rx_list[i].sis_mbuf);
    2019           0 :                         sc->sis_ldata->sis_rx_list[i].sis_mbuf = NULL;
    2020           0 :                 }
    2021           0 :                 bzero(&sc->sis_ldata->sis_rx_list[i],
    2022             :                     sizeof(struct sis_desc) - sizeof(bus_dmamap_t));
    2023             :         }
    2024             : 
    2025             :         /*
    2026             :          * Free the TX list buffers.
    2027             :          */
    2028           0 :         for (i = 0; i < SIS_TX_LIST_CNT; i++) {
    2029           0 :                 if (sc->sis_ldata->sis_tx_list[i].map->dm_nsegs != 0) {
    2030             :                         bus_dmamap_t map = sc->sis_ldata->sis_tx_list[i].map;
    2031             : 
    2032           0 :                         bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    2033             :                             BUS_DMASYNC_POSTWRITE);
    2034           0 :                         bus_dmamap_unload(sc->sc_dmat, map);
    2035           0 :                 }
    2036           0 :                 if (sc->sis_ldata->sis_tx_list[i].sis_mbuf != NULL) {
    2037           0 :                         m_freem(sc->sis_ldata->sis_tx_list[i].sis_mbuf);
    2038           0 :                         sc->sis_ldata->sis_tx_list[i].sis_mbuf = NULL;
    2039           0 :                 }
    2040           0 :                 bzero(&sc->sis_ldata->sis_tx_list[i],
    2041             :                     sizeof(struct sis_desc) - sizeof(bus_dmamap_t));
    2042             :         }
    2043           0 : }

Generated by: LCOV version 1.13