From 192e8d37a312e56b618c8800dc1fc1189d99de0e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 9 Jun 2022 10:50:26 +0200 Subject: if_lpe.c: Port to LibBSD --- libbsd.py | 1 + rtemsbsd/sys/arm/lpc/if_lpe.c | 475 ++++++++++++++++++++---------------------- 2 files changed, 231 insertions(+), 245 deletions(-) diff --git a/libbsd.py b/libbsd.py index 82ced4dd..e3840f37 100644 --- a/libbsd.py +++ b/libbsd.py @@ -221,6 +221,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..33321f6f 100755 --- a/rtemsbsd/sys/arm/lpc/if_lpe.c +++ b/rtemsbsd/sys/arm/lpc/if_lpe.c @@ -22,28 +22,32 @@ #include -#include -#include -#include -#include -#include -#include +#include -#include -#include -#include +#if defined(LIBBSP_ARM_LPC24XX_BSP_H) || defined(LIBBSP_ARM_LPC32XX_BSP_H) #include +#include +#include +#include +#include #include #include -#include + +#include +#include #include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include + +#include + +#include #include #include @@ -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,10 +1364,9 @@ 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) { - lpc_eth_config_module_enable(); /* Enable RX/TX reset and disable soft reset */ @@ -1376,6 +1381,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 +1407,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,26 +1429,25 @@ 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 */ + ifp->if_drv_flags |= IFF_DRV_RUNNING; e->state = LPC_ETH_STATE_UP; } - - if (eno != 0) { - 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 +1458,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; @@ -1463,97 +1469,49 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up) static void lpc_eth_interface_init(void *arg) { - /* Nothing to do */ -} - -static void lpc_eth_interface_stats(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); - } - - rtems_bsdnet_semaphore_release(); - - if (eno == 0) { - rtems_ifmedia2str(media, NULL, 0); - printf("\n"); - } + lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg; - 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(); + (void) lpc_eth_up_or_down(e, true); } -static int lpc_eth_multicast_control( - bool add, - struct ifreq *ifr, - struct arpcom *ac -) +static void lpc_eth_setup_rxfilter(lpc_eth_driver_entry *e) { - int eno = 0; + struct ifnet *ifp = e->ifp; - if (add) { - eno = ether_addmulti(ifr, ac); - } else { - eno = ether_delmulti(ifr, ac); - } + lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0); - if (eno == ENETRESET) { - struct ether_multistep step; - struct ether_multi *enm; + if ((ifp->if_flags & IFF_ALLMULTI)) { + lpc_eth->hashfilterl = 0xffffffff; + lpc_eth->hashfilterh = 0xffffffff; + } else { + 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 +1529,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 +1574,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 +1619,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) +{ + (void) ifp; + return EINVAL; +} + +static void lpc_eth_media_status(struct ifnet *ifp, struct ifmediareq *imr) { - if (count <= 0) { - count = default_value; - } else if (count > max) { - count = max; + (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 +1703,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 +1731,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 +1800,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 */ -- cgit v1.2.3