[BACK]Return to if_smap.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / playstation2 / dev

Annotation of src/sys/arch/playstation2/dev/if_smap.c, Revision 1.12.2.1

1.12.2.1! yamt        1: /*     $NetBSD: if_smap.c,v 1.12 2008/03/12 17:23:13 dyoung Exp $      */
1.1       uch         2:
                      3: /*-
                      4:  * Copyright (c) 2001 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by UCHIYAMA Yasushi.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.5       lukem      31:
                     32: #include <sys/cdefs.h>
1.12.2.1! yamt       33: __KERNEL_RCSID(0, "$NetBSD: if_smap.c,v 1.12 2008/03/12 17:23:13 dyoung Exp $");
1.1       uch        34:
                     35: #include "debug_playstation2.h"
                     36:
                     37: #include "bpfilter.h"
                     38: #include "rnd.h"
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42:
                     43: #include <sys/syslog.h>
                     44: #include <sys/mbuf.h>
                     45: #include <sys/ioctl.h>
                     46: #include <sys/socket.h>
                     47:
                     48: #include <playstation2/ee/eevar.h>
                     49:
                     50: #if NRND > 0
                     51: #include <sys/rnd.h>
                     52: #endif
                     53:
                     54: #include <net/if.h>
                     55: #include <net/if_dl.h>
                     56: #include <net/if_types.h>
                     57:
                     58: #include <net/if_ether.h>
                     59: #include <net/if_media.h>
                     60:
                     61: #include <dev/mii/mii.h>
                     62: #include <dev/mii/miivar.h>
                     63:
                     64: #include <netinet/in.h>
                     65: #include <netinet/in_systm.h>
                     66: #include <netinet/in_var.h>
                     67: #include <netinet/ip.h>
                     68: #include <netinet/if_inarp.h>
                     69:
                     70: #if NBPFILTER > 0
                     71: #include <net/bpf.h>
                     72: #include <net/bpfdesc.h>
                     73: #endif
                     74:
                     75: #include <playstation2/dev/spdvar.h>
                     76: #include <playstation2/dev/spdreg.h>
                     77: #include <playstation2/dev/emac3var.h>
                     78: #include <playstation2/dev/if_smapreg.h>
                     79:
                     80: #ifdef SMAP_DEBUG
                     81: #include <playstation2/ee/gsvar.h>
                     82: int    smap_debug = 0;
                     83: #define        DPRINTF(fmt, args...)                                           \
                     84:        if (smap_debug)                                                 \
1.10      perry      85:                printf("%s: " fmt, __func__ , ##args)
1.1       uch        86: #define        DPRINTFN(n, arg)                                                \
                     87:        if (smap_debug > (n))                                           \
1.10      perry      88:                printf("%s: " fmt, __func__ , ##args)
1.1       uch        89: #define STATIC
                     90: struct smap_softc *__sc;
                     91: void __smap_status(int);
                     92: void __smap_lock_check(const char *, int);
1.10      perry      93: #define FUNC_ENTER()   __smap_lock_check(__func__, 1)
                     94: #define FUNC_EXIT()    __smap_lock_check(__func__, 0)
1.1       uch        95: #else
                     96: #define        DPRINTF(arg...)         ((void)0)
                     97: #define DPRINTFN(n, arg...)    ((void)0)
                     98: #define STATIC                 static
                     99: #define FUNC_ENTER()           ((void)0)
                    100: #define FUNC_EXIT()            ((void)0)
                    101: #endif
                    102:
                    103: struct smap_softc {
                    104:        struct emac3_softc emac3;
                    105:        struct ethercom ethercom;
                    106:
                    107:        u_int32_t *tx_buf;
                    108:        u_int32_t *rx_buf;
                    109:        struct smap_desc *tx_desc;
                    110:        struct smap_desc *rx_desc;
                    111:
                    112: #define        SMAP_FIFO_ALIGN         4
                    113:        int tx_buf_freesize;    /* buffer usage */
                    114:        int tx_desc_cnt;        /* descriptor usage */
                    115:        u_int16_t tx_fifo_ptr;
                    116:        int tx_done_index, tx_start_index;
                    117:        int rx_done_index;
                    118:
                    119: #if NRND > 0
                    120:        rndsource_element_t rnd_source;
                    121: #endif
                    122: };
                    123:
                    124: #define DEVNAME                (sc->emac3.dev.dv_xname)
                    125: #define ROUND4(x)      (((x) + 3) & ~3)
                    126: #define ROUND16(x)     (((x) + 15) & ~15)
                    127:
                    128: STATIC int smap_match(struct device *, struct cfdata *, void *);
                    129: STATIC void smap_attach(struct device *, struct device *, void *);
                    130:
