[rtems commit] bsps/arm: Add interface down support

Sebastian Huber sebh at rtems.org
Tue Dec 18 10:18:05 UTC 2012


Module:    rtems
Branch:    master
Commit:    2cd48da071950ad73baa3802200449c17b6a0893
Changeset: http://git.rtems.org/rtems/commit/?id=2cd48da071950ad73baa3802200449c17b6a0893

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Dec 14 13:08:10 2012 +0100

bsps/arm: Add interface down support

---

 .../arm/lpc24xx/include/lpc-ethernet-config.h      |    5 +
 .../arm/lpc32xx/include/lpc-ethernet-config.h      |    5 +
 .../libbsp/arm/shared/lpc/network/lpc-ethernet.c   |  138 ++++++++++++++------
 3 files changed, 105 insertions(+), 43 deletions(-)

diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h
index 8c787b7..26482bf 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/lpc-ethernet-config.h
@@ -92,6 +92,11 @@ extern "C" {
   }
 #endif
 
+static void lpc_eth_config_module_disable(void)
+{
+  lpc24xx_module_disable(LPC24XX_MODULE_ETHERNET);
+}
+
 static char *lpc_eth_config_alloc_table_area(size_t size)
 {
   if (size < LPC24XX_ETH_RAM_SIZE) {
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h
index 12dbd79..3dc1dc0 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/lpc-ethernet-config.h
@@ -71,6 +71,11 @@ extern "C" {
   }
 #endif
 
+static void lpc_eth_config_module_disable(void)
+{
+  LPC32XX_MAC_CLK_CTRL = 0;
+}
+
 #define LPC_ETH_CONFIG_USE_TRANSMIT_DMA
 
 static char *lpc_eth_config_alloc_table_area(size_t size)
diff --git a/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
index df71776..fd7effd 100644
--- a/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
+++ b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
@@ -253,10 +253,12 @@ static volatile lpc_eth_controller *const lpc_eth =
 
 #define LPC_ETH_EVENT_INITIALIZE RTEMS_EVENT_1
 
-#define LPC_ETH_EVENT_START RTEMS_EVENT_2
+#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2
 
 #define LPC_ETH_EVENT_INTERRUPT RTEMS_EVENT_3
 
+#define LPC_ETH_EVENT_STOP RTEMS_EVENT_4
+
 /* Status */
 
 #define LPC_ETH_INTERRUPT_RECEIVE \
@@ -560,7 +562,9 @@ static void lpc_eth_receive_task(void *arg)
   while (true) {
     /* Wait for events */
     sc = rtems_bsdnet_event_receive(
-      LPC_ETH_EVENT_INITIALIZE | LPC_ETH_EVENT_INTERRUPT,
+      LPC_ETH_EVENT_INITIALIZE
+        | LPC_ETH_EVENT_STOP
+        | LPC_ETH_EVENT_INTERRUPT,
       RTEMS_EVENT_ANY | RTEMS_WAIT,
       RTEMS_NO_TIMEOUT,
       &events
@@ -569,6 +573,14 @@ static void lpc_eth_receive_task(void *arg)
 
     LPC_ETH_PRINTF("rx: wake up: 0x%08" PRIx32 "\n", events);
 
+    /* Stop receiver? */
+    if ((events & LPC_ETH_EVENT_STOP) != 0) {
+      lpc_eth_control_request_complete(e);
+
+      /* Wait for events */
+      continue;
+    }
+
     /* Initialize receiver? */
     if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
       /* Disable receive interrupts */
@@ -799,7 +811,8 @@ static void lpc_eth_transmit_task(void *arg)
     /* Wait for events */
     sc = rtems_bsdnet_event_receive(
       LPC_ETH_EVENT_INITIALIZE
-        | LPC_ETH_EVENT_START
+        | LPC_ETH_EVENT_STOP
+        | LPC_ETH_EVENT_TXSTART
         | LPC_ETH_EVENT_INTERRUPT,
       RTEMS_EVENT_ANY | RTEMS_WAIT,
       RTEMS_NO_TIMEOUT,
@@ -809,6 +822,14 @@ static void lpc_eth_transmit_task(void *arg)
 
     LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events);
 
+    /* Stop transmitter? */
+    if ((events & LPC_ETH_EVENT_STOP) != 0) {
+      lpc_eth_control_request_complete(e);
+
+      /* Wait for events */
+      continue;
+    }
+
     /* Initialize transmitter? */
     if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
       /* Disable transmit interrupts */
@@ -1131,6 +1152,13 @@ static int lpc_eth_mdio_write(
   return eno;
 }
 
+static void lpc_eth_soft_reset(void)
+{
+  lpc_eth->command = 0x38;
+  lpc_eth->mac1 = 0xcf00;
+  lpc_eth->mac1 = 0x0;
+}
+
 static void lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
@@ -1139,12 +1167,7 @@ static void lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
   if (up && e->state == LPC_ETH_STATE_DOWN) {
     lpc_eth_config_module_enable();
 
-    /* Soft reset */
-
-    /* Do soft reset */
-    lpc_eth->command = 0x38;
-    lpc_eth->mac1 = 0xcf00;
-    lpc_eth->mac1 = 0x0;
+    lpc_eth_soft_reset();
 
     /* Initialize PHY */
     lpc_eth->mcfg = ETH_MCFG_CLOCK_SELECT(0x7);
@@ -1200,7 +1223,26 @@ static void lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
     /* Change state */
     e->state = LPC_ETH_STATE_UP;
   } else if (!up && e->state == LPC_ETH_STATE_UP) {
-    /* TODO */
+    /* Remove interrupt handler */
+    sc = rtems_interrupt_handler_remove(
+      e->interrupt_number,
+      lpc_eth_interrupt_handler,
+      e
+    );
+    assert(sc == RTEMS_SUCCESSFUL);
+
+    /* Stop tasks */
+    lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_STOP);
+    lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_STOP);
+
+    lpc_eth_soft_reset();
+    lpc_eth_config_module_disable();
+
+    /* Stop watchdog timer */
+    ifp->if_timer = 0;
+
+    /* Change state */
+    e->state = LPC_ETH_STATE_DOWN;
   }
 }
 
@@ -1211,8 +1253,13 @@ static void lpc_eth_interface_init(void *arg)
 
 static void lpc_eth_interface_stats(lpc_eth_driver_entry *e)
 {
-  int media = IFM_MAKEWORD(0, 0, 0, 0);
-  int eno = rtems_mii_ioctl(&e->mdio, e, SIOCGIFMEDIA, &media);
+  int eno = EIO;
+  int media = 0;
+
+  if (e->state == LPC_ETH_STATE_UP) {
+    media = IFM_MAKEWORD(0, 0, 0, 0);
+    eno = rtems_mii_ioctl(&e->mdio, e, SIOCGIFMEDIA, &media);
+  }
 
   rtems_bsdnet_semaphore_release();
 
@@ -1340,46 +1387,51 @@ static void lpc_eth_interface_start(struct ifnet *ifp)
 
   ifp->if_flags |= IFF_OACTIVE;
 
-  sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_START);
-  assert(sc == RTEMS_SUCCESSFUL);
+  if (e->state == LPC_ETH_STATE_UP) {
+    sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART);
+    assert(sc == RTEMS_SUCCESSFUL);
+  }
 }
 
 static void lpc_eth_interface_watchdog(struct ifnet *ifp)
 {
   lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
-  uint32_t anlpar = lpc_eth_mdio_read_anlpar();
-
-  if (e->anlpar != anlpar) {
-    bool full_duplex = false;
-    bool speed = false;
-
-    e->anlpar = anlpar;
-
-    if ((anlpar & ANLPAR_TX_FD) != 0) {
-      full_duplex = true;
-      speed = true;
-    } else if ((anlpar & ANLPAR_T4) != 0) {
-      speed = true;
-    } else if ((anlpar & ANLPAR_TX) != 0) {
-      speed = true;
-    } else if ((anlpar & ANLPAR_10_FD) != 0) {
-      full_duplex = true;
-    }
 
-    if (full_duplex) {
-      lpc_eth->mac2 |= ETH_MAC2_FULL_DUPLEX;
-    } else {
-      lpc_eth->mac2 &= ~ETH_MAC2_FULL_DUPLEX;
-    }
+  if (e->state == LPC_ETH_STATE_UP) {
+    uint32_t anlpar = lpc_eth_mdio_read_anlpar();
 
-    if (speed) {
-      lpc_eth->supp |= ETH_SUPP_SPEED;
-    } else {
-      lpc_eth->supp &= ~ETH_SUPP_SPEED;
+    if (e->anlpar != anlpar) {
+      bool full_duplex = false;
+      bool speed = false;
+
+      e->anlpar = anlpar;
+
+      if ((anlpar & ANLPAR_TX_FD) != 0) {
+        full_duplex = true;
+        speed = true;
+      } else if ((anlpar & ANLPAR_T4) != 0) {
+        speed = true;
+      } else if ((anlpar & ANLPAR_TX) != 0) {
+        speed = true;
+      } else if ((anlpar & ANLPAR_10_FD) != 0) {
+        full_duplex = true;
+      }
+
+      if (full_duplex) {
+        lpc_eth->mac2 |= ETH_MAC2_FULL_DUPLEX;
+      } else {
+        lpc_eth->mac2 &= ~ETH_MAC2_FULL_DUPLEX;
+      }
+
+      if (speed) {
+        lpc_eth->supp |= ETH_SUPP_SPEED;
+      } else {
+        lpc_eth->supp &= ~ETH_SUPP_SPEED;
+      }
     }
-  }
 
-  ifp->if_timer = WATCHDOG_TIMEOUT;
+    ifp->if_timer = WATCHDOG_TIMEOUT;
+  }
 }
 
 static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max)




More information about the vc mailing list