Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1849 lines
51 KiB

/****************************************************************************
*
* DRV_SRB.C : Part of the FASTMAC TOOL-KIT (FTK)
*
* THE DRIVER MODULE (SRBs)
*
* 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.
*
* The DRV_SRB.C module contains those routines that involve issuing SRBs,
* such as open adapter and set functional address. It also contains the
* code that calls the user when an SRB completes.
*
****************************************************************************/
/*---------------------------------------------------------------------------
|
| 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 */
/*---------------------------------------------------------------------------
|
| GLOBAL VARIABLES
|
---------------------------------------------------------------------------*/
export char ftk_product_inst_id[SIZEOF_PRODUCT_ID] = FASTMAC_PRODUCT_ID;
/*---------------------------------------------------------------------------
|
| LOCAL FUNCTIONS
|
---------------------------------------------------------------------------*/
local void
driver_issue_srb(
ADAPTER * adapter
);
local WBOOLEAN
get_open_and_ring_status(
void * ptr
);
local WBOOLEAN
issue_srb(
void * ptr
);
/****************************************************************************
*
* driver_ring_speed
* =================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter whose ring speed is to be returned.
*
* BODY :
* ======
*
* This is a short helper function (that could easily be replaced by a
* macro). It just digs out the stored ring speed from the adapter
* structure, so that external users of the FTK have some way of getting at
* this piece of information.
*
* RETURNS :
* =========
*
* The current ring speed.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_ring_speed)
#endif
export UINT
driver_ring_speed(
ADAPTER_HANDLE adapter_handle
)
{
return adapter_record[adapter_handle]->ring_speed;
}
/****************************************************************************
*
* driver_max_frame_size
* =====================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter whose maximum supported frame size is
* to be returned.
*
* BODY :
* ======
*
* This is a short helper function (that could easily be replaced by a
* macro). It just digs out the stored maximum frame size from the adapter
* structure, so that external users of the FTK have some way of getting at
* this piece of information.
*
* RETURNS :
* =========
*
* The current maximum frame size.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_max_frame_size)
#endif
export UINT
driver_max_frame_size(
ADAPTER_HANDLE adapter_handle
)
{
return adapter_record[adapter_handle]->max_frame_size;
}
/****************************************************************************
*
* driver_modify_open_options
* ==========================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter on which to modify the open options.
*
* WORD open_options
*
* This gives the new modified open options for the adapter.
*
* BODY :
* ======
*
* The driver_modify_open_options routine issues a modify open parms SRB.
* The adapter must be open for this command to complete successfully. It
* does not matter whether the adapter has been opened in auto-open mode or
* using an open adapter SRB.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_modify_open_options)
#endif
export WBOOLEAN
driver_modify_open_options(
ADAPTER_HANDLE adapter_handle,
WORD open_options
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_MODIFY_OPEN_PARMS));
/*
* Set up non-zero modify open parms SRB fields.
*/
srb_gen->mod_parms.header.function = MODIFY_OPEN_PARMS_SRB;
srb_gen->mod_parms.open_options = open_options;
/*
* Save a copy of the open options in the fastmac init block, in
* case we later have to re-open the adapter with the same state. This
* is the case with NDIS3 MacReset(), which causes the card to be re-
* initialized, but the open options must be left as they were before
* the reset.
*/
adapter->init_block->fastmac_parms.open_options = open_options;
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_MODIFY_OPEN_PARMS);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_open_adapter
* ===================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to be opened.
*
* PTR_OPEN_DATA open_data
*
* This points to a structure containing : the open options, the opening
* node address, the opening functional address, and the opening group
* address. If the opening node address is NULL, the BIA PROM node address
* will be used instead.
*
* BODY :
* ======
*
* The driver_open_adapter routine issues an open adapter SRB. This routine
* is not needed when the Fastmac auto_open option is used.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_open_adapter)
#endif
export WBOOLEAN
driver_open_adapter(
ADAPTER_HANDLE adapter_handle,
PTR_OPEN_DATA open_data
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
UINT i;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter( adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_OPEN_ADAPTER));
/*
* Set up non-zero open adapter SRB fields.
*/
srb_gen->open_adap.header.function = OPEN_ADAPTER_SRB;
srb_gen->open_adap.open_options = open_data->open_options;
/*
* Fill in opening node address field.
*/
for (i = 0; i < sizeof(NODE_ADDRESS); i++)
{
if (open_data->opening_node_address.byte[i] != 0)
{
break;
}
}
if (i == sizeof(NODE_ADDRESS))
{
/*
* If opening node address not given then use BIA PROM address.
*/
srb_gen->open_adap.open_address = adapter->permanent_address;
}
else
{
/*
* Otherwise use supplied node address.
*/
srb_gen->open_adap.open_address = open_data->opening_node_address;
}
srb_gen->open_adap.group_address = open_data->group_address;
srb_gen->open_adap.functional_address = open_data->functional_address;
/*
* Byte swap node address before downloading to adapter.
*/
util_byte_swap_structure(
(BYTE *) &srb_gen->open_adap.open_address,
sizeof(NODE_ADDRESS)
);
/*
* Fill in the product id with product ID string.
*/
util_mem_copy(
srb_gen->open_adap.product_id,
ftk_product_inst_id,
SIZEOF_PRODUCT_ID
);
/*
* Byte swap the product id string before downloading.
*/
util_byte_swap_structure(
(BYTE *) srb_gen->open_adap.product_id,
SIZEOF_PRODUCT_ID
);
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_OPEN_ADAPTER);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_close_adapter
* ====================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to be closed.
*
*
* BODY :
* ======
*
* The driver_close_adapter routine issues a close adapter SRB. If the
* auto_open feature is being used then it is disabled by this call.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_close_adapter)
#endif
export WBOOLEAN
driver_close_adapter(
ADAPTER_HANDLE adapter_handle
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_CLOSE_ADAPTER));
/*
* Place SRB type into header.
*/
srb_gen->close_adap.header.function = CLOSE_ADAPTER_SRB;
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_CLOSE_ADAPTER);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_set_group_address
* ========================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the required adapter.
*
* MULTI_ADDRESS * group_address
*
* The adapter is configured to receive frames sent to the group address
* formed from this parameter with the prefix 0xC000 and logically ANDed
* with 0x80000000. For example {0x12,0x34,0x56,0x78} gives the group
* address 0xC00092345678.
*
* BODY :
* ======
*
* The driver_set_group_address routine issues a set group address SRB. The
* adapter must be open for the SRB to complete successfully.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_set_group_address)
#endif
export WBOOLEAN
driver_set_group_address(
ADAPTER_HANDLE adapter_handle,
MULTI_ADDRESS * group_address
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_GROUP_ADDRESS));
/*
* Place SRB type into header.
*/
srb_gen->set_group.header.function = SET_GROUP_ADDRESS_SRB;
/*
* Byte swap group address (for downloading) when putting it in SRB.
*/
srb_gen->set_group.multi_address = *group_address;
util_byte_swap_structure(
(BYTE *) &srb_gen->set_group.multi_address,
sizeof(MULTI_ADDRESS)
);
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_SET_GROUP_ADDRESS);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_set_functional_address
* =============================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the required adapter.
*
* MULTI_ADDRESS * functional_address
*
* For each bit set in this parameter, the adapter is configured to receive
* frames sent to that functional address (0xC000xxxxxxxx). For example, if
* functional_address equals {0x40,0x00,0x00,0x80} then the corresponding
* functional addresses are 0xC00040000000 and 0xC00000000080.
*
*
* BODY :
* ======
*
* The driver_set_functional_address routine issues a set functional
* address SRB. The adapter must be open for the SRB to complete
* successfully. The effects of this call are not cumulative - that is
* each call must specify ALL functional addresses required.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_set_functional_address)
#endif
export WBOOLEAN
driver_set_functional_address(
ADAPTER_HANDLE adapter_handle,
MULTI_ADDRESS * functional_address
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_FUNCTIONAL_ADDRESS));
/*
* Place SRB type into header.
*/
srb_gen->set_func.header.function = SET_FUNCTIONAL_ADDRESS_SRB;
/*
* Byte swap functional address (for downloading) when putting in SRB.
*/
srb_gen->set_func.multi_address = *functional_address;
util_byte_swap_structure(
(BYTE *) &srb_gen->set_func.multi_address,
sizeof(MULTI_ADDRESS)
);
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_SET_FUNCTIONAL_ADDRESS);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_get_open_and_ring_status
* ===============================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to get the adapter status information
* on.
*
* WORD * pwRingStatus
* WORD * pwOpenStatus
*
* These OUT parameters are filled with the Open and Ring status values in
* addition to them being written into the status structure. It is often
* convenient to be able to have these values stored at the callers whim.
* They can be NULL if the caller does not need these values directly.
*
* BODY :
* ======
*
* The driver_get_open_and_ring_status routine accesses DIO space to get
* the current adapter open status and the current ring status. These two
* bits of information are filled into the status information structure in
* the adapter structure, and written to the supplied locations.
*
* RETURNS :
* =========
*
* Nothing. But see the status information structure in the current adapter
* for the open status and ring status.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_get_open_and_ring_status)
#endif
export void
driver_get_open_and_ring_status(
ADAPTER_HANDLE adapter_handle,
WORD * pwRingStatus,
WORD * pwOpenStatus
)
{
ADAPTER * adapter;
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
if (adapter == NULL)
{
if (pwRingStatus != NULL)
{
*pwRingStatus = 0;
}
if (pwOpenStatus != NULL)
{
*pwOpenStatus = 0;
}
return;
}
/*
* Inform the system about the IO ports we are going to access.
*/
#ifndef FTK_NO_IO_ENABLE
macro_enable_io(adapter);
#endif
/*
* Get adapter open status from the STB in DIO space.
*/
sys_sync_with_interrupt(
adapter->adapter_handle,
get_open_and_ring_status,
adapter);
/*
* Let the system know we have finished accessing the IO ports.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io(adapter);
#endif
if (pwRingStatus != NULL)
{
*pwRingStatus = adapter->status_info->ring_status;
}
if (pwOpenStatus != NULL)
{
*pwOpenStatus = adapter->status_info->adapter_open;
}
}
/****************************************************************************
*
* driver_get_status
* =================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to get the adapter status information
* on.
*
* BODY :
* ======
*
* The driver_get_status routine issues a read error log SRB in order to
* get the error log maintained by the protocol handler. This routine also
* accesses DIO space to get the current adapter open status and the
* current ring status. These two bits of information are actually filled
* into the status information structure immediately - they are available
* before the user_completed_srb routine is called.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the actual SRB completes. It is this
* user routine that is informed as to whether the SRB completed
* successfully and it is at this time that the error log is filled into
* the status information structure. Also, until the user_completed_srb
* routine is called by the driver, no other driver routines involving the
* issuing of SRBs for the given adapter will work. This is because there
* is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* Note there is no need to worry about an interrupt occuring, (between the
* setting of the EAGLE SIFADR register and the reading/writing of the
* required DIO space data), that would alter the contents of the EAGLE
* SIFADR register (and hence the SIFDAT and SIFDAT_INC registers too).
* This is because the receive frame interrupt handler exits leaving the
* contents of SIFADR as on entry.
*
* RETURNS :
* =========
*
* The routine returns TRUE if it succeeds and will have filled in the
* requested status information but not the error log. 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb. Also, in this particular case, it
* is important to note that the error log is not filled in until the SRB
* completes.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_get_status)
#endif
export WBOOLEAN
driver_get_status(
ADAPTER_HANDLE adapter_handle
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Get the adapter open status and ring status.
*/
driver_get_open_and_ring_status(adapter_handle, NULL, NULL);
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_READ_ERROR_LOG));
/*
* Place SRB type into header.
*/
srb_gen->err_log.header.function = READ_ERROR_LOG_SRB;
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_READ_ERROR_LOG);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_set_bridge_parms
* =======================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter to get the adapter status information
* on.
*
* WBOOLEAN single_route_bcast
*
* If this is TRUE, then single route broadcast frames will be rejected
* by the SRA.
*
* UINT this_ring
*
* This is the ring number that the SRA will recognise as the source ring.
* It must be the number of the ring to which this adapter is connected. It
* will be matched against the source ring field in the routing information
* section of frames received from this ring.
*
* UINT that_ring
*
* This is the ring number that the SRA will recognise as the destination
* ring. It must be the number of the ring to which the other adapter in
* this host is connected. It will be matched against the target ring field
* in the routing information section of frames received from the source
* ring.
*
* UINT bridge_num
*
* This is the number that identifies this bridge on both rings. It will be
* matched against the bridge number field in the routing information field
* of frames received from the source ring.
*
* BODY :
* ======
*
* The driver_set_bridge_parms routine issues a set bridge parms SRB.
* The adapter must be open for the SRB to complete successfully.
* Two of the fields use default values to simplify the calling procedure a
* little - these are the number of bridge bits and the maximum length of
* the routing information field. The number of bridge bits defaults to 4
* allowing bridge numbers between 0 and 0xF, and ring numbers between 0
* and 0xFFF. All bridges on the network must agree on this value. The max.
* routing field causes all frames with routing information fields longer
* than the specified value to be rejected by the SRA. To be IBM compatible
* this value should be 18, which is the default value.
* These values are defined in FTK_SRB.H.
*
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the SRB completes. It is this user
* routine that is informed as to whether the SRB completed successfully.
* Also, until this routine is called by the driver, no other driver
* routines involving the issuing of SRBs for the given adapter will work.
* This is because there is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_set_bridge_parms)
#endif
export WBOOLEAN
driver_set_bridge_parms(
ADAPTER_HANDLE adapter_handle,
WBOOLEAN single_route_bcast,
UINT this_ring,
UINT that_ring,
UINT bridge_num
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
WORD options;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_BRIDGE_PARMS));
/*
* Place SRB type into header.
*/
srb_gen->set_bridge_parms.header.function = SET_BRIDGE_PARMS_SRB;
/*
* Fill in the bridge parameters, using defaults from FTK_SRB.H and the
* user supplied values.
*
* Note that the bit fields in the options word are filled in here using
* shifts and ORs, because of the danger that different compilers will
* order bit fields in a structure differently.
*/
options = ((single_route_bcast ? 0x8000 : 0)
| ((SRB_SBP_DFLT_ROUTE_LEN & 0x3f) << 4)
| (SRB_SBP_DFLT_BRIDGE_BITS & 0xf));
srb_gen->set_bridge_parms.options = options;
srb_gen->set_bridge_parms.this_ring = this_ring;
srb_gen->set_bridge_parms.that_ring = that_ring;
srb_gen->set_bridge_parms.bridge_num = bridge_num;
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_SET_BRIDGE_PARMS);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_set_product_instance_id
* ==============================
*
* PARAMETERS :
* ============
*
* ADAPTER_HANDLE adapter_handle
*
* This handle identifies the adapter on which to set the product instance
* identification string.
*
* BYTE * product_id
*
* A pointer to an eighteen byte ASCII Identification string.
*
* BODY :
* ======
*
* The driver_set_product_instance_id issues an SRB to set the product id
* string. This string is written into certain MAC frames to report various
* software and hardware conditions.
* As with all the routines that involve issuing SRBs, the user routine
* user_completed_srb is called when the actual SRB completes. It is this
* user routine that is informed as to whether the SRB completed
* successfully and it is at this time that the error log is filled into
* the status information structure. Also, until the user_completed_srb
* routine is called by the driver, no other driver routines involving the
* issuing of SRBs for the given adapter will work. This is because there
* is only one SRB per adapter.
*
* Note that only those fields that are used in the SRB (ie. have non-zero
* values) that need to be byte swapped are byte swapped either in this
* routine or in driver_issue_srb. Hence, if any adjustments are made to
* the code it may be necessary to make sure that any newly used fields are
* correctly byte swapped before downloading.
*
* Take special note of the fact that the user_completed_srb routine can be
* called before this routine completes. This is because it is called out
* of interrupts.
*
* 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 a successful call to this routine only means that the SRB has
* been issued successfully. It does not mean that it has completed
* successfully. The success or failure of the SRB is indicated in a
* subsequent call to user_completed_srb. Also, in this particular case, it
* is important to note that the error log is not filled in until the SRB
* completes.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_set_product_instance_id)
#endif
export WBOOLEAN
driver_set_product_instance_id(
ADAPTER_HANDLE adapter_handle,
BYTE * product_id
)
{
ADAPTER * adapter;
SRB_GENERAL * srb_gen;
/*
* Check adapter handle and status of adapter for validity.
* If routine fails return failure (error record already filled in).
*/
if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
{
return FALSE;
}
/*
* Get pointer to adapter structure.
*/
adapter = adapter_record[adapter_handle];
/*
* Set adapter SRB status to show that SRB is now in use.
*/
adapter->srb_status = SRB_NOT_FREE;
/*
* Get pointer to general SRB structure to be used.
*/
srb_gen = &adapter->srb_general;
/*
* Clear part of general SRB to be used.
*/
util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_PROD_INST_ID));
/*
* Place SRB type into header - this is a Fastmac Plus specific one, so
* we have to set a subcode value too.
*/
srb_gen->set_prod_inst_id.header.function = FMPLUS_SPECIFIC_SRB;
srb_gen->set_prod_inst_id.subcode = SET_PROD_INST_ID_SUBCODE;
/*
* Copy in the product instance id.
*/
util_mem_copy(
srb_gen->set_prod_inst_id.product_id,
product_id,
SIZEOF_PRODUCT_ID
);
/*
* Byte swap the product instance id.
*/
util_byte_swap_structure(
(BYTE *) srb_gen->set_prod_inst_id.product_id,
SIZEOF_PRODUCT_ID
);
/*
* Record size of SRB that is being issued.
*/
adapter->size_of_srb = sizeof(SRB_SET_PROD_INST_ID);
/*
* Call routine to issue SRB.
*/
driver_issue_srb(adapter);
/*
* SRB issued successfully.
*/
return TRUE;
}
/****************************************************************************
*
* driver_issue_srb
* ================
*
* The driver_issue_srb routine issues an SRB. It does this by copying it
* into DIO space and issuing an SRB command interrupt to Fastmac via the
* SIFINT register.
*
* Note there is no need to worry about an interrupt occuring, (between the
* setting of the EAGLE SIFADR register and the reading/writing of the
* required DIO space data), that would alter the contents of the EAGLE
* SIFADR register (and hence the SIFDAT and SIFDAT_INC registers too).
* This is because the receive frame interrupt handler exits leaving the
* contents of SIFADR as on entry.
*
****************************************************************************/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(driver_issue_srb)
#endif
local void
driver_issue_srb(
ADAPTER * adapter
)
{
ADAPTER_HANDLE hnd = adapter->adapter_handle;
SRB_GENERAL * srb_gen = &adapter->srb_general;
/*
* Before downloading need to byte swap the SRB header.
*/
util_byte_swap_structure(
(BYTE *) &srb_gen->header,
sizeof(SRB_HEADER)
);
/*
* Inform the system about the IO ports we are going to access.
*/
#ifndef FTK_NO_IO_ENABLE
macro_enable_io( adapter);
#endif
sys_sync_with_interrupt(hnd, issue_srb, adapter);
/*
* Let the system know we have finished accessing the IO ports.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io( adapter);
#endif
}
/****************************************************************************
*
* driver_completing_srb
* =====================
*
* PARAMETERS (passed by driver_interrupt_entry) :
* ===============================================
*
* ADAPTER_HANDLE adapter_handle
*
* The adapter handle for the adapter so it can be passed to the user
* supplied user_completed_srb routine.
*
* ADAPTER * adapter
*
* The details of the adapter that the SRB has completed on.
*
* BODY :
* ======
*
* The driver_completing_srb routine is called by driver_interrupt_entry.
* It is called when Fastmac has generated an interrupt to say that the
* SRB, associated with a particular adapter, has completed and further
* SRBs can be issued.
*
* The routine reads the SRB out of DIO space into the SRB structure
* maintained for the correct adapter. It then checks the SRB return code
* to see if the SRB completed successfully and records the fact that the
* SRB is now free. Then, it informs the user as to the success of the
* completed SRB by calling user_completed_srb.
*
* The user_completed_srb routine should do a minimum amount of processing
* because it is being called out of interrupts. Sensibly, it should just
* set a flag, to say that the SRB has completed, that can be checked for
* at strategy time when a further driver routine involving the use of the
* SRB is called.
*
* Note that only those fields that are needed in the completed SRB that
* need to be byte swapped back to Intel format are byte swapped. Hence,
* if any adjustments are made to the code it may be necessary to make sure
* that any newly used fields are correctly byte swapped back.
*
* RETURNS :
* =========
*
* The routine always succeeds and returns control to the driver routine
* driver_interrupt_entry.
*
****************************************************************************/
#ifdef FTK_IRQ_FUNCTION
#pragma FTK_IRQ_FUNCTION(driver_completing_srb)
#endif
export void
driver_completing_srb(
ADAPTER_HANDLE adapter_handle,
ADAPTER * adapter
)
{
SRB_GENERAL * srb_gen = &adapter->srb_general;
WORD saved_sifadr_value;
WBOOLEAN user_success_code;
/*
* Before accessing SIFADR, save current value for restoring on exit.
* Do this so interrupt not effect SIFADR value.
*/
saved_sifadr_value = sys_insw(adapter_handle, adapter->sif_adr);
/*
* Copy SRB out of DIO space into adapter's SRB structure.
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) adapter->srb_dio_addr
);
sys_rep_insw(
adapter_handle,
adapter->sif_datinc,
(BYTE *) srb_gen,
(WORD) (adapter->size_of_srb / 2)
);
if (adapter->size_of_srb & 1)
{
*(((BYTE * ) srb_gen) + adapter->size_of_srb - 1) =
sys_insb(adapter_handle, adapter->sif_datinc);
}
/*
* Once read from DIO space, byte swap SRB header back to Intel format.
*/
util_byte_swap_structure((BYTE *) &srb_gen->header, sizeof(SRB_HEADER));
/*
* Check if SRB has completed successfully.
*/
if (srb_gen->header.return_code == SRB_E_00_SUCCESS)
{
/*
* SRB completed successfully so record this to inform user.
*/
user_success_code = TRUE;
/*
* If read error log SRB completed successfully
* then copy error log information into user's structure.
* Need to byte swap error log structure to Intel format first.
*/
if (srb_gen->header.function == READ_ERROR_LOG_SRB)
{
util_byte_swap_structure(
(BYTE *) &srb_gen->err_log.error_log,
sizeof(ERROR_LOG)
);
adapter->status_info->error_log = srb_gen->err_log.error_log;
}
}
else
{
/*
* SRB not completed successfully so record this to inform user
* and fill in error record.
*/
user_success_code = FALSE;
adapter->error_record.type = ERROR_TYPE_SRB;
adapter->error_record.value = srb_gen->header.return_code;
}
/*
* If issued an open adapter SRB and error is E_07_CMD_CANCELLED_FAIL
* then actually have an open error so change adapter error record.
*/
if ((srb_gen->header.function == OPEN_ADAPTER_SRB) &&
(srb_gen->header.return_code == SRB_E_07_CMD_CANCELLED_FAIL))
{
/*
* Fill in error record with open error (not SRB error).
*/
adapter->error_record.type = ERROR_TYPE_OPEN;
adapter->error_record.value = OPEN_E_01_OPEN_ERROR;
}
/*
* Set adapter SRB status to show that SRB is now free.
*/
adapter->srb_status = SRB_FREE;
/*
* Inform user as to success of completed SRB.
* Disable and re-enable accessing IO locations around user call.
*/
#ifndef FTK_NO_IO_ENABLE
macro_disable_io( adapter);
#endif
user_completed_srb(adapter_handle, user_success_code);
#ifndef FTK_NO_IO_ENABLE
macro_enable_io( adapter);
#endif
/*
* Before finishing, restore saved value of EAGLE SIFADR register.
* Do this so interrupt does not effect SIFADR value.
*/
sys_outsw(adapter_handle, adapter->sif_adr, saved_sifadr_value);
}
/*---------------------------------------------------------------------------
|
| Function - get_open_and_ring_status
|
| Paramters - ptr -> Pointer to our ADAPTER structure.
|
| Purpose - Reads status information from DIO space. This
| function is called via NdisSynchronizeWithInterrupt when
| in PIO mode so that we don't get SIF register contention
| on a multiprocessor.
|
| Returns - Nothing.
|
|--------------------------------------------------------------------------*/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(get_open_and_ring_status)
#endif
local WBOOLEAN
get_open_and_ring_status(
void * ptr
)
{
ADAPTER * adapter = (ADAPTER *) ptr;
ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
WORD saved_sifadr;
/*
* Get adapter open status from the STB in DIO space.
*/
saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->adapter_open
);
adapter->status_info->adapter_open =
sys_insw(adapter_handle, adapter->sif_dat);
/*
* Get ring status from the STB in DIO space.
*/
sys_outsw(
adapter_handle,
adapter->sif_adr,
(WORD) (card_t) &adapter->stb_dio_addr->ring_status
);
adapter->status_info->ring_status =
sys_insw(adapter_handle, adapter->sif_dat);
sys_outsw(
adapter_handle,
adapter->sif_adr, saved_sifadr
);
return FALSE;
}
/*---------------------------------------------------------------------------
|
| Function - issue_srb
|
| Paramters - ptr -> Pointer to our ADAPTER structure.
|
| Purpose - Copy an SRB to the adapter. This
| function is called via NdisSynchronizeWithInterrupt when
| in PIO mode so that we don't get SIF register contention
| on a multiprocessor.
|
| Returns - Nothing.
|
|--------------------------------------------------------------------------*/
#ifdef FTK_RES_FUNCTION
#pragma FTK_RES_FUNCTION(issue_srb)
#endif
local WBOOLEAN
issue_srb(
void * ptr
)
{
ADAPTER * adapter = (ADAPTER *) ptr;
ADAPTER_HANDLE hnd = adapter->adapter_handle;
SRB_GENERAL * srb_gen = &adapter->srb_general;
WORD sifint_value;
/*
* Copy the SRB into DIO space at Fastmac specified location.
* only copy the required amount for the specific type of SRB.
*/
sys_outsw(
hnd,
adapter->sif_adr,
(WORD) (card_t) adapter->srb_dio_addr
);
sys_rep_outsw(
hnd,
adapter->sif_datinc,
(BYTE *) srb_gen,
(WORD) (adapter->size_of_srb / 2)
);
if (adapter->size_of_srb & 1)
{
sys_outsb(
hnd,
adapter->sif_datinc,
*(((BYTE * ) srb_gen) + adapter->size_of_srb - 1)
);
}
/*
* Set up SIFCMD value for SRB command interrupt.
*/
sifint_value = DRIVER_SIFINT_SRB_COMMAND;
/*
* Set interrupt adapter bit in SIFCMD.
*/
sifint_value = (sifint_value | DRIVER_SIFINT_IRQ_FASTMAC);
/*
* Mask SIFSTS so not clear interrupt if outstanding Fastmac interrupt.
*/
sifint_value = (sifint_value | DRIVER_SIFINT_FASTMAC_IRQ_MASK);
/*
* Interrupt Fastmac.
*/
sys_outsw(hnd, adapter->sif_int, sifint_value);
return FALSE;
}
/**** End of DRV_SRB.C file ************************************************/