//********************************************************************** //********************************************************************** // // File Name: INIT.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 #include "tmsstrct.h" #include "macstrct.h" #include "adapter.h" #include "protos.h" //----------------- // Variables //----------------- MAC macgbls = {0}; USHORT gbl_addingdualport = 0; USHORT gbl_portnumbertoadd = 0; USHORT RxIntRatio = 1; #ifdef XMIT_INTS USHORT TxIntRatio = 1; #endif //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: DriverEntry // // Description: This routine is the initialization entry // point into the driver. In this routine, // the driver registers itself with the wrapper // and initializes the global variables for the // driver. // // Input: DriverObject Pointer to the driver object // assigned to the MAC driver. // // Output: Returns NDIS_STATUS_SUCCESS for a successful // completion and returns an error code if an // error is encountered. // // Called_By: OS // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #pragma NDIS_INIT_FUNCTION(DriverEntry) NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NDIS_STATUS Status; // // The characteristics table // NDIS_MINIPORT_CHARACTERISTICS NetFlexChar; DebugPrint(1,("NetFlex: Dynamic Ratio Version\n")); #ifdef XMIT_INTS DebugPrint(1,("NetFlex: with Transmit Interrupts\n")); #endif // // Indicate that we are in initialization mode. // macgbls.Initializing = TRUE; // // Initialize the Wrapper // NdisMInitializeWrapper( &macgbls.mac_wrapper, DriverObject, RegistryPath, NULL); // // Store the driver object. We will need this for Unloading // the driver. macgbls.mac_object = DriverObject; // // Initialize the Miniport characteristics for the call to // NdisMRegisterMiniport. // NetFlexChar.MajorNdisVersion = NETFLEX_MAJ_VER; NetFlexChar.MinorNdisVersion = NETFLEX_MIN_VER; NetFlexChar.CheckForHangHandler = NetFlexCheckForHang; NetFlexChar.DisableInterruptHandler = NetFlexDisableInterrupt; NetFlexChar.EnableInterruptHandler = NetFlexEnableInterrupt; NetFlexChar.HaltHandler = NetFlexHalt; NetFlexChar.HandleInterruptHandler = NetFlexHandleInterrupt; NetFlexChar.InitializeHandler = NetFlexInitialize; NetFlexChar.ISRHandler = NetFlexISR; NetFlexChar.QueryInformationHandler = NetFlexQueryInformation; NetFlexChar.ReconfigureHandler = NULL; NetFlexChar.ResetHandler = NetFlexResetDispatch; NetFlexChar.SendHandler = NetFlexSend; NetFlexChar.SetInformationHandler = NetFlexSetInformation; NetFlexChar.TransferDataHandler = NetFlexTransferData; NetFlexChar.ReturnPacketHandler = NULL; NetFlexChar.SendPacketsHandler = NULL; NetFlexChar.AllocateCompleteHandler = NULL; // // Register this driver with NDIS // Status = NdisMRegisterMiniport( macgbls.mac_wrapper, &NetFlexChar, sizeof(NetFlexChar) ); // // Set to non-initializing mode // macgbls.Initializing = FALSE; if (Status == NDIS_STATUS_SUCCESS) { return STATUS_SUCCESS; } // // We can only get here if something went wrong with registering // the driver or *ALL* of the adapters. // if ((macgbls.mac_adapters == NULL) && (macgbls.mac_wrapper != NULL)) { NdisTerminateWrapper(macgbls.mac_wrapper, NULL); } return STATUS_UNSUCCESSFUL; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexInitialize // // Description: See NDIS 3.0 Miniport spec. // Called to initialize each adapter // // Input: See NDIS 3.0 Miniport spec. // // Output: NDIS_STATUS_SUCCESS or NDIS_STATUS_PENDING // // Called_By: NDIS Miniport Wrapper // //---------------------------------------------------------------- NDIS_STATUS NetFlexInitialize( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE ConfigurationHandle ) { NDIS_STATUS status; PACB acb = NULL; PACB FirstHeadsAcb = NULL; USHORT baseaddr; UINT slot,i; NDIS_STRING portnumber = NDIS_STRING_CONST("PortNumber"); NDIS_HANDLE ConfigHandle = NULL; NDIS_EISA_FUNCTION_INFORMATION EisaData; PNDIS_CONFIGURATION_PARAMETER cfgp; DebugPrint(2,("NetFlex: NetFlexInitialize\n")); // // Make sure we still have the wrapper, this is needed if an adapter // fails to open and there isn't any already opened, the halt routine // will remove the wrapper, and thus all adapters fail. I don't know // if this means that I should remove the code from the halt routine // or if I need to come up with aditional logic... // if (macgbls.mac_wrapper == NULL) { DebugPrint(0,("NetFlex: Don't have a handle to the Wrapper!\n")); status = NDIS_STATUS_FAILURE; goto ConfigError; } // // Check if we have a configuration handle before proceeding. // if (ConfigurationHandle == NULL) { DebugPrint(0,("NetFlex: Adapter not set up properly - no config handle\n")); status = NDIS_STATUS_FAILURE; goto ConfigError; } // // Open the configuration handle // NdisOpenConfiguration( &status, &ConfigHandle, ConfigurationHandle ); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NetFlex: Adapter not set up properly - couldn't open config\n")); status = NDIS_STATUS_FAILURE; ConfigHandle = NULL; goto ConfigError; } // // Find out what slot number the adapter associated with // this name is in. // NdisReadEisaSlotInformation( &status, ConfigurationHandle, &slot, &EisaData ); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NetFlex: Slot number not set up\n")); status = NDIS_ERROR_CODE_ADAPTER_NOT_FOUND; goto ConfigError; } baseaddr = slot * 0x1000; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &portnumber, NdisParameterInteger); // // If we didn't read a portnumber, that means we're adding a // non-dual port card - NETFLX, MAPLE, CPQTOK // if (status != NDIS_STATUS_SUCCESS) { gbl_portnumbertoadd = 0; gbl_addingdualport = FALSE; } else { gbl_portnumbertoadd = (USHORT)cfgp->ParameterData.IntegerData; if (gbl_portnumbertoadd == PORT0) gbl_addingdualport = FALSE; else gbl_addingdualport = TRUE; } // // See if this adapter has been added. If so return an error. // The very first time we are called, acb should be NULL. // if (macgbls.DownloadCode == NULL) { // On Initial Init, We need to get the global stuff... // status = NetFlexInitGlobals(); if (status != NDIS_STATUS_SUCCESS) { goto ConfigError; } } else { acb = macgbls.mac_adapters; while (acb) { if ( acb->acb_baseaddr == baseaddr) { // // If the card has the same slot and we're adding a dual port // then go to the next acb, otherwise it is an error. // if ( gbl_addingdualport ) { FirstHeadsAcb = acb; acb = acb->acb_next; } else { DebugPrint(0,("NetFlex: Adapter already added\n")); status = NDIS_STATUS_FAILURE; goto ConfigError; } } else { acb = acb->acb_next; } } } // // Allocate adapter control block and register adapter. // status = NetFlexRegisterAdapter( &acb, FirstHeadsAcb, ConfigHandle, baseaddr, MiniportAdapterHandle ); if (status != NDIS_STATUS_SUCCESS) { goto ConfigError; } // // Search for the medium type supported matches adapter configuration // for (i = 0; i < MediumArraySize; i++) { if (MediumArray[i] == acb->acb_gen_objs.media_type_in_use) { *SelectedMediumIndex = i; break; } } // // If supported medium not found. Return an error. // if (i == MediumArraySize) { DebugPrint(0,("NetFlex: No supported media found!\n")); status = NDIS_STATUS_UNSUPPORTED_MEDIA; goto ConfigError; } // // Now, initialize the board and the data structures. // glb_ErrorCode will be set if there was an error. // status = NetFlexBoardInitandReg(acb,&EisaData); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF(%d): Board Init and Reg Failed\n",acb->anum)); goto ConfigError; } ConfigError: // // Were there any errors? // if (status != NDIS_STATUS_SUCCESS) { // // if we allocated an acb, we need to get rid of it... // if (acb != NULL) { // // Since there was an acb, the error data and section code will be in // the acb instead of the globals. // NetFlexDeregisterAdapter(acb); } DebugPrint(0, ("NF: NetFlexInitialize Failed!\n")); } if (ConfigHandle != NULL) { NdisCloseConfiguration(ConfigHandle); } return status; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexRegisterAdapter // // Description: This routine allocates memory for the adapter // control block and registers with the wrapper. // // Input: acbp - pointer to adapter control block // // // Output: Returns NDIS_STATUS_SUCCESS for a successful // completion. Otherwise, an error code is // returned. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NDIS_STATUS NetFlexRegisterAdapter( PACB *acbp, PACB FirstHeadsAcb, NDIS_HANDLE ConfigHandle, USHORT baseaddr, NDIS_HANDLE MiniportAdapterHandle ) { PACB acb; USHORT cpqid, boardid, reg_value; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; // // Allocate the Memory for the adapter's acb. // NdisAllocateMemory( (PVOID *)&acb, (UINT) (sizeof (ACB)), (UINT) 0, NetFlexHighestAddress ); // // If we did not get the memory, flag any error. // if (acb == NULL) { return(NDIS_STATUS_RESOURCES); } // // Zero out the memory. Save configuration handle. // NdisZeroMemory(acb, sizeof (ACB)); acb->acb_state = AS_REGISTERING; acb->acb_baseaddr = baseaddr; // // Indicate that we are initializing the adapter. // acb->AdapterInitializing = TRUE; // // link in this acb // *acbp = acb; macgbls.mac_numadpts++; #if (DBG || DBGPRINT) acb->anum = macgbls.mac_numadpts; #endif // // save reference to our Miniport Handle // acb->acb_handle = MiniportAdapterHandle; // // Initialize reset timer // NdisMInitializeTimer( &acb->ResetTimer, acb->acb_handle, (PVOID) NetFlexResetHandler, (PVOID) acb ); // // Initialize DPC timer // NdisMInitializeTimer( &acb->DpcTimer, acb->acb_handle, (PVOID) NetFlexDeferredTimer, (PVOID) acb ); // // Set the attributes for this adapter // NdisMSetAttributes( MiniportAdapterHandle, (NDIS_HANDLE) acb, TRUE, NdisInterfaceEisa ); // // Register our shutdown handler. // NdisMRegisterAdapterShutdownHandler( MiniportAdapterHandle, // wrapper miniport handle. acb, // shutdown context. NetFlexShutdown // shutdown handler. ); // // Reserve this adapters IO ports, if they haven't allready been added by the first // head... // if (gbl_addingdualport) { if (FirstHeadsAcb == NULL) { // This is the first instance of a head on a dual port board, // so register all the io ports for both heads. acb->FirstHeadsAcb = acb; // // grab ports z000 - z02f // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->BasePorts, MiniportAdapterHandle, baseaddr, NUM_DUALHEAD_CFG_PORTS ); if (Status == NDIS_STATUS_SUCCESS) { // Save the master base port addresses // acb->MasterBasePorts = acb->BasePorts; // grab zc80 - zc85 // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ConfigPorts, MiniportAdapterHandle, baseaddr + CFG_PORT_OFFSET, NUM_CFG_PORTS ); if (Status == NDIS_STATUS_SUCCESS) { // grab zc63 - zc67 // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ExtConfigPorts, MiniportAdapterHandle, baseaddr + EXTCFG_PORT_OFFSET, NUM_EXTCFG_PORTS ); } } } else { // Get the pointers to the other head's ports, which are already mapped. // acb->FirstHeadsAcb = FirstHeadsAcb; acb->BasePorts = FirstHeadsAcb->MasterBasePorts; acb->ConfigPorts = FirstHeadsAcb->ConfigPorts; acb->ExtConfigPorts = FirstHeadsAcb->ExtConfigPorts; acb->MasterBasePorts= FirstHeadsAcb->MasterBasePorts; Status = NDIS_STATUS_SUCCESS; } } else { // grab ports z000 - z01f // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->BasePorts, MiniportAdapterHandle, baseaddr, NUM_BASE_PORTS ); if (Status == NDIS_STATUS_SUCCESS) { // grab zc80 - zc85 // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ConfigPorts, MiniportAdapterHandle, baseaddr + CFG_PORT_OFFSET, NUM_CFG_PORTS ); if (Status == NDIS_STATUS_SUCCESS) { // grab zc63 - zc67 // Status = NdisMRegisterIoPortRange( (PVOID *)&acb->ExtConfigPorts, MiniportAdapterHandle, baseaddr + EXTCFG_PORT_OFFSET, NUM_EXTCFG_PORTS ); } } } // // If the registration fails, free up the memory we allocated // for the acb. // if (Status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF: Registration FAILED for slot#%d\n",(baseaddr / 1000))); goto HandleRegisterError; } // // Read in the company product id. // NdisRawReadPortUshort( acb->ConfigPorts, (PUSHORT) &cpqid); // // Read in the board product id. // NdisRawReadPortUshort( acb->ConfigPorts + 2, (PUSHORT) &boardid); // // Does it have a Compaq id? // // NETFLEX_ID covers NetFlex and NetFlex-2 // CPQTOK_ID covers DualSpeed and 16/4 Token-Ring if ( !( (cpqid == COMPAQ_ID) && ( ((boardid & NETFLEX_REVMASK) == NETFLEX_ID) || ((boardid & NETFLEX_REVMASK) == CPQTOK_ID) || ((boardid & NETFLEX_REVMASK) == RODAN_ID) || ((boardid & NETFLEX_REVMASK) == BONSAI_ID) ) ) ) { // // Not a Compaq id. // DebugPrint(0,("NF(%d): No Compaq adapter found\n",acb->anum)); Status = NDIS_STATUS_ADAPTER_NOT_FOUND; goto HandleRegisterError; } // // Make sure this is our board. // NdisRawReadPortUshort( acb->ConfigPorts + CFG_REGISTER, ®_value); if (!(reg_value & CFG_ENABLE)) { DebugPrint(0,("NF(%d): Adapter is not enabled\n",acb->anum)); DebugPrint(0,("NF(%d): Board Test Failed\n",acb->anum)); Status = NDIS_STATUS_ADAPTER_NOT_FOUND; goto HandleRegisterError; } // // Check to see if it's a card with FPA or a dual port adapter // if ( (boardid == MAPLE_ID) || (boardid == DURANGO_ID) ) { DebugPrint(1,("NF(%d): We're adding a card using FPA ! \n",acb->anum)); acb->acb_usefpa = TRUE; } else if ( ((boardid & NETFLEX_REVMASK) == BONSAI_ID) || ((boardid & NETFLEX_REVMASK) == RODAN_ID ) ) { acb->acb_usefpa = TRUE; acb->acb_dualport = TRUE; acb->acb_portnumber = gbl_portnumbertoadd; DebugPrint(1,("NF(%d): We're adding BONSAI or RODAN port #%d\n",acb->anum,acb->acb_portnumber)); } // // Set up the Config register location and the extended sif address // register location. // acb->AdapterConfigPort = acb->ConfigPorts + CFG_REGISTER; if (acb->acb_dualport && (acb->acb_portnumber == PORT2) ) { // // Align the ports right for the head #2's ports // acb->BasePorts = acb->FirstHeadsAcb->BasePorts + DUALHEAD_CFG_PORT_OFFSET; if ((boardid & NETFLEX_REVMASK) == RODAN_ID) { acb->AdapterConfigPort = acb->MasterBasePorts + CFG_REGRODAN; } } acb->SifDataPort = acb->BasePorts + SIF_DATA_OFF; /* SIF data register */ acb->SifDIncPort = acb->BasePorts + SIF_DINC_OFF; /* SIF data autoincrment reg */ acb->SifAddrPort = acb->BasePorts + SIF_ADDR_OFF; /* SIF address register */ acb->SifIntPort = acb->BasePorts + SIF_INT_OFF; /* SIF interrupt register */ acb->SifActlPort = acb->BasePorts + SIF_ACTL_OFF; /* SIF ACTL register */ acb->SifAddrxPort = acb->BasePorts + SIF_ACTL_EXT_OFF;/* SIF SIF extended address reg */ // // Save the Board ID // acb->acb_boardid = boardid; // // Do a reset to the adapter // NdisRawWritePortUshort(acb->SifActlPort, 0xEE); // // Wait 15 milliseconds to let the reset take place. // NdisStallExecution((UINT)15000); // Wait 15 milliseconds // // Get the Network type and speed from the eisa config info. // NetFlexSetupNetType(acb); // // Read configuration parameters from the registry if there are any // Status = NetFlexReadConfigurationParameters(acb,ConfigHandle); if (Status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF(%d): NetFlexReadConfigurationParameters Failed\n",acb->anum)); Status = NDIS_STATUS_RESOURCES; goto HandleRegisterError; } HandleRegisterError: if (Status != NDIS_STATUS_SUCCESS) { if (acb!=NULL) { if (acb->acb_parms != NULL) { NdisFreeMemory( (PVOID) acb->acb_parms, (UINT) sizeof(PNETFLEX_PARMS), (UINT) 0); } *acbp = NULL; NdisFreeMemory( (PVOID) acb, (UINT) sizeof(ACB), (UINT) 0); } } return(Status); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexReadConfigurationParameters // // Description: This routine reads configuration parameters // set by the user in the registry if exist. // // Input: acb - Adapter Context // ConfigHandle // // Output: Returns NDIS_STATUS_SUCCESS for a successful // completion. Otherwise, an error code is // returned. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NDIS_STATUS NetFlexReadConfigurationParameters( PACB acb, NDIS_HANDLE ConfigHandle ) { NDIS_STATUS status; PNETFLEX_PARMS pParms = NULL; ULONG length; PVOID NetworkAddress; BOOLEAN WriteError; PNDIS_CONFIGURATION_PARAMETER cfgp; ULONG netspeed = acb->acb_gen_objs.link_speed; NDIS_STRING maxreceives = NDIS_STRING_CONST("MAXRECEIVES"); NDIS_STRING productid = NDIS_STRING_CONST("PRODUCTID"); NDIS_STRING earlyrelease = NDIS_STRING_CONST("EARLYRELEASE"); NDIS_STRING maxtransmits = NDIS_STRING_CONST("MAXTRANSMITS"); NDIS_STRING maxframesz = NDIS_STRING_CONST("MAXFRAMESIZE"); NDIS_STRING maxmulticast = NDIS_STRING_CONST("MAXMULTICAST"); NDIS_STRING maxinternalreqs = NDIS_STRING_CONST("MAXINTERNALREQS"); NDIS_STRING maxinternalbufs = NDIS_STRING_CONST("MAXINTERNALBUFS"); NDIS_STRING maxtxbuf = NDIS_STRING_CONST("MAXTXBUF"); NDIS_STRING mintxbuf = NDIS_STRING_CONST("MINTXBUF"); NDIS_STRING extremecheckforhang = NDIS_STRING_CONST("ExtremeCheckForHang"); #ifdef XMIT_INTS NDIS_STRING xmitintratio = NDIS_STRING_CONST("TXINTRATIO"); #endif NDIS_STRING rcvintratio = NDIS_STRING_CONST("RXINTRATIO"); // // Allocate the Memory for the adapter's parms structure. // NdisAllocateMemory( (PVOID *)&pParms, (UINT) (sizeof (NETFLEX_PARMS)), (UINT) 0, NetFlexHighestAddress ); // // If we did not get the memory, flag any error. // if (pParms == NULL) { return(NDIS_STATUS_RESOURCES); } NdisMoveMemory(pParms, &NetFlex_Defaults, sizeof(NETFLEX_PARMS)); // // See if the user has specified the maximum number of internal // transmit buffers // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxinternalbufs, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_INTERNALBUFS) && (cfgp->ParameterData.IntegerData >= MIN_INTERNALBUFS) ) { pParms->utd_maxinternalbufs = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MAXINTERNALBUFS parameter is out of range, using default\n",acb->anum)); NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXINTERNALBUFS_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxinternalbufs); } } // // Read the network specific information from the registry // if (acb->acb_gen_objs.media_type_in_use == NdisMedium802_5) { // TokenRing // // // See if early token release has been selected. // if (netspeed == 16) { // Default to early token release. // pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_ETR); NdisReadConfiguration( &status, &cfgp, ConfigHandle, &earlyrelease, NdisParameterInteger ); if (status == NDIS_STATUS_SUCCESS) { if ( cfgp->ParameterData.IntegerData == 0) { // The user does not want early token release. // pParms->utd_open.OPEN_Options &= SWAPS((~OOPTS_ETR)); } } } // // Set the framehold bit so that we can allow promiscuous mode // to be set later on. We don't necessarily have to set // promiscuous mode but if we do, this is a requirement. // pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_FHOLD); // // Set MaxTransmits // pParms->utd_numsmallbufs = pParms->utd_maxtrans = DF_XMITS_TR; // // See if the user has specified the maximum number of transmit // lists supported. // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxtransmits, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_XMITS_TR) && (cfgp->ParameterData.IntegerData >= MIN_XMITS) ) { pParms->utd_numsmallbufs = pParms->utd_maxtrans = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MAXTRANSMITS parameter is out of range, using default\n",acb->anum)); NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXTRANSMITS_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxtrans); } } // // See if the user has specified the maximum frame size. // pParms->utd_maxframesz = DF_FRAMESIZE_TR; WriteError = FALSE; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxframesz, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if (cfgp->ParameterData.IntegerData < MIN_FRAMESIZE) { pParms->utd_maxframesz = MIN_FRAMESIZE; WriteError = TRUE; } else if (netspeed == 16) { // 16 Mb // if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_TR16) { pParms->utd_maxframesz = MAX_FRAMESIZE_TR16; WriteError = TRUE; } else { pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData; } } // // 4Mb // else if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_TR4) { pParms->utd_maxframesz = MAX_FRAMESIZE_TR4; WriteError = TRUE; } else { pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData; } if (WriteError) { // The parameter is out of range. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXFRAMESIZE_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxframesz); DebugPrint(0,("NF(%d): MaxFrameSize parameter is out of range, using default\n",acb->anum)); } } // // See if the user has specified the maximum number of Receive // lists supported. // pParms->utd_maxrcvs = DF_RCVS_TR; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxreceives, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_RCVS_TR) && (cfgp->ParameterData.IntegerData >= MIN_RCVS) ) { pParms->utd_maxrcvs = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXRECEIVES_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxrcvs); DebugPrint(0,("NF(%d): MAXReceives parameter is out of range, using default\n",acb->anum)); } } // // Adjust Number of Lists based on size of Max TR Frame Size // // // For every frame size which is greater than a multiple of 4096, // decrease number of transmits, Receives, and internal buffers. // if (pParms->utd_maxframesz > DF_FRAMESIZE_TR) { if (pParms->utd_maxframesz < ( (DF_FRAMESIZE_TR*2)+2) ) { pParms->utd_maxtrans = MAX_XMITS_TR-2; /* 6 xmits, 30 mapregs */ pParms->utd_maxrcvs = MAX_XMITS_TR-2; pParms->utd_maxinternalbufs = pParms->utd_maxtrans / 2; } else { pParms->utd_maxtrans = MAX_XMITS_TR-4; /* 4 xmits, 25 mapregs */ pParms->utd_maxrcvs = MAX_XMITS_TR-4; pParms->utd_maxinternalbufs = pParms->utd_maxtrans / 2; } } } else { // Ethernet // // // Set the framehold bit so that we can allow promiscuous mode // to be set later on. We don't necessarily have to set // promiscuous mode but if we do, this is a requirement. // pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_REQ + OOPTS_FHOLD); pParms->utd_maxframesz = DF_FRAMESIZE_ETH; // // See if the user has specified the maximum number of multicast // addresses supported. // pParms->utd_maxmulticast = DF_MULTICASTS; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxmulticast, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_MULTICASTS) && (cfgp->ParameterData.IntegerData >= MIN_MULTICASTS) ) { pParms->utd_maxmulticast = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MAXMULTICAST Parameter is out of range, using default\n",acb->anum)); NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXMULTICAST_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxmulticast); } } // // See if the user has specified the maximum number of transmit lists. // pParms->utd_numsmallbufs = pParms->utd_maxtrans = DF_XMITS_ETH; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxtransmits, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_XMITS_ETH) && (cfgp->ParameterData.IntegerData >= MIN_XMITS) ) { pParms->utd_numsmallbufs = pParms->utd_maxtrans = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MAXTRANSMITS parameter is out of range, using default\n",acb->anum)); NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXTRANSMITS_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxtrans); } } // // See if the user has specified the maximum frame size. // WriteError = FALSE; pParms->utd_maxframesz = MAX_FRAMESIZE_ETH; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxframesz, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if (cfgp->ParameterData.IntegerData < MIN_FRAMESIZE) { pParms->utd_maxframesz = MIN_FRAMESIZE; WriteError = TRUE; } else if (cfgp->ParameterData.IntegerData > MAX_FRAMESIZE_ETH) { pParms->utd_maxframesz = MAX_FRAMESIZE_ETH; WriteError = TRUE; } else { pParms->utd_maxframesz = (USHORT)cfgp->ParameterData.IntegerData; } if (WriteError) { // The parameter is out of range. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXFRAMESIZE_ERROR, 2, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxframesz); DebugPrint(0,("NF(%d): MaxFrameSize parameter is out of range, using default\n",acb->anum)); } } // // See if the user has specified the maximum number of Receive // lists supported. // pParms->utd_maxrcvs = DF_RCVS_ETH; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxreceives, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_RCVS_ETH) && (cfgp->ParameterData.IntegerData >= MIN_RCVS) ) { pParms->utd_maxrcvs = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_MAXRECEIVES_ERROR, (ULONG)cfgp->ParameterData.IntegerData, (ULONG)pParms->utd_maxrcvs); DebugPrint(0,("NF(%d): MAXReceives parameter is out of range, using default\n",acb->anum)); } } } DebugPrint(1,("NF(%d): MaxFrameSize = %d\n",acb->anum,pParms->utd_maxframesz)); DebugPrint(1,("NF(%d): MaxTransmits = %d\n",acb->anum,pParms->utd_maxtrans)); DebugPrint(1,("NF(%d): MaxReceives = %d\n",acb->anum,pParms->utd_maxrcvs)); // // Common Configuration settings for both Ethernet and TokenRing // // // See if the user has specified extreme checking for adapter hang. // NdisReadConfiguration(&status, &cfgp, ConfigHandle, &extremecheckforhang, NdisParameterInteger); if ((NDIS_STATUS_SUCCESS == status) && (cfgp->ParameterData.IntegerData != 0)) { // // They want the extreme checking to see if this adapter is // hung. // pParms->utd_extremecheckforhang = TRUE; } // // See if the user has specified the maximum number of adapter transmit buffers. // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxtxbuf, NdisParameterInteger); // // Set default Transmist_Buffer_Maximum_Count based on the max frame size * 2 tx lists // pParms->utd_open.OPEN_Xbufmax = ((pParms->utd_maxframesz / 1024) + 1 ) * 2; if (status == NDIS_STATUS_SUCCESS) { // Make Sure the value doesn't preclude us from transmiting a max frame size // if (cfgp->ParameterData.IntegerData > (UINT) (pParms->utd_maxframesz / 1024)) { pParms->utd_open.OPEN_Xbufmax = (UCHAR)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MaxTXBuf parameter is out of range, using default\n",acb->anum)); } } DebugPrint(1,("NF(%d): MaxTXBuf = 0x%x\n",acb->anum,pParms->utd_open.OPEN_Xbufmax)); // // See if the user has specified the minimum number of adapter transmit buffers. // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &mintxbuf, NdisParameterInteger); // // Set default Transmist_Buffer_Minimum_Count based on the max // pParms->utd_open.OPEN_Xbufmin = pParms->utd_open.OPEN_Xbufmax; if (status == NDIS_STATUS_SUCCESS) { if ((cfgp->ParameterData.IntegerData >= 0) && (cfgp->ParameterData.IntegerData <= pParms->utd_open.OPEN_Xbufmax) ) { pParms->utd_open.OPEN_Xbufmin = (UCHAR)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MinTXBuf parameter is out of range, using default\n",acb->anum)); } } DebugPrint(1,("NF(%d): MinTXBuf = 0x%x\n",acb->anum,pParms->utd_open.OPEN_Xbufmin)); // // See if the user has specified the maximum number of internal // requests supported. // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &maxinternalreqs, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { if ( (cfgp->ParameterData.IntegerData <= MAX_INTERNALREQS) && (cfgp->ParameterData.IntegerData >= MIN_INTERNALREQS) ) { pParms->utd_maxinternalreqs = (USHORT)cfgp->ParameterData.IntegerData; } else { // The parameter is out of range. DebugPrint(0,("NF(%d): MAXINTERNALREQS parameter is out of range, using default\n",acb->anum)); } } // // See if the user has specified the node address // NdisReadNetworkAddress( &status, &NetworkAddress, &length, ConfigHandle ); if ((length == NET_ADDR_SIZE) && (status == NDIS_STATUS_SUCCESS)) { NdisMoveMemory((PUCHAR)pParms->utd_open.OPEN_NodeAddr, (PUCHAR)NetworkAddress, NET_ADDR_SIZE); } else { DebugPrint(1,("NF(%d): Error in NdisReadNetworkAddress or none specified\n",acb->anum)); } // // See if the user has specified the product id // NdisReadConfiguration( &status, &cfgp, ConfigHandle, &productid,NdisParameterString ); if (status == NDIS_STATUS_SUCCESS) { status = NetFlexAsciiToHex( &(cfgp->ParameterData.StringData), (PUCHAR)pParms->utd_open.OPEN_ProdID, (USHORT)(18) ); if (status != NDIS_STATUS_SUCCESS) { // The parameter is out of range. DebugPrint(1,("NF(%d): PRODUCTID parameter is invalid, using default\n",acb->anum)); NdisWriteErrorLogEntry( acb->acb_handle, EVENT_NDIS_PRODUCTID_ERROR, 0); } } // // See if we need to open in Full Duplex // if (acb->FullDuplexEnabled) { // // Allocate the xmit spin lock. // NdisAllocateSpinLock(&acb->XmitLock); pParms->utd_open.OPEN_Options |= SWAPS(OOPTS_FULLDUP); } acb->acb_parms = pParms; #ifdef XMIT_INTS // // See if the user has specified the xmit_int_ratio // acb->XmitIntRatio = TxIntRatio; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &xmitintratio, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { acb->XmitIntRatio = (USHORT)cfgp->ParameterData.IntegerData; } DebugPrint(1,("NF(%d): TxIntRatio = 1:%d\n",acb->anum,acb->XmitIntRatio)); #endif // // See if the user has specified the rcv_int_ratio // acb->RcvIntRatio = RxIntRatio; NdisReadConfiguration( &status, &cfgp, ConfigHandle, &rcvintratio, NdisParameterInteger); if (status == NDIS_STATUS_SUCCESS) { acb->RcvIntRatio = (USHORT)cfgp->ParameterData.IntegerData; } DebugPrint(1,("NF(%d): Rx Int Ratio = 1:%d\n",acb->anum,acb->RcvIntRatio)); return NDIS_STATUS_SUCCESS; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexBoardInitandReg // // Description: This routine initiailizes the board, downloads // the mac code, and registers the adapter with // the wrapper. // // Input: acbp - Pointer to an acb ptr. // pParms - Settable parameters // // Output: acbp - Pointer to allocated acb // Returns NDIS_STATUS_SUCCESS for a successful // completion. Otherwise, an error code is // returned. // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NDIS_STATUS NetFlexBoardInitandReg( PACB acb, PNDIS_EISA_FUNCTION_INFORMATION EisaData ) { UINT int_vector; NDIS_INTERRUPT_MODE int_mode; NDIS_STATUS status; UINT i=0; // // Initialize the fields of the acb. // if ((status = NetFlexInitializeAcb(acb)) != NDIS_STATUS_SUCCESS) { // Failed, get out now... // return status; } // // Get EISA Config Data so we can set the interrupt data // int_vector = EisaData->EisaIrq[0].ConfigurationByte.Interrupt; if (!int_vector) { return NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION; } if (gbl_addingdualport) { // Dualport boards share the same interupt between heads // acb->InterruptsShared = TRUE; } else { acb->InterruptsShared = EisaData->EisaIrq[0].ConfigurationByte.Shared; } int_mode = EisaData->EisaIrq[0].ConfigurationByte.LevelTriggered ? NdisInterruptLevelSensitive : NdisInterruptLatched; // // Add this acb to the global list // acb->acb_next = macgbls.mac_adapters; macgbls.mac_adapters = acb; // // Initialize the interrupt. // status = NdisMRegisterInterrupt( &acb->acb_interrupt, acb->acb_handle, int_vector, int_vector, FALSE, // TRUE, acb->InterruptsShared, int_mode ); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF(%d): Initialization of the Interrupt FAILED\n",acb->anum)); NetFlexDequeue_OnePtrQ( (PVOID *)&macgbls.mac_adapters, (PVOID)acb); return status; } // // Ok, we're set, so reset the adapter and open'er up! // Try three times... // do { status = NetFlexAdapterReset(acb,HARD_RESET); if (status == NDIS_STATUS_SUCCESS) { // // Send the Open Command // status = NetFlexOpenAdapter(acb); } } while ((++i < 3) && (status != NDIS_STATUS_SUCCESS)); if (status != NDIS_STATUS_SUCCESS) { // Something failed, so get out. // return status; } // // Get the Burned In Address // NetFlexGetBIA(acb); // // Set the Default DPC timer // NdisMSetTimer(&acb->DpcTimer, 10); // // Indidicate that we're done with initializing this adapter. // acb->AdapterInitializing = FALSE; return NDIS_STATUS_SUCCESS; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Routine Name: NetFlexInitGlobals // // Description: This routine initializes the global // variables and downloads the mac download // code into our map buffer area. // // Input: None. // // Output: Status = SUCCESS . // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NDIS_STATUS NetFlexInitGlobals( ) { NDIS_STRING maccode = NDIS_STRING_CONST("NETFLX.BIN"); UINT length; NDIS_STATUS status; PUSHORT MappedBuffer; NDIS_HANDLE mac_filehandle; // // Open the file containing the MAC download code. // NdisOpenFile( &status, &mac_filehandle, &length, &maccode, NetFlexHighestAddress); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF: Download file could not be opened\n")); return status; } // // Allocate the buffer. // NdisAllocateMemory( (PVOID *)&macgbls.DownloadCode, length, FALSE, NetFlexHighestAddress); if (macgbls.DownloadCode == NULL) { status = NDIS_STATUS_FAILURE; } else { // Store the length // macgbls.DownloadLength = length; // // Get a mapping to the opened download file. // NdisMapFile( &status, (PVOID *)&MappedBuffer, mac_filehandle); if (status != NDIS_STATUS_SUCCESS) { DebugPrint(0,("NF: Download file could not be mapped\n")); } else { // Copy the download code into the shared memory space // NdisMoveMemory(macgbls.DownloadCode,MappedBuffer,length); NdisUnmapFile(mac_filehandle); } // // Done with the file NdisCloseFile(mac_filehandle); } return status; }