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

Annotation of src/sys/dev/ic/dm9000.c, Revision 1.12.2.2

1.12.2.2! pgoyette    1: /*     $NetBSD: dm9000.c,v 1.15 2018/06/26 06:48:00 msaitoh Exp $      */
1.1       ahoka       2:
                      3: /*
                      4:  * Copyright (c) 2009 Paul Fleischer
                      5:  * All rights reserved.
                      6:  *
                      7:  * 1. Redistributions of source code must retain the above copyright
                      8:  *    notice, this list of conditions and the following disclaimer.
                      9:  * 2. Redistributions in binary form must reproduce the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer in the
                     11:  *    documentation and/or other materials provided with the distribution.
                     12:  * 3. The name of the company nor the name of the author may be used to
                     13:  *    endorse or promote products derived from this software without specific
                     14:  *    prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28:
                     29: /* based on sys/dev/ic/cs89x0.c */
                     30: /*
                     31:  * Copyright (c) 2004 Christopher Gilbert
                     32:  * All rights reserved.
                     33:  *
                     34:  * 1. Redistributions of source code must retain the above copyright
                     35:  *    notice, this list of conditions and the following disclaimer.
                     36:  * 2. Redistributions in binary form must reproduce the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer in the
                     38:  *    documentation and/or other materials provided with the distribution.
                     39:  * 3. The name of the company nor the name of the author may be used to
                     40:  *    endorse or promote products derived from this software without specific
                     41:  *    prior written permission.
                     42:  *
                     43:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     44:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     45:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     46:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     47:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     48:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     49:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     50:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     51:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     52:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     53:  * SUCH DAMAGE.
                     54:  */
                     55:
                     56: /*
                     57:  * Copyright 1997
                     58:  * Digital Equipment Corporation. All rights reserved.
                     59:  *
                     60:  * This software is furnished under license and may be used and
                     61:  * copied only in accordance with the following terms and conditions.
                     62:  * Subject to these conditions, you may download, copy, install,
                     63:  * use, modify and distribute this software in source and/or binary
                     64:  * form. No title or ownership is transferred hereby.
                     65:  *
                     66:  * 1) Any source code used, modified or distributed must reproduce
                     67:  *    and retain this copyright notice and list of conditions as
                     68:  *    they appear in the source file.
                     69:  *
                     70:  * 2) No right is granted to use any trade name, trademark, or logo of
                     71:  *    Digital Equipment Corporation. Neither the "Digital Equipment
                     72:  *    Corporation" name nor any trademark or logo of Digital Equipment
                     73:  *    Corporation may be used to endorse or promote products derived
                     74:  *    from this software without the prior written permission of
                     75:  *    Digital Equipment Corporation.
                     76:  *
                     77:  * 3) This software is provided "AS-IS" and any express or implied
                     78:  *    warranties, including but not limited to, any implied warranties
                     79:  *    of merchantability, fitness for a particular purpose, or
                     80:  *    non-infringement are disclaimed. In no event shall DIGITAL be
                     81:  *    liable for any damages whatsoever, and in particular, DIGITAL
                     82:  *    shall not be liable for special, indirect, consequential, or
                     83:  *    incidental damages or damages for lost profits, loss of
                     84:  *    revenue or loss of use, whether such damages arise in contract,
                     85:  *    negligence, tort, under statute, in equity, at law or otherwise,
                     86:  *    even if advised of the possibility of such damage.
                     87:  */
                     88:
                     89: #include <sys/cdefs.h>
                     90:
                     91: #include <sys/param.h>
1.4       nisimura   92: #include <sys/kernel.h>
1.1       ahoka      93: #include <sys/systm.h>
                     94: #include <sys/mbuf.h>
                     95: #include <sys/syslog.h>
                     96: #include <sys/socket.h>
                     97: #include <sys/device.h>
                     98: #include <sys/malloc.h>
                     99: #include <sys/ioctl.h>
                    100: #include <sys/errno.h>
                    101:
                    102: #include <net/if.h>
                    103: #include <net/if_ether.h>
                    104: #include <net/if_media.h>
1.12.2.1  pgoyette  105: #include <net/bpf.h>
                    106:
1.1       ahoka     107: #ifdef INET
                    108: #include <netinet/in.h>
                    109: #include <netinet/if_inarp.h>
                    110: #endif
                    111:
                    112: #include <sys/bus.h>
                    113: #include <sys/intr.h>
                    114:
                    115: #include <dev/ic/dm9000var.h>
                    116: #include <dev/ic/dm9000reg.h>
                    117:
                    118: #if 1
                    119: #undef DM9000_DEBUG
1.4       nisimura  120: #undef DM9000_TX_DEBUG
1.1       ahoka     121: #undef DM9000_TX_DATA_DEBUG
                    122: #undef DM9000_RX_DEBUG
                    123: #undef  DM9000_RX_DATA_DEBUG
                    124: #else
                    125: #define DM9000_DEBUG
                    126: #define  DM9000_TX_DEBUG
                    127: #define DM9000_TX_DATA_DEBUG
                    128: #define DM9000_RX_DEBUG
                    129: #define  DM9000_RX_DATA_DEBUG
                    130: #endif
                    131:
                    132: #ifdef DM9000_DEBUG
                    133: #define DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
                    134: #else
                    135: #define DPRINTF(s) do {} while (/*CONSTCOND*/0)
                    136: #endif
                    137:
                    138: #ifdef DM9000_TX_DEBUG
                    139: #define TX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
                    140: #else
                    141: #define TX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
                    142: #endif
                    143:
                    144: #ifdef DM9000_RX_DEBUG
                    145: #define RX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
                    146: #else
                    147: #define RX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
                    148: #endif
                    149:
                    150: #ifdef DM9000_RX_DATA_DEBUG
                    151: #define RX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
                    152: #else
                    153: #define RX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
                    154: #endif
                    155:
                    156: #ifdef DM9000_TX_DATA_DEBUG
                    157: #define TX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
                    158: #else
                    159: #define TX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
                    160: #endif
                    161:
1.4       nisimura  162: /*** Internal PHY functions ***/
1.7       macallan  163: uint16_t dme_phy_read(struct dme_softc *, int );
                    164: void   dme_phy_write(struct dme_softc *, int, uint16_t);
                    165: void   dme_phy_init(struct dme_softc *);
                    166: void   dme_phy_reset(struct dme_softc *);
                    167: void   dme_phy_update_media(struct dme_softc *);
                    168: void   dme_phy_check_link(void *);
1.1       ahoka     169:
                    170: /*** Methods registered in struct ifnet ***/
1.7       macallan  171: void   dme_start_output(struct ifnet *);
                    172: int    dme_init(struct ifnet *);
                    173: int    dme_ioctl(struct ifnet *, u_long, void *);
                    174: void   dme_stop(struct ifnet *, int);
