STARTCOUNTER

Tuesday, August 9, 2011

Procedure to write an Ethernet driver in VxWorks



1. Introduction
This document describes about how to write an Ethernet driver in vxWorks. In vxWorks ,the network driver will be called as END Driver. The End drivers are based on the M_BLK,CL_BLK, and cluster packet model used by the Wind River Network Stack.
2. Initilization
Include END Driver support in the vxWorks project. Then End Device Table
(END_TBL_ENTRY endDevTbl[IP_MAX_UNITS+1];) has to be initialized for each interface.
typedef struct end_tbl_entry
{
int unit; /* This device's unit # */
END_OBJ* (*endLoadFunc) (char*, void*); /* The Load function. */
char* endLoadString; /* The load string. */
BOOL endLoan; /* Do we loan buffers? */
void* pBSP; /* BSP private */
BOOL processed; /* Has this been processed? */
} END_TBL_ENTRY;

endLoadfunc is the driver load function. endLoadString is the parameter for the endload function. It is a colon-separated string of parameters.
Usually it will have the number of End device name,TX buffers,Rx Buffers, Buffer size and etc,. All other variables in the END_TBL_ENTRY are optional.
After filling this structure for all the drivers, the table has to be terminated with a NULL.



endDevTbl[endDevIndex].unit = -1;
endDevTbl[endDevIndex].endLoadFunc = NULL;
endDevTbl[endDevIndex].endLoadString = NULL;
endDevTbl[endDevIndex].endLoan = FALSE;
endDevTbl[endDevIndex].processed = FALSE;

End Load function will do the following things


2.1 End driver initialization
Initialize the END object with the function END_OBJ_INIT.
STATUS endObjInit
(
END_OBJ * pEndObj, /* object to be initialized */
DEV_OBJ* pDevice, /* ptr to device struct */
char * pBaseName, /* device base name, for example, "ln" */
int unit, /* unit number */
NET_FUNCS * pFuncTable, /* END device functions */
char* pDescription
)
This routine initializes an END_OBJ structure and fills it with data from the argument list. It also creates and initializes semaphores and protocol list.pDevice is the device structure pointer which will passed to all the driver functions called by the operating system. pBaseName/unit are the device name and number.NET_FUNCS is the function table for the particular driver.



Here is the list of functions which has to be registered to the OS.
1. Function to start the device
2. Function to stop the device.
3. Unloading function for the driver.
4. Ioctl function for the driver.
5. Send function for the driver.
6. Multicast add function for the driver.
7. Multicast delete function for the driver.
8. Multicast retrieve function for the driver.
9. Polling send function
10.Polling receive function
11.Put address info into a NET_BUFFER
12.Get pointer to data in NET_BUFFER
13.Get packet addresses.

All the below three initilization has to be initialized from the END LOAD function before the brings up the interface using the END_OBJ_UP. endEtherAddressForm (put address info into a NET_BUFFER), endEtherPacketDataGet(get pointer to data in NET_BUFFER ), and endEtherPacketAddrGet( Get packet addresses)—are implemented in endEtherHdr.c, and are used only to support M_BLK-oriented protocols

2.2 Memory Initialization

This will perform memory allocation and distribution. The number of TX/RX buffers can be taken from the init string. All the network buffers and the descriptors for the DMA engine has to be prepared here.



2.3 Device configuration

Once the memory is intialized, the device hardware is ready for the configuration. Bring MAC and Phy out of reset,configure the MII and initialize all the register values.
MII – Media independent Interface
The Media Independent Interface (MII) is a standard interface used to connect a Fast Ethernet (i.e. 100 Mbit/s) MAC-block to a PHY chip. The MII may be used to connect the MAC to connect a MAC chip to a PHY chip. Media independent means that any of several different types of PHY devices for connecting to different media (i.e. Twisted pair copper, fiber optic, etc.) can be used without redesigning or replacing the MAC hardware. The equivalents of MII for other speeds are GMII/RGMII (for gigabit Ethernet)

2.4 Interrupt Initialization

This is the final part of initialization. Most of the network drivers are interrupt based. But we have an option for polling as well. Once the interrupt is initialized the interface is considered to be ready for up and running. So this must be the final part. So enabling the interrupt should be in AdminStart(Function to start the device).
3. MAC - PHY Configuration
This will be performed in the configuration phase for the MAC controller, and it will the attach PHY device. It will be called from the Endload function. Make the DMA engine ready,setup the Phy.

4. Send Handler
This will be called by the operating system whenever it wants to send an packet. Almost all operating system will deliver an Ethernet packet to the Send handler,doesn't matter what kind of driver it is. If it is an wireless driver the packet has to be converted to WIFI packet. So if it is an Ethernet driver, the packet can be send to the underlying hardware without any alteration to the packet unless VLAN is enabled. This can be done by DMA or without DMA.If the DMA is available, prepare the DMA descriptor with the packet and write descriptor to the Tx Descriptor register.Else, copy the packet to Ethernet controller's memory. Then set the TX Enable bit. This is to initimate the PHY that the current packet is ready to transmit. The handler can be called multiple times before it finishes its previous packet transmission. The driver has to handle this with any blocking system like semaphores.