1.3       thorpej   131: CFATTACH_DECL(smap, sizeof (struct smap_softc),
                    132:     smap_match, smap_attach, NULL, NULL);
1.1       uch       133:
                    134: STATIC int smap_intr(void *);
                    135: STATIC void smap_rxeof(void *);
                    136: STATIC void smap_txeof(void *);
                    137: STATIC void smap_start(struct ifnet *);
                    138: STATIC void smap_watchdog(struct ifnet *);
1.9       christos  139: STATIC int smap_ioctl(struct ifnet *, u_long, void *);
1.1       uch       140: STATIC int smap_init(struct ifnet *);
                    141: STATIC void smap_stop(struct ifnet *, int);
                    142:
                    143: STATIC int smap_get_eaddr(struct smap_softc *, u_int8_t *);
                    144: STATIC int smap_fifo_init(struct smap_softc *);
                    145: STATIC int smap_fifo_reset(bus_addr_t);
                    146: STATIC void smap_desc_init(struct smap_softc *);
                    147:
                    148: int
                    149: smap_match(struct device *parent, struct cfdata *cf, void *aux)
                    150: {
                    151:        struct spd_attach_args *spa = aux;
                    152:
                    153:        if (spa->spa_slot != SPD_NIC)
                    154:                return (0);
                    155:
                    156:        return (1);
                    157: }
                    158:
                    159: void
                    160: smap_attach(struct device *parent, struct device *self, void *aux)
                    161: {
                    162:        struct spd_attach_args *spa = aux;
                    163:        struct smap_softc *sc = (void *)self;
                    164:        struct emac3_softc *emac3 = &sc->emac3;
                    165:        struct ifnet *ifp = &sc->ethercom.ec_if;
                    166:        struct mii_data *mii = &emac3->mii;
                    167:        void *txbuf, *rxbuf;
                    168:        u_int16_t r;
                    169:
                    170: #ifdef SMAP_DEBUG
                    171:        __sc = sc;
                    172: #endif
                    173:
                    174:        printf(": %s\n", spa->spa_product_name);
                    175:
                    176:        /* SPD EEPROM */
                    177:        if (smap_get_eaddr(sc, emac3->eaddr) != 0)
                    178:                return;
                    179:
                    180:        printf("%s: Ethernet address %s\n", DEVNAME,
                    181:            ether_sprintf(emac3->eaddr));
                    182:
                    183:        /* disable interrupts */
                    184:        r = _reg_read_2(SPD_INTR_ENABLE_REG16);
                    185:        r &= ~(SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV |
                    186:            SPD_INTR_EMAC3);
                    187:        _reg_write_2(SPD_INTR_ENABLE_REG16, r);
                    188:        emac3_intr_disable();
                    189:
                    190:        /* clear pending interrupts */
                    191:        _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
                    192:            SPD_INTR_RXDNV);
                    193:        emac3_intr_clear();
                    194:
                    195:        /* buffer descriptor mode */
                    196:        _reg_write_1(SMAP_DESC_MODE_REG8, 0);
                    197:
                    198:        if (smap_fifo_init(sc) != 0)
                    199:                return;
                    200:
                    201:        if (emac3_init(&sc->emac3) != 0)
                    202:                return;
                    203:        emac3_intr_disable();
                    204:        emac3_disable();
                    205:
                    206:        smap_desc_init(sc);
                    207:
                    208:        /* allocate temporary buffer */
                    209:        txbuf = malloc(ETHER_MAX_LEN - ETHER_CRC_LEN + SMAP_FIFO_ALIGN + 16,
                    210:            M_DEVBUF, M_NOWAIT);
                    211:        if (txbuf == NULL) {
                    212:                printf("%s: no memory.\n", DEVNAME);
                    213:                return;
                    214:        }
                    215:
                    216:        rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16,
                    217:            M_DEVBUF, M_NOWAIT);
                    218:        if (rxbuf == NULL) {
                    219:                printf("%s: no memory.\n", DEVNAME);
                    220:                free(txbuf, M_DEVBUF);
                    221:                return;
                    222:        }
                    223:
                    224:        sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf);
                    225:        sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf);
                    226:
                    227:        /*
                    228:         * setup MI layer
                    229:         */
                    230:        strcpy(ifp->if_xname, DEVNAME);
                    231:        ifp->if_softc   = sc;
                    232:        ifp->if_start   = smap_start;
                    233:        ifp->if_ioctl   = smap_ioctl;
                    234:        ifp->if_init    = smap_init;
                    235:        ifp->if_stop    = smap_stop;
                    236:        ifp->if_watchdog= smap_watchdog;
                    237:        ifp->if_flags   = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
                    238:            IFF_MULTICAST;
                    239:        IFQ_SET_READY(&ifp->if_snd);
                    240:
                    241:        /* ifmedia setup. */
                    242:        mii->mii_ifp            = ifp;
                    243:        mii->mii_readreg        = emac3_phy_readreg;
                    244:        mii->mii_writereg       = emac3_phy_writereg;
                    245:        mii->mii_statchg        = emac3_phy_statchg;
