[libbsd 2/4] if_lpe.c: Port to LibBSD

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jun 23 09:20:18 UTC 2022


---
 libbsd.py                     |   1 +
 rtemsbsd/sys/arm/lpc/if_lpe.c | 466 +++++++++++++++++-----------------
 2 files changed, 228 insertions(+), 239 deletions(-)

diff --git a/libbsd.py b/libbsd.py
index de22eaa9..983f41a1 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -235,6 +235,7 @@ class rtems(builder.Module):
                 'rtems/rtems-legacy-rtrequest.c',
                 'rtems/rtems-legacy-newproc.c',
                 'rtems/rtems-legacy-mii.c',
+                'sys/arm/lpc/if_lpe.c',
                 'sys/arm/lpc/lpc_pwr.c',
                 'sys/dev/atsam/if_atsam.c',
                 'sys/dev/atsam/if_atsam_media.c',
diff --git a/rtemsbsd/sys/arm/lpc/if_lpe.c b/rtemsbsd/sys/arm/lpc/if_lpe.c
index ccfe1696..247bd486 100755
--- a/rtemsbsd/sys/arm/lpc/if_lpe.c
+++ b/rtemsbsd/sys/arm/lpc/if_lpe.c
@@ -22,28 +22,32 @@
 
 #include <machine/rtems-bsd-kernel-space.h>
 
-#include <errno.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
+#include <bsp.h>
 
-#include <rtems.h>
-#include <rtems/rtems_bsdnet.h>
-#include <rtems/rtems_mii_ioctl.h>
+#if defined(LIBBSP_ARM_LPC24XX_BSP_H) || defined(LIBBSP_ARM_LPC32XX_BSP_H)
 
 #include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
-#include <sys/mbuf.h>
+
+#include <sys/bus.h>
+#include <machine/bus.h>
 
 #include <net/if.h>
+#include <net/ethernet.h>
 #include <net/if_arp.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+
+#include <dev/mii/mii.h>
+
+#include <rtems/bsd/bsd.h>
 
 #include <bsp.h>
 #include <bsp/irq.h>
@@ -128,6 +132,10 @@ typedef struct {
   uint32_t powerdown;
 } lpc_eth_controller;
 
+#define LPE_LOCK(e) mtx_lock(&(e)->mtx)
+
+#define LPE_UNLOCK(e) mtx_unlock(&(e)->mtx)
+
 static volatile lpc_eth_controller *const lpc_eth = 
   (volatile lpc_eth_controller *) LPC_ETH_CONFIG_REG_BASE;
 
