/****************************************************************************
*
* DRV_IRQ.C : Part of the FASTMAC TOOL-KIT (FTK)
*
* THE DRIVER MODULE (INTERRUPT HANDLE)
*
* Copyright (c) Madge Networks Ltd. 1991-1994
*
* COMPANY CONFIDENTIAL
*
*****************************************************************************
*
* The driver module provides a simple interface to allow the use of
* Fastmac in as general a setting as possible. It handles the downloading
* of the Fastmac code and the initialization of the adapter card. It
* provides simple transmit and receive routines. It is desgined to
* quickly allow the implementation of Fastmac applications. It is not
* designed as the fastest or most memory efficient solution.
*
* DRV_IRQ.C contains code to handle SIF interrupts from the adapter card.
* The HWI_ modules take care of any PIO interrupts, and anything else is
* passed here. There is also code for calling the received frame handler
* from the foreground task rather than at interrupt time.
*
****************************************************************************/
/*---------------------------------------------------------------------------
|
| DEFINITIONS
|
---------------------------------------------------------------------------*/
#include "ftk_defs.h"
/*---------------------------------------------------------------------------
|
| MODULE ENTRY POINTS
|
---------------------------------------------------------------------------*/
#include "ftk_intr.h" /* routines internal to FTK */
#include "ftk_extr.h" /* routines provided or used by external FTK user */
/****************************************************************************
*
* driver_interrupt_entry
* ======================
*
* PARAMETERS (passed by hwi_<card_type>_sif_interrupt) :
* ======================================================
*
* ADAPTER_HANDLE adapter_handle
*
* The adapter handle for the adapter so it can be passed to the user
* supplied user_receive_frame or user_completed_srb routine.
*
* ADAPTER * adapter
*
* The details of the adapter that the interrupt has occured on.
*
* WORD sifint_actual
*
* The actual contents of the EAGLE SIF interrupt register.
*
* BODY :
* ======
*
* The driver_interupt_entry routine is called by the HWI. It is entered
* when an interrupt has occured for the given adapter. This could be
* because of an SRB free interrupt, an adapter chack interrupt or because
* frames are in the Fastmac receive buffer. Note these frames may have
* been in the receive buffer some time but not yet dealt with.
*
* On an SRB free interrupt, the interrupt is acknowledged and the
* driver_completing_srb routine in DRV_SRB.C is called. This results in
* the user supplied routine user_completed_srb being called informing the
* user on the success or failure of the current SRB and letting the user
* know that another SRB can be issued.
*
* On adapter check interrupts, the error record for the adapter is filled
* in to mark the adapter as no longer working. A call to a user function
* is made in case higher level code needs to take action.
*
* On receive frame interrupts, the action taken depends on the receive
* method being used. In FTK_RX_BY_SCHEDULED_PROCESS mode, the user routine
* user_schedule_receive_process is called with the adapter handle as the
* only parameter. It is the job of this user routine to schedule a process
* to call driver_get_outstanding_receive to get the received frames out of
* the Fastmac receive buffer. In FTK_RX_OUT_OF_INTERRUPTS mode, the received
* frames are dealt with immediately via the rxtx_irq_rx_frame_handler
* routine and the user supplied receive routine user_receive_frame.
*
* The rxtx_irq_rx_frame_handler routine is actually the same routine
* that is called by the driver_get_outstanding_receive routine if the
* FTK_RX_BY_SCHEDULED_PROCESS receive method is being used.
*
*
* Note on increasing speed:
*
* One way of speeding up execution of the receive routine would be to
* replace the sys_outsw and sys_insw routines by similar routines supplied
* with your C compiler and have them compiled in-line.
*
*
* RETURNS :
* =========
*
* The routine always succeeds and returns control to the HWI routine
* hwi_<type>_sif_interrupt.
*
****************************************************************************/
#ifdef FTK_IRQ_FUNCTION
#pragma FTK_IRQ_FUNCTION(driver_interrupt_entry)
#endif
export void
driver_interrupt_entry(
ADAPTER_HANDLE adapter_handle,
ADAPTER * adapter,
WORD sifint_actual
)
{
WORD sifint_value;
WBOOLEAN ack_needed = FALSE;
/*
* XOR the high byte and low byte of contents of EAGLE_SIFINT register.
*/
sifint_value = (sifint_actual & 0x00FF) ^ (sifint_actual >> 8);
/*
* AND with 0x000F so left with a nibble identifying interrupt type.
*/
sifint_value = sifint_value & 0x000F;
/*
* Action depends on interrupt type.
*/
if (sifint_value != 0)
{
if ((sifint_value & FASTMAC_SIFINT_ADAPTER_CHECK) != 0)
{
/*
* For adapter check, fill in error record so adapter now dead.
* No need to check if any other interrupt bits set.
*/
adapter->error_record.type = ERROR_TYPE_ADAPTER;
adapter->error_record.value = ADAPTER_E_01_ADAPTER_CHECK;
/*
* Allow the user to give some sort of warning.
*/
user_handle_adapter_check(adapter_handle);
}
else
{
if ((sifint_value & FASTMAC_SIFINT_SRB_FREE) != 0)
{
/*
* For SRB free interrupts, call routine which informs user.
*/
driver_completing_srb(adapter_handle, adapter);
ack_needed = TRUE;
}
if ((sifint_value & FASTMAC_SIFINT_ARB_COMMAND) != 0)
{
/*
* For ARB command interrupts, do nothing as
* they should never happen.
*/
ack_needed = TRUE;
}
if ((sifint_value & FASTMAC_SIFINT_SSB_RESPONSE) != 0)
{
/*
* For SSB response interrupts, do nothing as
* they should never happen.
*/
ack_needed = TRUE;
}
}
}
/*
* Now check for receives and transmits...
*/
#ifdef FMPLUS
/*
* For Fastmac Plus, we must allow for the possibility that the
* interrupt is because a large transmit buffer DMA is complete.
*/
#ifdef FTK_TX_WITH_COMPLETION
#ifndef FTK_NO_TX_COMPLETION_CALL
rxtx_irq_tx_completion_check(adapter_handle, adapter);
#endif
#endif
#endif
/*
* Invoke received frame processing based on the receive mode.
*/
#ifdef FTK_RX_OUT_OF_INTERRUPTS
rxtx_irq_rx_frame_handler(adapter_handle, adapter);
#endif
#ifdef FTK_RX_BY_SCHEDULED_PROCESS
#ifndef FTK_NO_IO_ENABLE
macro_disable_io(adapter);
#endif
user_schedule_receive_process(adapter_handle);
#ifndef FTK_NO_IO_ENABLE
macro_enable_io(adapter);
#endif
#endif
/*
* Now do any cleaning up that is needed ...
* For certain interrupts, need to interrupt Fastmac to acknowledge.
*/
if (ack_needed)
{
/*
* Convert from FASTMAC_SIFINT interrupt into DRIVER_SIFINT_ACK
* to acknowledge interrupt.
*/
sifint_value = (sifint_value << 8);
/*
* Set interrupt adapter bit in SIFCMD.
*/
sifint_value = (sifint_value | DRIVER_SIFINT_IRQ_FASTMAC);
/*
* Mask SIFSTS so not clear interrupt if Fastmac interrupted again.
*/
sifint_value = (sifint_value | DRIVER_SIFINT_FASTMAC_IRQ_MASK);
/*
* Interrupt Fastmac.
*/
sys_outsw(adapter_handle, adapter->sif_int, sifint_value);
}
/*
* Return to hwi_interrupt_entry routine.
*/
}
/****************************************************************************
*
* driver_get_outstanding_receive
* ==============================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter which we wish to deal with
* outstanding received frames on.
*
* BODY :
* ======
*
* The driver_get_outstanding_receive routine should be called only when
* using the FTK_RX_BY_SCHEDULED_PROCESS receive method. The user supplied
* receive routine (user_receive_frame) is called with the adapter handle
* and the length and a physical address pointer to the oldest unprocessed
* received frame for the given adapter. If there are no oustanding
* received frames the user routine is never called but this is not an
* error and is not regsitered as such.
*
* If the receive routine processes the frame (returns DO_NOT_KEEP_FRAME),
* and if the Fastmac receive buffer is not empty, the receive routine is
* called again with the details of the next frame. This continues until
* either the Fastmac buffer is empty or the receive routine does not
* process the frame (returns KEEP_FRAME). However, no more than one buffer
* full of frames is passed to the user receive routine on any one entry to
* driver_get_outstanding_receive. Note that if the receive buffer is not
* emptied by the user then another interrupt will occur later and the
* process that calls driver_get_outstanding_receive will be rescheduled.
*
* To deal with the details of handling received frames in the Fastmac
* buffers, this routine uses rxtx_irq_rx_frame_handler. This is the
* same routine called out of driver_interrupt_entry if the
* FTK_RX_OUT_OF_INTERRUPTS receive method is being used. The routine uses
* an algorithm for dealing with received frames similar to that in the
* Fastmac specification document.
*
* Dealing with received frames using the driver_get_outstanding_receive
* routine is different to using the driver_interrupt_entry routine in that
* the former routine is called under user control, in strategy time as
* opposed to interrupt time, and hence gives the user receive frame
* routine more time to process frames. This is necessary under certain
* operating systems such as AIX.
*
* Notes on increasing speed:
*
* The code between "#ifndef SPEED_ABOVE_TESTING" to "#endif" is only for
* testing purposes. If SPEED_ABOVE_TESTING is defined during compilation
* then the code will not be included so the receive routine will execute
* faster. However, an erroneous adapter handle would then cause a program
* to crash unpredicatably. The SPEED_ABOVE_TESTING option should be used
* with care.
*
* Another way of speeding up execution of the receive routine would be to
* replace the sys_outsw and sys_insw routines by similar routines supplied
* with your C compiler and have them compiled in-line.
*
* RETURNS :
* =========
*
* The routine returns TRUE if it succeeds. If this routine fails (returns
* FALSE) then a subsequent call to driver_explain_error with the same
* adapter handle will give an explanation. Note that it will not fail just
* because there are no frames to receive.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_get_outstanding_receive)
#endif
export WBOOLEAN
driver_get_outstanding_receive(
ADAPTER_HANDLE adapter_handle
)
{
ADAPTER * adapter;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
#ifndef SPEED_ABOVE_TESTING
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_ANY_STATE))
{
return FALSE;
}
#endif
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Inform the system about the IO ports we are going to access.
*/
#ifndef FTK_NO_IO_ENABLE
macro_enable_io(adapter);
#endif
/*
* Perform the actual frame receiving uses same routine called out
* of interrupts with FTK_RX_OUT_OF_INTERRUPTS.
*/
rxtx_irq_rx_frame_handler(adapter_handle, adapter);
/*
* Let the system know we have finished accessing the IO ports.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io(adapter);
#endif
/*
* Receive completed.
*/
return TRUE;
}
/**** End of DRV_IRQ.C file ************************************************/