Changeset 80a7fe6 in rtems-libbsd


Ignore:
Timestamp:
Sep 22, 2017, 7:41:18 AM (19 months ago)
Author:
Christian Mauderer <Christian.Mauderer@…>
Branches:
647dd08ae2aa69b935c2847ea450fb824322ecae, c6261f97870562d4c797cfb1ff1ba0affb85a916
Children:
0190cfd
Parents:
b16eca9
git-author:
Christian Mauderer <Christian.Mauderer@…> (09/22/17 07:41:18)
git-committer:
Sebastian Huber <sebastian.huber@…> (09/22/17 08:17:24)
Message:

if-atsam: Port to rtems-libbsd.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • libbsd.py

    rb16eca9 r80a7fe6  
    161161            'sys/dev/smc/if_smc_nexus.c',
    162162            'sys/dev/ffec/if_ffec_mcf548x.c',
     163            'sys/dev/atsam/if_atsam.c',
    163164            'sys/dev/dw_mmc/dw_mmc.c',
    164165            'sys/fs/devfs/devfs_devs.c',
  • libbsd_waf.py

    rb16eca9 r80a7fe6  
    22222222              'rtemsbsd/rtems/rtems-routes.c',
    22232223              'rtemsbsd/rtems/syslog.c',
     2224              'rtemsbsd/sys/dev/atsam/if_atsam.c',
    22242225              'rtemsbsd/sys/dev/dw_mmc/dw_mmc.c',
    22252226              'rtemsbsd/sys/dev/ffec/if_ffec_mcf548x.c',
  • rtemsbsd/include/bsp/nexus-devices.h

    rb16eca9 r80a7fe6  
    9696RTEMS_BSD_DRIVER_USB;
    9797RTEMS_BSD_DRIVER_USB_MASS;
     98RTEMS_BSD_DRIVER_IF_ATSAM;
     99SYSINIT_DRIVER_REFERENCE(ukphy, miibus);
    98100
    99101#elif defined(LIBBSP_ARM_ALTERA_CYCLONE_V_BSP_H)
  • rtemsbsd/include/machine/rtems-bsd-nexus-bus.h

    rb16eca9 r80a7fe6  
    309309    RTEMS_BSD_DEFINE_NEXUS_DEVICE(fec, 0, 0, NULL);
    310310#endif /* RTEMS_BSD_DRIVER_FEC */
     311
     312/*
     313 * Atmel SAMv71 Ethernet Controller (sam) driver.
     314 */
     315#if !defined(RTEMS_BSD_DRIVER_IF_ATSAM)
     316  #define RTEMS_BSD_DRIVER_IF_ATSAM                       \
     317    RTEMS_BSD_DEFINE_NEXUS_DEVICE(if_atsam, 0, 0, NULL);
     318#endif /* RTEMS_BSD_DRIVER_IF_ATSAM */
    311319
    312320/*
  • rtemsbsd/sys/dev/atsam/if_atsam.c

    rb16eca9 r80a7fe6  
    3030 */
    3131
    32 #include <libchip/chip.h>
    33 #include <libchip/include/gmacd.h>
    34 #include <libchip/include/pio.h>
    35 
    36 #define __INSIDE_RTEMS_BSD_TCPIP_STACK__        1
    37 #define __BSD_VISIBLE                           1
     32#include <machine/rtems-bsd-kernel-space.h>
    3833
    3934#include <bsp.h>
     35
     36#ifdef LIBBSP_ARM_ATSAM_BSP_H
     37
    4038#include <bsp/irq.h>
    4139
    4240#include <stdio.h>
    43 
    44 #include <rtems/error.h>
    45 #include <rtems/rtems_bsdnet.h>
    46 #include <rtems/rtems_mii_ioctl.h>
    4741
    4842#include <sys/types.h>
     
    5145#include <sys/socket.h>
    5246#include <sys/sockio.h>
     47#include <sys/kernel.h>
     48#include <sys/module.h>
     49#include <sys/bus.h>
    5350
    5451#include <net/if.h>
    5552#include <net/if_var.h>
    5653#include <net/if_types.h>
     54#include <net/if_media.h>
    5755
    5856#include <netinet/in.h>
     
    6058
    6159#include <dev/mii/mii.h>
     60#include <dev/mii/miivar.h>
     61
     62#include <libchip/chip.h>
     63#include <libchip/include/gmacd.h>
     64#include <libchip/include/pio.h>
     65
     66#include <rtems/rtems_mii_ioctl.h>
     67#include <rtems/bsd/local/miibus_if.h>
    6268
    6369/*
     
    8389/** The runtime pin configure list for GMAC */
    8490#define BOARD_GMAC_RUN_PINS                     BOARD_GMAC_PINS
    85 
    86 /** The PIN list of PIO for GMAC */
    87 #define BOARD_GMAC_RESET_PIN                                               \
    88                                                 { PIO_PC10, PIOC, ID_PIOC, \
    89                                                           PIO_OUTPUT_1,    \
    90                                                           PIO_PULLUP }
    9191
    9292/** Multicast Enable */
     
    123123#define WATCHDOG_TIMEOUT                        5
    124124
     125#define SIO_RTEMS_SHOW_STATS _IO('i', 250)
     126
     127/* FIXME: Make these configurable */
     128#define MDIO_RETRIES 10
     129#define MDIO_PHY MII_PHY_ANY
     130#define RXBUF_COUNT 8
     131#define TXBUF_COUNT 64
     132#define IGNORE_RX_ERR false
     133
     134
    125135/** The PINs for GMAC */
    126136static const Pin gmacPins[] = { BOARD_GMAC_RUN_PINS };
    127 
    128 static const Pin gmacResetPin = BOARD_GMAC_RESET_PIN;
    129137
    130138typedef struct if_atsam_gmac {
     
    132140        sGmacd gGmacd;
    133141        uint32_t retries;
    134         uint8_t phy_address;
    135142} if_atsam_gmac;
    136143
     
    148155         * Data
    149156         */
    150         struct arpcom arpcom;
     157        device_t dev;
     158        struct ifnet *ifp;
     159        struct mtx mtx;
    151160        if_atsam_gmac Gmac_inst;
    152         struct rtems_mdio_info mdio;
    153161        uint8_t GMacAddress[6];
    154162        rtems_id rx_daemon_tid;
     
    158166        struct mbuf **tx_mbuf;
    159167        volatile sGmacTxDescriptor *tx_bd_base;
    160         uint32_t anlpar;
    161168        size_t rx_bd_fill_idx;
    162169        size_t amount_rx_buf;
    163170        size_t amount_tx_buf;
    164171        ring_buffer tx_ring;
     172
     173        /*
     174         * mii bus
     175         */
     176        device_t miibus;
     177        uint8_t link_speed;
     178        uint8_t link_duplex;
     179        struct callout mii_tick_ch;
    165180
    166181        /*
     
    177192} if_atsam_softc;
    178193
    179 static struct if_atsam_softc if_atsam_softc_inst;
     194static void if_atsam_watchdog(void *arg);
     195
     196#define IF_ATSAM_LOCK(sc) mtx_lock(&(sc)->mtx)
     197
     198#define IF_ATSAM_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
     199
     200static void if_atsam_event_send(rtems_id task, rtems_event_set event)
     201{
     202        rtems_event_send(task, event);
     203}
     204
     205
     206static void if_atsam_event_receive(if_atsam_softc *sc, rtems_event_set in)
     207{
     208        rtems_event_set out;
     209
     210        IF_ATSAM_UNLOCK(sc);
     211        rtems_event_receive(
     212            in,
     213            RTEMS_EVENT_ANY | RTEMS_WAIT,
     214            RTEMS_NO_TIMEOUT,
     215            &out
     216        );
     217        IF_ATSAM_LOCK(sc);
     218}
     219
    180220
    181221static struct mbuf *if_atsam_new_mbuf(struct ifnet *ifp)
     
    183223        struct mbuf *m;
    184224
    185         MGETHDR(m, M_DONTWAIT, MT_DATA);
     225        MGETHDR(m, M_NOWAIT, MT_DATA);
    186226        if (m != NULL) {
    187                 MCLGET(m, M_DONTWAIT);
     227                MCLGET(m, M_NOWAIT);
    188228                if ((m->m_flags & M_EXT) != 0) {
    189229                        m->m_pkthdr.rcvif = ifp;
     
    245285
    246286
    247 static void atsamv7_find_valid_phy(if_atsam_gmac *gmac_inst)
    248 {
    249         Gmac *pHw = gmac_inst->gGmacd.pHw;
    250         uint32_t value = 0;
    251         uint8_t phy_address;
    252         int i;
    253 
    254         if (gmac_inst->phy_address != 0xFF) {
    255                 return;
    256         }
    257 
    258         /* Find another one */
    259         phy_address = 0xFF;
    260 
    261         for (i = 31; i >= 0; --i) {
    262                 int rv;
    263 
    264                 rv = if_atsam_read_phy(pHw, (uint8_t)i, MII_PHYIDR1,
    265                     &value, gmac_inst->retries);
    266                 if (rv == 0 && value != 0 && value < 0xffff) {
    267                         phy_address = (uint8_t)i;
    268                         break;
    269                 }
    270         }
    271 
    272         if (phy_address != 0xFF) {
    273                 if_atsam_read_phy(pHw, phy_address, MII_PHYIDR1, &value,
    274                     gmac_inst->retries);
    275                 if_atsam_read_phy(pHw, phy_address, MII_PHYIDR2, &value,
    276                     gmac_inst->retries);
    277                 gmac_inst->phy_address = phy_address;
    278         }
    279 }
    280 
    281 
    282 static uint8_t if_atsam_reset_phy(if_atsam_gmac *gmac_inst)
    283 {
    284         uint32_t retry_max;
    285         uint32_t bmcr;
    286         uint8_t phy_address;
    287         uint32_t timeout = 10;
    288         uint8_t ret = 0;
    289 
    290         Gmac *pHw = gmac_inst->gGmacd.pHw;
    291 
    292         phy_address = gmac_inst->phy_address;
    293         retry_max = gmac_inst->retries;
    294 
    295         bmcr = BMCR_RESET;
    296         if_atsam_write_phy(pHw, phy_address, MII_BMCR, bmcr, retry_max);
    297         do {
    298                 if_atsam_read_phy(pHw, phy_address, MII_BMCR, &bmcr,
    299                     retry_max);
    300                 timeout--;
    301         } while ((bmcr & BMCR_RESET) && timeout);
    302 
    303         if (!timeout) {
    304                 ret = 1;
    305         }
    306         return (ret);
    307 }
    308 
    309 
    310287static uint8_t
    311288if_atsam_init_phy(if_atsam_gmac *gmac_inst, uint32_t mck,
     
    332309                        return (0);
    333310                }
    334                 if_atsam_reset_phy(gmac_inst);
    335311        }
    336312        return (rc);
    337313}
    338314
    339 static bool if_atsam_is_valid_phy(int phy)
    340 {
    341         return phy >= 0 && phy <= 31;
    342 }
    343 
    344 static int if_atsam_mdio_read(int phy, void *arg, unsigned reg, uint32_t *pval)
    345 {
    346         if_atsam_softc *sc = (if_atsam_softc *)arg;
    347 
    348         if (!if_atsam_is_valid_phy(phy)) {
    349                 return (EINVAL);
    350         }
    351 
    352         return (if_atsam_read_phy(sc->Gmac_inst.gGmacd.pHw,
    353             (uint8_t)phy, (uint8_t)reg, pval, sc->Gmac_inst.retries));
    354 }
    355 
    356 
    357 static int if_atsam_mdio_write(int phy, void *arg, unsigned reg, uint32_t pval)
    358 {
    359         if_atsam_softc *sc = (if_atsam_softc *)arg;
    360 
    361         if (!if_atsam_is_valid_phy(phy)) {
    362                 return (EINVAL);
    363         }
    364 
    365         return if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw,
    366             (uint8_t)phy, (uint8_t)reg, pval, sc->Gmac_inst.retries);
     315
     316static int
     317if_atsam_miibus_readreg(device_t dev, int phy, int reg)
     318{
     319        uint32_t val;
     320        uint8_t err;
     321        if_atsam_softc *sc = device_get_softc(dev);
     322
     323        IF_ATSAM_LOCK(sc);
     324        err = if_atsam_read_phy(sc->Gmac_inst.gGmacd.pHw,
     325            (uint8_t)phy, (uint8_t)reg, &val, sc->Gmac_inst.retries);
     326        IF_ATSAM_UNLOCK(sc);
     327
     328        return (err == 0 ? val : 0);
     329}
     330
     331
     332static int
     333if_atsam_miibus_writereg(device_t dev, int phy, int reg, int data)
     334{
     335        uint8_t err;
     336        if_atsam_softc *sc = device_get_softc(dev);
     337
     338        IF_ATSAM_LOCK(sc);
     339        err = if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw,
     340            (uint8_t)phy, (uint8_t)reg, data, sc->Gmac_inst.retries);
     341        IF_ATSAM_UNLOCK(sc);
     342
     343        return 0;
    367344}
    368345
     
    395372                /* Erase the interrupts for RX completion and errors */
    396373                GMAC_DisableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
    397                 (void)rtems_bsdnet_event_send(sc->rx_daemon_tid, rx_event);
     374                (void)if_atsam_event_send(sc->rx_daemon_tid, rx_event);
    398375        }
    399376        if ((irq_status_val & GMAC_IER_TUR) != 0) {
     
    422399                /* Erase the interrupts for TX completion and errors */
    423400                GMAC_DisableIt(pHw, GMAC_INT_TX_BITS, 0);
    424                 (void)rtems_bsdnet_event_send(sc->tx_daemon_tid, tx_event);
     401                (void)if_atsam_event_send(sc->tx_daemon_tid, tx_event);
    425402        }
    426403}
     
    431408{
    432409        if_atsam_softc *sc = (if_atsam_softc *)arg;
     410        struct ifnet *ifp = sc->ifp;
    433411        rtems_event_set events = 0;
    434412        void *rx_bd_base;
     
    437415        volatile sGmacRxDescriptor *buffer_desc;
    438416        int frame_len;
    439         struct ether_header *eh;
    440417        uint32_t tmp_rx_bd_address;
    441 
     418        size_t i;
    442419        Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
     420
     421        IF_ATSAM_LOCK(sc);
     422
     423        if (IGNORE_RX_ERR) {
     424                pHw->GMAC_NCFGR |= GMAC_NCFGR_IRXER;
     425        } else {
     426                pHw->GMAC_NCFGR &= ~GMAC_NCFGR_IRXER;
     427        }
    443428
    444429        /* Allocate memory space for priority queue descriptor list */
     
    464449        for (sc->rx_bd_fill_idx = 0; sc->rx_bd_fill_idx < sc->amount_rx_buf;
    465450            ++sc->rx_bd_fill_idx) {
    466                 m = if_atsam_new_mbuf(&sc->arpcom.ac_if);
     451                m = if_atsam_new_mbuf(ifp);
    467452                assert(m != NULL);
    468453                sc->rx_mbuf[sc->rx_bd_fill_idx] = m;
     
    498483        while (true) {
    499484                /* Wait for events */
    500                 rtems_bsdnet_event_receive(ATSAMV7_ETH_RX_EVENT_INTERRUPT,
    501                     RTEMS_EVENT_ANY | RTEMS_WAIT,
    502                     RTEMS_NO_TIMEOUT, &events);
     485                if_atsam_event_receive(sc, ATSAMV7_ETH_RX_EVENT_INTERRUPT);
    503486
    504487                /*
     
    510493
    511494                                /* New mbuf for desc */
    512                                 n = if_atsam_new_mbuf(&sc->arpcom.ac_if);
     495                                n = if_atsam_new_mbuf(ifp);
    513496                                if (n != NULL) {
    514497                                        frame_len = (int)
    515498                                            (buffer_desc->status.bm.len);
    516499
    517                                         /* Discard Ethernet header */
    518                                         int sz = frame_len - ETHER_HDR_LEN;
    519 
    520500                                        /* Update mbuf */
    521                                         eh = (struct ether_header *)
    522                                             (mtod(m, char *) + 2);
    523                                         m->m_len = sz;
    524                                         m->m_pkthdr.len = sz;
    525                                         m->m_data = (void *)(eh + 1);
    526                                         ether_input(&sc->arpcom.ac_if, eh, m);
     501                                        m->m_data = mtod(m, char*)+ETHER_ALIGN;
     502                                        m->m_len = frame_len;
     503                                        m->m_pkthdr.len = frame_len;
     504                                        IF_ATSAM_UNLOCK(sc);
     505                                        sc->ifp->if_input(ifp, m);
     506                                        IF_ATSAM_LOCK(sc);
    527507                                        m = n;
    528508                                } else {
    529                                         (void)rtems_bsdnet_event_send(
     509                                        (void)if_atsam_event_send(
    530510                                            sc->tx_daemon_tid, ATSAMV7_ETH_START_TRANSMIT_EVENT);
    531511                                }
     
    706686        bool success;
    707687
     688        IF_ATSAM_LOCK(sc);
     689
    708690        Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
    709         struct ifnet *ifp = &sc->arpcom.ac_if;
     691        struct ifnet *ifp = sc->ifp;
    710692
    711693        GMAC_TransmitEnable(pHw, 0);
     
    753735        while (true) {
    754736                /* Wait for events */
    755                 rtems_bsdnet_event_receive(ATSAMV7_ETH_START_TRANSMIT_EVENT | ATSAMV7_ETH_TX_EVENT_INTERRUPT,
    756                     RTEMS_EVENT_ANY | RTEMS_WAIT,
    757                     RTEMS_NO_TIMEOUT, &events);
     737                if_atsam_event_receive(sc,
     738                    ATSAMV7_ETH_START_TRANSMIT_EVENT |
     739                    ATSAMV7_ETH_TX_EVENT_INTERRUPT);
    758740                //printf("TX Transmit Event received\n");
    759741
     
    766748                         */
    767749                        if_atsam_tx_bd_cleanup(sc);
    768                         IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
     750                        IF_DEQUEUE(&ifp->if_snd, m);
    769751                        if (!m) {
    770                                 ifp->if_flags &= ~IFF_OACTIVE;
     752                                ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
    771753                                break;
    772754                        }
     
    787769        if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
    788770
    789         ifp->if_flags |= IFF_OACTIVE;
    790         rtems_bsdnet_event_send(sc->tx_daemon_tid,
     771        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
     772        if_atsam_event_send(sc->tx_daemon_tid,
    791773            ATSAMV7_ETH_START_TRANSMIT_EVENT);
    792774}
    793775
    794776
    795 /*
    796  * Attach a watchdog for autonegotiation to the system
    797  */
    798 static void if_atsam_interface_watchdog(struct ifnet *ifp)
    799 {
    800         uint32_t anlpar;
    801         uint8_t speed = GMAC_SPEED_100M;
    802         uint8_t full_duplex = GMAC_DUPLEX_FULL;
    803 
    804         if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
     777static void if_atsam_miibus_statchg(device_t dev)
     778{
     779        uint8_t link_speed = GMAC_SPEED_100M;
     780        uint8_t link_duplex = GMAC_DUPLEX_FULL;
     781        if_atsam_softc *sc = device_get_softc(dev);
     782        struct mii_data *mii = device_get_softc(sc->miibus);
     783
    805784        Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
    806         uint8_t phy = sc->Gmac_inst.phy_address;
    807         uint32_t retries = sc->Gmac_inst.retries;
    808 
    809         if (if_atsam_read_phy(pHw, phy, MII_ANLPAR, &anlpar, retries)) {
    810                 anlpar = 0;
    811         }
    812         if (sc->anlpar != anlpar) {
    813                 /* Set up the GMAC link speed */
    814                 if (anlpar & ANLPAR_TX_FD) {
    815                         /* Set MII for 100BaseTx and Full Duplex */
    816                         speed = GMAC_SPEED_100M;
    817                         full_duplex = GMAC_DUPLEX_FULL;
    818                 } else if (anlpar & ANLPAR_10_FD) {
    819                         /* Set MII for 10BaseTx and Full Duplex */
    820                         speed = GMAC_SPEED_10M;
    821                         full_duplex = GMAC_DUPLEX_FULL;
    822                 } else if (anlpar & ANLPAR_TX) {
    823                         /* Set MII for 100BaseTx and half Duplex */
    824                         speed = GMAC_SPEED_100M;
    825                         full_duplex = GMAC_DUPLEX_HALF;
    826                 } else if (anlpar & ANLPAR_10) {
    827                         /* Set MII for 10BaseTx and half Duplex */
    828                         speed = GMAC_SPEED_10M;
    829                         full_duplex = GMAC_DUPLEX_HALF;
    830                 } else {
    831                         /* Set MII for 100BaseTx and Full Duplex */
    832                         speed = GMAC_SPEED_100M;
    833                         full_duplex = GMAC_DUPLEX_FULL;
    834                 }
    835                 GMAC_SetLinkSpeed(pHw, speed, full_duplex);
    836                 sc->anlpar = anlpar;
    837         }
    838         ifp->if_timer = WATCHDOG_TIMEOUT;
     785
     786        if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
     787                link_duplex = GMAC_DUPLEX_FULL;
     788        } else {
     789                link_duplex = GMAC_DUPLEX_HALF;
     790        }
     791
     792        switch (IFM_SUBTYPE(mii->mii_media_active)) {
     793        case IFM_10_T:
     794                link_speed = GMAC_SPEED_10M;
     795                break;
     796        case IFM_100_TX:
     797                link_speed = GMAC_SPEED_100M;
     798                break;
     799        case IFM_1000_T:
     800                link_speed = GMAC_SPEED_1000M;
     801                break;
     802        default:
     803                /* FIXME: What to do in that case? */
     804                break;
     805        }
     806
     807        if (sc->link_speed != link_speed || sc->link_duplex != link_duplex) {
     808                GMAC_SetLinkSpeed(pHw, link_speed, link_duplex);
     809                sc->link_speed = link_speed;
     810                sc->link_duplex = link_duplex;
     811        }
     812}
     813
     814
     815static int
     816if_atsam_mii_ifmedia_upd(struct ifnet *ifp)
     817{
     818        if_atsam_softc *sc;
     819        struct mii_data *mii;
     820
     821        sc = ifp->if_softc;
     822        if (sc->miibus == NULL)
     823                return (ENXIO);
     824
     825        mii = device_get_softc(sc->miibus);
     826        return (mii_mediachg(mii));
     827}
     828
     829
     830static void
     831if_atsam_mii_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
     832{
     833        if_atsam_softc *sc;
     834        struct mii_data *mii;
     835
     836        sc = ifp->if_softc;
     837        if (sc->miibus == NULL)
     838                return;
     839
     840        mii = device_get_softc(sc->miibus);
     841        mii_pollstat(mii);
     842        ifmr->ifm_active = mii->mii_media_active;
     843        ifmr->ifm_status = mii->mii_media_status;
     844}
     845
     846
     847static void
     848if_atsam_mii_tick(void *context)
     849{
     850        if_atsam_softc *sc = context;
     851
     852        if (sc->miibus == NULL)
     853                return;
     854
     855        IF_ATSAM_UNLOCK(sc);
     856
     857        mii_tick(device_get_softc(sc->miibus));
     858        callout_reset(&sc->mii_tick_ch, hz, if_atsam_mii_tick, sc);
    839859}
    840860
     
    848868
    849869        if_atsam_softc *sc = (if_atsam_softc *)arg;
    850         struct ifnet *ifp = &sc->arpcom.ac_if;
     870        struct ifnet *ifp = sc->ifp;
    851871        uint32_t dmac_cfg = 0;
    852872        uint32_t gmii_val = 0;
    853873
    854         if (sc->arpcom.ac_if.if_flags & IFF_RUNNING) {
     874        if (ifp->if_flags & IFF_DRV_RUNNING) {
    855875                return;
    856876        }
    857         sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
     877        ifp->if_flags |= IFF_DRV_RUNNING;
    858878        sc->interrupt_number = GMAC_IRQn;
    859879
     
    868888        NVIC_ClearPendingIRQ(GMAC_IRQn);
    869889        NVIC_EnableIRQ(GMAC_IRQn);
    870 
    871         GMACD_Init(&sc->Gmac_inst.gGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE,
    872             GMAC_NBC_DISABLE);
    873 
    874         /* Enable MDIO interface */
    875         GMAC_EnableMdio(sc->Gmac_inst.gGmacd.pHw);
    876 
    877         /* PHY initialize */
    878         if_atsam_init_phy(&sc->Gmac_inst, BOARD_MCK, &gmacResetPin, 1,
    879             gmacPins, PIO_LISTSIZE(gmacPins));
    880         /* Find valid Phy */
    881         atsamv7_find_valid_phy(&sc->Gmac_inst);
    882 
    883         /* Set Link Speed */
    884         sc->anlpar = 0xFFFFFFFF;
    885         if_atsam_interface_watchdog(ifp);
    886 
    887         /* Enable autonegotation */
    888         if_atsam_read_phy(sc->Gmac_inst.gGmacd.pHw, sc->Gmac_inst.phy_address,
    889             MII_BMCR, &gmii_val, sc->Gmac_inst.retries);
    890         if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw, sc->Gmac_inst.phy_address,
    891             MII_BMCR, (gmii_val | BMCR_AUTOEN), sc->Gmac_inst.retries);
    892890
    893891        /* Configuration of DMAC */
     
    906904         */
    907905        sc->rx_mbuf = malloc(sc->amount_rx_buf * sizeof *sc->rx_mbuf,
    908                 M_MBUF, M_NOWAIT);
     906                M_TEMP, M_NOWAIT);
    909907        sc->tx_mbuf = malloc(sc->amount_tx_buf * sizeof *sc->tx_mbuf,
    910                 M_MBUF, M_NOWAIT);
     908                M_TEMP, M_NOWAIT);
    911909
    912910        /* Install interrupt handler */
     
    926924                if_atsam_tx_daemon, sc);
    927925
    928         /* Start Watchdog Timer */
    929         ifp->if_timer = 1;
     926        callout_reset(&sc->mii_tick_ch, hz, if_atsam_mii_tick, sc);
     927
     928        ifp->if_drv_flags |= IFF_DRV_RUNNING;
    930929}
    931930
     
    936935static void if_atsam_stop(struct if_atsam_softc *sc)
    937936{
    938         struct ifnet *ifp = &sc->arpcom.ac_if;
     937        struct ifnet *ifp = sc->ifp;
    939938        Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
    940939
    941         ifp->if_flags &= ~IFF_RUNNING;
     940        ifp->if_flags &= ~IFF_DRV_RUNNING;
    942941
    943942        /* Disable MDIO interface and TX/RX */
     
    953952{
    954953        int eno = EIO;
    955         int media = 0;
    956954        Gmac *pHw;
    957955
    958         media = (int)IFM_MAKEWORD(0, 0, 0, sc->Gmac_inst.phy_address);
    959         eno = rtems_mii_ioctl(&sc->mdio, sc, SIOCGIFMEDIA, &media);
    960 
    961         rtems_bsdnet_semaphore_release();
    962 
    963         if (eno == 0) {
    964                 rtems_ifmedia2str(media, NULL, 0);
    965                 printf("\n");
    966         }
    967956        pHw = sc->Gmac_inst.gGmacd.pHw;
    968957
     
    10251014        printf("TCP Checksum Errors: %lu\n", pHw->GMAC_TCE);
    10261015        printf("UDP Checksum Errors: %lu\n", pHw->GMAC_UCE);
    1027 
    1028         rtems_bsdnet_semaphore_obtain();
    10291016}
    10301017
     
    10721059
    10731060
    1074 /*
    1075  * Multicast handler
    1076  */
    10771061static int
    1078 if_atsam_multicast_control(bool add, struct ifreq *ifr, if_atsam_softc *sc)
    1079 {
    1080         int eno = 0;
    1081         struct arpcom *ac = &sc->arpcom;
    1082         Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
    1083 
    1084         /* Switch off Multicast Hashing */
    1085         pHw->GMAC_NCFGR &= ~GMAC_MC_ENABLE;
    1086 
    1087         if (add) {
    1088                 eno = ether_addmulti(ifr, ac);
    1089         } else {
    1090                 eno = ether_delmulti(ifr, ac);
    1091         }
    1092 
    1093         if (eno == ENETRESET) {
    1094                 struct ether_multistep step;
    1095                 struct ether_multi *enm;
    1096 
    1097                 eno = 0;
    1098 
    1099                 pHw->GMAC_HRB = 0;
    1100                 pHw->GMAC_HRT = 0;
    1101 
    1102                 ETHER_FIRST_MULTI(step, ac, enm);
    1103                 while (enm != NULL) {
    1104                         uint64_t addrlo = 0;
    1105                         uint64_t addrhi = 0;
    1106                         uint32_t val = 0;
    1107 
    1108                         memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
    1109                         memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
    1110                         while (addrlo <= addrhi) {
    1111                                 if_atsam_get_hash_index(addrlo, &val);
    1112                                 if (val < 32) {
    1113                                         pHw->GMAC_HRB |= (1u << val);
    1114                                 } else {
    1115                                         pHw->GMAC_HRT |= (1u << (val - 32));
    1116                                 }
    1117                                 ++addrlo;
    1118                         }
    1119                         ETHER_NEXT_MULTI(step, enm);
    1120                 }
    1121         }
    1122         /* Switch on Multicast Hashing */
    1123         pHw->GMAC_NCFGR |= GMAC_MC_ENABLE;
    1124         return (eno);
     1062if_atsam_mediaioctl(if_atsam_softc *sc, struct ifreq *ifr, u_long command)
     1063{
     1064        struct mii_data *mii;
     1065
     1066        if (sc->miibus == NULL)
     1067                return (EINVAL);
     1068
     1069        mii = device_get_softc(sc->miibus);
     1070        return (ifmedia_ioctl(sc->ifp, ifr, &mii->mii_media, command));
    11251071}
    11261072
     
    11321078if_atsam_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
    11331079{
    1134         struct if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
     1080        if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
    11351081        struct ifreq *ifr = (struct ifreq *)data;
    11361082        int rv = 0;
    11371083        bool prom_enable;
     1084        struct mii_data *mii;
    11381085
    11391086        switch (command) {
    11401087        case SIOCGIFMEDIA:
    11411088        case SIOCSIFMEDIA:
    1142                 rtems_mii_ioctl(&sc->mdio, sc, command, &ifr->ifr_media);
    1143                 break;
    1144         case SIOCGIFADDR:
    1145         case SIOCSIFADDR:
    1146                 ether_ioctl(ifp, command, data);
     1089                rv = if_atsam_mediaioctl(sc, ifr, command);
    11471090                break;
    11481091        case SIOCSIFFLAGS:
    11491092                if (ifp->if_flags & IFF_UP) {
    1150                         if (ifp->if_flags & IFF_RUNNING) {
    1151                                 /* Don't do anything */
    1152                         } else {
     1093                        if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
    11531094                                if_atsam_init(sc);
    11541095                        }
     
    11561097                        if_atsam_promiscuous_mode(sc, prom_enable);
    11571098                } else {
    1158                         if (ifp->if_flags & IFF_RUNNING) {
     1099                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
    11591100                                if_atsam_stop(sc);
    11601101                        }
    11611102                }
    1162                 break;
    1163         case SIOCADDMULTI:
    1164         case SIOCDELMULTI:
    1165                 if_atsam_multicast_control(command == SIOCADDMULTI, ifr, sc);
    11661103                break;
    11671104        case SIO_RTEMS_SHOW_STATS:
     
    11691106                break;
    11701107        default:
    1171                 rv = EINVAL;
     1108                rv = ether_ioctl(ifp, command, data);
    11721109                break;
    11731110        }
     
    11751112}
    11761113
    1177 
    11781114/*
    11791115 * Attach an SAMV71 driver to the system
    11801116 */
    1181 static int if_atsam_driver_attach(struct rtems_bsdnet_ifconfig *config)
    1182 {
    1183         if_atsam_softc *sc = &if_atsam_softc_inst;
    1184         struct ifnet *ifp = &sc->arpcom.ac_if;
    1185         const if_atsam_config *conf = config->drv_ctrl;
    1186         int unitNumber;
     1117static int if_atsam_driver_attach(device_t dev)
     1118{
     1119        if_atsam_softc *sc;
     1120        struct ifnet *ifp;
     1121        int unit;
    11871122        char *unitName;
    1188 
    1189         if (conf != NULL) {
    1190                 sc->Gmac_inst.retries = conf->mdio_retries;
    1191                 sc->Gmac_inst.phy_address = conf->phy_addr;
    1192         } else {
    1193                 sc->Gmac_inst.retries = 10;
    1194                 sc->Gmac_inst.phy_address = 0xFF;
    1195         }
    1196 
    1197         /* The MAC address used */
    1198         memcpy(sc->GMacAddress, config->hardware_address, ETHER_ADDR_LEN);
    1199         memcpy(sc->arpcom.ac_enaddr, sc->GMacAddress, ETHER_ADDR_LEN);
    1200 
    1201         /*
    1202          * Parse driver name
    1203          */
    1204         unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName);
    1205         assert(unitNumber == 0);
    1206 
    1207         assert(ifp->if_softc == NULL);
    1208 
    1209         /* MDIO */
    1210         sc->mdio.mdio_r = if_atsam_mdio_read;
    1211         sc->mdio.mdio_w = if_atsam_mdio_write;
    1212         sc->mdio.has_gmii = 1;
    1213 
    1214         if (config->rbuf_count > 0) {
    1215                 sc->amount_rx_buf = config->rbuf_count;
    1216         } else {
    1217                 sc->amount_rx_buf = 8;
    1218         }
    1219 
    1220         if (config->xbuf_count > 0) {
    1221                 sc->amount_tx_buf = config->xbuf_count;
    1222         } else {
    1223                 sc->amount_tx_buf = 64;
    1224         }
     1123        uint8_t eaddr[ETHER_ADDR_LEN];
     1124
     1125        sc = device_get_softc(dev);
     1126        unit = device_get_unit(dev);
     1127        assert(unit == 0);
     1128
     1129        sc->dev = dev;
     1130        sc->ifp = ifp = if_alloc(IFT_ETHER);
     1131
     1132        mtx_init(&sc->mtx, device_get_nameunit(sc->dev), MTX_NETWORK_LOCK,
     1133            MTX_DEF);
     1134
     1135        rtems_bsd_get_mac_address(device_get_name(sc->dev), unit, eaddr);
     1136
     1137        sc->Gmac_inst.retries = MDIO_RETRIES;
     1138
     1139        memcpy(sc->GMacAddress, eaddr, ETHER_ADDR_LEN);
     1140
     1141        sc->amount_rx_buf = RXBUF_COUNT;
     1142        sc->amount_tx_buf = TXBUF_COUNT;
    12251143
    12261144        sc->tx_ring.tx_bd_used = 0;
    12271145        sc->tx_ring.tx_bd_free = 0;
    12281146        sc->tx_ring.length = sc->amount_tx_buf;
     1147
     1148        /* Set Initial Link Speed */
     1149        sc->link_speed = GMAC_SPEED_100M;
     1150        sc->link_duplex = GMAC_DUPLEX_FULL;
     1151
     1152        GMACD_Init(&sc->Gmac_inst.gGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE,
     1153            GMAC_NBC_DISABLE);
     1154
     1155        /* Enable MDIO interface */
     1156        GMAC_EnableMdio(sc->Gmac_inst.gGmacd.pHw);
     1157
     1158        /* PHY initialize */
     1159        if_atsam_init_phy(&sc->Gmac_inst, BOARD_MCK, NULL, 0,
     1160            gmacPins, PIO_LISTSIZE(gmacPins));
     1161
     1162        /*
     1163         * MII Bus
     1164         */
     1165        callout_init_mtx(&sc->mii_tick_ch, &sc->mtx, CALLOUT_RETURNUNLOCKED);
     1166        mii_attach(dev, &sc->miibus, ifp,
     1167            if_atsam_mii_ifmedia_upd, if_atsam_mii_ifmedia_sts, BMSR_DEFCAPMASK,
     1168            MDIO_PHY, MII_OFFSET_ANY, 0);
    12291169
    12301170        /*
     
    12321172         */
    12331173        ifp->if_softc = sc;
    1234         ifp->if_unit = (short int)unitNumber;
    1235         ifp->if_name = unitName;
    1236         ifp->if_mtu = ETHERMTU;
     1174        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
    12371175        ifp->if_init = if_atsam_init;
    12381176        ifp->if_ioctl = if_atsam_ioctl;
    12391177        ifp->if_start = if_atsam_enet_start;
    1240         ifp->if_output = ether_output;
    1241         ifp->if_watchdog = if_atsam_interface_watchdog;
    1242         ifp->if_flags = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX;
    1243         ifp->if_snd.ifq_maxlen = ifqmaxlen;
    1244         ifp->if_timer = 0;
     1178        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
     1179        IFQ_SET_MAXLEN(&ifp->if_snd, TXBUF_COUNT - 1);
     1180        ifp->if_snd.ifq_drv_maxlen = TXBUF_COUNT - 1;
     1181        IFQ_SET_READY(&ifp->if_snd);
    12451182
    12461183        /*
    12471184         * Attach the interface
    12481185         */
    1249         if_attach(ifp);
    1250         ether_ifattach(ifp);
    1251         return (1);
    1252 }
    1253 
    1254 
    1255 int if_atsam_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
    1256 {
    1257         (void)attaching;
    1258         return (if_atsam_driver_attach(config));
    1259 }
     1186        ether_ifattach(ifp, eaddr);
     1187
     1188        return (0);
     1189}
     1190
     1191static int
     1192if_atsam_probe(device_t dev)
     1193{
     1194        int unit = device_get_unit(dev);
     1195        int error;
     1196
     1197        if (unit >= 0 && unit < NIFACES) {
     1198                error = BUS_PROBE_DEFAULT;
     1199        } else {
     1200                error = ENXIO;
     1201        }
     1202
     1203        return (error);
     1204}
     1205
     1206static device_method_t if_atsam_methods[] = {
     1207        DEVMETHOD(device_probe,         if_atsam_probe),
     1208        DEVMETHOD(device_attach,        if_atsam_driver_attach),
     1209        DEVMETHOD(miibus_readreg,       if_atsam_miibus_readreg),
     1210        DEVMETHOD(miibus_writereg,      if_atsam_miibus_writereg),
     1211        DEVMETHOD(miibus_statchg,       if_atsam_miibus_statchg),
     1212        DEVMETHOD_END
     1213};
     1214
     1215static driver_t if_atsam_nexus_driver = {
     1216        "if_atsam",
     1217        if_atsam_methods,
     1218        sizeof(struct if_atsam_softc)
     1219};
     1220
     1221static devclass_t if_atsam_devclass;
     1222DRIVER_MODULE(if_atsam, nexus, if_atsam_nexus_driver, if_atsam_devclass, 0, 0);
     1223MODULE_DEPEND(if_atsam, miibus, 1, 1, 1);
     1224MODULE_DEPEND(if_atsam, nexus, 1, 1, 1);
     1225MODULE_DEPEND(if_atsam, ether, 1, 1, 1);
     1226DRIVER_MODULE(miibus, if_atsam, miibus_driver, miibus_devclass, NULL, NULL);
     1227
     1228#endif /* LIBBSP_ARM_ATSAM_BSP_H */
Note: See TracChangeset for help on using the changeset viewer.