@@ -300,10 +308,12 @@ typedef enum {
 } lpc_eth_state;
 
 typedef struct {
-  struct arpcom arpcom;
+  device_t dev;
+  struct ifnet *ifp;
+  struct mtx mtx;
   lpc_eth_state state;
-  struct rtems_mdio_info mdio;
   uint32_t anlpar;
+  struct callout watchdog_callout;
   rtems_id receive_task;
   rtems_id transmit_task;
   unsigned rx_unit_count;
@@ -338,14 +348,18 @@ typedef struct {
   int phy;
   rtems_vector_number interrupt_number;
   rtems_id control_task;
+  int if_flags;
+  struct ifmedia ifmedia;
 } lpc_eth_driver_entry;
 
-static lpc_eth_driver_entry lpc_eth_driver_data;
+static void lpc_eth_interface_watchdog(void *arg);
+
+static void lpc_eth_setup_rxfilter(lpc_eth_driver_entry *e);
 
 static void lpc_eth_control_request_complete(const lpc_eth_driver_entry *e)
 {
   rtems_status_code sc = rtems_event_transient_send(e->control_task);
-  assert(sc == RTEMS_SUCCESSFUL);
+  BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 }
 
 static void lpc_eth_control_request(
@@ -355,17 +369,14 @@ static void lpc_eth_control_request(
 )
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  uint32_t nest_count = 0;
 
   e->control_task = rtems_task_self();
 
-  sc = rtems_bsdnet_event_send(task, event);
-  assert(sc == RTEMS_SUCCESSFUL);
+  sc = rtems_event_send(task, event);
+  BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
-  nest_count = rtems_bsdnet_semaphore_release_recursive();
   sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-  assert(sc == RTEMS_SUCCESSFUL);
-  rtems_bsdnet_semaphore_obtain_recursive(nest_count);
+  BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
   e->control_task = 0;
 }
@@ -418,7 +429,7 @@ static void lpc_eth_interrupt_handler(void *arg)
   /* Send events to receive task */
   if (re != 0) {
     ++e->receive_interrupts;
-    (void) rtems_bsdnet_event_send(e->receive_task, re);
+    (void) rtems_event_send(e->receive_task, re);
   }
 
   /* Check transmit interrupts */
@@ -433,7 +444,7 @@ static void lpc_eth_interrupt_handler(void *arg)
   /* Send events to transmit task */
   if (te != 0) {
     ++e->transmit_interrupts;
-    (void) rtems_bsdnet_event_send(e->transmit_task, te);
+    (void) rtems_event_send(e->transmit_task, te);
   }
 
   LPC_ETH_PRINTK("interrupt: rx = 0x%08x, tx = 0x%08x\n", re, te);
@@ -486,7 +497,7 @@ static void lpc_eth_disable_transmit_interrupts(void)
 static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait)
 {
   struct mbuf *m = NULL;
-  int mw = wait ? M_WAIT : M_DONTWAIT;
+  int mw = wait ? M_WAITOK : M_NOWAIT;
 
   MGETHDR(m, mw, MT_DATA);
   if (m != NULL) {
@@ -546,12 +557,12 @@ static bool lpc_eth_add_new_mbuf(
   }
 }
 
-static void lpc_eth_receive_task(void *arg)
+static void lpc_eth_receive_task(rtems_task_argument arg)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   rtems_event_set events = 0;
   lpc_eth_driver_entry *const e = (lpc_eth_driver_entry *) arg;
-  struct ifnet *const ifp = &e->arpcom.ac_if;
+  struct ifnet *const ifp = e->ifp;
   volatile lpc_eth_transfer_descriptor *const desc = e->rx_desc_table;
   volatile lpc_eth_receive_status *const status = e->rx_status_table;
   struct mbuf **const mbufs = e->rx_mbuf_table;
@@ -564,7 +575,7 @@ static void lpc_eth_receive_task(void *arg)
   /* Main event loop */
   while (true) {
     /* Wait for events */
-    sc = rtems_bsdnet_event_receive(
+    sc = rtems_event_receive(
       LPC_ETH_EVENT_INITIALIZE
         | LPC_ETH_EVENT_STOP
         | LPC_ETH_EVENT_INTERRUPT,
@@ -572,7 +583,7 @@ static void lpc_eth_receive_task(void *arg)
       RTEMS_NO_TIMEOUT,
       &events
     );
-    assert(sc == RTEMS_SUCCESSFUL);
+    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
     LPC_ETH_PRINTF("rx: wake up: 0x%08" PRIx32 "\n", events);
 
@@ -667,22 +678,17 @@ static void lpc_eth_receive_task(void *arg)
           struct mbuf *m = mbufs [consume_index];
 
           if (lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, false)) {
-            /* Ethernet header */
-            struct ether_header *eh = mtod(m, struct ether_header *);
-
-            /* Discard Ethernet header and CRC */
-            int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1
-              - ETHER_HDR_LEN - ETHER_CRC_LEN;
+            /* Discard Ethernet CRC */
+            int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1 - ETHER_CRC_LEN;
 
             /* Update mbuf */
             m->m_len = sz;
             m->m_pkthdr.len = sz;
-            m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
 
             LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", consume_index, sz);
 
             /* Hand over */
-            ether_input(ifp, eh, m);
+            (*ifp->if_input)(ifp, m);
 
             /* Increment received frames counter */
             ++e->received_frames;
@@ -776,12 +782,12 @@ static struct mbuf *lpc_eth_next_fragment(
   return m;
 }
 
-static void lpc_eth_transmit_task(void *arg)
+static void lpc_eth_transmit_task(rtems_task_argument arg)
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   rtems_event_set events = 0;
   lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
-  struct ifnet *ifp = &e->arpcom.ac_if;
+  struct ifnet *ifp = e->ifp;
   volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
   volatile uint32_t *const status = e->tx_status_table;
   #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
@@ -812,7 +818,7 @@ static void lpc_eth_transmit_task(void *arg)
   /* Main event loop */
   while (true) {
     /* Wait for events */
-    sc = rtems_bsdnet_event_receive(
+    sc = rtems_event_receive(
       LPC_ETH_EVENT_INITIALIZE
         | LPC_ETH_EVENT_STOP
         | LPC_ETH_EVENT_TXSTART
@@ -821,7 +827,7 @@ static void lpc_eth_transmit_task(void *arg)
       RTEMS_NO_TIMEOUT,
       &events
     );
-    assert(sc == RTEMS_SUCCESSFUL);
+    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
     LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events);
 
@@ -1030,7 +1036,7 @@ static void lpc_eth_transmit_task(void *arg)
             /* Cache flush of data */
             rtems_cache_flush_multiple_data_lines(
               (const void *) desc [produce_index].start,
-              new_frame_length
+              new_frame_length 
             );
 
             /* Cache flush of descriptor  */
@@ -1071,7 +1077,7 @@ static void lpc_eth_transmit_task(void *arg)
     /* No more fragments? */
     if (m == NULL) {
       /* Interface is now inactive */
-      ifp->if_flags &= ~IFF_OACTIVE;
+      ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
     } else {
       LPC_ETH_PRINTF("tx: enable interrupts\n");
 
@@ -1358,9 +1364,10 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
 {
   int eno = 0;
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  struct ifnet *ifp = &e->arpcom.ac_if;
+  struct ifnet *ifp = e->ifp;
 
   if (up && e->state == LPC_ETH_STATE_DOWN) {
+    ifp->if_drv_flags |= IFF_DRV_RUNNING;
 
     lpc_eth_config_module_enable();
 
@@ -1376,6 +1383,8 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
     eno = lpc_eth_phy_up(e);
 
     if (eno == 0) {
+      const uint8_t *eaddr;
+
       /*
        * We must have a valid external clock from the PHY at this point,
        * otherwise the system bus hangs and only a watchdog reset helps.
@@ -1400,12 +1409,12 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
       lpc_eth->powerdown = 0;
 
       /* MAC address */
-      lpc_eth->sa0 = ((uint32_t) e->arpcom.ac_enaddr [5] << 8)
-        | (uint32_t) e->arpcom.ac_enaddr [4];
-      lpc_eth->sa1 = ((uint32_t) e->arpcom.ac_enaddr [3] << 8)
-        | (uint32_t) e->arpcom.ac_enaddr [2];
-      lpc_eth->sa2 = ((uint32_t) e->arpcom.ac_enaddr [1] << 8)
-        | (uint32_t) e->arpcom.ac_enaddr [0];
+      eaddr = IF_LLADDR(e->ifp);
+      lpc_eth->sa0 = ((uint32_t) eaddr [5] << 8) | (uint32_t) eaddr [4];
+      lpc_eth->sa1 = ((uint32_t) eaddr [3] << 8) | (uint32_t) eaddr [2];
+      lpc_eth->sa2 = ((uint32_t) eaddr [1] << 8) | (uint32_t) eaddr [0];
+
+      lpc_eth_setup_rxfilter(e);
 
       /* Enable receiver */
       lpc_eth->mac1 = 0x03;
@@ -1422,10 +1431,10 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
         lpc_eth_interrupt_handler,
         e
       );
-      assert(sc == RTEMS_SUCCESSFUL);
+      BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
       /* Start watchdog timer */
-      ifp->if_timer = 1;
+      callout_reset(&e->watchdog_callout, hz, lpc_eth_interface_watchdog, e);
 
       /* Change state */
       e->state = LPC_ETH_STATE_UP;
@@ -1435,13 +1444,15 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
       ifp->if_flags &= ~IFF_UP;
     }
   } else if (!up && e->state == LPC_ETH_STATE_UP) {
+    ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
     /* Remove interrupt handler */
     sc = rtems_interrupt_handler_remove(
       e->interrupt_number,
       lpc_eth_interrupt_handler,
       e
     );
-    assert(sc == RTEMS_SUCCESSFUL);
+    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
     /* Stop tasks */
     lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_STOP);
@@ -1452,7 +1463,7 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
     lpc_eth_config_module_disable();
 
     /* Stop watchdog timer */
-    ifp->if_timer = 0;
+    callout_stop(&e->watchdog_callout);
 
     /* Change state */
     e->state = LPC_ETH_STATE_DOWN;
@@ -1466,94 +1477,44 @@ static void lpc_eth_interface_init(void *arg)
   /* Nothing to do */
 }
 
-static void lpc_eth_interface_stats(lpc_eth_driver_entry *e)
+static void lpc_eth_setup_rxfilter(lpc_eth_driver_entry *e)
 {
-  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);
-  }
+  struct ifnet *ifp = e->ifp;
 
-  rtems_bsdnet_semaphore_release();
-
-  if (eno == 0) {
-    rtems_ifmedia2str(media, NULL, 0);
-    printf("\n");
-  }
-
-  printf("received frames:                     %u\n", e->received_frames);
-  printf("receive interrupts:                  %u\n", e->receive_interrupts);
-  printf("transmitted frames:                  %u\n", e->transmitted_frames);
-  printf("transmit interrupts:                 %u\n", e->transmit_interrupts);
-  printf("receive drop errors:                 %u\n", e->receive_drop_errors);
-  printf("receive overrun errors:              %u\n", e->receive_overrun_errors);
-  printf("receive fragment errors:             %u\n", e->receive_fragment_errors);
-  printf("receive CRC errors:                  %u\n", e->receive_crc_errors);
-  printf("receive symbol errors:               %u\n", e->receive_symbol_errors);
-  printf("receive length errors:               %u\n", e->receive_length_errors);
-  printf("receive alignment errors:            %u\n", e->receive_alignment_errors);
-  printf("receive no descriptor errors:        %u\n", e->receive_no_descriptor_errors);
-  printf("receive fatal errors:                %u\n", e->receive_fatal_errors);
-  printf("transmit underrun errors:            %u\n", e->transmit_underrun_errors);
-  printf("transmit late collision errors:      %u\n", e->transmit_late_collision_errors);
-  printf("transmit excessive collision errors: %u\n", e->transmit_excessive_collision_errors);
-  printf("transmit excessive defer errors:     %u\n", e->transmit_excessive_defer_errors);
-  printf("transmit no descriptor errors:       %u\n", e->transmit_no_descriptor_errors);
-  printf("transmit overflow errors:            %u\n", e->transmit_overflow_errors);
-  printf("transmit fatal errors:               %u\n", e->transmit_fatal_errors);
-
-  rtems_bsdnet_semaphore_obtain();
-}
+  lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0);
 
-static int lpc_eth_multicast_control(
-  bool add,
-  struct ifreq *ifr,
-  struct arpcom *ac
-)
-{
-  int eno = 0;
-
-  if (add) {
-    eno = ether_addmulti(ifr, ac);
+  if ((ifp->if_flags & IFF_ALLMULTI)) {
+    lpc_eth->hashfilterl = 0xffffffff;
+    lpc_eth->hashfilterh = 0xffffffff;
   } else {
-    eno = ether_delmulti(ifr, ac);
-  }
-
-  if (eno == ENETRESET) {
-    struct ether_multistep step;
-    struct ether_multi *enm;
+    struct ifmultiaddr *ifma;
 
-    eno = 0;
+    lpc_eth->hashfilterl = 0x0;
+    lpc_eth->hashfilterh = 0x0;
 
-    lpc_eth->hashfilterl = 0;
-    lpc_eth->hashfilterh = 0;
+    if_maddr_rlock(ifp);
+    CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+      uint32_t crc;
+      uint32_t index;
 
-    ETHER_FIRST_MULTI(step, ac, enm);
-    while (enm != NULL) {
-      uint64_t addrlo = 0;
-      uint64_t addrhi = 0;
+      if (ifma->ifma_addr->sa_family != AF_LINK)
+        continue;
 
-      memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN);
-      memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN);
-      while (addrlo <= addrhi) {
-        /* XXX: ether_crc32_le() does not work, why? */
-        uint32_t crc = ether_crc32_be((uint8_t *) &addrlo, ETHER_ADDR_LEN);
-        uint32_t index = (crc >> 23) & 0x3f;
+      /* XXX: ether_crc32_le() does not work, why? */
+      crc = ether_crc32_be(
+        LLADDR((struct sockaddr_dl *) ifma->ifma_addr),
+        ETHER_ADDR_LEN
+      );
+      index = (crc >> 23) & 0x3f;
 
-        if (index < 32) {
-          lpc_eth->hashfilterl |= 1U << index;
-        } else {
-          lpc_eth->hashfilterh |= 1U << (index - 32);
-        }
-        ++addrlo;
+      if (index < 32) {
+        lpc_eth->hashfilterl |= 1U << index;
+      } else {
+        lpc_eth->hashfilterh |= 1U << (index - 32);
       }
-      ETHER_NEXT_MULTI(step, enm);
     }
+    if_maddr_runlock(ifp);
   }
-
-  return eno;
 }
 
 static int lpc_eth_interface_ioctl(
@@ -1571,27 +1532,40 @@ static int lpc_eth_interface_ioctl(
   switch (cmd)  {
     case SIOCGIFMEDIA:
     case SIOCSIFMEDIA:
-      rtems_mii_ioctl(&e->mdio, e, cmd, &ifr->ifr_media);
+      eno = ifmedia_ioctl(ifp, ifr, &e->ifmedia, cmd);
       break;
     case SIOCGIFADDR:
     case SIOCSIFADDR:
       ether_ioctl(ifp, cmd, data);
       break;
     case SIOCSIFFLAGS:
-      eno = lpc_eth_up_or_down(e, (ifp->if_flags & IFF_UP) != 0);
-      if (eno == 0 && (ifp->if_flags & IFF_UP) != 0) {
-        lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0);
+      LPE_LOCK(e);
+      if (ifp->if_flags & IFF_UP) {
+        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+          if ((ifp->if_flags ^ e->if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) {
+            lpc_eth_setup_rxfilter(e);
+          }
+        } else {
+          eno = lpc_eth_up_or_down(e, true);
+        }
+      } else {
+        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+          eno = lpc_eth_up_or_down(e, false);
+        }
       }
+      e->if_flags = ifp->if_flags;
+      LPE_UNLOCK(e);
       break;
     case SIOCADDMULTI:
     case SIOCDELMULTI:
-      eno = lpc_eth_multicast_control(cmd == SIOCADDMULTI, ifr, &e->arpcom);
-      break;
-    case SIO_RTEMS_SHOW_STATS:
-      lpc_eth_interface_stats(e);
+      if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+        LPE_LOCK(e);
+        lpc_eth_setup_rxfilter(e);
+        LPE_UNLOCK(e);
+      }
       break;
     default:
-      eno = EINVAL;
+      eno = ether_ioctl(ifp, cmd, data);
       break;
   }
 
@@ -1603,17 +1577,17 @@ static void lpc_eth_interface_start(struct ifnet *ifp)
   rtems_status_code sc = RTEMS_SUCCESSFUL;
   lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
 
-  ifp->if_flags |= IFF_OACTIVE;
+  ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 
   if (e->state == LPC_ETH_STATE_UP) {
-    sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART);
-    assert(sc == RTEMS_SUCCESSFUL);
+    sc = rtems_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART);
+    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
   }
 }
 