1.1       ahoka     175:
1.7       macallan  176: int    dme_mediachange(struct ifnet *);
                    177: void   dme_mediastatus(struct ifnet *, struct ifmediareq *);
1.1       ahoka     178:
                    179: /*** Internal methods ***/
                    180:
                    181: /* Prepare data to be transmitted (i.e. dequeue and load it into the DM9000) */
1.7       macallan  182: void    dme_prepare(struct dme_softc *, struct ifnet *);
1.1       ahoka     183:
                    184: /* Transmit prepared data */
1.7       macallan  185: void    dme_transmit(struct dme_softc *);
1.1       ahoka     186:
                    187: /* Receive data */
1.7       macallan  188: void    dme_receive(struct dme_softc *, struct ifnet *);
1.1       ahoka     189:
                    190: /* Software Initialize/Reset of the DM9000 */
1.7       macallan  191: void    dme_reset(struct dme_softc *);
1.1       ahoka     192:
1.4       nisimura  193: /* Configure multicast filter */
1.7       macallan  194: void   dme_set_addr_filter(struct dme_softc *);
1.4       nisimura  195:
                    196: /* Set media */
1.7       macallan  197: int    dme_set_media(struct dme_softc *, int );
1.4       nisimura  198:
                    199: /* Read/write packet data from/to DM9000 IC in various transfer sizes */
1.7       macallan  200: int    dme_pkt_read_2(struct dme_softc *, struct ifnet *, struct mbuf **);
                    201: int    dme_pkt_write_2(struct dme_softc *, struct mbuf *);
                    202: int    dme_pkt_read_1(struct dme_softc *, struct ifnet *, struct mbuf **);
                    203: int    dme_pkt_write_1(struct dme_softc *, struct mbuf *);
1.6       macallan  204: /* TODO: Implement 32 bit read/write functions */
1.4       nisimura  205:
1.1       ahoka     206: uint16_t
                    207: dme_phy_read(struct dme_softc *sc, int reg)
                    208: {
                    209:        uint16_t val;
                    210:        /* Select Register to read*/
                    211:        dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
                    212:            (reg & DM9000_EPAR_EROA_MASK));
                    213:        /* Select read operation (DM9000_EPCR_ERPRR) from the PHY */
                    214:        dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRR + DM9000_EPCR_EPOS_PHY);
                    215:
                    216:        /* Wait until access to PHY has completed */
                    217:        while (dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE);
                    218:
                    219:        /* Reset ERPRR-bit */
                    220:        dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
                    221:
                    222:        val = dme_read(sc, DM9000_EPDRL);
                    223:        val += dme_read(sc, DM9000_EPDRH) << 8;
                    224:
                    225:        return val;
                    226: }
                    227:
                    228: void
                    229: dme_phy_write(struct dme_softc *sc, int reg, uint16_t value)
                    230: {
                    231:        /* Select Register to write*/
                    232:        dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
                    233:            (reg & DM9000_EPAR_EROA_MASK));
                    234:
                    235:        /* Write data to the two data registers */
                    236:        dme_write(sc, DM9000_EPDRL, value & 0xFF);
                    237:        dme_write(sc, DM9000_EPDRH, (value >> 8) & 0xFF);
                    238:
                    239:        /* Select write operation (DM9000_EPCR_ERPRW) from the PHY */
                    240:        dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRW + DM9000_EPCR_EPOS_PHY);
                    241:
                    242:        /* Wait until access to PHY has completed */
                    243:        while(dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE);
                    244:
1.4       nisimura  245:        /* Reset ERPRR-bit */
                    246:        dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
                    247: }
                    248:
                    249: void
                    250: dme_phy_init(struct dme_softc *sc)
                    251: {
                    252:        u_int ifm_media = sc->sc_media.ifm_media;
                    253:        uint32_t bmcr, anar;
                    254:
                    255:        bmcr = dme_phy_read(sc, DM9000_PHY_BMCR);
                    256:        anar = dme_phy_read(sc, DM9000_PHY_ANAR);
                    257:
                    258:        anar = anar & ~DM9000_PHY_ANAR_10_HDX
                    259:                & ~DM9000_PHY_ANAR_10_FDX
                    260:                & ~DM9000_PHY_ANAR_TX_HDX
                    261:                & ~DM9000_PHY_ANAR_TX_FDX;
                    262:
                    263:        switch (IFM_SUBTYPE(ifm_media)) {
                    264:        case IFM_AUTO:
                    265:                bmcr |= DM9000_PHY_BMCR_AUTO_NEG_EN;
                    266:                anar |= DM9000_PHY_ANAR_10_HDX |
                    267:                        DM9000_PHY_ANAR_10_FDX |
                    268:                        DM9000_PHY_ANAR_TX_HDX |
                    269:                        DM9000_PHY_ANAR_TX_FDX;
                    270:                break;
                    271:        case IFM_10_T:
                    272:                //bmcr &= ~DM9000_PHY_BMCR_AUTO_NEG_EN;
                    273:                bmcr &= ~DM9000_PHY_BMCR_SPEED_SELECT;
                    274:                if (ifm_media & IFM_FDX)
                    275:                        anar |= DM9000_PHY_ANAR_10_FDX;
                    276:                else
                    277:                        anar |= DM9000_PHY_ANAR_10_HDX;
                    278:                break;
                    279:        case IFM_100_TX:
                    280:                //bmcr &= ~DM9000_PHY_BMCR_AUTO_NEG_EN;
                    281:                bmcr |= DM9000_PHY_BMCR_SPEED_SELECT;
                    282:                if (ifm_media & IFM_FDX)
                    283:                        anar |= DM9000_PHY_ANAR_TX_FDX;
                    284:                else
                    285:                        anar |= DM9000_PHY_ANAR_TX_HDX;
                    286:
                    287:                break;
                    288:        }
                    289:
                    290:        if(ifm_media & IFM_FDX) {
                    291:                bmcr |= DM9000_PHY_BMCR_DUPLEX_MODE;
                    292:        } else {
                    293:                bmcr &= ~DM9000_PHY_BMCR_DUPLEX_MODE;
                    294:        }
                    295:
                    296:        dme_phy_write(sc, DM9000_PHY_BMCR, bmcr);
                    297:        dme_phy_write(sc, DM9000_PHY_ANAR, anar);
                    298: }
                    299:
                    300: void
                    301: dme_phy_reset(struct dme_softc *sc)
                    302: {
                    303:        uint32_t reg;
                    304:
                    305:        /* PHY Reset */
                    306:        dme_phy_write(sc, DM9000_PHY_BMCR, DM9000_PHY_BMCR_RESET);
                    307:
                    308:        reg = dme_read(sc, DM9000_GPCR);
                    309:        dme_write(sc, DM9000_GPCR, reg & ~DM9000_GPCR_GPIO0_OUT);
                    310:        reg = dme_read(sc, DM9000_GPR);
                    311:        dme_write(sc, DM9000_GPR, reg | DM9000_GPR_PHY_PWROFF);
                    312:
                    313:        dme_phy_init(sc);
1.1       ahoka     314:
1.4       nisimura  315:        reg = dme_read(sc, DM9000_GPR);
                    316:        dme_write(sc, DM9000_GPR, reg & ~DM9000_GPR_PHY_PWROFF);
                    317:        reg = dme_read(sc, DM9000_GPCR);
                    318:        dme_write(sc, DM9000_GPCR, reg | DM9000_GPCR_GPIO0_OUT);
1.1       ahoka     319:
1.4       nisimura  320:        dme_phy_update_media(sc);
                    321: }
                    322:
                    323: void
                    324: dme_phy_update_media(struct dme_softc *sc)
                    325: {
                    326:        u_int ifm_media = sc->sc_media.ifm_media;
                    327:        uint32_t reg;
                    328:
                    329:        if (IFM_SUBTYPE(ifm_media) == IFM_AUTO) {
                    330:                /* If auto-negotiation is used, ensures that it is completed
                    331:                 before trying to extract any media information. */
                    332:                reg = dme_phy_read(sc, DM9000_PHY_BMSR);
                    333:                if ((reg & DM9000_PHY_BMSR_AUTO_NEG_AB) == 0) {
                    334:                        /* Auto-negotation not possible, therefore there is no
                    335:                           reason to try obtain any media information. */
                    336:                        return;
                    337:                }
                    338:
                    339:                /* Then loop until the negotiation is completed. */
                    340:                while ((reg & DM9000_PHY_BMSR_AUTO_NEG_COM) == 0) {
                    341:                        /* TODO: Bail out after a finite number of attempts
                    342:                         in case something goes wrong. */
                    343:                        preempt();
                    344:                        reg = dme_phy_read(sc, DM9000_PHY_BMSR);
                    345:                }
                    346:        }
                    347:
                    348:
                    349:        sc->sc_media_active = IFM_ETHER;
                    350:        reg = dme_phy_read(sc, DM9000_PHY_BMCR);
                    351:
                    352:        if (reg & DM9000_PHY_BMCR_SPEED_SELECT) {
                    353:                sc->sc_media_active |= IFM_100_TX;
                    354:        } else {
                    355:                sc->sc_media_active |= IFM_10_T;
                    356:        }
                    357:
                    358:        if (reg & DM9000_PHY_BMCR_DUPLEX_MODE) {
                    359:                sc->sc_media_active |= IFM_FDX;
                    360:        }
                    361: }
                    362:
                    363: void
                    364: dme_phy_check_link(void *arg)
                    365: {
                    366:        struct dme_softc *sc = arg;
                    367:        uint32_t reg;
                    368:        int s;
                    369:
                    370:        s = splnet();
                    371:
                    372:        reg = dme_read(sc, DM9000_NSR) & DM9000_NSR_LINKST;
                    373:
                    374:        if( reg )
                    375:                reg = IFM_ETHER | IFM_AVALID | IFM_ACTIVE;
                    376:        else {
                    377:                reg = IFM_ETHER | IFM_AVALID;
                    378:                sc->sc_media_active = IFM_NONE;
                    379:        }
                    380:
                    381:        if ( (sc->sc_media_status != reg) && (reg & IFM_ACTIVE)) {
                    382:                dme_phy_reset(sc);
                    383:        }
                    384:
                    385:        sc->sc_media_status = reg;
                    386:
                    387:        callout_schedule(&sc->sc_link_callout, mstohz(2000));
                    388:        splx(s);
                    389: }
                    390:
                    391: int
                    392: dme_set_media(struct dme_softc *sc, int media)
                    393: {
                    394:        int s;
                    395:
                    396:        s = splnet();
                    397:        sc->sc_media.ifm_media = media;
                    398:        dme_phy_reset(sc);
                    399:
                    400:        splx(s);
                    401:
                    402:        return 0;
1.1       ahoka     403: }
                    404:
                    405: int
1.4       nisimura  406: dme_attach(struct dme_softc *sc, const uint8_t *enaddr)
1.1       ahoka     407: {
1.4       nisimura  408:        struct ifnet    *ifp = &sc->sc_ethercom.ec_if;
                    409:        uint8_t         b[2];
                    410:        uint16_t        io_mode;
1.1       ahoka     411:
                    412:        dme_read_c(sc, DM9000_VID0, b, 2);
                    413: #if BYTE_ORDER == BIG_ENDIAN
                    414:        sc->sc_vendor_id = (b[0] << 8) | b[1];
                    415: #else
                    416:        sc->sc_vendor_id = b[0] | (b[1] << 8);
                    417: #endif
                    418:        dme_read_c(sc, DM9000_PID0, b, 2);
                    419: #if BYTE_ORDER == BIG_ENDIAN
                    420:        sc->sc_product_id = (b[0] << 8) | b[1];
                    421: #else
                    422:        sc->sc_product_id = b[0] | (b[1] << 8);
                    423: #endif
                    424:        /* TODO: Check the vendor ID as well */
                    425:        if (sc->sc_product_id != 0x9000) {
                    426:                panic("dme_attach: product id mismatch (0x%hx != 0x9000)",
                    427:                    sc->sc_product_id);
                    428:        }
                    429:
                    430:        /* Initialize ifnet structure. */
                    431:        strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
                    432:        ifp->if_softc = sc;
                    433:        ifp->if_start = dme_start_output;
                    434:        ifp->if_init = dme_init;
                    435:        ifp->if_ioctl = dme_ioctl;
                    436:        ifp->if_stop = dme_stop;
                    437:        ifp->if_watchdog = NULL;        /* no watchdog at this stage */
1.4       nisimura  438:        ifp->if_flags = IFF_SIMPLEX | IFF_NOTRAILERS | IFF_BROADCAST |
                    439:                        IFF_MULTICAST;
1.1       ahoka     440:        IFQ_SET_READY(&ifp->if_snd);
                    441:
                    442:        /* Initialize ifmedia structures. */
                    443:        ifmedia_init(&sc->sc_media, 0, dme_mediachange, dme_mediastatus);
1.4       nisimura  444:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL);
                    445:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
                    446:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T, 0, NULL);
                    447:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
                    448:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX, 0, NULL);
                    449:
                    450:        ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
1.1       ahoka     451:
                    452:        if (enaddr != NULL)
                    453:                memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr));
1.4       nisimura  454:        /* TODO: Support an EEPROM attached to the DM9000 chip */
                    455:
                    456:        callout_init(&sc->sc_link_callout, 0);
                    457:        callout_setfunc(&sc->sc_link_callout, dme_phy_check_link, sc);
                    458:
                    459:        sc->sc_media_status = 0;