1.11      dyoung    246:        sc->ethercom.ec_mii = mii;
                    247:        ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
1.1       uch       248:        mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY,
                    249:            MII_OFFSET_ANY, 0);
                    250:
                    251:        /* Choose a default media. */
                    252:        if (LIST_FIRST(&mii->mii_phys) == NULL) {
                    253:                ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
                    254:                ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE);
                    255:        } else {
                    256:                ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
                    257:        }
                    258:
                    259:        if_attach(ifp);
                    260:        ether_ifattach(ifp, emac3->eaddr);
                    261:
                    262:        spd_intr_establish(SPD_NIC, smap_intr, sc);
                    263:
                    264: #if NRND > 0
                    265:        rnd_attach_source(&sc->rnd_source, DEVNAME,
                    266:            RND_TYPE_NET, 0);
                    267: #endif
                    268: }
                    269:
                    270: int
1.9       christos  271: smap_ioctl(struct ifnet *ifp, u_long command, void *data)
1.1       uch       272: {
                    273:        struct smap_softc *sc = ifp->if_softc;
                    274:        struct ifreq *ifr = (struct ifreq *) data;
                    275:        int error, s;
                    276:
                    277:        s = splnet();
                    278:
1.11      dyoung    279:        error = ether_ioctl(ifp, command, data);
                    280:
                    281:        if (error == ENETRESET) {
                    282:                if (ifp->if_flags & IFF_RUNNING)
                    283:                        emac3_setmulti(&sc->emac3, &sc->ethercom);
                    284:                error = 0;
1.1       uch       285:        }
                    286:
                    287:        splx(s);
                    288:
                    289:        return (error);
                    290: }
                    291:
                    292: int
                    293: smap_intr(void *arg)
                    294: {
                    295:        struct smap_softc *sc = arg;
                    296:        struct ifnet *ifp;
                    297:        u_int16_t cause, disable, r;
                    298:
                    299:        cause = _reg_read_2(SPD_INTR_STATUS_REG16) &
                    300:            _reg_read_2(SPD_INTR_ENABLE_REG16);
                    301:
                    302:        disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV);
                    303:        if (disable) {
                    304:                r = _reg_read_2(SPD_INTR_ENABLE_REG16);
                    305:                r &= ~disable;
                    306:                _reg_write_2(SPD_INTR_ENABLE_REG16, r);
                    307:
                    308:                printf("%s: invalid descriptor. (%c%c)\n", DEVNAME,
                    309:                    disable & SPD_INTR_RXDNV ? 'R' : '_',
                    310:                    disable & SPD_INTR_TXDNV ? 'T' : '_');
                    311:
                    312:                if (disable & SPD_INTR_RXDNV)
                    313:                        smap_rxeof(arg);
                    314:
                    315:                _reg_write_2(SPD_INTR_CLEAR_REG16, disable);
                    316:        }
                    317:
                    318:        if (cause & SPD_INTR_TXEND) {
                    319:                _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND);
                    320:                if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0)
                    321:                        cause |= SPD_INTR_RXEND;
                    322:                smap_txeof(arg);
                    323:        }
                    324:
                    325:        if (cause & SPD_INTR_RXEND) {
                    326:                _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND);
                    327:                smap_rxeof(arg);
                    328:                if (sc->tx_desc_cnt > 0 &&
                    329:                    sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8))
                    330:                        smap_txeof(arg);
                    331:        }
                    332:
                    333:        if (cause & SPD_INTR_EMAC3)
                    334:                emac3_intr(arg);
                    335:
1.4       wiz       336:        /* if transmission is pending, start here */
1.1       uch       337:        ifp = &sc->ethercom.ec_if;
                    338:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                    339:                smap_start(ifp);
                    340: #if NRND > 0
                    341:        rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16);
                    342: #endif
                    343:
                    344:        return (1);
                    345: }
                    346:
                    347: void
                    348: smap_rxeof(void *arg)
                    349: {
                    350:        struct smap_softc *sc = arg;
                    351:        struct smap_desc *d;
                    352:        struct ifnet *ifp = &sc->ethercom.ec_if;
                    353:        struct mbuf *m;
                    354:        u_int16_t r16, stat;
                    355:        u_int32_t *p;
                    356:        int i, j, sz, rxsz, cnt;
                    357:
                    358:        FUNC_ENTER();
                    359:
                    360:        i = sc->rx_done_index;
                    361:
                    362:        for (cnt = 0;; cnt++, i = (i + 1) & 0x3f) {
                    363:                m = NULL;
                    364:                d = &sc->rx_desc[i];
                    365:                stat = d->stat;
                    366:
                    367:                if ((stat & SMAP_RXDESC_EMPTY) != 0) {
                    368:                        break;
                    369:                } else if (stat & 0x7fff) {
                    370:                        ifp->if_ierrors++;
                    371:                        goto next_packet;
                    372:                }
                    373:
                    374:                sz = d->sz;
                    375:                rxsz = ROUND4(sz);
                    376:
                    377:                KDASSERT(sz >= ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN);
                    378:                KDASSERT(sz <= ETHER_MAX_LEN);
                    379:
                    380:                /* load data from FIFO */
                    381:                _reg_write_2(SMAP_RXFIFO_PTR_REG16, d->ptr & 0x3ffc);
                    382:                p = sc->rx_buf;
                    383:                for (j = 0; j < rxsz; j += sizeof(u_int32_t)) {
                    384:                        *p++ = _reg_read_4(SMAP_RXFIFO_DATA_REG);
                    385:                }
                    386:
                    387:                /* put to mbuf */
                    388:                MGETHDR(m, M_DONTWAIT, MT_DATA);
                    389:                if (m == NULL) {
                    390:                        printf("%s: unable to allocate Rx mbuf\n", DEVNAME);
                    391:                        ifp->if_ierrors++;
                    392:                        goto next_packet;
                    393:                }
                    394:
                    395:                if (sz > (MHLEN - 2)) {
                    396:                        MCLGET(m, M_DONTWAIT);
                    397:                        if ((m->m_flags & M_EXT) == 0) {
                    398:                                printf("%s: unable to allocate Rx cluster\n",
                    399:                                    DEVNAME);
                    400:                                m_freem(m);
                    401:                                m = NULL;
                    402:                                ifp->if_ierrors++;
                    403:                                goto next_packet;
                    404:                        }
                    405:                }
                    406:
                    407:                m->m_data += 2; /* for alignment */
                    408:                m->m_pkthdr.rcvif = ifp;
                    409:                m->m_pkthdr.len = m->m_len = sz;
1.9       christos  410:                memcpy(mtod(m, void *), (void *)sc->rx_buf, sz);
1.1       uch       411:
                    412:        next_packet:
                    413:                ifp->if_ipackets++;
                    414:
                    415:                _reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1);
                    416:
                    417:                /* free descriptor */
                    418:                d->sz   = 0;
                    419:                d->ptr  = 0;
                    420:                d->stat = SMAP_RXDESC_EMPTY;
                    421:                _wbflush();
                    422:
                    423:                if (m != NULL) {
                    424: #if NBPFILTER > 0
                    425:                        if (ifp->if_bpf)
                    426:                                bpf_mtap(ifp->if_bpf, m);
                    427: #endif
                    428:                        (*ifp->if_input)(ifp, m);
                    429:                }
                    430:        }
                    431:        sc->rx_done_index = i;
                    432:
                    433:        r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
                    434:        if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) {
                    435:                r16  |= SPD_INTR_RXDNV;
                    436:                _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
                    437:        }
                    438:
                    439:        FUNC_EXIT();
                    440: }
                    441:
                    442: void
                    443: smap_txeof(void *arg)
                    444: {
                    445:        struct smap_softc *sc = arg;
                    446:        struct ifnet *ifp = &sc->ethercom.ec_if;
                    447:        struct smap_desc *d;
                    448:        int i;
                    449:
                    450:        FUNC_ENTER();
                    451:
                    452:        /* clear the timeout timer. */
                    453:        ifp->if_timer = 0;
                    454:
                    455:        /* garbage collect */
                    456:        for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) {
                    457:                u_int16_t stat;
                    458:
                    459:                d = &sc->tx_desc[i];
                    460:                stat = d->stat;
                    461:                if (stat & SMAP_TXDESC_READY) {
                    462:                        /* all descriptor processed. */
                    463:                        break;
                    464:                } else if (stat & 0x7fff) {
                    465:                        if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL |
                    466:                            SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL))
                    467:                                ifp->if_collisions++;
                    468:                        else
                    469:                                ifp->if_oerrors++;
                    470:                } else {
                    471:                        ifp->if_opackets++;
                    472:                }
                    473:
                    474:                if (sc->tx_desc_cnt == 0)
                    475:                        break;
                    476:
                    477:                sc->tx_buf_freesize += ROUND4(d->sz);
                    478:                sc->tx_desc_cnt--;
                    479:
                    480:                d->sz = 0;
                    481:                d->ptr = 0;
                    482:                d->stat = 0;
                    483:                _wbflush();
                    484:        }
                    485:        sc->tx_done_index = i;
                    486:
                    487:        /* OK to start transmit */
                    488:        ifp->if_flags &= ~IFF_OACTIVE;
                    489:
                    490:        FUNC_EXIT();
                    491: }
                    492:
                    493: void
                    494: smap_start(struct ifnet *ifp)
                    495: {
                    496:        struct smap_softc *sc = ifp->if_softc;
                    497:        struct smap_desc *d;
                    498:        struct mbuf *m0, *m;
                    499:        u_int8_t *p, *q;
                    500:        u_int32_t *r;
                    501:        int i, sz, pktsz;
                    502:        u_int16_t fifop;
                    503:        u_int16_t r16;
                    504:
                    505:        KDASSERT(ifp->if_flags & IFF_RUNNING);
                    506:        FUNC_ENTER();
                    507:
                    508:        while (1) {
                    509:                IFQ_POLL(&ifp->if_snd, m0);
                    510:                if (m0 == NULL)
                    511:                        goto end;
                    512:
                    513:                pktsz = m0->m_pkthdr.len;
                    514:                KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN);
                    515:                sz = ROUND4(pktsz);
                    516:
                    517:                if (sz > sc->tx_buf_freesize ||
                    518:                    sc->tx_desc_cnt >= SMAP_DESC_MAX ||
                    519:                    emac3_tx_done() != 0) {
                    520:                        ifp->if_flags |= IFF_OACTIVE;
                    521:                        goto end;
                    522:                }
                    523:
                    524:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                    525:                KDASSERT(m0 != NULL);
                    526: #if NBPFILTER > 0
                    527:                if (ifp->if_bpf)
                    528:                        bpf_mtap(ifp->if_bpf, m0);
                    529: #endif
                    530:
                    531:                p = (u_int8_t *)sc->tx_buf;
                    532:                q = p + sz;
                    533:                /* copy to temporary buffer area */
                    534:                for (m = m0; m != 0; m = m->m_next) {
1.9       christos  535:                        memcpy(p, mtod(m, void *), m->m_len);
1.1       uch       536:                        p += m->m_len;
                    537:                }
                    538:                m_freem(m0);
                    539:
                    540:                /* zero padding area */
                    541:                for (; p < q; p++)
                    542:                        *p = 0;
                    543:
                    544:                /* put to FIFO */
                    545:                fifop = sc->tx_fifo_ptr;
                    546:                KDASSERT((fifop & 3) == 0);
                    547:                _reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop);
                    548:                sc->tx_fifo_ptr = (fifop + sz) & 0xfff;
                    549:
                    550:                r = sc->tx_buf;
                    551:                for (i = 0; i < sz; i += sizeof(u_int32_t))