-static void lpc_eth_interface_watchdog(struct ifnet *ifp)
+static void lpc_eth_interface_watchdog(void *arg)
 {
-  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
+  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
 
   if (e->state == LPC_ETH_STATE_UP) {
     uint32_t anlpar = lpc_eth_mdio_read_anlpar(e->phy);
@@ -1648,79 +1622,77 @@ static void lpc_eth_interface_watchdog(struct ifnet *ifp)
       }
     }
 
-    ifp->if_timer = WATCHDOG_TIMEOUT;
+    callout_reset(&e->watchdog_callout, WATCHDOG_TIMEOUT * hz, lpc_eth_interface_watchdog, e);
   }
 }
 
-static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max)
+static int lpc_eth_media_change(struct ifnet *ifp)
 {
-  if (count <= 0) {
-    count = default_value;
-  } else if (count > max) {
-    count = max;
+  (void) ifp;
+  return EINVAL;
+}
+
+static void lpc_eth_media_status(struct ifnet *ifp, struct ifmediareq *imr)
+{
+  (void) ifp;
+
+  imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+  imr->ifm_active = IFM_ETHER;
+
+  if ((lpc_eth->supp & ETH_SUPP_SPEED) != 0) {
+    imr->ifm_active |= IFM_100_TX;
+  } else {
+    imr->ifm_active |= IFM_10_T;
   }
 
-  return LPC_ETH_CONFIG_UNIT_MULTIPLE
-    + (((unsigned) count - 1U) & ~(LPC_ETH_CONFIG_UNIT_MULTIPLE - 1U));
+  if ((lpc_eth->mac2 & ETH_MAC2_FULL_DUPLEX) != 0) {
+    imr->ifm_active |= IFM_FDX;
+  } else {
+    imr->ifm_active |= IFM_HDX;
+  }
 }
 
-static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config)
+int lpc_eth_probe(device_t dev)
 {
-  lpc_eth_driver_entry *e = &lpc_eth_driver_data;
-  struct ifnet *ifp = &e->arpcom.ac_if;
+  int unit = device_get_unit(dev);
+
+  if (unit != 0) {
+    return ENXIO;
+  }
+
+  return 0;
+}
+
+static int lpc_eth_attach(device_t dev)
+{
+  lpc_eth_driver_entry *e = device_get_softc(dev);
+  struct ifnet *ifp = NULL;
   char *unit_name = NULL;
-  int unit_index = rtems_bsdnet_parse_driver_name(config, &unit_name);
+  int unit_index = device_get_unit(dev);
   size_t table_area_size = 0;
   char *table_area = NULL;
   char *table_location = NULL;
+  rtems_status_code status;
+  uint8_t eaddr[ETHER_ADDR_LEN];
 
-  /* Check parameter */
-  if (unit_index < 0) {
-    return 0;
-  }
-  if (unit_index != 0) {
-    goto cleanup;
-  }
-  if (config->hardware_address == NULL) {
-    goto cleanup;
-  }
-  if (e->state != LPC_ETH_STATE_NOT_INITIALIZED) {
-    goto cleanup;
-  }
+  BSD_ASSERT(e->state == LPC_ETH_STATE_NOT_INITIALIZED);
 
-  /* MDIO */
-  e->mdio.mdio_r = lpc_eth_mdio_read;
-  e->mdio.mdio_w = lpc_eth_mdio_write;
-  e->mdio.has_gmii = 0;
-  e->anlpar = 0;
+  mtx_init(&e->mtx, device_get_nameunit(e->dev), MTX_NETWORK_LOCK, MTX_DEF);
 
-  /* Interrupt number */
-  config->irno = LPC_ETH_CONFIG_INTERRUPT;
+  ifmedia_init(&e->ifmedia, 0, lpc_eth_media_change, lpc_eth_media_status);
+  ifmedia_add(&e->ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
+  ifmedia_set(&e->ifmedia, IFM_ETHER | IFM_AUTO);
 
-  /* Device control */
-  config->drv_ctrl = e;
+  callout_init_mtx(&e->watchdog_callout, &e->mtx, 0);
 
   /* Receive unit count */
-  e->rx_unit_count = lpc_eth_fixup_unit_count(
-    config->rbuf_count,
-    LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT,
-    LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX
-  );
-  config->rbuf_count = (int) e->rx_unit_count;
+  e->rx_unit_count = LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT;
 
   /* Transmit unit count */
-  e->tx_unit_count = lpc_eth_fixup_unit_count(
-    config->xbuf_count,
-    LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT,
-    LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX
-  );
-  config->xbuf_count = (int) e->tx_unit_count;
+  e->tx_unit_count = LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT;
 
   /* Remember interrupt number */
-  e->interrupt_number = config->irno;
-
-  /* Copy MAC address */
-  memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
+  e->interrupt_number = LPC_ETH_CONFIG_INTERRUPT;
 
   /* Allocate and clear table area */
   table_area_size =
@@ -1734,7 +1706,7 @@ static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config)
         + LPC_ETH_CONFIG_TX_BUF_SIZE);
   table_area = lpc_eth_config_alloc_table_area(table_area_size);
   if (table_area == NULL) {
-    goto cleanup;
+    return ENOMEM;
   }
   memset(table_area, 0, table_area_size);
 
