Milos RTOS v0.3.4a
Real Time Operating System
Ethernet interface
Collaboration diagram for Ethernet interface:

Modules

 Private constants
 Typedefs
 Private functions
 Functions
 Constants

Functions

i32 __ethifOut (__PNETIF netif, u16 type, u8 *dest, __PNET_BUFFER nb, __BOOL freenb)
 Queues or transmits a Network Buffer.
__VOID __ethifThread (__VOID)
 The network interface thread.

Function Documentation

i32 __ethifOut ( __PNETIF  netif,
u16  type,
u8 *  dest,
__PNET_BUFFER  nb,
__BOOL  freenb 
)

Queues or transmits a Network Buffer.

The __NET_BUFFER will be reordered using the __nbReorder() function. The reordered buffer is allocated an deallocated locally.

Parameters:
netifPointer to a network interface.
typeType of protocol. See Protocols.
  • __ETH_TYPE_IP IP type.
  • __ETH_TYPE_ARP ARP type.
destMAC address of the remote host. If null the packet will be sent to the broadcast address.
nbPointer to a Network Buffer to be sent.
freenbIf __TRUE, the nb Network Buffer will be deallocated (with __nbDealloc()) after queuing or transmission. Otherwise is up to the caller to free the buffer (useful for packet broadcasting).
Returns:
Zero on success, otherwise non-zero.

Definition at line 204 of file ethif.c.

{
    __ETHERNET_HDR *hdr;
    u8* ptr;
    u32 size;
    i32 ret = 0;

    if (!__nbAlloc(nb, __NB_LAYER_DATALINK, sizeof(__ETHERNET_HDR)))
    {
        return -1;
    }

    hdr = (__ETHERNET_HDR*) nb->nl_dl.ptr;
    __memCpy(hdr->shost, netif->addr.type.mac, 6);

    if (dest)
    {
        __memCpy(hdr->dhost, dest, 6);
    } else {
        __memSet(hdr->dhost, 0xff, 6);
    }

    hdr->type = __htons(type);

    /*
     * Reorder the Network Buffer.
     */
    ptr = __nbReorder(nb, &size);
    if (ptr)
    {
        if (__lockOwn(netif->lock, 1000))
        {
            if (__deviceWrite(netif->dv, ptr, size) == size)
            {
                NETMSG(__NET_DEBUG_ETH, ("[ETH] (%s) frame written, size = %lu", netif->dv->dv_name, (u32) size));
            } else {
                ret = -1;
                NETMSG(__NET_DEBUG_ETH, ("[ETH] (%s) error writing frame, size = %lu", netif->dv->dv_name, (u32) size));
            }

            __lockRelease(netif->lock);
        } else {
            ret = -1;
            NETMSG(__NET_DEBUG_ETH, ("[ETH] (%s) error writing, device is busy", netif->dv->dv_name));
        }

        __heapFree(ptr);
    }

    if (freenb) __nbDealloc(nb);
    return ret;
}

Here is the call graph for this function:

The network interface thread.

This thread will be created by calling the __netifInit() function.

The thread will initialize and open the underlying device (if not already initialized and opened) with default values.

By default the thread will check for the status of the Ethernet link, and switch between modes according to the status. If the link goes down and the interface was configured to work with DHCP, the DHCP reboot procedure is launched.

The main function of this thread is to read Ethernet frames from the underlying device.

It will also call the DHCP and ARP state machines.

Returns:
Nothing.

Definition at line 276 of file ethif.c.

{
    __PNET_BUFFER nb;
    __PNETIF netif = __threadGetParameter();
    u8 link_status = __ETHERNET_LINK_UNKNOWN;
    u8 temp_status = 0;
    u32 seconds = __systemGetTickCount();

    /* Check if the device is initialized */
    if (!__deviceInitialized(netif->dv))
    {
        /* Try to initialize the device with the default values */
        if (__deviceInit(netif->dv, __NULL, 0) == __DEV_OK)
        {
            if (__deviceIOCtl(netif->dv, __IOCTL_GET_MAC_ADDRESS, 0, netif->addr.type.mac, 6) == __DEV_OK)
            {
                netif->addr.addr_type = __NET_ADDR_MAC;
            }
        } else {
            NETMSG(__NET_DEBUG_ETH, ("[ETH] %s device initialization failed.", netif->dv->dv_name));
            while (__TRUE) __threadSleep(1000);
        }
    }

    /* Check if the device is opened */
    if (!__deviceOpened(netif->dv))
    {
        while (__deviceOpen(netif->dv, 0) != __DEV_OK)
        {
            NETMSG(__NET_DEBUG_ETH, ("[ETH] %s device not ready.", netif->dv->dv_name));
            __threadSleep(2000);
        }
    }

    /* Set the RX timeout */
    __deviceIOCtl(netif->dv, __IOCTL_SETRXTIMEOUT, 1000, __NULL, 0);

    /* Allocate local buffer */
    netif->params = __heapAlloc(netif->mtu);

    for (;;)
    {
        /* Query for link status every two seconds */
        if (__systemGetSecondsCount() - seconds > 2)
        {
            /* Check the device answer */
            switch (__deviceIOCtl(netif->dv, __IOCTL_QUERY_LINK_STATUS, 0, &temp_status, 1))
            {
                case __DEV_UNK_IOCTL:
                    /* The device does not manage the __IOCTL_GET_LINK_STATUS ioctl,
                     * so assume the link is up. */
                    temp_status = 1;
                    break;

                case __DEV_OK:
                    break;

                /* If the device throws error or not ready, do nothing */
                case __DEV_ERROR:
                case __DEV_NOT_READY:
                    temp_status = 0;
                    break;
            }

            seconds = __systemGetSecondsCount();

            /* Detect link status change */
            switch (link_status)
            {
                case __ETHERNET_LINK_UNKNOWN:
                    if (temp_status) link_status = __ETHERNET_LINK_UP;
                    break;
                case __ETHERNET_LINK_UP:
                    if (!temp_status)
                    {
                        NETMSG(__NET_DEBUG_ETH, ("[ETH] (%s) link lost", netif->dv->dv_name));
                        link_status = __ETHERNET_LINK_LOST;
                    }
                    break;
                case __ETHERNET_LINK_LOST:
                    if (temp_status)
                    {
                        /* Link back */
                        NETMSG(__NET_DEBUG_ETH, ("[ETH] (%s) link back", netif->dv->dv_name));
                        link_status = __ETHERNET_LINK_UP;
                        if (netif->flags == __NETIF_FLAG_DHCP) __dhcpInitReboot(netif);
                    }
                    break;
            }
        }

        if (link_status == __ETHERNET_LINK_UP)
        {
            /* Call the DHCP state machine, if configured with __NETIF_FLAG_DHCP */
            if (netif->flags & __NETIF_FLAG_DHCP) __dhcpSm(netif);

            /* Call the ARP state machine */
            __arpSm(netif);

            /* Get a frame from the device */
            nb = __ethifGetFrame(netif);
            if (nb)
            {
                /* Pass it to the Ethernet handler */
                __ethifIn(netif, nb);
            }

        } else __threadSleep(1);
    }
}

Here is the call graph for this function:

 All Data Structures Files Functions Variables Typedefs Defines