[BACK]Return to if_sis.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/if_sis.c, Revision 1.1

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

CVSweb