1.1       ahoka     460:
                    461:        /* Configure DM9000 with the MAC address */
                    462:        dme_write_c(sc, DM9000_PAB0, sc->sc_enaddr, 6);
                    463:
                    464: #ifdef DM9000_DEBUG
                    465:        {
                    466:                uint8_t macAddr[6];
                    467:                dme_read_c(sc, DM9000_PAB0, macAddr, 6);
                    468:                printf("DM9000 configured with MAC address: ");
                    469:                for (int i = 0; i < 6; i++) {
                    470:                        printf("%02X:", macAddr[i]);
                    471:                }
                    472:                printf("\n");
                    473:        }
                    474: #endif
                    475:
                    476:        if_attach(ifp);
                    477:        ether_ifattach(ifp, sc->sc_enaddr);
                    478:
                    479: #ifdef DM9000_DEBUG
                    480:        {
                    481:                uint8_t network_state;
                    482:                network_state = dme_read(sc, DM9000_NSR);
                    483:                printf("DM9000 Link status: ");
                    484:                if (network_state & DM9000_NSR_LINKST) {
                    485:                        if (network_state & DM9000_NSR_SPEED)
                    486:                                printf("10Mbps");
                    487:                        else
                    488:                                printf("100Mbps");
                    489:                } else {
                    490:                        printf("Down");
                    491:                }
                    492:                printf("\n");
                    493:        }
                    494: #endif
                    495:
1.4       nisimura  496:        io_mode = (dme_read(sc, DM9000_ISR) &
1.1       ahoka     497:            DM9000_IOMODE_MASK) >> DM9000_IOMODE_SHIFT;
1.4       nisimura  498:
                    499:        DPRINTF(("DM9000 Operation Mode: "));
                    500:        switch( io_mode) {
1.1       ahoka     501:        case DM9000_MODE_16BIT:
1.4       nisimura  502:                DPRINTF(("16-bit mode"));
                    503:                sc->sc_data_width = 2;
                    504:                sc->sc_pkt_write = dme_pkt_write_2;
                    505:                sc->sc_pkt_read = dme_pkt_read_2;
1.1       ahoka     506:                break;
                    507:        case DM9000_MODE_32BIT:
1.4       nisimura  508:                DPRINTF(("32-bit mode"));
                    509:                sc->sc_data_width = 4;
1.6       macallan  510:                panic("32bit mode is unsupported\n");
1.1       ahoka     511:                break;
                    512:        case DM9000_MODE_8BIT:
1.4       nisimura  513:                DPRINTF(("8-bit mode"));
                    514:                sc->sc_data_width = 1;
1.6       macallan  515:                sc->sc_pkt_write = dme_pkt_write_1;
                    516:                sc->sc_pkt_read = dme_pkt_read_1;
1.1       ahoka     517:                break;
1.4       nisimura  518:        default:
                    519:                DPRINTF(("Invalid mode"));
1.1       ahoka     520:                break;
                    521:        }
1.4       nisimura  522:        DPRINTF(("\n"));
                    523:
                    524:        callout_schedule(&sc->sc_link_callout, mstohz(2000));
1.1       ahoka     525:
                    526:        return 0;
                    527: }
                    528:
                    529: int dme_intr(void *arg)
                    530: {
                    531:        struct dme_softc *sc = arg;
                    532:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
                    533:        uint8_t status;
                    534:
1.4       nisimura  535:
                    536:        DPRINTF(("dme_intr: Begin\n"));
                    537:
1.1       ahoka     538:        /* Disable interrupts */
                    539:        dme_write(sc, DM9000_IMR, DM9000_IMR_PAR );
                    540:
                    541:        status = dme_read(sc, DM9000_ISR);
                    542:        dme_write(sc, DM9000_ISR, status);
                    543:
                    544:        if (status & DM9000_ISR_PRS) {
                    545:                if (ifp->if_flags & IFF_RUNNING )
                    546:                        dme_receive(sc, ifp);
                    547:        }
                    548:        if (status & DM9000_ISR_PTS) {
                    549:                uint8_t nsr;
                    550:                uint8_t tx_status = 0x01; /* Initialize to an error value */
                    551:
                    552:                /* A packet has been transmitted */
                    553:                sc->txbusy = 0;
                    554:
                    555:                nsr = dme_read(sc, DM9000_NSR);
                    556:
                    557:                if (nsr & DM9000_NSR_TX1END) {
                    558:                        tx_status = dme_read(sc, DM9000_TSR1);
                    559:                        TX_DPRINTF(("dme_intr: Sent using channel 0\n"));
                    560:                } else if (nsr & DM9000_NSR_TX2END) {
                    561:                        tx_status = dme_read(sc, DM9000_TSR2);
                    562:                        TX_DPRINTF(("dme_intr: Sent using channel 1\n"));
                    563:                }
                    564:
                    565:                if (tx_status == 0x0) {
                    566:                        /* Frame successfully sent */
                    567:                        ifp->if_opackets++;
                    568:                } else {
                    569:                        ifp->if_oerrors++;
                    570:                }
                    571:
                    572:                /* If we have nothing ready to transmit, prepare something */
                    573:                if (!sc->txready) {
                    574:                        dme_prepare(sc, ifp);
                    575:                }
                    576:
                    577:                if (sc->txready)
                    578:                        dme_transmit(sc);
                    579:
                    580:                /* Prepare the next frame */
                    581:                dme_prepare(sc, ifp);
                    582:
                    583:        }
                    584: #ifdef notyet
                    585:        if (status & DM9000_ISR_LNKCHNG) {
                    586:        }
                    587: #endif
                    588:
                    589:        /* Enable interrupts again */
                    590:        dme_write(sc, DM9000_IMR, DM9000_IMR_PAR | DM9000_IMR_PRM |
                    591:                 DM9000_IMR_PTM);
                    592:
1.4       nisimura  593:        DPRINTF(("dme_intr: End\n"));
                    594:
1.1       ahoka     595:        return 1;
                    596: }
                    597:
                    598: void
                    599: dme_start_output(struct ifnet *ifp)
                    600: {
                    601:        struct dme_softc *sc;
                    602:
                    603:        sc = ifp->if_softc;
                    604:
1.4       nisimura  605:        DPRINTF(("dme_start_output: Begin\n"));
                    606:
1.1       ahoka     607:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) {
                    608:                printf("No output\n");
                    609:                return;
                    610:        }
                    611:
                    612:        if (sc->txbusy && sc->txready) {
                    613:                panic("DM9000: Internal error, trying to send without"
                    614:                    " any empty queue\n");
                    615:        }
                    616:
                    617:        dme_prepare(sc, ifp);
                    618:
                    619:        if (sc->txbusy == 0) {
                    620:                /* We are ready to transmit right away */
                    621:                dme_transmit(sc);
                    622:                dme_prepare(sc, ifp); /* Prepare next one */
                    623:        } else {
                    624:                /* We need to wait until the current packet has
                    625:                 * been transmitted.
                    626:                 */
                    627:                ifp->if_flags |= IFF_OACTIVE;
                    628:        }
