diff --git a/arch/arm/src/sam34/sam_emac.c b/arch/arm/src/sam34/sam_emac.c index dc881c605c..3e4a9b92de 100644 --- a/arch/arm/src/sam34/sam_emac.c +++ b/arch/arm/src/sam34/sam_emac.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "up_arch.h" #include "up_internal.h" @@ -370,6 +371,9 @@ static int sam_txavail(struct net_driver_s *dev); static int sam_addmac(struct net_driver_s *dev, const uint8_t *mac); static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac); #endif +#ifdef CONFIG_NETDEV_PHY_IOCTL +static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg); +#endif /* PHY Initialization */ @@ -1759,6 +1763,89 @@ static int sam_rmmac(struct net_driver_s *dev, const uint8_t *mac) } #endif +/**************************************************************************** + * Function: sam_ioctl + * + * Description: + * Handles driver ioctl calls: + * + * SIOCMIINOTIFY - Set up to received notifications from PHY interrupting + * events. + * + * SIOCGMIIPHY, SIOCGMIIREG, and SIOCSMIIREG: + * Executes the SIOCxMIIxxx command and responds using the request struct + * that must be provided as its 2nd parameter. + * + * When called with SIOCGMIIPHY it will get the PHY address for the device + * and write it to the req->phy_id field of the request struct. + * + * When called with SIOCGMIIREG it will read a register of the PHY that is + * specified using the req->reg_no struct field and then write its output + * to the req->val_out field. + * + * When called with SIOCSMIIREG it will write to a register of the PHY that + * is specified using the req->reg_no struct field and use req->val_in as + * its input. + * + * Parameters: + * dev - Ethernet device structure + * cmd - SIOCxMIIxxx command code + * arg - Request structure also used to return values + * + * Returned Value: Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_PHY_IOCTL +static int sam_ioctl(struct net_driver_s *dev, int cmd, long arg) +{ + struct sam_emac_s *priv = (struct sam_emac_s *)dev->d_private; + int ret; + + switch (cmd) + { +#ifdef CONFIG_ARCH_PHY_INTERRUPT + case SIOCMIINOTIFY: /* Set up for PHY event notifications */ + { + struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg); + ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg); + } + break; +#endif + + case SIOCGMIIPHY: /* Get MII PHY address */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + req->phy_id = priv->phyaddr; + ret = OK; + } + break; + + case SIOCGMIIREG: /* Get register from MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = sam_phyread(priv, req->phy_id, req->reg_num, &req->val_out); + } + break; + + case SIOCSMIIREG: /* Set register in MII PHY */ + { + struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); + ret = sam_phywrite(priv, req->phy_id, req->reg_num, req->val_in); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_PHY_IOCTL */ + /**************************************************************************** * Function: sam_phydump * @@ -2842,10 +2929,13 @@ void up_netinitialize(void) #ifdef CONFIG_NET_IGMP priv->dev.d_addmac = sam_addmac; /* Add multicast MAC address */ priv->dev.d_rmmac = sam_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_PHY_IOCTL + priv->dev.d_ioctl = sam_ioctl; /* Support PHY ioctl() calls */ #endif priv->dev.d_private = (void*)&g_emac; /* Used to recover private state from dev */ - /* Create a watchdog for timing polling for and timing of transmisstions */ + /* Create a watchdog for timing polling for and timing of transmissions */ priv->txpoll = wd_create(); if (!priv->txpoll)