1.8       perry     552:                        *(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++;
1.1       uch       553:                _wbflush();
                    554:
                    555:                /* put FIFO to EMAC3 */
                    556:                d = &sc->tx_desc[sc->tx_start_index];
                    557:                KDASSERT((d->stat & SMAP_TXDESC_READY) == 0);
                    558:
                    559:                d->sz = pktsz;
                    560:                d->ptr = fifop + SMAP_TXBUF_BASE;
                    561:                d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS |
                    562:                    SMAP_TXDESC_GENPAD;
                    563:                _wbflush();
                    564:
                    565:                sc->tx_buf_freesize -= sz;
                    566:                sc->tx_desc_cnt++;
                    567:                sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f;
                    568:                _reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1);
                    569:
                    570:                emac3_tx_kick();
                    571:                r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
                    572:                if ((r16 & SPD_INTR_TXDNV) == 0) {
                    573:                        r16 |= SPD_INTR_TXDNV;
                    574:                        _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
                    575:                }
                    576:        }
                    577:  end:
                    578:        /* set watchdog timer */
                    579:        ifp->if_timer = 5;
                    580:
                    581:        FUNC_EXIT();
                    582: }
                    583:
                    584: void
                    585: smap_watchdog(struct ifnet *ifp)
                    586: {
                    587:        struct smap_softc *sc = ifp->if_softc;
                    588:
                    589:        printf("%s: watchdog timeout\n",DEVNAME);
                    590:        sc->ethercom.ec_if.if_oerrors++;
                    591:
                    592:        smap_fifo_init(sc);
                    593:        smap_desc_init(sc);
                    594:        emac3_reset(&sc->emac3);
                    595: }
                    596:
                    597: int
                    598: smap_init(struct ifnet *ifp)
                    599: {
                    600:        struct smap_softc *sc = ifp->if_softc;
                    601:        u_int16_t r16;
1.11      dyoung    602:        int rc;
1.1       uch       603:
                    604:        smap_fifo_init(sc);
                    605:        emac3_reset(&sc->emac3);
                    606:        smap_desc_init(sc);
                    607:
                    608:        _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
                    609:            SPD_INTR_RXDNV);
                    610:        emac3_intr_clear();
                    611:
                    612:        r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
                    613:        r16 |=  SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND |
                    614:            SPD_INTR_RXDNV;
                    615:        _reg_write_2(SPD_INTR_ENABLE_REG16, r16);
                    616:        emac3_intr_enable();
                    617:
                    618:        emac3_enable();
                    619:
                    620:        /* Program the multicast filter, if necessary. */
                    621:        emac3_setmulti(&sc->emac3, &sc->ethercom);
                    622:
                    623:        /* Set current media. */
