VxWorks Reference Manual : Libraries

if_eihk

NAME

if_eihk - Intel 82596 Ethernet network interface driver for hkv3500

ROUTINES

eihkattach( ) - publish the ei network interface and initialize the driver and device
eiTxStartup( ) - start output on the chip
eiInt( ) - entry point for handling interrupts from the 82596

DESCRIPTION

This module implements a hkv3500 specfic Intel 82596 Ethernet network interface driver.

This driver is derived from the generic if_ei ethernet driver to support hkv3500 target board. The receive buffer scheme has been modified from a simplified memory structure to a flexible memory structure so that receive buffers can be word-aligned, and thus support buffer loaning on a MIPS CPU architecture.

The driver requires several target-specific parameters, and some external support routines which are detailed below.

This driver can run with the device configured in either big-endian or little-endian modes. Error recovery code has been added to deal with some of the known errata in the A0 version of the device. This driver supports up to four individual units per CPU.

BOARD LAYOUT

This device is on-board. No jumpering diagram is necessary.

EXTERNAL INTERFACE

This driver provides the standard external interface with the following exceptions. All initialization is performed within the attach routine; there is no separate initialization routine. Therefore, in the global interface structure, the function pointer to the initialization routine is NULL.

The only user-callable routine is eihkattach( ), which publishes the ei interface and initializes the driver and device.

TARGET-SPECIFIC PARAMETERS

the sysbus value
This parameter is passed to the driver by eihkattach( ).

The Intel 82596 requires this parameter during initialization. This parameter tells the device about the system bus, hence the name "sysbus." To determine the correct value for a target, refer to the document Intel 32-bit Local Area Network (LAN) Component User's Manual.

interrupt vector
This parameter is passed to the driver by eihkattach( ).

The Intel 82596 generates hardware interrupts for various events within the device; thus it contains an interrupt handler routine. This driver calls intConnect( ) to connect its interrupt handler to the interrupt vector generated as a result of the 82596 interrupt.

shared memory address
This parameter is passed to the driver by eihkattach( ).

The Intel 82596 device is a DMA type device and typically shares access to some region of memory with the CPU. This driver is designed for systems that directly share memory between the CPU and the 82596.

This parameter can be used to specify an explicit memory region for use by the 82596. This should be done on targets that restrict the 82596 to a particular memory region. The constant NONE can be used to indicate that there are no memory limitations, in which case, the driver attempts to allocate the shared memory from the system space.

number of Receive and Transmit Frame Descriptors
These parameters are passed to the driver by eihkattach( ).

The Intel 82596 accesses frame descriptors in memory for each frame transmitted or received. The number of frame descriptors at run-time can be configured using these parameters.

Ethernet address
This parameter is obtained by a call to an external support routine.

During initialization, the driver needs to know the Ethernet address for the Intel 82596 device. The driver calls the external support routine, sysEnetAddrGet( ), to obtain the Ethernet address. For a description of sysEnetAddrGet( ), see "External Support Requirements" below.

EXTERNAL SUPPORT REQUIREMENTS

This driver requires seven external support functions:

STATUS sysEnetAddrGet (int unit, char *pCopy)
This routine provides the six-byte Ethernet address used by unit. It must copy the six-byte address to the space provided by pCopy. This routine returns OK, or ERROR if it fails. The driver calls this routine, once per unit, using eihkattach( ).

STATUS sys596Init (int unit, SCB *pScb)
This routine performs any target-specific initialization required before the 82596 is initialized. Typically, it is empty. This routine must return OK, or ERROR if it fails. The driver calls this routine, once per unit, using eihkattach( ).

void sys596Port (int unit, int cmd, UINT32 addr)
This routine provides access to the special port function of the 82596. It delivers the command and address arguments to the port of the specified unit. The driver calls this routine primarily during initialization, but may also call it during error recovery procedures.

void sys596ChanAtn (int unit)
This routine provides the channel attention signal to the 82596, for the specified unit. The driver calls this routine frequently throughout all phases of operation.

void sys596IntEnable (int unit), void sys596IntDisable (int unit)
These routines enable or disable the interrupt from the 82596 for the specified unit. Typically, this involves interrupt controller hardware, either internal or external to the CPU. Since the 82596 itself has no mechanism for controlling its interrupt activity, these routines are vital to the correct operation of the driver. The driver calls these routines throughout normal operation to protect certain critical sections of code from interrupt handler intervention.

void sys596IntAck (int unit)
This routine must perform any required interrupt acknowledgment or clearing. Typically, this involves an operation to some interrupt control hardware. Note that the INT signal from the 82596 behaves in an "edge-triggered" mode; therefore, this routine typically clears a latch within the control circuitry. The driver calls this routine from the interrupt handler.

SYSTEM RESOURCE USAGE

When implemented, this driver requires the following system resources:

    - one mutual exclusion semaphore
    - one interrupt vector
    - one watchdog timer.
    - 8 bytes in the initialized data section (data)
    - 912 bytes in the uninitialized data section (BSS)

The above data and BSS requirements are for the MC68020 architecture and may vary for other architectures. Code size (text) varies greatly between architectures and is therefore not quoted here.