5. Receive Handler
It is an interrupt handler, once the entire packet is received by the physical layer, the MAC will generate an interrupt. Since it is an interrupt handler usually we will verify only the status of the received packet and process and indication to the upper layer will be handled by an seperate task using netJobAdd in vxWorks. If there is no error in the packet reception, the packet has to be indicated to the upper layer.
END_RCV_RTN_CALL(&dev->end, pRxMblk);
6. IOCTLS
This is for controlling or getting the status of the interface from the upper layer. These are the major things
1. Set the MAC address
2. Get the MAC address
3. Set the Media status (Like auto negotiation,full duplex,...)
4. Get the Media status
5. Get the device name
6. MIB details

Saturday, August 6, 2011

Inter task communication in vxWorks

We can use the following mechanisms for inter task communication in vxWorks.

1) shared memory
2) semaphores
3) Message Queues
4) pipes
5) events
6) signals

Let's discuss about these inter task communication mechanisms in some posts.

Let's have a look at message queues.

  VxWorks applications are constructed using cooperating tasks. These tasks have high speed inter task communication mechanism called Message queues. Remember you can use semaphores only for mutual execution or synchronization of tasks.
   Each task and ISRs can send messages to msgQ and tasks can receive messages from a msgQ. Message queues allow a variable number of messages, each of variable length, to be queued. For full duplex communication between two tasks you need two msg  Queues.

Using Message Queues in your application is very simple. You need to know only four functions to use messages queues in your application. They are
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1) msgQCreate( ) ---> Allocates and initializes a message queue.
       
        Message Queues can be created with the call to msgQCreate. It has three parameters.
       
MSG_Q_ID msgQCreate
    (
    int maxMsgs,              /* max messages that can be queued */
    int maxMsgLength,         /* max bytes in a message */
    int options               /* message queue options */
    )

       

    The options parameter can have three values.
   
    MSG_Q_FIFO (0x00)
            queue pended tasks in FIFO order. If there are two are more tasks are waiting on this message queue then these tasks are queued in FIFO order. That is the fast task that calls the msgQReceive with this msgQID will receive the message that sent to the message Queue.
    MSG_Q_PRIORITY (0x01)
           queue pended tasks in priority order. If there are two or more tasks waiting for messages on a queue then thetasks are queued in priority order. The message sent to the queue will be received by the maximum priority task that is waiting on the queue for messages.
    MSG_Q_EVENTSEND_ERR_NOTIFY (0x02)
            When a message is sent, if a task is registered for events and the actual sending of events fails, a value of ERROR is returned and the errno is set accordingly. This option is off by default.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2. msgQDelete( ) - delete a message queue
  
STATUS msgQDelete
    (
    MSG_Q_ID msgQId           /* message queue to delete */
    )


    This routine deletes a message queue. All tasks pending on either msgQSend( ), msgQReceive( ) or pending for the reception of events meant to be sent from the message queue will unblock and return ERROR. When this function returns, msgQId is no longer a valid message queue ID.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3) msgQSend( ) - send a message to a message queue

STATUS msgQSend
    (
    MSG_Q_ID msgQId,          /* message queue on which to send */
    char *   buffer,          /* message to send */
    UINT     nBytes,          /* length of message */
    int      timeout,         /* ticks to wait */
    int      priority         /* MSG_PRI_NORMAL or MSG_PRI_URGENT */
    )

    The timeout parameter specifies the number of ticks to wait for free space if the message queue is full. The timeout parameter can also have the following special values:

    NO_WAIT (0)
            return immediately, even if the message has not been sent.
    WAIT_FOREVER (-1)
            never time out.

    The priority parameter specifies the priority of the message being sent. The possible values are:

    MSG_PRI_NORMAL (0)
            normal priority; add the message to the tail of the list of queued messages.
    MSG_PRI_URGENT (1)
            urgent priority; add the message to the head of the list of queued messages.

     Note that msgQSend can send a message to only one task. that is a message that is sent to a message queue (using msgQSend) can be received by only one task even though there are two or more tasks waiting for messages on this message queue.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4) msgQReceive( ) - receive a message from a message queue
   
   
int msgQReceive
    (
    MSG_Q_ID msgQId,          /* message queue from which to receive */
    char *   buffer,          /* buffer to receive message */
    UINT     maxNBytes,       /* length of buffer */
    int      timeout          /* ticks to wait */
    )

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     You can also use the msgQNumMsgs( ) to get the number of messages queued to a message queue

int msgQNumMsgs
    (
    MSG_Q_ID msgQId           /* message queue to examine */
    )
 
returns the number of messages queued.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~






Sunday, July 24, 2011

Introduction

Hello folks. We are group of Network engineers namely, Gomathisankar, Prathap Rajendran and Seshagopalan. Here is our blog which will talk about wired and wireless networking concepts etc.

Here we will update frequently on
- Logical and code wise explanation on network drivers
- Networking protocols
- Networking application which will be usefull for testing.


This blog will be useful for newbies in networking and for network engineers. Looking forward for some healthy discussions and share our knowledge with you all.