Network Driver

Initializing net_device

The function mydev_init() is used to initialize the net_device structure. The prototype of the function is int mydev_init(struct net_device *dev); The important fields of net_device needed are given below open: Which is used to store the address of the function which gets invoked when the network driver is activated. Here address of the function mydev_open() is stored in the field open. stop: Which is used to store the address of the function which gets invoked when the network driver is disabled. Here address of the function mydev_release() is stored in the field open. mtu: Maximum Transmission Unit is used to store the size of maximum size of the data packet. hard_start_xmit: This field is used to store the address of the function who transmit the data over the serial port. Here the address of the function mydev_xmit() is stored, which inturn calls the function send_packet for transmitting data. type: This field is used to store the type of the protocol used. Here the flag ARPHRD_SLIP is stored.

Registering net_device object

After performig the initialization of net_device we have to register the object for making it as a standard network interface. For this we have to create an object of net_device say mydev. In the 'init' field of mydev we have to place the address of the function which performs the initialization of the net_device objet. This can be achieve by using the code given below. struct net_device mydev = {init: mydev_init}; Then register the object mydev using the function register_netdev(). If the registering function return a nonzero value, there might be some error. If the function returns a zero, it indicates that the network driver is successfully registred.

Registering IRQ

The function request_irq() is used to request the IRQ. The first argument is the IRQ number, for which the interrupt handler is going to be installed. The second argument is the address of the interrupt handler routine. The third argument is a flag. Fourth argument is the name of the owner and the last argument is a pointer to the driver object. The prototype is given below. int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id); Here the flag is set to SA_INTERRUPT, which indicates a "fast" interrupt handler.

When the module is removed from the kernel, the IRQ line must be freed. The function free_irq() is used for this purpose. The prototype is given below. void free_irq(unsigned int irq, void *dev_id);

mydev_open()

Function prototype is given below int mydev_open(struct net_device *) This function is called when the networkdriver is activated. This function increments the usage count of the module using the macro MOD_INC_USE_COUNT. This function also starts a queue using the function netif_start_queue(). This queue is used for the communication with the upper layer protocols.

mydev_release()

Function prototype is given below int mydev_release(struct net_device *) This function is called when the networkdriver is disabled. This function decrements the usage count of the module using the macro MOD_DEC_USE_COUNT. This function also stops the queue which was created by mydev_open() for the communication with the upper layers using the function netif_stop_queue().

mydev_xmit()

Function prototype is given below static int mydev_xmit(struct sk_buff, struct net_device *); This function is called when the data is ready to transmit. This function has 2 arguments. The first argument is a pointer to the skbuff structure, which contains the data to be transmitted. This function calls the function calls the function send_packet() for encoding the using SLIP protocol an the transmission of data packets. Finally this routinr free s the memory used by the skbuff object using dev_kfree_skb().

Interrupt handler

the function uart_int_handler() is acting as the interrupt handler. Whenever an interrupt is occured, this function gets called. Then the interrupt identification register is checked to know whether it is a sending interrupt or a receiving interrupt. According to the interrupt the corresponding sending or receiving function is called.

If the interrupt occured is a receiving interrupt then the following actions are executed.An object for the structure skbuff is created and memory is allocated to the object using the function dev_alloc_skb(). The various fields of the skbuff object are set accordingly. The received data which is in slip_buffer[] ic copied to the data field of the struct skbuff object. Then the struct skbuff object is given to the upper layers using the function netif_rx() function.

Getting the Statistical Information

The ifconfig displays the number of received/transmitted packets, total number of bytes received/transmitted etc. To get the above statistical information, we have to do the following. The net_device structure contains a "private" pointer field, which can be used for holding information. We will allocate an object of type struct net_device_stats and store it's address in the private data area. As and when we receive/transmit data, we will update certain fields of this structure. When ifconfig wants to get statistical information about interface, it will call a function whose address is stored in the get_stats field of the net_device object. This function should simply return the address of the net_device object which holds the statistical information.

The important fields of the structure net_device_stats are tx_bytes : Which gives the number of transmitted bytes. rx_bytes : Which gives the number of received bytes. tx_packets : Which gives the number of transmitted packets rx_packets : Which gives the number of received packets.

When we transmit or receive the data packets we will update these fields.