1.11      dyoung    624:        if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO)
                    625:                rc = 0;
                    626:        else if (rc != 0)
                    627:                return rc;
1.1       uch       628:
                    629:        ifp->if_flags |= IFF_RUNNING;
                    630:
                    631:        return (0);
                    632: }
                    633:
                    634: void
                    635: smap_stop(struct ifnet *ifp, int disable)
                    636: {
                    637:        struct smap_softc *sc = ifp->if_softc;
                    638:
                    639:        mii_down(&sc->emac3.mii);
                    640:
1.12      dyoung    641:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    642:
1.1       uch       643:        if (disable)
                    644:                emac3_disable();
                    645: }
                    646:
                    647: /*
                    648:  * FIFO
                    649:  */
                    650: int
                    651: smap_fifo_init(struct smap_softc *sc)
                    652: {
                    653:
                    654:        if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0)
                    655:                goto error;
                    656:
                    657:        if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0)
                    658:                goto error;
                    659:
                    660:        return (0);
                    661: error:
                    662:        printf("%s: FIFO reset not complete.\n", DEVNAME);
                    663:
                    664:        return (1);
                    665: }
                    666:
                    667: int
                    668: smap_fifo_reset(bus_addr_t a)
                    669: {
                    670:        int retry = 10000;
                    671:
                    672:        _reg_write_1(a, SMAP_FIFO_RESET);
                    673:
                    674:        while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0)
                    675:                ;
                    676:
                    677:        return (retry == 0);
                    678: }
                    679:
                    680: /*
                    681:  * Buffer descriptor
                    682:  */
                    683: void
                    684: smap_desc_init(struct smap_softc *sc)
                    685: {
                    686:        struct smap_desc *d;
                    687:        int i;
                    688:
                    689:        sc->tx_desc = (void *)SMAP_TXDESC_BASE;
                    690:        sc->rx_desc = (void *)SMAP_RXDESC_BASE;
                    691:
                    692:        sc->tx_buf_freesize = SMAP_TXBUF_SIZE;
                    693:        sc->tx_fifo_ptr = 0;
                    694:        sc->tx_start_index = 0;
                    695:        sc->tx_done_index = 0;
                    696:        sc->rx_done_index = 0;
                    697:
                    698:        /* intialize entry */
                    699:        d = sc->tx_desc;
                    700:        for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
                    701:                d->stat = 0;
                    702:                d->__reserved = 0;
                    703:                d->sz = 0;
                    704:                d->ptr = 0;
                    705:        }
                    706:
                    707:        d = sc->rx_desc;
                    708:        for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
                    709:                d->stat = SMAP_RXDESC_EMPTY;
                    710:                d->__reserved = 0;
                    711:                d->sz = 0;
                    712:                d->ptr = 0;
                    713:        }
                    714:        _wbflush();
                    715: }
                    716:
                    717:
                    718: /*
                    719:  * EEPROM
                    720:  */
                    721: int
                    722: smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr)
                    723: {
                    724:        u_int16_t checksum, *p = (u_int16_t *)eaddr;
                    725:
                    726:        spd_eeprom_read(0, p, 3);
                    727:        spd_eeprom_read(3, &checksum, 1);
                    728:
                    729:        if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) {
                    730:                printf("%s: Ethernet address checksum error.(%s)\n",
                    731:                    DEVNAME, ether_sprintf(eaddr));
                    732:                return (1);
                    733:        }
                    734:
                    735:        return (0);
                    736: }
                    737:
                    738: #ifdef SMAP_DEBUG
                    739: #include <mips/locore.h>
                    740: void
                    741: __smap_lock_check(const char *func, int enter)
                    742: {
                    743:        static int cnt;
                    744:        static const char *last;
                    745:
                    746:        cnt += enter ? 1 : -1;
                    747:
                    748:        if (cnt < 0 || cnt > 1)
                    749:                panic("%s cnt=%d last=%s", func, cnt, last);
                    750:
                    751:        last = func;
                    752: }
                    753:
                    754: void
                    755: __smap_status(int msg)
                    756: {
                    757:        static int cnt;
                    758:        __gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg,
                    759:            _reg_read_1(SMAP_TXFIFO_FRAME_REG8),
                    760:            _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt,
                    761:            __sc->tx_buf_freesize, cnt++);
                    762: }
                    763: #endif /* SMAP_DEBUG */

CVSweb <webmaster@jp.NetBSD.org>