From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/madge/driver/drv_srb.c | 1849 ++++++++++++++++++++++++++++++ 1 file changed, 1849 insertions(+) create mode 100644 private/ntos/ndis/madge/driver/drv_srb.c (limited to 'private/ntos/ndis/madge/driver/drv_srb.c') diff --git a/private/ntos/ndis/madge/driver/drv_srb.c b/private/ntos/ndis/madge/driver/drv_srb.c new file mode 100644 index 000000000..cd84d70d3 --- /dev/null +++ b/private/ntos/ndis/madge/driver/drv_srb.c @@ -0,0 +1,1849 @@ +/**************************************************************************** +* +* 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 ************************************************/ -- cgit v1.2.3