int AT91_EMAC_LWIP_Driver::Open(int index)
{
    /* Network interface variables */
    struct ip_addr ipaddr, subnetmask, gateway;
    struct netif *pNetIF;
    int len;
    const SOCK_NetworkConfiguration *iface;

    /* Apply network configuration */
    iface = &g_NetworkConfig.NetworkInterfaces[index];

    len = g_AT91_EMAC_NetIF.hwaddr_len;
    if(len == 0 || iface->macAddressLen < len)
    {
        len = iface->macAddressLen;
        g_AT91_EMAC_NetIF.hwaddr_len = len;
    }
    memcpy(g_AT91_EMAC_NetIF.hwaddr, iface->macAddressBuffer, len);

    if(0 == (iface->flags & SOCK_NETWORKCONFIGURATION_FLAGS_DHCP))
    {
        ipaddr.addr     = iface->ipaddr;
        gateway.addr    = iface->gateway;
        subnetmask.addr = iface->subnetmask;
    }
    else
    {
        /* Set network address variables - this will be set by either DHCP or when the configuration is applied */
        IP4_ADDR(&gateway, 0,0,0,0);
        IP4_ADDR(&ipaddr, 0,0,0,0);
        IP4_ADDR(&subnetmask, 255,255,255,0);
    }

    // PHY Power Up
    CPU_GPIO_EnableOutputPin(g_AT91_EMAC_LWIP_Config.PHY_PD_GPIO_Pin, FALSE);

    // Enable Interrupt
    CPU_INTC_ActivateInterrupt(AT91C_ID_EMAC, (HAL_CALLBACK_FPN)AT91_EMAC_LWIP_interrupt, &g_AT91_EMAC_NetIF);

    g_AT91_EMAC_NetIF.flags = NETIF_FLAG_IGMP | NETIF_FLAG_BROADCAST;

    pNetIF = netif_add( &g_AT91_EMAC_NetIF, &ipaddr, &subnetmask, &gateway, NULL, AT91_EMAC_ethhw_init, ethernet_input );

    netif_set_default( pNetIF );

    LWIP_STATUS_setorclear( LWIP_STATUS_LinkUp, 0 != dm9161_lwip_GetLinkStatus( ) );

    if (LWIP_STATUS_isset(LWIP_STATUS_LinkUp))
    {
        netif_set_link_up( pNetIF );
        netif_set_up     ( pNetIF );

        Network_PostEvent( NETWORK_EVENT_TYPE__AVAILABILITY_CHANGED, NETWORK_EVENT_FLAGS_IS_AVAILABLE );
    }

    /* Initialize the continuation routine for the driver interrupt and receive */    
    InitContinuations( pNetIF );

    return g_AT91_EMAC_NetIF.num;
}
void lwip_network_uptime_completion(void *arg)
{
    NATIVE_PROFILE_PAL_NETWORK();

    BOOL status = dm9161_lwip_GetLinkStatus( );

    if(status != LwipNetworkStatus)
    {
        struct netif* pNetIf = (struct netif*)arg;

        if(status)
        {
            SOCK_NetworkConfiguration *pNetCfg = &g_NetworkConfig.NetworkInterfaces[0];

            dm9161_lwip_AutoNegotiate( );
            netif_set_up( pNetIf );

            if(pNetCfg->flags & SOCK_NETWORKCONFIGURATION_FLAGS_DHCP)
            {
                dhcp_start( pNetIf );
            }
            Network_PostEvent( NETWORK_EVENT_TYPE__AVAILABILITY_CHANGED, NETWORK_EVENT_FLAGS_IS_AVAILABLE );
        }
        else
        {
            netif_set_down( (struct netif*)arg );
            Network_PostEvent( NETWORK_EVENT_TYPE__AVAILABILITY_CHANGED, 0);
        }

        LwipNetworkStatus = status;
    }

    LwipUpTimeCompletion.EnqueueDelta64( 2000000 );
}
void lwip_network_uptime_completion(void *arg)
{
    NATIVE_PROFILE_PAL_NETWORK();

    BOOL status = dm9161_lwip_GetLinkStatus( ) != 0;

    if(!status)
    {
        status = dm9161_lwip_GetLinkStatus( ) != 0;
    }

    if(status != LWIP_STATUS_isset(LWIP_STATUS_LinkUp) )
    {
        struct netif* pNetIf = (struct netif*)arg;

        if(status)
        {
            tcpip_timeout(1000, (sys_timeout_handler)netif_set_link_up, (void*)pNetIf);
            tcpip_timeout(1000, (sys_timeout_handler)netif_set_up, (void*)pNetIf);

            Network_PostEvent( NETWORK_EVENT_TYPE__AVAILABILITY_CHANGED, NETWORK_EVENT_FLAGS_IS_AVAILABLE );
        }
        else
        {
            tcpip_callback((sys_timeout_handler)netif_set_link_down, (void*)pNetIf);
            tcpip_callback((sys_timeout_handler)netif_set_down, (void*)pNetIf);

            Network_PostEvent( NETWORK_EVENT_TYPE__AVAILABILITY_CHANGED, 0);
        }

        Events_Set(SYSTEM_EVENT_FLAG_SOCKET);
        Events_Set(SYSTEM_EVENT_FLAG_NETWORK);

        LWIP_STATUS_setorclear( LWIP_STATUS_LinkUp, status );
    }

    LwipUpTimeCompletion.EnqueueDelta64( 2000000 );
}
int AT91_EMAC_LWIP_Driver::Open(int index)
{
    /* Network interface variables */
    struct ip_addr ipaddr, subnetmask, gateway;
    struct netif *pNetIF;
    int len;
    const SOCK_NetworkConfiguration *iface;

    /* Apply network configuration */
    iface = &g_NetworkConfig.NetworkInterfaces[index];

    len = g_AT91_EMAC_NetIF.hwaddr_len;
    if(len == 0 || iface->macAddressLen < len)
    {
        len = iface->macAddressLen;
        g_AT91_EMAC_NetIF.hwaddr_len = len;
    }
    memcpy(g_AT91_EMAC_NetIF.hwaddr, iface->macAddressBuffer, len);

    ipaddr.addr = iface->ipaddr;
    gateway.addr = iface->gateway;
    subnetmask.addr = iface->subnetmask;

    // PHY Power Up
    CPU_GPIO_EnableOutputPin(g_AT91_EMAC_LWIP_Config.PHY_PD_GPIO_Pin, FALSE);

    // Enable Interrupt
    CPU_INTC_ActivateInterrupt(AT91C_ID_EMAC, (HAL_CALLBACK_FPN)AT91_EMAC_LWIP_interrupt, &g_AT91_EMAC_NetIF);

    /* Initialize the continuation routine for the driver interrupt and receive */    
    InitContinuations( pNetIF );

    pNetIF = netif_add( &g_AT91_EMAC_NetIF, &ipaddr, &subnetmask, &gateway, NULL, AT91_EMAC_ethhw_init, ethernet_input );

    netif_set_default( pNetIF );

    LwipNetworkStatus = dm9161_lwip_GetLinkStatus( );
    if (LwipNetworkStatus)
    {
        netif_set_up( pNetIF );
    }
    /* Initialize the continuation routine for the driver interrupt and receive */    
    InitContinuations( pNetIF );

    return g_AT91_EMAC_NetIF.num;
}