From e99893f986c7719e75d652cfc1525cb4f47ec6e6 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 14 Dec 2012 12:17:15 +0100 Subject: bsps/arm: Prepare for interface down support --- .../libbsp/arm/shared/lpc/network/lpc-ethernet.c | 161 +++++++++++---------- 1 file changed, 83 insertions(+), 78 deletions(-) (limited to 'c') 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 33d41998d9..df71776d90 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 @@ -291,10 +291,9 @@ static volatile lpc_eth_controller *const lpc_eth = #endif typedef enum { - LPC_ETH_NOT_INITIALIZED, - LPC_ETH_INITIALIZED, - LPC_ETH_STARTED, - LPC_ETH_RUNNING + LPC_ETH_STATE_NOT_INITIALIZED = 0, + LPC_ETH_STATE_DOWN, + LPC_ETH_STATE_UP } lpc_eth_state; typedef struct { @@ -332,13 +331,39 @@ typedef struct { unsigned transmit_no_descriptor_errors; unsigned transmit_overflow_errors; unsigned transmit_fatal_errors; + rtems_vector_number interrupt_number; + rtems_id control_task; } lpc_eth_driver_entry; -static lpc_eth_driver_entry lpc_eth_driver_data = { - .state = LPC_ETH_NOT_INITIALIZED, - .receive_task = RTEMS_ID_NONE, - .transmit_task = RTEMS_ID_NONE -}; +static lpc_eth_driver_entry lpc_eth_driver_data; + +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); +} + +static void lpc_eth_control_request( + lpc_eth_driver_entry *e, + rtems_id task, + rtems_event_set event +) +{ + 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); + + 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); + + e->control_task = 0; +} static inline uint32_t lpc_eth_increment( uint32_t value, @@ -596,6 +621,8 @@ static void lpc_eth_receive_task(void *arg) /* Enable receive interrupts */ lpc_eth_enable_receive_interrupts(); + lpc_eth_control_request_complete(e); + /* Wait for events */ continue; } @@ -830,6 +857,8 @@ static void lpc_eth_transmit_task(void *arg) /* Enable transmitter */ lpc_eth->command |= ETH_CMD_TX_ENABLE; + + lpc_eth_control_request_complete(e); } /* Free consumed fragments */ @@ -1102,15 +1131,12 @@ static int lpc_eth_mdio_write( return eno; } -static void lpc_eth_interface_init(void *arg) +static void lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up) { rtems_status_code sc = RTEMS_SUCCESSFUL; - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg; struct ifnet *ifp = &e->arpcom.ac_if; - LPC_ETH_PRINTF("%s\n", __func__); - - if (e->state == LPC_ETH_INITIALIZED) { + if (up && e->state == LPC_ETH_STATE_DOWN) { lpc_eth_config_module_enable(); /* Soft reset */ @@ -1137,7 +1163,7 @@ static void lpc_eth_interface_init(void *arg) #else lpc_eth->command = 0x0400; #endif - lpc_eth->intenable = 0; + lpc_eth->intenable = ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN; lpc_eth->intclear = 0x30ff; lpc_eth->powerdown = 0; @@ -1149,59 +1175,40 @@ static void lpc_eth_interface_init(void *arg) lpc_eth->sa2 = ((uint32_t) e->arpcom.ac_enaddr [1] << 8) | (uint32_t) e->arpcom.ac_enaddr [0]; + lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0); + /* Enable receiver */ lpc_eth->mac1 = 0x03; - /* Start receive task */ - if (e->receive_task == RTEMS_ID_NONE) { - e->receive_task = rtems_bsdnet_newproc( - "ntrx", - 4096, - lpc_eth_receive_task, - e - ); - sc = rtems_bsdnet_event_send(e->receive_task, LPC_ETH_EVENT_INITIALIZE); - RTEMS_SYSLOG_ERROR_SC(sc, "send receive initialize event"); - } - - /* Start transmit task */ - if (e->transmit_task == RTEMS_ID_NONE) { - e->transmit_task = rtems_bsdnet_newproc( - "nttx", - 4096, - lpc_eth_transmit_task, - e - ); - sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_INITIALIZE); - RTEMS_SYSLOG_ERROR_SC(sc, "send transmit initialize event"); - } - - /* Change state */ - if ( - e->receive_task != RTEMS_ID_NONE && e->transmit_task != RTEMS_ID_NONE - ) { - e->state = LPC_ETH_STARTED; - } - } - - if (e->state == LPC_ETH_STARTED) { - /* Enable fatal interrupts */ - lpc_eth->intenable = ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN; - - /* Enable promiscous mode */ - lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0); + /* Initialize tasks */ + lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INITIALIZE); + lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_INITIALIZE); + + /* Install interrupt handler */ + sc = rtems_interrupt_handler_install( + e->interrupt_number, + "Ethernet", + RTEMS_INTERRUPT_UNIQUE, + lpc_eth_interrupt_handler, + e + ); + assert(sc == RTEMS_SUCCESSFUL); /* Start watchdog timer */ ifp->if_timer = 1; - /* Set interface to running state */ - ifp->if_flags |= IFF_RUNNING; - /* Change state */ - e->state = LPC_ETH_RUNNING; + e->state = LPC_ETH_STATE_UP; + } else if (!up && e->state == LPC_ETH_STATE_UP) { + /* TODO */ } } +static void lpc_eth_interface_init(void *arg) +{ + /* Nothing to do */ +} + static void lpc_eth_interface_stats(lpc_eth_driver_entry *e) { int media = IFM_MAKEWORD(0, 0, 0, 0); @@ -1309,13 +1316,7 @@ static int lpc_eth_interface_ioctl( ether_ioctl(ifp, cmd, data); break; case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_RUNNING) { - /* TODO: off */ - } - if (ifp->if_flags & IFF_UP) { - ifp->if_flags |= IFF_RUNNING; - /* TODO: init */ - } + lpc_eth_up_or_down(e, (ifp->if_flags & IFF_UP) != 0); break; case SIOCADDMULTI: case SIOCDELMULTI: @@ -1395,7 +1396,6 @@ static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max) static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config) { - rtems_status_code sc = RTEMS_SUCCESSFUL; lpc_eth_driver_entry *e = &lpc_eth_driver_data; struct ifnet *ifp = &e->arpcom.ac_if; char *unit_name = NULL; @@ -1446,18 +1446,8 @@ static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config) ); config->xbuf_count = (int) e->tx_unit_count; - /* Disable interrupts */ - lpc_eth->intenable = 0; - - /* Install interrupt handler */ - sc = rtems_interrupt_handler_install( - config->irno, - "Ethernet", - RTEMS_INTERRUPT_UNIQUE, - lpc_eth_interrupt_handler, - e - ); - RTEMS_CLEANUP_SC(sc, cleanup, "install interrupt handler"); + /* Remember interrupt number */ + e->interrupt_number = config->irno; /* Copy MAC address */ memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); @@ -1515,8 +1505,23 @@ static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config) ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_timer = 0; + /* Create tasks */ + e->receive_task = rtems_bsdnet_newproc( + "ntrx", + 4096, + lpc_eth_receive_task, + e + ); + e->transmit_task = rtems_bsdnet_newproc( + "nttx", + 4096, + lpc_eth_transmit_task, + e + ); + /* Change status */ - e->state = LPC_ETH_INITIALIZED; + ifp->if_flags |= IFF_RUNNING; + e->state = LPC_ETH_STATE_DOWN; /* Attach the interface */ if_attach(ifp); -- cgit v1.2.3