The driver uses cacheDmaMalloc( ) to allocate memory to share with the 82596. The fixed-size pieces in this area total 160 bytes. The variable-size pieces in this area are affected by the configuration parameters specified in the eihkattach( ) call. The size of one RFD (Receive Frame Descriptor) is 1536 bytes. The size of one TFD (Transmit Frame Descriptor) is 1534 bytes. For more information about RFDs and TFDs, see the Intel 82596 User's Manual.

The 82596 can be operated only if this shared memory region is non-cacheable or if the hardware implements bus snooping. The driver cannot maintain cache coherency for the device because fields within the command structures are asynchronously modified by both the driver and the device, and these fields may share the same cache line.

TUNING HINTS

The only adjustable parameters are the number of TFDs and RFDs that will be created at run-time. These parameters are given to the driver when eihkattach( ) is called. There is one TFD and one RFD associated with each transmitted frame and each received frame respectively. For memory-limited applications, decreasing the number of TFDs and RFDs may be desirable. Increasing the number of TFDs will provide no performance benefit after a certain point. Increasing the number of RFDs will provide more buffering before packets are dropped. This can be useful if there are tasks running at a higher priority than the net task.

SEE ALSO

if_eihk, ifLib, Intel 82596 User's Manual, Intel 32-bit Local Area Network (LAN) Component User's Manual


Libraries : Routines

eihkattach( )

NAME

eihkattach( ) - publish the ei network interface and initialize the driver and device

SYNOPSIS

STATUS eihkattach
    (
    int    unit,    /* unit number */
    int    ivec,    /* interrupt vector number */
    UINT8  sysbus,  /* sysbus field of SCP */
    char * memBase, /* address of memory pool or NONE */
    int    nTfds,   /* no. of transmit frames (0 = default) */
    int    nRfds    /* no. of receive frames (0 = default) */
    )

DESCRIPTION

This routine publishes the ei interface by filling in a network interface record and adding this record to the system list. This routine also initializes the driver and the device to the operational state.

The 82596 shares a region of memory with the driver. The caller of this routine can specify the address of this memory region, or can specify that the driver must obtain this memory region from the system resources.

The sysbus parameter accepts values as described in the Intel manual for the 82596. A default number of transmit/receive frames of 32 can be selected by passing zero in the parameters nTfds and nRfds. In other cases, the number of frames selected should be greater than two.

The memBase parameter is used to inform the driver about the shared memory region. If this parameter is set to the constant "NONE," then this routine will attempt to allocate the shared memory from the system. Any other value for this parameter is interpreted by this routine as the address of the shared memory region to be used.

If the caller provides the shared memory region, then the driver assumes that this region does not require cache coherency operations, nor does it require conversions between virtual and physical addresses.

If the caller indicates that this routine must allocate the shared memory region, then this routine will use cacheDmaMalloc( ) to obtain some non-cacheable memory. The attributes of this memory will be checked, and if the memory is not both read and write coherent, this routine will abort and return ERROR.

RETURNS

OK or ERROR.

SEE ALSO

if_eihk, ifLib, Intel 82596 User's Manual


Libraries : Routines

eiTxStartup( )

NAME

eiTxStartup( ) - start output on the chip

SYNOPSIS

#ifdef BSD43_DRIVER static void eiTxStartup
    (
    int unit
    )

DESCRIPTION

Looks for any action on the queue, and begins output if there is anything there. This routine is called from several possible threads. Each will be described below.

The first, and most common thread, is when a user task requests the transmission of data. Under BSD 4.3, this will cause eiOutput( ) to be called, which calls ether_output( ), which will usually call this routine. This routine will not be called if ether_output( ) finds that our interface output queue is full. In this case, the outgoing data will be thrown out. BSD 4.4 uses a slightly different model in which the generic ether_output( ) routine is called directly, followed by a call to this routine.

The second, and most obscure thread, is when the reception of certain packets causes an immediate (attempted) response. For example, ICMP echo packets (ping), and ICMP "no listener on that port" notifications. All functions in this driver that handle the reception side are executed in the context of netTask( ). Always. So, in the case being discussed, netTask( ) will receive these certain packets, cause IP to be stimulated, and cause the generation of a response to be sent. We then find ourselves following the thread explained in the second example, with the important distinction that the context is that of netTask( ).

The third thread occurs when this routine runs out of TFDs and returns. If this occurs when our output queue is not empty, this routine would typically not get called again until new output was requested. Even worse, if the output queue was also full, this routine would never get called again and we would have a lock state. It DOES happen. To guard against this, the transmit clean-up handler detects the out-of-TFDs state and calls this function. The clean-up handler also runs from netTask.

Note that this function is ALWAYS called between an splnet( ) and an splx( ). This is true because netTask( ), and ether_output( ) take care of this when calling this function. Therefore, no calls to these spl functions are needed anywhere in this output thread.

SEE ALSO

if_eihk


Libraries : Routines

eiInt( )

NAME

eiInt( ) - entry point for handling interrupts from the 82596

SYNOPSIS

void eiInt
    (
    DRV_CTRL * pDrvCtrl
    )

DESCRIPTION

The interrupting events are acknowledged to the device, so that the device will deassert its interrupt signal. The amount of work done here is kept to a minimum; the bulk of the work is defered to the netTask. Several flags are used here to synchronize with task level code and eliminate races.

SEE ALSO

if_eihk