mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
12 KiB
413 lines
12 KiB
/****************************************************************************
|
|
*
|
|
* 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 ************************************************/
|