@@ -1762,56 +1734,66 @@ static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config)
   e->tx_buf_table = table_location;
 
   /* Set interface data */
+  e->dev = dev;
+  e->ifp = ifp = if_alloc(IFT_ETHER);
   ifp->if_softc = e;
-  ifp->if_unit = (short) unit_index;
-  ifp->if_name = unit_name;
-  ifp->if_mtu = (config->mtu > 0) ? (u_long) config->mtu : ETHERMTU;
+  if_initname(ifp, device_get_name(dev), device_get_unit(dev));
   ifp->if_init = lpc_eth_interface_init;
   ifp->if_ioctl = lpc_eth_interface_ioctl;
   ifp->if_start = lpc_eth_interface_start;
-  ifp->if_output = ether_output;
-  ifp->if_watchdog = lpc_eth_interface_watchdog;
-  ifp->if_flags = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX;
-  ifp->if_snd.ifq_maxlen = ifqmaxlen;
-  ifp->if_timer = 0;
+  ifp->if_qflush = if_qflush;
+  ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
+  IFQ_SET_MAXLEN(&ifp->if_snd, LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX - 1);
+  ifp->if_snd.ifq_drv_maxlen = LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX - 1;
+  IFQ_SET_READY(&ifp->if_snd);
+  ifp->if_hdrlen = sizeof(struct ether_header);
+
+  rtems_bsd_get_mac_address(device_get_name(e->dev), unit_index, eaddr);
 
   /* Create tasks */