1.4       nisimura  629:
                    630:        DPRINTF(("dme_start_output: End\n"));
1.1       ahoka     631: }
                    632:
                    633: void
                    634: dme_prepare(struct dme_softc *sc, struct ifnet *ifp)
                    635: {
                    636:        struct mbuf *bufChain;
                    637:        uint16_t length;
                    638:
                    639:        TX_DPRINTF(("dme_prepare: Entering\n"));
                    640:
                    641:        if (sc->txready)
                    642:                panic("dme_prepare: Someone called us with txready set\n");
                    643:
                    644:        IFQ_DEQUEUE(&ifp->if_snd, bufChain);
                    645:        if (bufChain == NULL) {
                    646:                TX_DPRINTF(("dme_prepare: Nothing to transmit\n"));
                    647:                ifp->if_flags &= ~IFF_OACTIVE; /* Clear OACTIVE bit */
                    648:                return; /* Nothing to transmit */
                    649:        }
                    650:
                    651:        /* Element has now been removed from the queue, so we better send it */
                    652:
1.12.2.2! pgoyette  653:        bpf_mtap(ifp, bufChain, BPF_D_OUT);
1.1       ahoka     654:
                    655:        /* Setup the DM9000 to accept the writes, and then write each buf in
                    656:           the chain. */
                    657:
                    658:        TX_DATA_DPRINTF(("dme_prepare: Writing data: "));
                    659:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->dme_io, DM9000_MWCMD);
1.4       nisimura  660:        length = sc->sc_pkt_write(sc, bufChain);
1.1       ahoka     661:        TX_DATA_DPRINTF(("\n"));
                    662:
1.4       nisimura  663:        if (length % sc->sc_data_width != 0) {
                    664:                panic("dme_prepare: length is not compatible with IO_MODE");
1.1       ahoka     665:        }
                    666:
                    667:        sc->txready_length = length;
                    668:        sc->txready = 1;
                    669:
                    670:        TX_DPRINTF(("dme_prepare: txbusy: %d\ndme_prepare: "
                    671:                "txready: %d, txready_length: %d\n",
                    672:                sc->txbusy, sc->txready, sc->txready_length));
                    673:
                    674:        m_freem(bufChain);
                    675:
                    676:        TX_DPRINTF(("dme_prepare: Leaving\n"));
                    677: }
                    678:
                    679: int
                    680: dme_init(struct ifnet *ifp)
                    681: {
                    682:        int s;
                    683:        struct dme_softc *sc = ifp->if_softc;
                    684:
                    685:        dme_stop(ifp, 0);
                    686:
                    687:        s = splnet();
                    688:
                    689:        dme_reset(sc);
                    690:
                    691:        sc->sc_ethercom.ec_if.if_flags |= IFF_RUNNING;
                    692:        sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
                    693:        sc->sc_ethercom.ec_if.if_timer = 0;
                    694:
                    695:        splx(s);
                    696:
                    697:        return 0;
                    698: }
                    699:
                    700: int
                    701: dme_ioctl(struct ifnet *ifp, u_long cmd, void *data)
                    702: {
                    703:        struct dme_softc *sc = ifp->if_softc;
                    704:        struct ifreq *ifr = data;
                    705:        int s, error = 0;
                    706:
                    707:        s = splnet();
                    708:
                    709:        switch(cmd) {
                    710:        case SIOCGIFMEDIA:
                    711:        case SIOCSIFMEDIA:
                    712:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                    713:                break;
                    714:        default:
                    715:                error = ether_ioctl(ifp, cmd, data);
1.4       nisimura  716:                if (error == ENETRESET) {
                    717:                        if (ifp->if_flags && IFF_RUNNING) {
                    718:                                /* Address list has changed, reconfigure
                    719:                                   filter */
                    720:                                dme_set_addr_filter(sc);
                    721:                        }
                    722:                        error = 0;
                    723:                }
1.1       ahoka     724:                break;
                    725:        }
                    726:
                    727:        splx(s);
                    728:        return error;
                    729: }
                    730:
                    731: void
                    732: dme_stop(struct ifnet *ifp, int disable)
                    733: {
                    734:        struct dme_softc *sc = ifp->if_softc;
                    735:
                    736:        /* Not quite sure what to do when called with disable == 0 */
                    737:        if (disable) {
                    738:                /* Disable RX */
                    739:                dme_write(sc, DM9000_RCR, 0x0);
                    740:        }
                    741:
                    742:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    743:        ifp->if_timer = 0;
                    744: }
                    745:
                    746: int
                    747: dme_mediachange(struct ifnet *ifp)
                    748: {
1.4       nisimura  749:        struct dme_softc *sc = ifp->if_softc;
                    750:
                    751:        return dme_set_media(sc, sc->sc_media.ifm_cur->ifm_media);
1.1       ahoka     752: }
                    753:
                    754: void
                    755: dme_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
                    756: {
                    757:        struct dme_softc *sc = ifp->if_softc;
                    758:
1.4       nisimura  759:        ifmr->ifm_active = sc->sc_media_active;
                    760:        ifmr->ifm_status = sc->sc_media_status;
1.1       ahoka     761: }
                    762:
                    763: void
                    764: dme_transmit(struct dme_softc *sc)
                    765: {
                    766:
                    767:        TX_DPRINTF(("dme_transmit: PRE: txready: %d, txbusy: %d\n",
                    768:                sc->txready, sc->txbusy));
                    769:
                    770:        dme_write(sc, DM9000_TXPLL, sc->txready_length & 0xff);
                    771:        dme_write(sc, DM9000_TXPLH, (sc->txready_length >> 8) & 0xff );
                    772:
                    773:        /* Request to send the packet */
1.5       skrll     774:        dme_read(sc, DM9000_ISR);
1.1       ahoka     775:
                    776:        dme_write(sc, DM9000_TCR, DM9000_TCR_TXREQ);
                    777:
                    778:        sc->txready = 0;
                    779:        sc->txbusy = 1;
                    780:        sc->txready_length = 0;
                    781: }
                    782:
                    783: void
                    784: dme_receive(struct dme_softc *sc, struct ifnet *ifp)
                    785: {
                    786:        uint8_t ready = 0x01;
                    787:
                    788:        DPRINTF(("inside dme_receive\n"));
                    789:
                    790:        while (ready == 0x01) {
                    791:                /* Packet received, retrieve it */
                    792:
1.7       macallan  793:                /* Read without address increment to get the ready byte without
                    794:                   moving past it. */
1.1       ahoka     795:                bus_space_write_1(sc->sc_iot, sc->sc_ioh,
                    796:                    sc->dme_io, DM9000_MRCMDX);
                    797:                /* Dummy ready */
                    798:                ready = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
                    799:                ready = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
                    800:                ready &= 0x03;  /* we only want bits 1:0 */
                    801:                if (ready == 0x01) {
1.4       nisimura  802:                        uint8_t         rx_status;
                    803:                        struct mbuf     *m;
1.1       ahoka     804:
                    805:                        /* Read with address increment. */
                    806:                        bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1.4       nisimura  807:                                          sc->dme_io, DM9000_MRCMD);
1.1       ahoka     808:
1.4       nisimura  809:                        rx_status = sc->sc_pkt_read(sc, ifp, &m);
1.8       macallan  810:                        if (m == NULL) {
                    811:                                /* failed to allocate a receive buffer */
                    812:                                ifp->if_ierrors++;
                    813:                                RX_DPRINTF(("dme_receive: "
                    814:                                        "Error allocating buffer\n"));
                    815:                        } else if (rx_status & (DM9000_RSR_CE | DM9000_RSR_PLE)) {
1.1       ahoka     816:                                /* Error while receiving the packet,
                    817:                                 * discard it and keep track of counters
                    818:                                 */
                    819:                                ifp->if_ierrors++;
                    820:                                RX_DPRINTF(("dme_receive: "
                    821:                                        "Error reciving packet\n"));
                    822:                        } else if (rx_status & DM9000_RSR_LCS) {
                    823:                                ifp->if_collisions++;
                    824:                        } else {
1.9       ozaki-r   825:                                if_percpuq_enqueue(ifp->if_percpuq, m);
1.1       ahoka     826:                        }
                    827:
                    828:                } else if (ready != 0x00) {
                    829:                        /* Should this be logged somehow? */
1.4       nisimura  830:                        printf("%s: Resetting chip\n",
                    831:                               device_xname(sc->sc_dev));
1.1       ahoka     832:                        dme_reset(sc);
                    833:                }
                    834:        }
                    835: }
                    836:
                    837: void
                    838: dme_reset(struct dme_softc *sc)
                    839: {
                    840:        uint8_t var;
                    841:
1.4       nisimura  842:        /* We only re-initialized the PHY in this function the first time it is
                    843:           called. */
                    844:        if( !sc->sc_phy_initialized) {
                    845:                /* PHY Reset */
                    846:                dme_phy_write(sc, DM9000_PHY_BMCR, DM9000_PHY_BMCR_RESET);
                    847:
                    848:                /* PHY Power Down */
                    849:                var = dme_read(sc, DM9000_GPR);
                    850:                dme_write(sc, DM9000_GPR, var | DM9000_GPR_PHY_PWROFF);
                    851:        }
1.1       ahoka     852:
1.4       nisimura  853:        /* Reset the DM9000 twice, as described in section 2 of the Programming
                    854:           Guide.
                    855:           The PHY is initialized and enabled between those two resets.
1.1       ahoka     856:         */
1.4       nisimura  857:
                    858:        /* Software Reset*/
1.1       ahoka     859:        dme_write(sc, DM9000_NCR,
                    860:            DM9000_NCR_RST | DM9000_NCR_LBK_MAC_INTERNAL);
                    861:        delay(20);
                    862:        dme_write(sc, DM9000_NCR, 0x0);
1.4       nisimura  863:
                    864:        if( !sc->sc_phy_initialized) {
                    865:                /* PHY Initialization */
                    866:                dme_phy_init(sc);
                    867:
                    868:                /* PHY Enable */
                    869:                var = dme_read(sc, DM9000_GPR);
                    870:                dme_write(sc, DM9000_GPR, var & ~DM9000_GPR_PHY_PWROFF);
                    871:                var = dme_read(sc, DM9000_GPCR);
                    872:                dme_write(sc, DM9000_GPCR, var | DM9000_GPCR_GPIO0_OUT);
                    873:
                    874:                dme_write(sc, DM9000_NCR,
                    875:                          DM9000_NCR_RST | DM9000_NCR_LBK_MAC_INTERNAL);
                    876:                delay(20);
                    877:                dme_write(sc, DM9000_NCR, 0x0);
                    878:        }
1.1       ahoka     879:
                    880:        /* Select internal PHY, no wakeup event, no collosion mode,
1.4       nisimura  881:         * normal loopback mode.
1.1       ahoka     882:         */
                    883:        dme_write(sc, DM9000_NCR, DM9000_NCR_LBK_NORMAL );
                    884:
                    885:        /* Will clear TX1END, TX2END, and WAKEST fields by reading DM9000_NSR*/
                    886:        dme_read(sc, DM9000_NSR);
                    887:
                    888:        /* Enable wraparound of read/write pointer, packet received latch,
                    889:         * and packet transmitted latch.
                    890:         */
                    891:        dme_write(sc, DM9000_IMR,
                    892:            DM9000_IMR_PAR | DM9000_IMR_PRM | DM9000_IMR_PTM);
                    893:
1.4       nisimura  894:        /* Setup multicast address filter, and enable RX. */
                    895:        dme_set_addr_filter(sc);
                    896:
                    897:        /* Obtain media information from PHY */
                    898:        dme_phy_update_media(sc);
1.1       ahoka     899:
                    900:        sc->txbusy = 0;
                    901:        sc->txready = 0;
1.4       nisimura  902:        sc->sc_phy_initialized = 1;
                    903: }
                    904:
                    905: void
                    906: dme_set_addr_filter(struct dme_softc *sc)
                    907: {
                    908:        struct ether_multi      *enm;
                    909:        struct ether_multistep  step;
                    910:        struct ethercom         *ec;
                    911:        struct ifnet            *ifp;
                    912:        uint16_t                af[4];
                    913:        int                     i;
                    914:
                    915:        ec = &sc->sc_ethercom;
                    916:        ifp = &ec->ec_if;
                    917:
                    918:        if (ifp->if_flags & IFF_PROMISC) {
                    919:                dme_write(sc, DM9000_RCR, DM9000_RCR_RXEN  |
                    920:                                          DM9000_RCR_WTDIS |
                    921:                                          DM9000_RCR_PRMSC);
                    922:                ifp->if_flags |= IFF_ALLMULTI;
                    923:                return;
                    924:        }
                    925:
                    926:        af[0] = af[1] = af[2] = af[3] = 0x0000;
                    927:        ifp->if_flags &= ~IFF_ALLMULTI;
                    928:
                    929:        ETHER_FIRST_MULTI(step, ec, enm);
                    930:        while (enm != NULL) {
                    931:                uint16_t hash;
                    932:                if (memcpy(enm->enm_addrlo, enm->enm_addrhi,
                    933:                    sizeof(enm->enm_addrlo))) {
                    934:                        /*
                    935:                         * We must listen to a range of multicast addresses.
                    936:                         * For now, just accept all multicasts, rather than
                    937:                         * trying to set only those filter bits needed to match
                    938:                         * the range.  (At this time, the only use of address
                    939:                         * ranges is for IP multicast routing, for which the
                    940:                         * range is big enough to require all bits set.)
                    941:                         */
                    942:                        ifp->if_flags |= IFF_ALLMULTI;
                    943:                        af[0] = af[1] = af[2] = af[3] = 0xffff;
                    944:                        break;
                    945:                } else {
                    946:                        hash = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3F;
                    947:                        af[(uint16_t)(hash>>4)] |= (uint16_t)(1 << (hash % 16));
                    948:                        ETHER_NEXT_MULTI(step, enm);
                    949:                }
                    950:        }
                    951:
                    952:        /* Write the multicast address filter */
                    953:        for(i=0; i<4; i++) {
                    954:                dme_write(sc, DM9000_MAB0+i*2, af[i] & 0xFF);
                    955:                dme_write(sc, DM9000_MAB0+i*2+1, (af[i] >> 8) & 0xFF);
                    956:        }
                    957:
                    958:        /* Setup RX controls */
                    959:        dme_write(sc, DM9000_RCR, DM9000_RCR_RXEN | DM9000_RCR_WTDIS);
                    960: }
                    961:
                    962: int
                    963: dme_pkt_write_2(struct dme_softc *sc, struct mbuf *bufChain)
                    964: {
                    965:        int left_over_count = 0; /* Number of bytes from previous mbuf, which
                    966:                                    need to be written with the next.*/
                    967:        uint16_t left_over_buf = 0;
                    968:        int length = 0;
                    969:        struct mbuf *buf;
                    970:        uint8_t *write_ptr;
                    971:
                    972:        /* We expect that the DM9000 has been setup to accept writes before
                    973:           this function is called. */
                    974:
                    975:        for (buf = bufChain; buf != NULL; buf = buf->m_next) {
                    976:                int to_write = buf->m_len;
                    977:
                    978:                length += to_write;
                    979:
                    980:                write_ptr = buf->m_data;
                    981:                while (to_write > 0 ||
                    982:                       (buf->m_next == NULL && left_over_count > 0)
                    983:                       ) {
                    984:                        if (left_over_count > 0) {
                    985:                                uint8_t b = 0;
                    986:                                DPRINTF(("dme_pkt_write_16: "
                    987:                                         "Writing left over byte\n"));
                    988:
                    989:                                if (to_write > 0) {
                    990:                                        b = *write_ptr;
                    991:                                        to_write--;
                    992:                                        write_ptr++;
                    993:
                    994:                                        DPRINTF(("Took single byte\n"));
                    995:                                } else {
                    996:                                        DPRINTF(("Leftover in last run\n"));
                    997:                                        length++;
                    998:                                }
                    999:
                   1000:                                /* Does shift direction depend on endianess? */
                   1001:                                left_over_buf = left_over_buf | (b << 8);
                   1002:
                   1003:                                bus_space_write_2(sc->sc_iot, sc->sc_ioh,
                   1004:                                                  sc->dme_data, left_over_buf);
                   1005:                                TX_DATA_DPRINTF(("%02X ", left_over_buf));
                   1006:                                left_over_count = 0;
                   1007:                        } else if ((long)write_ptr % 2 != 0) {
                   1008:                                /* Misaligned data */
                   1009:                                DPRINTF(("dme_pkt_write_16: "
                   1010:                                         "Detected misaligned data\n"));
                   1011:                                left_over_buf = *write_ptr;
                   1012:                                left_over_count = 1;
                   1013:                                write_ptr++;
                   1014:                                to_write--;
                   1015:                        } else {
                   1016:                                int i;
1.7       macallan 1017:                                uint16_t *dptr = (uint16_t *)write_ptr;
1.4       nisimura 1018:
                   1019:                                /* A block of aligned data. */
1.7       macallan 1020:                                for(i = 0; i < to_write / 2; i++) {
1.4       nisimura 1021:                                        /* buf will be half-word aligned
                   1022:                                         * all the time
                   1023:                                         */
                   1024:                                        bus_space_write_2(sc->sc_iot,
1.7       macallan 1025:                                            sc->sc_ioh, sc->dme_data, *dptr);
1.4       nisimura 1026:                                        TX_DATA_DPRINTF(("%02X %02X ",
1.7       macallan 1027:                                            *dptr & 0xFF, (*dptr >> 8) & 0xFF));
1.4       nisimura 1028:                                        dptr++;
                   1029:                                }
                   1030:
1.7       macallan 1031:                                write_ptr += i * 2;
1.4       nisimura 1032:                                if (to_write % 2 != 0) {
                   1033:                                        DPRINTF(("dme_pkt_write_16: "
                   1034:                                                 "to_write %% 2: %d\n",
                   1035:                                                 to_write % 2));
                   1036:                                        left_over_count = 1;
                   1037:                                        /* XXX: Does this depend on
                   1038:                                         * the endianess?
                   1039:                                         */
                   1040:                                        left_over_buf = *write_ptr;
                   1041:
                   1042:                                        write_ptr++;
                   1043:                                        to_write--;
                   1044:                                        DPRINTF(("dme_pkt_write_16: "
                   1045:                                                 "to_write (after): %d\n",
                   1046:                                                 to_write));
1.7       macallan 1047:                                        DPRINTF(("dme_pkt_write_16: i * 2: %d\n",
1.4       nisimura 1048:                                                 i*2));
                   1049:                                }
1.7       macallan 1050:                                to_write -= i * 2;
1.4       nisimura 1051:                        }
                   1052:                } /* while(...) */
                   1053:        } /* for(...) */
                   1054:
                   1055:        return length;
                   1056: }
                   1057:
                   1058: int
                   1059: dme_pkt_read_2(struct dme_softc *sc, struct ifnet *ifp, struct mbuf **outBuf)
                   1060: {
                   1061:        uint8_t rx_status;
                   1062:        struct mbuf *m;
                   1063:        uint16_t data;
                   1064:        uint16_t frame_length;
                   1065:        uint16_t i;
                   1066:        uint16_t *buf;
                   1067:
1.7       macallan 1068:        data = bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->dme_data);
1.4       nisimura 1069:
                   1070:        rx_status = data & 0xFF;
                   1071:        frame_length = bus_space_read_2(sc->sc_iot,
                   1072:                                        sc->sc_ioh, sc->dme_data);
                   1073:        if (frame_length > ETHER_MAX_LEN) {
                   1074:                printf("Got frame of length: %d\n", frame_length);
                   1075:                printf("ETHER_MAX_LEN is: %d\n", ETHER_MAX_LEN);
                   1076:                panic("Something is rotten");
                   1077:        }
                   1078:        RX_DPRINTF(("dme_receive: "
                   1079:                    "rx_statux: 0x%x, frame_length: %d\n",
                   1080:                    rx_status, frame_length));
                   1081:
                   1082:
                   1083:        m = dme_alloc_receive_buffer(ifp, frame_length);
