[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.17.6.5

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

CVSweb <webmaster@jp.NetBSD.org>