-  e->receive_task = rtems_bsdnet_newproc(
-    "ntrx",
+  status = rtems_task_create(
+    rtems_build_name('n', 't', 'r', 'x'),
+    rtems_bsd_get_task_priority(device_get_name(e->dev)),
     4096,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &e->receive_task
+  );
+  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
+  status = rtems_task_start(
+    e->receive_task,
     lpc_eth_receive_task,
-    e
+    (rtems_task_argument)e
   );
-  e->transmit_task = rtems_bsdnet_newproc(
-    "nttx",
+  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
+  status = rtems_task_create(
+    rtems_build_name('n', 't', 't', 'x'),
+    rtems_bsd_get_task_priority(device_get_name(e->dev)),
     4096,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &e->transmit_task
+  );
+  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
+  status = rtems_task_start(
+    e->transmit_task,
     lpc_eth_transmit_task,
-    e
+    (rtems_task_argument)e
   );
+  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
+
+  if_link_state_change(e->ifp, LINK_STATE_UP);
 
   /* Change status */
-  ifp->if_flags |= IFF_RUNNING;
   e->state = LPC_ETH_STATE_DOWN;
 
   /* Attach the interface */
-  if_attach(ifp);
-  ether_ifattach(ifp);
-
-  return 1;
-
-cleanup:
-
-  lpc_eth_config_free_table_area(table_area);
-
-  /* FIXME: Type */
-  free(unit_name, (int) 0xdeadbeef);
+  ether_ifattach(ifp, eaddr);
 
   return 0;
 }
 
-static int lpc_eth_detach(
-  struct rtems_bsdnet_ifconfig *config RTEMS_UNUSED
-)
+static int lpc_eth_detach(device_t dev)
 {
   /* FIXME: Detach the interface from the upper layers? */
 
@@ -1821,19 +1803,25 @@ static int lpc_eth_detach(
 
   /* FIXME: More cleanup */
 
-  return 0;
+  return ENXIO;
 }
 
-int lpc_eth_attach_detach(
-  struct rtems_bsdnet_ifconfig *config,
-  int attaching
-)
-{
-  /* FIXME: Return value */
+static device_method_t lpe_methods[] = {
+  DEVMETHOD(device_probe, lpc_eth_probe),
+  DEVMETHOD(device_attach, lpc_eth_attach),
+  DEVMETHOD(device_detach, lpc_eth_detach),
+  DEVMETHOD_END
+};
 
-  if (attaching) {
-    return lpc_eth_attach(config);
-  } else {
-    return lpc_eth_detach(config);
-  }
-}
+static driver_t lpe_nexus_driver = {
+  "lpe",
+  lpe_methods,
+  sizeof(lpc_eth_driver_entry)
+};
+
+static devclass_t lpe_devclass;
+DRIVER_MODULE(lpe, nexus, lpe_nexus_driver, lpe_devclass, 0, 0);
+MODULE_DEPEND(lpe, nexus, 1, 1, 1);
+MODULE_DEPEND(lpe, ether, 1, 1, 1);
+
+#endif /* LIBBSP_ARM_LPC24XX_BSP_H || LIBBSP_ARM_LPC32XX_BSP_H */
-- 
2.35.3



More information about the devel mailing list