1.8       macallan 1084:        if (m == NULL) {
                   1085:                /*
                   1086:                 * didn't get a receive buffer, so we read the rest of the
                   1087:                 * packet, throw it away and return an error
                   1088:                 */
                   1089:                for (i = 0; i < frame_length; i += 2 ) {
                   1090:                        data = bus_space_read_2(sc->sc_iot,
                   1091:                                        sc->sc_ioh, sc->dme_data);
                   1092:                }
                   1093:                *outBuf = NULL;
                   1094:                return 0;
                   1095:        }
1.4       nisimura 1096:
                   1097:        buf = mtod(m, uint16_t*);
                   1098:
                   1099:        RX_DPRINTF(("dme_receive: "));
                   1100:
1.7       macallan 1101:        for (i = 0; i < frame_length; i += 2 ) {
1.4       nisimura 1102:                data = bus_space_read_2(sc->sc_iot,
                   1103:                                        sc->sc_ioh, sc->dme_data);
                   1104:                if ( (frame_length % 2 != 0) &&
1.7       macallan 1105:                     (i == frame_length - 1) ) {
1.4       nisimura 1106:                        data = data & 0xff;
                   1107:                        RX_DPRINTF((" L "));
                   1108:                }
                   1109:                *buf = data;
                   1110:                buf++;
                   1111:                RX_DATA_DPRINTF(("%02X %02X ", data & 0xff,
1.7       macallan 1112:                                 (data >> 8) & 0xff));
1.4       nisimura 1113:        }
                   1114:
                   1115:        RX_DATA_DPRINTF(("\n"));
                   1116:        RX_DPRINTF(("Read %d bytes\n", i));
                   1117:
                   1118:        *outBuf = m;
                   1119:        return rx_status;
                   1120: }
                   1121:
1.6       macallan 1122: int
                   1123: dme_pkt_write_1(struct dme_softc *sc, struct mbuf *bufChain)
                   1124: {
                   1125:        int length = 0, i;
                   1126:        struct mbuf *buf;
                   1127:        uint8_t *write_ptr;
                   1128:
                   1129:        /* We expect that the DM9000 has been setup to accept writes before
                   1130:           this function is called. */
                   1131:
                   1132:        for (buf = bufChain; buf != NULL; buf = buf->m_next) {
                   1133:                int to_write = buf->m_len;
                   1134:
                   1135:                length += to_write;
                   1136:
                   1137:                write_ptr = buf->m_data;
1.7       macallan 1138:                for (i = 0; i < to_write; i++) {
1.6       macallan 1139:                        bus_space_write_1(sc->sc_iot, sc->sc_ioh,
                   1140:                            sc->dme_data, *write_ptr);
                   1141:                        write_ptr++;
                   1142:                }
                   1143:        } /* for(...) */
                   1144:
                   1145:        return length;
                   1146: }
                   1147:
                   1148: int
                   1149: dme_pkt_read_1(struct dme_softc *sc, struct ifnet *ifp, struct mbuf **outBuf)
                   1150: {
                   1151:        uint8_t rx_status;
                   1152:        struct mbuf *m;
                   1153:        uint8_t *buf;
                   1154:        uint16_t frame_length;
                   1155:        uint16_t i, reg;
                   1156:        uint8_t data;
                   1157:
                   1158:        reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
                   1159:        reg |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data) << 8;
                   1160:        rx_status = reg & 0xFF;
                   1161:
                   1162:        reg = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
                   1163:        reg |= bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data) << 8;
                   1164:        frame_length = reg;
1.7       macallan 1165:
1.6       macallan 1166:        if (frame_length > ETHER_MAX_LEN) {
                   1167:                printf("Got frame of length: %d\n", frame_length);
                   1168:                printf("ETHER_MAX_LEN is: %d\n", ETHER_MAX_LEN);
                   1169:                panic("Something is rotten");
                   1170:        }
                   1171:        RX_DPRINTF(("dme_receive: "
                   1172:                    "rx_statux: 0x%x, frame_length: %d\n",
                   1173:                    rx_status, frame_length));
                   1174:
                   1175:
                   1176:        m = dme_alloc_receive_buffer(ifp, frame_length);
1.8       macallan 1177:        if (m == NULL) {
                   1178:                /*
                   1179:                 * didn't get a receive buffer, so we read the rest of the
                   1180:                 * packet, throw it away and return an error
                   1181:                 */
                   1182:                for (i = 0; i < frame_length; i++ ) {
                   1183:                        data = bus_space_read_2(sc->sc_iot,
                   1184:                                        sc->sc_ioh, sc->dme_data);
                   1185:                }
                   1186:                *outBuf = NULL;
                   1187:                return 0;
                   1188:        }
1.6       macallan 1189:
1.7       macallan 1190:        buf = mtod(m, uint8_t *);
1.6       macallan 1191:
                   1192:        RX_DPRINTF(("dme_receive: "));
                   1193:
1.7       macallan 1194:        for (i = 0; i< frame_length; i += 1 ) {
                   1195:                data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->dme_data);
1.6       macallan 1196:                *buf = data;
                   1197:                buf++;
                   1198:                RX_DATA_DPRINTF(("%02X ", data));
                   1199:        }
                   1200:
                   1201:        RX_DATA_DPRINTF(("\n"));
                   1202:        RX_DPRINTF(("Read %d bytes\n", i));
                   1203:
                   1204:        *outBuf = m;
                   1205:        return rx_status;
                   1206: }
                   1207:
1.4       nisimura 1208: struct mbuf*
                   1209: dme_alloc_receive_buffer(struct ifnet *ifp, unsigned int frame_length)
                   1210: {
                   1211:        struct dme_softc *sc = ifp->if_softc;
                   1212:        struct mbuf *m;
                   1213:        int pad;
                   1214:
                   1215:        MGETHDR(m, M_DONTWAIT, MT_DATA);
1.8       macallan 1216:        if (m == NULL) return NULL;
                   1217:
1.10      ozaki-r  1218:        m_set_rcvif(m, ifp);
1.4       nisimura 1219:        /* Ensure that we always allocate an even number of
                   1220:         * bytes in order to avoid writing beyond the buffer
                   1221:         */
                   1222:        m->m_pkthdr.len = frame_length + (frame_length % sc->sc_data_width);
                   1223:        pad = ALIGN(sizeof(struct ether_header)) -
                   1224:                sizeof(struct ether_header);
                   1225:        /* All our frames have the CRC attached */
                   1226:        m->m_flags |= M_HASFCS;
1.12      riastrad 1227:        if (m->m_pkthdr.len + pad > MHLEN) {
1.4       nisimura 1228:                MCLGET(m, M_DONTWAIT);
1.12      riastrad 1229:                if ((m->m_flags & M_EXT) == 0) {
                   1230:                        m_freem(m);
                   1231:                        return NULL;
                   1232:                }
                   1233:        }
1.4       nisimura 1234:
                   1235:        m->m_data += pad;
                   1236:        m->m_len = frame_length + (frame_length % sc->sc_data_width);
                   1237:
                   1238:        return m;
1.1       ahoka    1239: }

CVSweb <webmaster@jp.NetBSD.org>