summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/netflex/reset.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/netflex/reset.c1924
1 files changed, 1924 insertions, 0 deletions
diff --git a/private/ntos/ndis/netflex/reset.c b/private/ntos/ndis/netflex/reset.c
new file mode 100644
index 000000000..f907de47e
--- /dev/null
+++ b/private/ntos/ndis/netflex/reset.c
@@ -0,0 +1,1924 @@
+//**********************************************************************
+//**********************************************************************
+//
+// File Name: RESET.C
+//
+// Program Name: NetFlex NDIS 3.0 Miniport Driver
+//
+// Companion Files: None
+//
+// Function: This module contains the NetFlex Miniport Driver
+// interface routines called by the Wrapper and the
+// configuration manager.
+//
+// (c) Compaq Computer Corporation, 1992,1993,1994
+//
+// This file is licensed by Compaq Computer Corporation to Microsoft
+// Corporation pursuant to the letter of August 20, 1992 from
+// Gary Stimac to Mark Baber.
+//
+// History:
+//
+// 04/15/94 Robert Van Cleve - Converted from NDIS Mac Driver
+//
+//**********************************************************************
+//**********************************************************************
+
+
+//-------------------------------------
+// Include all general companion files
+//-------------------------------------
+
+#include <ndis.h>
+#include "tmsstrct.h"
+#include "macstrct.h"
+#include "adapter.h"
+#include "protos.h"
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexResetDispatch
+//
+// Description:
+// Kick off a reset!
+//
+// Input:
+// MiniportAdapterContext - really our acb.
+//
+// Output:
+// Returns NDIS_STATUS_PENDING unless we are already handling a reset,
+// in which case we return NDIS_STATUS_RESET_IN_PROGRESS.
+//
+// Called By:
+// Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexResetDispatch(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ BOOLEAN ReceiveResult = FALSE;
+
+ DebugPrint(1,("NF(%d): Reset Called!\n",acb->anum));
+
+ if ( acb->ResetState && (acb->ResetState != RESET_HALTED))
+ {
+ return NDIS_STATUS_RESET_IN_PROGRESS;
+ }
+
+ acb->acb_lastringstate = NdisRingStateClosed;
+ acb->acb_state = AS_RESETTING;
+ acb->ResetState = RESET_STAGE_1;
+
+ //
+ // Cancel the DPC Timer!
+ //
+
+ NdisMCancelTimer(&acb->DpcTimer,&ReceiveResult);
+
+ //
+ // Set the timer for the NetFlexResetHandler DPC.
+ //
+ NdisMSetTimer(&acb->ResetTimer,500 );
+
+ return NDIS_STATUS_PENDING;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexResetHandler
+//
+// Description:
+// Performs that operations to put the adatper
+// through a reset and back into operation.
+//
+//
+// Input:
+//
+// SystemSpecific1 - Not used.
+// acb - The Adapter whose hardware is being reset.
+// SystemSpecific2 - Not used.
+// SystemSpecific3 - Not used.
+//
+// Output:
+// None.
+//
+// Called By:
+// via acb->ResetTimer
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexResetHandler(
+ IN PVOID SystemSpecific1,
+ IN PACB acb,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3
+ )
+{
+ NDIS_STATUS Status;
+ BOOLEAN ReceiveResult;
+ BOOLEAN DoneWReset;
+
+ //
+ // Cancel the reset timer
+ //
+ NdisMCancelTimer(&acb->ResetTimer,&ReceiveResult);
+
+ do
+ {
+ DoneWReset = TRUE; // default to true...
+
+ //
+ // Based on the current acb->ResetState, proceed with the reset.
+ //
+ switch(acb->ResetState)
+ {
+
+ case RESET_STAGE_1:
+
+ acb->ResetRetries = 0;
+ acb->InitRetries = 0;
+
+ //
+ // Issue Close
+ //
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Remove all xmit mappings, and clean up queues
+ //
+ NetFlexRemoveRequests(acb);
+ acb->ResetState = RESET_STAGE_2;
+
+ case RESET_STAGE_2:
+
+ //
+ // Try soft resetting adapter
+ //
+ Status = NetFlexAdapterReset(acb,SOFT_RESET);
+ //
+ // Was the reset successful?
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // No!
+ // Increment the retry count
+ //
+ acb->ResetRetries++;
+ //
+ // have we tried 3 times?
+ //
+ if (acb->ResetRetries < 3 )
+ {
+ // no, try it again in 10 sec
+ //
+ NdisMSetTimer(&acb->ResetTimer,10000 );
+ }
+ else
+ {
+ // yes, try a hard reset
+ //
+ acb->ResetState = RESET_STAGE_3;
+ acb->ResetRetries = 0;
+ DoneWReset = FALSE;
+ }
+ break;
+ }
+
+ //
+ // Yes, soft reset was successful, send open request...
+ // Note: When the Open request completes/fails
+ // we wind up in Reset_Stage_4.
+ //
+ acb->ResetState = RESET_STAGE_4;
+ acb->InitRetries++;
+
+ NetFlexOpenAdapter(acb);
+
+ //
+ // Give the Open 20 seconds to Complete
+ //
+ NdisMSetTimer(&acb->ResetTimer,20000);
+ break;
+
+ case RESET_STAGE_3:
+ //
+ // Perform Hard Reset!
+ //
+ Status = NetFlexAdapterReset(acb,HARD_RESET);
+ //
+ // Was the reset successful?
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // No!
+ // Increment the retry count
+ //
+ acb->ResetRetries++;
+ //
+ // have we tried Hard Reset 3 times?
+ //
+ if (acb->ResetRetries < 3 )
+ {
+ // no, try it again in 10 sec
+ //
+ acb->ResetState = RESET_STAGE_3;
+ NdisMSetTimer(&acb->ResetTimer,10000 );
+ }
+ else
+ {
+ // Hard Reset timed out, do the reset indications.
+ //
+ DebugPrint(0,("NF(%d): Reset - Exceeded Hard Reset Retries\n",acb->anum));
+ NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE);
+ }
+ break;
+ }
+
+ //
+ // Yes, hard reset was successful, go do init stuff...
+ //
+ acb->ResetState = RESET_STAGE_4;
+ //
+ // Send Open Comand, when complete, we end up in Reset_Stage_4
+ //
+ NetFlexOpenAdapter(acb);
+ //
+ // Give the Open 20 seconds to Complete
+ //
+ NdisMSetTimer(&acb->ResetTimer,20000);
+ break;
+
+ case RESET_STAGE_4:
+
+ //
+ // Increment the retry count
+ //
+ acb->InitRetries++;
+
+ if (acb->acb_state != AS_OPENED)
+ {
+ // Have we expired the retry count, do the indications
+ //
+ if (acb->InitRetries > 4)
+ {
+ DebugPrint(0,("NF(%d): Reset - Exceeded Open Retries\n",acb->anum));
+
+ NetFlexDoResetIndications(acb,NDIS_STATUS_FAILURE);
+ }
+ else
+ {
+ // Perform a Soft Reset again!
+ //
+ acb->ResetState = RESET_STAGE_2;
+ DoneWReset = FALSE;
+ }
+ }
+ else
+ {
+ // We were successful!
+ //
+ NetFlexDoResetIndications(acb,NDIS_STATUS_SUCCESS);
+ }
+ break;
+ }
+ } while (!DoneWReset);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDoResetIndications
+//
+// Description:
+// This routine is called by NetFlexResetHandler to perform any
+// indications which need to be done after a reset. Note that
+// this routine will be called after either a successful reset
+// or a failed reset.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Status - The status of the reset to send to the protocol(s).
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexDoResetIndications(
+ IN PACB acb,
+ IN NDIS_STATUS Status
+ )
+{
+ USHORT actl_reg;
+ //
+ // If we have a bad result, we stop the chip and do the indication
+ // back to the protocol(s).
+ //
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Reset failed!\n",acb->anum));
+
+ //
+ // Stop the chip
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+
+ //
+ // Reset has failed, errorlog an entry if
+ // did not already send out a message.
+ //
+ if (!acb->ResetErrorLogged)
+ {
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_RESET_FAILURE_ERROR,
+ 1,
+ NETFLEX_RESET_FAILURE_ERROR_CODE
+ );
+ acb->ResetErrorLogged = TRUE;
+ }
+
+ acb->ResetState = RESET_HALTED;
+ acb->acb_state = AS_CARDERROR;
+ Status = NDIS_STATUS_HARD_ERRORS;
+
+ }
+
+ //
+ // Verify that the dpc timer is set.
+ //
+ NdisMSetTimer(&acb->DpcTimer,10);
+
+ NdisMResetComplete( acb->acb_handle,
+ Status,
+ TRUE );
+
+ //
+ // We are no longer resetting the Adapter.
+ //
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ acb->ResetState = 0;
+
+ //
+ // Did we send out a message that a reset failed before?
+ //
+ if (acb->ResetErrorLogged)
+ {
+ //
+ // Log the fact that everything is ok now...
+ //
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_RESET_FAILURE_CORRECTION,
+ 0);
+
+ acb->ResetErrorLogged = FALSE;
+ }
+ else
+ {
+ if (acb->acb_lastringstatus &
+ ( NDIS_RING_SIGNAL_LOSS |
+ NDIS_RING_LOBE_WIRE_FAULT |
+ NDIS_RING_AUTO_REMOVAL_ERROR |
+ NDIS_RING_REMOVE_RECEIVED
+ ))
+ {
+ //
+ // Log the fact that we have reinserted in a TR MAU...
+ //
+ acb->SentRingStatusLog = FALSE;
+ acb->acb_lastringstatus = 0;
+ NdisWriteErrorLogEntry( acb->acb_handle,
+ EVENT_NDIS_TOKEN_RING_CORRECTION,
+ 0);
+
+ }
+ }
+ }
+
+ DebugPrint(1,("NF(%d): Reset Complete.\n",acb->anum));
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexCheckForHang
+//
+// Description:
+// This function simply gets call once every two seconds to
+// check on the head of the command block queue.
+// It will fire off the queue if the head has been sleeping on
+// the job.
+//
+// It also detects when the NetFlex adapter has failed, where the
+// symptoms are that the adapter will transmit packets, but will
+// not receive them.
+//
+// Input: acb - Our Driver Context.
+//
+// Output: True if we think the adapter is hung..
+//
+// Called By: Miniport Wrapper
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PXMIT xmitptr;
+ PMACREQ macreq;
+ PSCBREQ scbreq;
+
+ PACB acb = (PACB) MiniportAdapterContext;
+
+ //
+ // If we're run into a hard error, return true
+ //
+
+ if (acb->acb_state == AS_HARDERROR)
+ {
+ return TRUE;
+ }
+
+ //
+ // If we're not open return false
+ //
+ else if (acb->acb_state != AS_OPENED)
+ {
+ return FALSE;
+ }
+
+ //
+ // Is there a command outstanding?
+ //
+ if (acb->acb_scbreq_head != NULL)
+ {
+ scbreq = acb->acb_scbreq_head;
+ macreq = scbreq->req_macreq;
+
+ if (macreq != NULL)
+ {
+ // See if the command block has timed-out.
+ //
+ if (macreq->req_timeout)
+ {
+ // See if we have given it enough time
+ //
+ if ( macreq->req_timeoutcount >= 40)
+ {
+ DebugPrint(1,("NF(%d): CheckHang - Command Timed Out!\n",acb->anum));
+ return TRUE;
+ }
+ else
+ {
+ macreq->req_timeoutcount++;
+ }
+ }
+ else
+ {
+ // Start testing this command to check timeout
+ //
+ macreq->req_timeout = TRUE;
+ macreq->req_timeoutcount = 0;
+ }
+ }
+ }
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisAcquireSpinLock(&acb->XmitLock);
+ }
+
+ //
+ // See if there is any xmits which have not been processed
+ //
+ if (acb->acb_xmit_ahead != NULL)
+ {
+ xmitptr = acb->acb_xmit_ahead;
+
+ if (xmitptr->XMIT_Timeout)
+ {
+#if DBG
+ if (xmitptr->XMIT_CSTAT & XCSTAT_COMPLETE)
+ {
+ DebugPrint(0,("NF(%d): CheckHang - Xmit Complete but Xmit Timed Out!\n",acb->anum));
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): CheckHang - Xmit Timed Out!\n",acb->anum));
+ }
+#endif
+
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ return TRUE;
+ }
+ xmitptr->XMIT_Timeout++;
+ }
+
+ //
+ // If we are in full-duplex mode then that is the extent of our
+ // checking to see if we are hung. If we are in half-duplex mode
+ // then we might want to send a dummy packet to see if our receiver
+ // is working correctly....
+ //
+ if (acb->FullDuplexEnabled)
+ {
+ NdisReleaseSpinLock(&acb->XmitLock);
+ }
+
+ //
+ // Should we do extreme checking?
+ //
+ if (!acb->acb_parms->utd_extremecheckforhang)
+ {
+ return(FALSE);
+ }
+
+ //
+ // Have we been getting interrupts?
+ //
+ if (acb->acb_int_count != 0)
+ {
+ //
+ // We got some, initialize the counts.
+ //
+ acb->acb_int_count = 0;
+ acb->acb_int_timeout = 0;
+ }
+ else
+ {
+ //
+ // Increment the timeout count.
+ //
+ acb->acb_int_timeout++;
+
+ //
+ // We will do this 5 times before we reset.
+ //
+ if (5 == acb->acb_int_timeout)
+ {
+ //
+ // Clear our counts and request a reset.
+ //
+ acb->acb_int_timeout = 0;
+ acb->acb_int_count = 0;
+
+ return(TRUE);
+ }
+ }
+
+ //
+ // Not certain we're hung yet...
+ //
+ return FALSE;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexOpenAdapter
+//
+// Description:
+// This routine is called to queue up and issue
+// an open command to the adapter.
+//
+// If the system is still in initialization, then
+// the routine polls for the open command to complete,
+// otherwise, the interrupt hander processes the complete
+// and then returns to the reset handler for completion.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Success or Failure.
+//
+// Called By:
+// NetFlexResetHandler, NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexOpenAdapter(
+ PACB acb
+ )
+{
+ NDIS_STATUS Status;
+ PMACREQ macreq;
+ PSCBREQ scbreq;
+ ULONG Counter=0;
+
+ //
+ // Open Adapter
+ //
+ acb->acb_state = AS_OPENING;
+ acb->acb_lastringstate = NdisRingStateOpening;
+
+ //
+ // Are we doing an open for reset or during initialization?
+ //
+ if (!acb->AdapterInitializing)
+ {
+ //
+ // Get a free block.
+ //
+ Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_scbreq_free),
+ (PVOID *)&scbreq);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Could not get an SCBREQ for the Open Command\n",acb->anum));
+ return Status;
+ }
+
+ acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions;
+ scbreq->req_scb.SCB_Cmd = TMS_OPEN;
+ scbreq->req_scb.SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr)));
+
+ Status = NetFlexDequeue_OnePtrQ_Head( (PVOID *)&(acb->acb_macreq_free),
+ (PVOID *)&macreq);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // We have no more room for another request currently
+ //
+ DebugPrint(0,("NF(%d): No macreq for the Open Command\n",acb->anum));
+ //
+ // Put the SCBREQ back...
+ //
+ NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq);
+ return Status;
+ }
+
+ macreq->req_info = 0;
+ macreq->req_type = OPENADAPTER_CMP;
+ macreq->req_status = NDIS_STATUS_SUCCESS;
+ scbreq->req_macreq = macreq;
+
+ NetFlexEnqueue_TwoPtrQ_Tail((PVOID *)&(acb->acb_macreq_head),
+ (PVOID *)&(acb->acb_macreq_tail),
+ (PVOID)macreq);
+ //
+ // Verify that interrupts are enabled!
+ //
+ NetFlexEnableInterrupt(acb);
+
+ //
+ // Send the command out...
+ //
+ NetFlexQueueSCB(acb, scbreq);
+
+ //
+ // Note: acb->ErrorCode will be set while processing the
+ // open command complete if there is an error.
+ //
+ }
+ else
+ {
+ //
+ // Open for Initialization
+ //
+ ULONG Counter = 0;
+ ULONG CounterTimeOut = 2000; // 2 seconds in miliseconds
+ USHORT sifint_reg;
+
+ Status = NDIS_STATUS_FAILURE;
+
+ //
+ // Make sure the command is clear, try for 2 seconds
+ //
+ while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut))
+ NdisStallExecution((UINT)1000);
+
+ if (Counter < CounterTimeOut)
+ {
+ // Get the command together...
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options = acb->acb_openoptions;
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_OPEN;
+ acb->acb_scb_virtptr->SCB_Ptr = SWAPL(CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_opnblk_physptr)));
+
+ //
+ // Make sure interrupts are disabled!
+ //
+ NetFlexDisableInterrupt(acb);
+
+ //
+ // Send the SCB to the adapter.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, SIFINT_CMD);
+
+ Counter = 0;
+ CounterTimeOut = 20000; // 20 seconds in miliseconds
+
+ do
+ {
+ Counter++;
+ NdisStallExecution((UINT)1000); // 1 milisecond in microseconds
+ //
+ // Read the Sifint register.
+ //
+ NdisRawReadPortUshort( acb->SifIntPort, &sifint_reg);
+
+ //
+ // Is there an interrupt pending?
+ //
+ if ((sifint_reg & SIFINT_SYSINT) && ((sifint_reg & INT_CODES) == INT_COMMAND))
+ {
+
+ // Ack the interrupt
+ //
+ sifint_reg &= ~SIFINT_SYSINT;
+ NdisRawWritePortUshort( acb->SifIntPort, sifint_reg);
+
+ if (acb->acb_ssb_virtptr->SSB_Status == SSB_GOOD)
+ {
+ Status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ DebugPrint(0,("NF(%d): Bad status %x\n",acb->anum,acb->acb_ssb_virtptr->SSB_Status));
+
+ if (acb->acb_ssb_virtptr->SSB_Status & SSB_OPENERR) // only Token Ring
+ {
+ Status = NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ acb->acb_lastopenstat = NDIS_STATUS_TOKEN_RING_OPEN_ERROR;
+ }
+ else
+ {
+ acb->acb_lastopenstat = 0;
+ }
+ acb->acb_lastringstate = NdisRingStateOpenFailure;
+ }
+ //
+ // Issue a ssb clear.
+ //
+ NdisRawWritePortUshort( acb->SifIntPort, SIFINT_SSBCLEAR);
+
+ break;
+ }
+ } while (Counter < CounterTimeOut);
+ }
+
+ //
+ // Did it work?
+ //
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ // Set State to Opened
+ //
+ acb->acb_state = AS_OPENED;
+ //
+ // Now lets finish the open by sending a receive command to the adapter.
+ //
+ acb->acb_rcv_whead = acb->acb_rcv_head;
+
+ //
+ // Now lets finish the open by sending a
+ // transmit command to the adapter.
+ //
+
+ acb->acb_xmit_whead = acb->acb_xmit_wtail = acb->acb_xmit_head;
+
+ //
+ // Verify that interrupts are enabled!
+ //
+ NetFlexEnableInterrupt(acb);
+
+ //
+ // If the adapter is ready for a command, call a
+ // routine that will kick off the transmit command.
+ //
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ NetFlexSendNextSCB(acb);
+ }
+ else if (!acb->acb_scbclearout)
+ {
+ // Make sure we are interrupted when the SCB is
+ // available so that we can send the transmit command.
+ //
+ acb->acb_scbclearout = TRUE;
+ NdisRawWritePortUshort( acb->SifIntPort, (USHORT) SIFINT_SCBREQST);
+ }
+ }
+ else
+ {
+ // Set State back to Initialized since the open failed.
+ //
+ acb->acb_state = AS_INITIALIZED;
+ }
+ }
+
+ return Status;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexCloseAdapter
+//
+// Description:
+// This routine is called to queue up and issue an close
+// command to the adapter.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Success or Failure.
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+BOOLEAN
+NetFlexCloseAdapter(
+ PACB acb)
+
+{
+ USHORT Counter = 0;
+ USHORT CounterTimeOut = 500;
+
+ if ((acb->acb_state == AS_OPENED) ||
+ (acb->acb_state == AS_RESETTING))
+ {
+ //
+ // Make sure the command is clear, try for 5 seconds
+ //
+ while ((acb->acb_scb_virtptr->SCB_Cmd != 0) && (Counter++ < CounterTimeOut)) {
+
+ NdisStallExecution((UINT)1000);
+ }
+
+ if (acb->acb_scb_virtptr->SCB_Cmd == 0)
+ {
+ //
+ // Send Close,
+ //
+
+ acb->acb_scb_virtptr->SCB_Cmd = TMS_CLOSE;
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD);
+
+ acb->acb_state = AS_CLOSING;
+ //
+ // Give it a little time...
+ //
+ NdisStallExecution((UINT)10000);
+ }
+
+ return (Counter >= CounterTimeOut);
+ }
+ return TRUE;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexHalt
+//
+// Description:
+// Removes an adapter previously initialized.
+//
+// Input:
+// MacAdapterContext - Actually as pointer to an PACB.
+//
+// Output:
+// None.
+//
+// Called By:
+// Miniport Wrapper.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ USHORT actl_reg;
+ BOOLEAN ReceiveResult1;
+ BOOLEAN ReceiveResult2;
+
+ //
+ // The adapter to halt
+ //
+ PACB acb = (PACB) MiniportAdapterContext;
+
+ DebugPrint(1,("NF(%d): Halt Called!\n", acb->anum));
+
+ //
+ // Cancel all of our timers.
+ //
+ NdisMCancelTimer(&acb->DpcTimer, &ReceiveResult1);
+ NdisMCancelTimer(&acb->ResetTimer, &ReceiveResult2);
+
+ //
+ // Is one of the timer dpc's going to fire?
+ //
+ if (!ReceiveResult1 || !ReceiveResult2)
+ {
+ NdisStallExecution(500000);
+ }
+
+ //
+ // Send Close
+ //
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Stop Adapter
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+
+ //
+ // Complete mappings
+ //
+ NetFlexRemoveRequests(acb);
+
+ //
+ // Free adapter resources
+ //
+ NetFlexDeregisterAdapter(acb);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexShutdown
+//
+// Description:
+// Removes an adapter previously initialized.
+//
+// Input:
+// MacAdapterContext - Actually as pointer to an PACB.
+//
+// Output:
+// None.
+//
+// Called By:
+// Miniport Wrapper.
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexShutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+{
+ PACB acb = (PACB) MiniportAdapterContext;
+ USHORT actl_reg;
+
+ //
+ // Send Close.
+ //
+
+ NetFlexCloseAdapter(acb);
+
+ //
+ // Stop Adapter
+ //
+
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&actl_reg));
+ actl_reg |= ACTL_ARESET;
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) actl_reg);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexRemoveRequests
+//
+// Description:
+// Clean up queues during a Reset and Halt
+//
+// Input:
+// acb - Pointer to acb
+//
+// Output:
+// None
+//
+// Called By:
+// NetFlexResetHandler,
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexRemoveRequests(
+ PACB acb
+ )
+{
+ PXMIT xmitptr;
+ PRCV rcvptr;
+ UINT curmap;
+ PNDIS_PACKET packet;
+ PNDIS_BUFFER curbuf;
+ PMULTI_TABLE mt;
+ PETH_OBJS ethobjs;
+ USHORT i;
+ PSCBREQ scbreq;
+ PMACREQ macreq;
+
+ //
+ // Terminate all the transmits on the active queue.
+ //
+ xmitptr = acb->acb_xmit_ahead;
+
+ while (xmitptr != NULL)
+ {
+ // Did we use an internal buffer?
+ //
+ if (xmitptr->XMIT_OurBufferPtr != NULL)
+ {
+ // We've used one of our adapter buffers, so put the adapter
+ // buffer back on the free list.
+ //
+ if (xmitptr->XMIT_OurBufferPtr->BufferSize != acb->acb_smallbufsz) {
+ xmitptr->XMIT_OurBufferPtr->Next = acb->OurBuffersListHead;
+ acb->OurBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ else { // small buffer
+ xmitptr->XMIT_OurBufferPtr->Next = acb->SmallBuffersListHead;
+ acb->SmallBuffersListHead = xmitptr->XMIT_OurBufferPtr;
+ }
+ xmitptr->XMIT_OurBufferPtr = NULL;
+ }
+ else
+ {
+ packet = xmitptr->XMIT_Packet;
+
+ if ( packet != NULL ) {
+
+ curmap = xmitptr->XMIT_MapReg;
+
+ // Complete mappings, but don't complete the sends...
+ //
+
+ NdisQueryPacket(
+ packet,
+ NULL,
+ NULL,
+ (PNDIS_BUFFER *) &curbuf,
+ NULL
+ );
+
+ while (curbuf)
+ {
+ NdisMCompleteBufferPhysicalMapping(
+ acb->acb_handle,
+ (PNDIS_BUFFER) curbuf,
+ curmap
+ );
+
+ curmap++;
+ if (curmap == acb->acb_maxmaps)
+ {
+ curmap = 0;
+ }
+
+ NdisGetNextBuffer(curbuf, &curbuf);
+ }
+ }
+ }
+
+ xmitptr->XMIT_CSTAT = 0;
+ xmitptr->XMIT_Packet = NULL;
+
+ //
+ // If we've reached the active queue tail, we are done.
+ //
+ if (xmitptr == acb->acb_xmit_atail)
+ xmitptr = NULL;
+ else
+ xmitptr = xmitptr->XMIT_Next;
+ }
+
+ acb->acb_xmit_ahead = acb->acb_xmit_atail = NULL;
+ acb->acb_avail_xmit = acb->acb_parms->utd_maxtrans;
+
+ //
+ // Clean up the Receive Lists
+ //
+
+ rcvptr = acb->acb_rcv_head;
+
+ do {
+
+ //
+ // Mark receive list available
+ //
+ rcvptr->RCV_CSTAT =
+ ((rcvptr->RCV_Number % acb->RcvIntRatio) == 0) ? RCSTAT_GO_INT : RCSTAT_GO;
+
+ //
+ // Get next receive list
+ //
+ rcvptr = rcvptr->RCV_Next;
+
+ } while (rcvptr != acb->acb_rcv_head);
+
+ //
+ // Clean up multicast if ethernet.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ ethobjs = (PETH_OBJS)acb->acb_spec_objs;
+
+ NdisZeroMemory(
+ ethobjs->MulticastEntries,
+ ethobjs->MaxMulticast * NET_ADDR_SIZE
+ );
+
+ ethobjs->NumberOfEntries = 0;
+ }
+
+ //
+ // Clean up SCB Requests
+ //
+ while (acb->acb_scbreq_head)
+ {
+ NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_scbreq_head,
+ (PVOID *)&acb->acb_scbreq_tail,
+ (PVOID *)&scbreq);
+
+ NdisZeroMemory(scbreq, sizeof(SCBREQ));
+
+ NetFlexEnqueue_OnePtrQ_Head((PVOID *)&acb->acb_scbreq_free,(PVOID)scbreq);
+
+ }
+
+ //
+ // Clean up MacReq Requests
+ //
+ while (acb->acb_macreq_head)
+ {
+ NetFlexDequeue_TwoPtrQ_Head((PVOID *)&acb->acb_macreq_head,
+ (PVOID *)&acb->acb_macreq_tail,
+ (PVOID *)&macreq);
+
+ NdisZeroMemory(macreq, sizeof(MACREQ));
+
+ NetFlexEnqueue_OnePtrQ_Head( (PVOID *)&acb->acb_macreq_free,
+ (PVOID)macreq);
+
+ }
+
+ //
+ // Clean Up some more State stuff...
+ //
+ acb->RequestInProgress = FALSE;
+ acb->acb_scbclearout = FALSE;
+ acb->acb_scbreq_next = NULL;
+ acb->acb_gen_objs.cur_filter = 0;
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexAdapterReset
+//
+// Description:
+// This routine resets the Super Eagle or Eagle
+//
+// Input:
+// mode - 0 = Hard Reset, ~0 = Soft Reset
+//
+// Output:
+// status - NDIS_STATUS_SUCCESS if Success
+//
+// Called By:
+// NetFlexResetHandler
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexAdapterReset(
+ PACB acb,
+ INT mode)
+{
+ NDIS_STATUS status;
+
+ //
+ // Which Reset?
+ //
+ if (mode == HARD_RESET)
+ {
+
+ // Do the reset
+ //
+ NdisRawWritePortUshort(acb->SifActlPort, ACTL_HARD_RESET);
+
+ //
+ // Wait 15 milliseconds to let the reset take place.
+ //
+ NdisStallExecution((UINT)15000); // Wait 15 milliseconds
+
+ //
+ // Call NetFlexSetupNetType to verify everything gets set correctly.
+ //
+ NetFlexSetupNetType(acb);
+
+ //
+ // Make sure that promiscuous mode is turned off
+ //
+ acb->acb_opnblk_virtptr->OPEN_Options &= SWAPS((USHORT) ~(OOPTS_CNMAC | OOPTS_CMAC));
+
+ //
+ // Download and initialize the adapter
+ //
+ if ((status = NetFlexDownload(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ // Verify Bring Up Diagnostics
+ //
+ if ((status = NetFlexBudWait(acb))== NDIS_STATUS_SUCCESS)
+ {
+ // Initialize the adapter
+ //
+ if ((status = NetFlexInitializeAdapter(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ // Yes, do we need to save the address that will give up our upstream address?
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5)
+ {
+ // Yes, get it...
+ //
+ NetFlexGetUpstreamAddrPtr(acb);
+ }
+ }
+ }
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Hard Reset Failed!\n",acb->anum));
+ }
+ }
+ else
+ {
+ // A Soft Reset was requested. Write the reset code into the
+ // SIF interrupt register.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, SIF_SOFT_RESET);
+
+ //
+ // Write the saved ACTL Settings.
+ //
+ NdisRawWritePortUshort( acb->SifActlPort, acb->actl_reg);
+
+ //
+ // Go check to see if the bring up diagnostics worked...
+ //
+ if ((status = NetFlexBudWait(acb)) == NDIS_STATUS_SUCCESS)
+ {
+ status = NetFlexInitializeAdapter(acb);
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DebugPrint(0,("NF(%d): Soft Reset Failed!\n",acb->anum));
+ }
+ }
+
+ return status;
+}
+
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexBudWait
+//
+// Description:
+// This routine waits for the Bring Up Diags
+// (BUD) code to finish on the Super Eagle or Eagle
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// status - 0 = SUCCESS, ~0 = failure
+//
+// Called By:
+// NetFlexAdapterReset, NetFlexDownload
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexBudWait(
+ PACB acb
+ )
+{
+ int i;
+ USHORT value;
+
+ //
+ // Wait for Bring Up Diagnotics to start.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) &value);
+ if ((value & 0x00f0) >= 0x0020)
+ break;
+ }
+
+ if (i >= 3000)
+ {
+ // Diags never got started!!
+ //
+ DebugPrint(0,("NF(%d): Diags never got started\n",acb->anum));
+ DebugPrint(0,("NF(%d): Sif int is 0x%x\n",acb->anum,value));
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ //
+ // Wait for either success or failure.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&value));
+ if ((value & 0x00f0) >= 0x0030)
+ break;
+ }
+
+ if (i >= 3000)
+ {
+ // Diags never finished!!
+ //
+ DebugPrint(0,("NetFlex: Diags never finished\n"));
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ if ((value & 0x00f0) != 0x0040)
+ {
+ // Diags failed!!
+ //
+ DebugPrint(0,("NF(%d): Diags Failed!\n",acb->anum));
+ return(NDIS_STATUS_FAILURE);
+ }
+ else
+ {
+ // The Diags passed OK!
+ //
+ DebugPrint(0,("NF(%d): Diags Passed OK\n",acb->anum));
+ return(NDIS_STATUS_SUCCESS);
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexInitializeAdapter
+//
+// Description:
+// This routine initializes the adapter for open.
+//
+// Input:
+// acb - Our Driver Context
+//
+// Output:
+// Returns a NDIS_STATUS_SUCCESS if the adapter
+// initialized properly. Otherwise, an error code is returned,
+// showing that an initialization error has occurred.
+//
+// Called By:
+// NetFlexProcess_Open_Request
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexInitializeAdapter(
+ PACB acb
+ )
+{
+ ULONG temp;
+ INT i;
+ SHORT *ps;
+
+ //
+ // Set the SIF address register to point to the INIT block location
+ // and copy the INIT block info into the data inc register.
+ // make sure we are at chapter 1.
+ //
+ NdisRawWritePortUshort(acb->SifAddrxPort, (USHORT) 1);
+ NdisRawWritePortUshort(acb->SifAddrPort, (USHORT) ADDR_INIT);
+
+ for (i = 0, ps = (SHORT *) &acb->acb_initblk;
+ i < (SIZE_INIT / 2); i++, ps++)
+ {
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) *ps);
+ }
+
+ //
+ // Now write the SCB and SSB addresses into the
+ // data inc register.
+ //
+ temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_scb_physptr) + sizeof(USHORT));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp);
+
+ temp = CTRL_ADDR(NdisGetPhysicalAddressLow(acb->acb_ssb_physptr));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) (temp >> 16));
+ NdisRawWritePortUshort(acb->SifDIncPort, (USHORT) temp);
+
+ //
+ // Now write the execute command out to the SIF.
+ //
+ NdisRawWritePortUshort(acb->SifIntPort, (USHORT) SIFINT_CMD);
+
+ //
+ // Wait for the intialization to complete.
+ //
+ for (i = 0; i < 3000; i++)
+ {
+ NdisStallExecution((UINT)1000); /* Wait 1 millisecond */
+ NdisRawReadPortUshort(acb->SifIntPort, (PUSHORT) (&temp));
+ if ((temp & 0x00ff) != 0x0040)
+ break;
+ }
+
+ if ( (i >= 3000) || ((temp & 0x00ff) != 0x0000) )
+ {
+ //
+ // Initialization never finished!! OR Initialization failed!!
+ //
+ return(NDIS_STATUS_FAILURE);
+
+ }
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDownload
+//
+// Description:
+// This routine downloads the TMS380 MAC code to the
+// Super Eagle or Eagle.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// status - 0 = SUCCESS, ~0 = failure
+//
+// Called By:
+// NetFlexAdapterReset
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+NDIS_STATUS
+NetFlexDownload(
+ PACB acb
+ )
+{
+ LONG j;
+ USHORT temp_value;
+ LONG totalbytes;
+ PUSHORT MappedBuffer;
+ PDL_STRUCT ds;
+ PUCHAR dataptr;
+
+ if (macgbls.DownloadCode == NULL)
+ {
+ DebugPrint(0,("NF(%d) - No Download code!\n",acb->anum));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Get our pointers ready. Currently the MappedBuffer is pointing
+ // to the length of the header. The data begins after the header.
+ // Also the section headers are contained within the header just
+ // past the length field which is 2 bytes long.
+ //
+
+ MappedBuffer = macgbls.DownloadCode;
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+
+ //
+ // If we're using FPA skip to the second set of mac code. The
+ // order of the mac code is TOK, ETH, TOKFPA and ETHFPA.
+ //
+ if (acb->acb_usefpa)
+ {
+ for (j=0; j<2; j++)
+ {
+ totalbytes = 0;
+ while (ds->dl_chap != 0x7ffe)
+ {
+ totalbytes += ds->dl_bytes;
+ ds++;
+ }
+
+ MappedBuffer = (PUSHORT)(dataptr + totalbytes);
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+ }
+ }
+
+ //
+ // No need to perform a hard reset of the Super Eagle or Eagle
+ // since we have already done.
+ //
+ if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_3)
+ {
+ //
+ // We need to skip around the download code for Token Ring.
+ // Therefore, find the end of the token ring download code.
+ //
+ totalbytes = 0;
+ while (ds->dl_chap != 0x7ffe)
+ {
+ totalbytes += ds->dl_bytes;
+ ds++;
+ }
+
+ MappedBuffer = (PUSHORT)(dataptr + totalbytes);
+
+ dataptr = (PUCHAR)(*MappedBuffer + (PUCHAR)(MappedBuffer) );
+ ds = (PDL_STRUCT)( (PUCHAR)(MappedBuffer) + 2);
+ }
+
+ //
+ // Download each section of data
+ //
+ while (ds->dl_chap != 0x7ffe)
+ {
+ NdisRawWritePortUshort( acb->SifAddrxPort, (USHORT) ds->dl_chap);
+ NdisRawWritePortUshort( acb->SifAddrPort, (USHORT) ds->dl_addr);
+
+ for (j = 0; j < (ds->dl_bytes / 2); j++)
+ {
+ NdisRawWritePortUshort( acb->SifDIncPort,
+ (USHORT)(SWAPS(*( (PUSHORT)(dataptr)))) );
+ dataptr += 2;
+ }
+ ds++;
+ }
+
+ //
+ // Now turn off the CP halt bit in the ACTL register to let the
+ // TMS380 chipset startup. Wait for the BUD to finish and report
+ // the appropriate status code.
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, (PUSHORT) (&temp_value));
+
+ temp_value &= ~ACTL_CPHALT;
+
+ NdisRawWritePortUshort( acb->SifActlPort, (USHORT) temp_value);
+
+ //
+ // Save the Current Actl value
+ //
+ acb->actl_reg = temp_value;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexSetupNetType
+//
+// Description:
+// This routine sets up the Super Eagle to run the type of
+// network and network speed requested by config. It assumes
+// that the adapter is in a halted state after reset.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// Returns NDIS_STATUS_SUCCESS for a successful
+// completion. Otherwise, an error code is returned.
+//
+// Called By:
+// NetFlexResetHandler, NetFlexBoardInitandReg
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID
+NetFlexSetupNetType(
+ PACB acb
+ )
+{
+ USHORT cfg_reg, actl_reg;
+ USHORT cfg_reg2, tmp_reg;
+ UCHAR cfg_regl, cfg_regh;
+ NDIS_MEDIUM nettype;
+ ULONG netspeed;
+ USHORT board_id = acb->acb_boardid;
+
+ //
+ // Get the network type and speed the user set up in EISA config.
+ // The port address for the cfg port is odd which will cause an
+ // alignment fault on RISC.
+ //
+ // NdisRawReadPortUshort(acb->AdapterConfigPort, &cfg_reg);
+ NdisRawReadPortUchar(acb->AdapterConfigPort, &cfg_regl);
+ NdisRawReadPortUchar(acb->AdapterConfigPort+1, &cfg_regh);
+ cfg_reg = (cfg_regh << 8) + cfg_regl;
+
+ //
+ // Read the actl register and turn off the reset bit.
+ //
+ NdisRawReadPortUshort( acb->SifActlPort, &actl_reg);
+
+ actl_reg &= ~ACTL_ARESET;
+
+ //
+ // If we're using FPA turn on ROM reserved bit 11
+ //
+ if (acb->acb_usefpa)
+ {
+ actl_reg |= ACTL_ROM;
+ }
+
+ //
+ // If the board is a Cpqtok board, just fill in the parameters,
+ // reset the board, and get out. If the board is a Netflx board,
+ // fill in the parameters, reset the board specifying the type and
+ // speed of the network, make sure we get what we asked for, and
+ // then get out.
+
+ if ( (board_id & NETFLEX_REVMASK) == CPQTOK_ID &&
+ (board_id != DURANGO_ID))
+ {
+ // This is a JUPITER board
+ //
+ DebugPrint(1,("NF(%d): Setting up Jupiter\n",acb->anum));
+
+ if (acb->AdapterInitializing)
+ {
+ nettype = NdisMedium802_5;
+ if (cfg_reg & CFG_16MBS)
+ netspeed = 4;
+ else
+ netspeed = 16;
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessTrRcv;
+ }
+ }
+ else if ( ((board_id & NETFLEX_REVMASK) == NETFLEX_ID) ||
+ ((board_id & NETFLEX_REVMASK) == RODAN_ID) ||
+ (board_id == DURANGO_ID) )
+ {
+ //
+ // This is a NETFLEX, MAPLE, DURANGO or RODAN board
+ //
+ // The Nselout1 bit has been redefined as the media bit. If this
+ // bit is set to a 1, AUI/DB-9 has been selected. Otherwise,
+ // unshielded has been selected.
+ // If the CFG_MEDIA bit is set, Unshielded has been selected.
+
+ DebugPrint(1,("NF(%d): Setting up Netflx, Durango, or Rodan\n",acb->anum));
+
+ if (cfg_reg & CFG_MEDIA)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+
+ if (cfg_reg & CFG_16MBS)
+ {
+ actl_reg |= ACTL_NSELOUT0;
+ }
+ else
+ {
+ actl_reg &= (~ACTL_NSELOUT0);
+ }
+ }
+ else
+ {
+ // This is a BONSAI board
+ //
+ // Bits 3 and 2 represent net type for head 1 and 2, respectively.
+ DebugPrint(1,("NF(%d): Setting up Bonsai head %d\n",acb->anum,acb->acb_portnumber));
+
+ if (acb->acb_portnumber == PORT1)
+ {
+ if (cfg_reg & CFG_DUALPT_ADP1)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+ }
+ else
+ {
+ if (cfg_reg & CFG_DUALPT_ADP2)
+ {
+ actl_reg &= (~ACTL_NSELOUT1);
+ }
+ else
+ {
+ actl_reg |= ACTL_NSELOUT1;
+ }
+ }
+ }
+
+ NdisRawWritePortUshort(acb->SifActlPort, actl_reg);
+
+ //
+ // If this is during an initial initialization
+ //
+ if (acb->AdapterInitializing)
+ {
+ //
+ // If this is a NETFLEX type board, make sure we got what
+ // we were asking for
+ //
+ if ( ( (board_id & NETFLEX_REVMASK) == NETFLEX_ID ) ||
+ ( (board_id & NETFLEX_REVMASK) == BONSAI_ID ) ||
+ ( (board_id & NETFLEX_REVMASK) == RODAN_ID ) ||
+ (board_id == DURANGO_ID) )
+ {
+ NdisRawReadPortUshort( acb->SifActlPort, &actl_reg);
+ //
+ // Now, find out our network type and speed.
+ //
+ if (actl_reg & ACTL_TEST1)
+ {
+ //
+ // We are token ring. Are we 16 mbps or 4 mbps.
+ //
+ nettype = NdisMedium802_5;
+ if (actl_reg & ACTL_TEST0)
+ netspeed = 4;
+ else
+ netspeed = 16;
+
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessTrRcv;
+
+ }
+ else
+ {
+ // Ethernet is selected
+ nettype = NdisMedium802_3;
+ netspeed = 10;
+ //
+ // Setup the ProcessReceiveHandler
+ //
+ acb->ProcessReceiveHandler = &NetFlexProcessEthRcv;
+ }
+ }
+ //
+ // Initialize some of acb fields as well as adapter information.
+ //
+ acb->acb_gen_objs.media_type_in_use = nettype;
+ acb->acb_gen_objs.link_speed = netspeed;
+ }
+ else
+ {
+ nettype = acb->acb_gen_objs.media_type_in_use;
+ netspeed = acb->acb_gen_objs.link_speed;
+ }
+
+ //
+ // Check Full Duplex Support... Ethernet Only!
+ //
+ if (nettype == NdisMedium802_3)
+ {
+ // Do we want Full Duplex?
+ //
+
+ if (acb->acb_portnumber != PORT2)
+ {
+ NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF , &cfg_reg2);
+ if (cfg_reg2 & CFG_FULL_DUPLEX)
+ {
+ acb->FullDuplexEnabled = TRUE;
+ }
+ }
+ else
+ {
+ NdisRawReadPortUchar( acb->BasePorts + CFG_REG2_OFF - DUALHEAD_CFG_PORT_OFFSET, &cfg_reg2);
+ if (cfg_reg2 & CFG_FULL_DUPLEX_HEAD2)
+ {
+ acb->FullDuplexEnabled = TRUE;
+ }
+ }
+
+ if (acb->FullDuplexEnabled)
+ {
+ DebugPrint(1,("NF(%d): Enabling FullDuplex Support!\n",acb->anum));
+ if ( (board_id & NETFLEX_REVMASK) == BONSAI_ID )
+ {
+ // On Bansai, disable colision detect by writing to 0xZc67 for H2 0xZc66 for H1
+ //
+ if (acb->acb_portnumber == PORT2)
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD2_OFF , 0xff);
+ }
+ else
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_HEAD1_OFF , 0xff);
+ }
+ }
+ else
+ {
+ // On NetFlex/NetFlex-2, disable colision detect by writing to 0xZc65
+ // until status indicates that it is ok, per Ray...
+ //
+ do
+ {
+ NdisRawWritePortUchar( acb->ExtConfigPorts + LOOP_BACK_ENABLE_OFF , 0xff);
+ NdisStallExecution((UINT)1000); // Wait 1 milliseconds
+ NdisRawReadPortUchar( acb->ExtConfigPorts + LOOP_BACK_STATUS_OFF , &tmp_reg);
+ } while (tmp_reg & COLL_DETECT_ENABLED);
+ }
+ }
+ }
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexFinishUnloading
+//
+// Description: This routine finishes the unloading process
+//
+// Input: None.
+//
+// Output: None.
+//
+// Calls: NdisDeregisterMac,NdisTerminateWrapper,
+//
+// Called By: NetFlexUnload, NetFlexDeregisterAdapter
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexFinishUnloading(VOID)
+{
+ //
+ //
+ // Free the memory with the download software in it.
+ //
+ if (macgbls.DownloadCode != NULL) {
+
+ NdisFreeMemory( macgbls.DownloadCode,
+ macgbls.DownloadLength,
+ 0);
+
+ }
+
+ NdisTerminateWrapper(macgbls.mac_wrapper,(PVOID)NULL);
+ macgbls.mac_wrapper = NULL;
+ macgbls.DownloadCode= NULL;
+ macgbls.DownloadLength = 0;
+}
+
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// Routine Name: NetFlexDeregisterAdapter
+//
+// Description:
+// This routine finishes the removal of an adapter.
+//
+// Input:
+// acb - Our Driver Context.
+//
+// Output:
+// None.
+//
+// Called By:
+// NetFlexHalt, NetFlexInitialize
+//
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+VOID NetFlexDeregisterAdapter(PACB acb)
+{
+ //
+ // Remove the acb from the mac's acb list
+ //
+ NetFlexDequeue_OnePtrQ((PVOID *) &macgbls.mac_adapters,(PVOID)acb);
+
+ if (acb->acb_interrupt.InterruptObject != NULL)
+ NdisMDeregisterInterrupt(&acb->acb_interrupt);
+
+ //
+ // Deallocate the memory for the acb.
+ //
+ NetFlexDeallocateAcb(acb);
+
+ if ((macgbls.mac_adapters == NULL) && !macgbls.Initializing)
+ {
+ NetFlexFinishUnloading();
+ }
+}
+