home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ndissrc.zip / UM9008.C < prev    next >
Text File  |  1998-07-01  |  48KB  |  2,010 lines

  1. /*++
  2.  
  3. Module Name:
  4.  
  5.     UM9008.c
  6.  
  7. Abstract:
  8.  
  9.     This is the main file for the UMC UM9008 Ethernet controller.
  10.     This driver conforms to the NDIS 3.0 miniport interface.
  11.  
  12. --*/
  13.  
  14. #include <ndis.h>
  15. #include "UM9008hw.h"
  16. #include "UM9008sw.h"
  17. #include "keywords.h"
  18.  
  19.  
  20.  
  21. //
  22. // On debug builds tell the compiler to keep the symbols for
  23. // internal functions, otw throw them out.
  24. //
  25. #if DBG
  26. #define STATIC
  27. #else
  28. #define STATIC static
  29. #endif
  30.  
  31. //
  32. // Debugging definitions
  33. //
  34. #if DBG
  35.  
  36. //
  37. // Default debug mode
  38. //
  39. ULONG UM9008DebugFlag = UM9008_DEBUG_LOG;
  40.  
  41. //
  42. // Debug tracing defintions
  43. //
  44. #define UM9008_LOG_SIZE 256
  45. UCHAR UM9008LogBuffer[UM9008_LOG_SIZE]={0};
  46. UINT UM9008LogLoc = 0;
  47.  
  48. extern
  49. VOID
  50. UM9008Log(UCHAR c) {
  51.  
  52.     UM9008LogBuffer[UM9008LogLoc++] = c;
  53.  
  54.         UM9008LogBuffer[(UM9008LogLoc + 4) % UM9008_LOG_SIZE] = '\0';
  55.  
  56.         if (UM9008LogLoc >= UM9008_LOG_SIZE)
  57.                 UM9008LogLoc = 0;
  58. }
  59.  
  60. #endif
  61.  
  62.  
  63.  
  64. //
  65. // This constant is used for places where NdisAllocateMemory
  66. // needs to be called and the HighestAcceptableAddress does
  67. // not matter.
  68. //
  69. NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
  70.     NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  71.  
  72. //
  73. // The global Miniport driver block.
  74. //
  75.  
  76. DRIVER_BLOCK UM9008MiniportBlock={0};
  77. STATIC CCHAR IRQTab[8] = {3, 4, 5, 9, 10, 11, 12, 15};
  78.  
  79. //
  80. // List of supported OID for this driver.
  81. //
  82. STATIC UINT UM9008SupportedOids[] = {
  83.     OID_GEN_SUPPORTED_LIST,
  84.     OID_GEN_HARDWARE_STATUS,
  85.     OID_GEN_MEDIA_SUPPORTED,
  86.     OID_GEN_MEDIA_IN_USE,
  87.     OID_GEN_MAXIMUM_LOOKAHEAD,
  88.     OID_GEN_MAXIMUM_FRAME_SIZE,
  89.     OID_GEN_MAXIMUM_TOTAL_SIZE,
  90.     OID_GEN_MAC_OPTIONS,
  91.     OID_GEN_PROTOCOL_OPTIONS,
  92.     OID_GEN_LINK_SPEED,
  93.     OID_GEN_TRANSMIT_BUFFER_SPACE,
  94.     OID_GEN_RECEIVE_BUFFER_SPACE,
  95.     OID_GEN_TRANSMIT_BLOCK_SIZE,
  96.     OID_GEN_RECEIVE_BLOCK_SIZE,
  97.     OID_GEN_VENDOR_DESCRIPTION,
  98.     OID_GEN_VENDOR_ID,
  99.     OID_GEN_DRIVER_VERSION,
  100.     OID_GEN_CURRENT_PACKET_FILTER,
  101.     OID_GEN_CURRENT_LOOKAHEAD,
  102.     OID_GEN_XMIT_OK,
  103.     OID_GEN_RCV_OK,
  104.     OID_GEN_XMIT_ERROR,
  105.     OID_GEN_RCV_ERROR,
  106.     OID_GEN_RCV_NO_BUFFER,
  107.     OID_802_3_PERMANENT_ADDRESS,
  108.     OID_802_3_CURRENT_ADDRESS,
  109.     OID_802_3_MULTICAST_LIST,
  110.     OID_802_3_MAXIMUM_LIST_SIZE,
  111.     OID_802_3_RCV_ERROR_ALIGNMENT,
  112.     OID_802_3_XMIT_ONE_COLLISION,
  113.     OID_802_3_XMIT_MORE_COLLISIONS
  114.     };
  115.  
  116. //
  117. // Determines whether failing the initial card test will prevent
  118. // the adapter from being registered.
  119. //
  120. #ifdef CARD_TEST
  121.  
  122. BOOLEAN InitialCardTest = TRUE;
  123.  
  124. #else  // CARD_TEST
  125.  
  126. BOOLEAN InitialCardTest = FALSE;
  127.  
  128. #endif // CARD_TEST
  129.  
  130.  
  131.  
  132.  
  133. NTSTATUS
  134. DriverEntry(
  135.     IN PDRIVER_OBJECT DriverObject,
  136.     IN PUNICODE_STRING RegistryPath
  137.     )
  138.  
  139. /*++
  140.  
  141. Routine Description:
  142.  
  143.     This is the primary initialization routine for the UM9008 driver.
  144.     It is simply responsible for the intializing the wrapper and registering
  145.     the Miniport driver.  It then calls a system and architecture specific
  146.     routine that will initialize and register each adapter.
  147.  
  148. Arguments:
  149.  
  150.     DriverObject - Pointer to driver object created by the system.
  151.  
  152.     RegistryPath - Path to the parameters for this driver in the registry.
  153.  
  154. Return Value:
  155.  
  156.     The status of the operation.
  157.  
  158. --*/
  159.  
  160. {
  161.  
  162.  
  163.     //
  164.     // Receives the status of the NdisMRegisterMiniport operation.
  165.     //
  166.     NDIS_STATUS Status;
  167.  
  168.     //
  169.     // Characteristics table for this driver.
  170.     //
  171.     NDIS_MINIPORT_CHARACTERISTICS UM9008Char;
  172.  
  173.     //
  174.     // Pointer to the global information for this driver
  175.     //
  176.     PDRIVER_BLOCK NewDriver = &UM9008MiniportBlock;
  177.  
  178.     //
  179.     // Handle for referring to the wrapper about this driver.
  180.     //
  181.     NDIS_HANDLE NdisWrapperHandle;
  182.  
  183. #if NDIS_WIN
  184.     UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + 3 * sizeof (USHORT)];
  185.     ((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=0;
  186.     ((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=3;
  187.     *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 0)=AE2_ADAPTER_ID;
  188.     *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 1)=UB_ADAPTER_ID;
  189.     *((PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray) + 2)=NE2_ADAPTER_ID;
  190.     (PVOID) DriverObject = (PVOID) pIds;
  191.  
  192. #endif
  193.  
  194.     //
  195.     // Initialize the wrapper.
  196.     //
  197.     NdisMInitializeWrapper(
  198.                 &NdisWrapperHandle,
  199.                 DriverObject,
  200.                 RegistryPath,
  201.                 NULL
  202.                 );
  203.  
  204.     //
  205.     // Save the global information about this driver.
  206.     //
  207.     NewDriver->NdisWrapperHandle = NdisWrapperHandle;
  208.     NewDriver->AdapterQueue = (PUM9008_ADAPTER)NULL;
  209.  
  210.     //
  211.     // Initialize the Miniport characteristics for the call to
  212.     // NdisMRegisterMiniport.
  213.     //
  214.     UM9008Char.MajorNdisVersion = UM9008_NDIS_MAJOR_VERSION;
  215.     UM9008Char.MinorNdisVersion = UM9008_NDIS_MINOR_VERSION;
  216.     UM9008Char.CheckForHangHandler = NULL;
  217.     UM9008Char.DisableInterruptHandler = UM9008DisableInterrupt;
  218.     UM9008Char.EnableInterruptHandler = UM9008EnableInterrupt;
  219.     UM9008Char.HaltHandler = UM9008Halt;
  220.     UM9008Char.HandleInterruptHandler = UM9008HandleInterrupt;
  221.     UM9008Char.InitializeHandler = UM9008Initialize;
  222.     UM9008Char.ISRHandler = UM9008Isr;
  223.     UM9008Char.QueryInformationHandler = UM9008QueryInformation;
  224.     UM9008Char.ReconfigureHandler = NULL;
  225.     UM9008Char.ResetHandler = UM9008Reset;
  226.     UM9008Char.SendHandler = UM9008Send;
  227. #if NDIS40_MINIPORT
  228.     UM9008Char.SendPacketsHandler = NULL;
  229.     UM9008Char.ReturnPacketHandler = NULL;
  230.     UM9008Char.AllocateCompleteHandler = NULL;
  231. #endif    
  232.     UM9008Char.SetInformationHandler = UM9008SetInformation;
  233.     UM9008Char.TransferDataHandler = UM9008TransferData;
  234.  
  235.     Status = NdisMRegisterMiniport(
  236.                  NdisWrapperHandle,
  237.                  &UM9008Char,
  238.                  sizeof(UM9008Char)
  239.                  );
  240.  
  241.     if (Status == NDIS_STATUS_SUCCESS) {
  242.  
  243.         return STATUS_SUCCESS;
  244.  
  245.     }
  246.  
  247.     return STATUS_UNSUCCESSFUL;
  248.  
  249. }
  250.  
  251. extern
  252. NDIS_STATUS
  253. UM9008Initialize(
  254.     OUT PNDIS_STATUS OpenErrorStatus,
  255.     OUT PUINT SelectedMediumIndex,
  256.     IN PNDIS_MEDIUM MediumArray,
  257.     IN UINT MediumArraySize,
  258.     IN NDIS_HANDLE MiniportAdapterHandle,
  259.     IN NDIS_HANDLE ConfigurationHandle
  260.     )
  261.  
  262. /*++
  263.  
  264. Routine Description:
  265.  
  266.     UM9008Initialize starts an adapter and registers resources with the
  267.     wrapper.
  268.  
  269. Arguments:
  270.  
  271.     OpenErrorStatus - Extra status bytes for opening token ring adapters.
  272.  
  273.     SelectedMediumIndex - Index of the media type chosen by the driver.
  274.  
  275.     MediumArray - Array of media types for the driver to chose from.
  276.  
  277.     MediumArraySize - Number of entries in the array.
  278.  
  279.     MiniportAdapterHandle - Handle for passing to the wrapper when
  280.        referring to this adapter.
  281.  
  282.     ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
  283.  
  284. Return Value:
  285.  
  286.     NDIS_STATUS_SUCCESS
  287.     NDIS_STATUS_PENDING
  288.  
  289. --*/
  290.  
  291. {
  292.     //
  293.     // Pointer to our newly allocated adapter.
  294.     //
  295.     PUM9008_ADAPTER Adapter;
  296.  
  297.     //
  298.     // The handle for reading from the registry.
  299.     //
  300.     NDIS_HANDLE ConfigHandle;
  301.  
  302.     //
  303.     // The value read from the registry.
  304.     //
  305.     PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
  306.  
  307.     //
  308.     // String names of all the parameters that will be read.
  309.     //
  310.     NDIS_STRING IOAddressStr = IOADDRESS;
  311.     NDIS_STRING InterruptStr = INTERRUPT;
  312.     NDIS_STRING MaxMulticastListStr = MAX_MULTICAST_LIST;
  313.     NDIS_STRING NetworkAddressStr = NETWORK_ADDRESS;
  314.     NDIS_STRING BusTypeStr = NDIS_STRING_CONST("BusType");
  315.     NDIS_STRING CardTypeStr = NDIS_STRING_CONST("CardType");
  316.  
  317.     //
  318.     // TRUE if there is a configuration error.
  319.     //
  320.     BOOLEAN ConfigError = FALSE;
  321.  
  322.     //
  323.     // A special value to log concerning the error.
  324.     //
  325.     ULONG ConfigErrorValue = 0;
  326.  
  327.     //
  328.     // The slot number the adapter is located in, used for
  329.     // Microchannel adapters.
  330.     //
  331.     UINT SlotNumber = 0;
  332.  
  333.     //
  334.     // TRUE if it is unnecessary to read the Io Base Address
  335.     // and Interrupt from the registry.  Used for Microchannel
  336.     // adapters, which get this information from the slot
  337.     // information.
  338.     //
  339.     BOOLEAN SkipIobaseAndInterrupt = FALSE;
  340.  
  341.     //
  342.     // The network address the adapter should use instead of the
  343.     // the default burned in address.
  344.     //
  345.     PVOID NetAddress;
  346.  
  347.     //
  348.     // The number of bytes in the address.  It should be
  349.     // UM9008_LENGTH_OF_ADDRESS
  350.     //
  351.     ULONG Length;
  352.  
  353.     //
  354.     // These are used when calling UM9008RegisterAdapter.
  355.     //
  356.  
  357.     //
  358.     // The physical address of the base I/O port.
  359.     //
  360.     PVOID IoBaseAddr;
  361.  
  362.  
  363.     //
  364.     // The interrupt number to use.
  365.     //
  366.     CCHAR InterruptNumber;
  367.  
  368.     //
  369.     // The number of multicast address to be supported.
  370.     //
  371.     UINT MaxMulticastList;
  372.  
  373.     //
  374.     // Temporary looping variable.
  375.     //
  376.     ULONG i;
  377.  
  378.     //
  379.     // Status of Ndis calls.
  380.     //
  381.     NDIS_STATUS Status;
  382.  
  383.     NDIS_MCA_POS_DATA McaData;
  384.  
  385.     //
  386.     // Search for the medium type (802.3) in the given array.
  387.     //
  388.     for (i = 0; i < MediumArraySize; i++){
  389.  
  390.         if (MediumArray[i] == NdisMedium802_3){
  391.  
  392.             break;
  393.  
  394.         }
  395.  
  396.     }
  397.  
  398.     if (i == MediumArraySize){
  399.  
  400.         return( NDIS_STATUS_UNSUPPORTED_MEDIA );
  401.  
  402.     }
  403.  
  404.     *SelectedMediumIndex = i;
  405.  
  406.  
  407.     //
  408.     // Set default values.
  409.     //
  410.     IoBaseAddr = DEFAULT_IOBASEADDR;
  411.     InterruptNumber = DEFAULT_INTERRUPTNUMBER;
  412.     MaxMulticastList = DEFAULT_MULTICASTLISTMAX;
  413.  
  414.     //
  415.     // Allocate memory for the adapter block now.
  416.     //
  417.     Status = NdisAllocateMemory( (PVOID *)&Adapter,
  418.                    sizeof(UM9008_ADAPTER),
  419.                    0,
  420.                    HighestAcceptableMax
  421.                    );
  422.  
  423.     if (Status != NDIS_STATUS_SUCCESS) {
  424.  
  425.         return Status;
  426.  
  427.     }
  428.  
  429.     //
  430.     // Clear out the adapter block, which sets all default values to FALSE,
  431.     // or NULL.
  432.     //
  433.     NdisZeroMemory (Adapter, sizeof(UM9008_ADAPTER));
  434.  
  435.     //
  436.     // Open the configuration space.
  437.     //
  438.     NdisOpenConfiguration(
  439.             &Status,
  440.             &ConfigHandle,
  441.             ConfigurationHandle
  442.             );
  443.  
  444.     if (Status != NDIS_STATUS_SUCCESS) {
  445.  
  446.         NdisFreeMemory(Adapter, sizeof(UM9008_ADAPTER), 0);
  447.  
  448.         return Status;
  449.  
  450.     }
  451.  
  452.     //
  453.     //  Read in the card type.
  454.     //
  455.     NdisReadConfiguration(
  456.             &Status,
  457.             &ReturnedValue,
  458.             ConfigHandle,
  459.             &CardTypeStr,
  460.             NdisParameterHexInteger
  461.             );
  462.     if (Status == NDIS_STATUS_SUCCESS)
  463.         Adapter->CardType = (UINT)ReturnedValue->ParameterData.IntegerData;
  464.  
  465.     //
  466.     // Read net address
  467.     //
  468.     NdisReadNetworkAddress(
  469.                     &Status,
  470.                     &NetAddress,
  471.                     &Length,
  472.                     ConfigHandle
  473.                     );
  474.  
  475.     if ((Length == UM9008_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
  476.  
  477.         //
  478.         // Save the address that should be used.
  479.         //
  480.         NdisMoveMemory(
  481.                 Adapter->StationAddress,
  482.                 NetAddress,
  483.                 UM9008_LENGTH_OF_ADDRESS
  484.                 );
  485.  
  486.     }
  487.  
  488. #if NDIS_NT
  489.     //
  490.     // Disallow multiple adapters in the same MP machine because of hardware
  491.     // problems this results in random packet corruption.
  492.     //
  493.     if ((NdisSystemProcessorCount() > 1) && (UM9008MiniportBlock.AdapterQueue != NULL)) {
  494.  
  495.         ConfigError = TRUE;
  496.         ConfigErrorValue = (ULONG)NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  497.         goto RegisterAdapter;
  498.  
  499.         return NDIS_STATUS_FAILURE;
  500.  
  501.     }
  502. #endif
  503.  
  504.  
  505.     //
  506.     // Read Bus Type (for NE2/AE2 support)
  507.     //
  508.  
  509.     NdisReadConfiguration(
  510.             &Status,
  511.             &ReturnedValue,
  512.             ConfigHandle,
  513.             &BusTypeStr,
  514.             NdisParameterHexInteger
  515.             );
  516.  
  517.     if (Status == NDIS_STATUS_SUCCESS) {
  518.  
  519.         Adapter->BusType = (UCHAR)ReturnedValue->ParameterData.IntegerData;
  520.  
  521.     }
  522.  
  523.  
  524.     if (Adapter->BusType == NdisInterfaceMca) {
  525.         ConfigError = TRUE;
  526.         ConfigErrorValue = (ULONG)NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  527.         goto RegisterAdapter;
  528.  
  529.         return NDIS_STATUS_FAILURE;
  530.  
  531.     }
  532.  
  533.     if (!SkipIobaseAndInterrupt) {
  534.  
  535.         //
  536.         // Read I/O Address
  537.         //
  538.         NdisReadConfiguration(
  539.                 &Status,
  540.                 &ReturnedValue,
  541.                 ConfigHandle,
  542.                 &IOAddressStr,
  543.                 NdisParameterHexInteger
  544.                 );
  545.  
  546.         if (Status == NDIS_STATUS_SUCCESS) {
  547.  
  548.             IoBaseAddr = (PVOID)(ReturnedValue->ParameterData.IntegerData);
  549.  
  550.         }
  551.  
  552.         //
  553.         // Check that the value is valid.
  554.         //
  555.         if ((IoBaseAddr < (PVOID)MIN_IOBASEADDR) ||
  556.             (IoBaseAddr > (PVOID)MAX_IOBASEADDR)) {
  557.  
  558.             ConfigError = TRUE;
  559.             ConfigErrorValue = (ULONG)IoBaseAddr;
  560.             goto RegisterAdapter;
  561.  
  562.         }
  563.  
  564.         //
  565.         // Read interrupt number
  566.         //
  567. #if NDIS_NT
  568.         NdisReadConfiguration(
  569.                 &Status,
  570.                 &ReturnedValue,
  571.                 ConfigHandle,
  572.                 &InterruptStr,
  573.                 NdisParameterHexInteger
  574.                 );
  575. #endif
  576.  
  577. #if NDIS_WIN
  578.         NdisReadConfiguration(
  579.                 &Status,
  580.                 &ReturnedValue,
  581.                 ConfigHandle,
  582.                 &InterruptStr,
  583.                 NdisParameterInteger
  584.                 );
  585. #endif
  586.  
  587.         if (Status == NDIS_STATUS_SUCCESS) {
  588.  
  589.             InterruptNumber = (CCHAR)(ReturnedValue->ParameterData.IntegerData);
  590.  
  591.         }
  592.  
  593.         //
  594.         // Verify that the value is valid.
  595.         //
  596.         if ((InterruptNumber < MIN_IRQ) ||
  597.             (InterruptNumber > MAX_IRQ)) {
  598.  
  599.             ConfigError = TRUE;
  600.             ConfigErrorValue = (ULONG)InterruptNumber;
  601.             goto RegisterAdapter;
  602.  
  603.         }
  604.     }
  605.  
  606.     //
  607.     // Read MaxMulticastList
  608.     //
  609.     NdisReadConfiguration(
  610.             &Status,
  611.             &ReturnedValue,
  612.             ConfigHandle,
  613.             &MaxMulticastListStr,
  614.             NdisParameterInteger
  615.             );
  616.  
  617.     if (Status == NDIS_STATUS_SUCCESS) {
  618.  
  619.         MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
  620.                 if (ReturnedValue->ParameterData.IntegerData <= DEFAULT_MULTICASTLISTMAX)
  621.                 MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
  622.     }
  623.  
  624.  
  625. RegisterAdapter:
  626.  
  627.     //
  628.     // Now to use this information and register with the wrapper
  629.     // and initialize the adapter.
  630.     //
  631.  
  632.     //
  633.     // First close the configuration space.
  634.     //
  635.     NdisCloseConfiguration(ConfigHandle);
  636.  
  637.     IF_LOUD( DbgPrint(
  638.         "Registering adapter # buffers %ld\n"
  639.         "Card type: 0x%x\n"
  640.         "I/O base addr 0x%lx\n"
  641.         "interrupt number %ld\n"
  642.         "max multicast %ld\nattribute memory address 0x%X\n"
  643.         "attribute memory size 0x%X\n"
  644.         "CardType: %d\n",
  645.         DEFAULT_NUMBUFFERS,
  646.         Adapter->CardType,
  647.         IoBaseAddr,
  648.         InterruptNumber,
  649.         DEFAULT_MULTICASTLISTMAX,
  650.         Adapter->AttributeMemoryAddress,
  651.         Adapter->AttributeMemorySize,
  652.         Adapter->CardType );)
  653.  
  654.  
  655.  
  656.     //
  657.     // Set up the parameters.
  658.     //
  659.     Adapter->NumBuffers = DEFAULT_NUMBUFFERS;
  660.     Adapter->IoBaseAddr = IoBaseAddr;
  661.  
  662.     Adapter->InterruptNumber = InterruptNumber;
  663.  
  664.     Adapter->MulticastListMax = MaxMulticastList;
  665.     Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
  666.  
  667.     Adapter->MaxLookAhead = UM9008_MAX_LOOKAHEAD;
  668.  
  669.  
  670.  
  671.     //
  672.     // Now do the work.
  673.     //
  674.     if (UM9008RegisterAdapter(Adapter,
  675.           ConfigurationHandle,
  676.           ConfigError,
  677.           ConfigErrorValue
  678.           ) != NDIS_STATUS_SUCCESS) {
  679.  
  680.         //
  681.         // UM9008RegisterAdapter failed.
  682.         //
  683.         NdisFreeMemory(Adapter, sizeof(UM9008_ADAPTER), 0);
  684.  
  685.         return NDIS_STATUS_FAILURE;
  686.  
  687.     }
  688.  
  689.  
  690.     IF_LOUD( DbgPrint( "UM9008RegisterAdapter succeeded\n" );)
  691.  
  692.     return NDIS_STATUS_SUCCESS;
  693. }
  694.  
  695.  
  696. NDIS_STATUS
  697. UM9008RegisterAdapter(
  698.     IN PUM9008_ADAPTER Adapter,
  699.     IN NDIS_HANDLE ConfigurationHandle,
  700.     IN BOOLEAN ConfigError,
  701.     IN ULONG ConfigErrorValue
  702.     )
  703.  
  704. /*++
  705.  
  706. Routine Description:
  707.  
  708.     Called when a new adapter should be registered. It allocates space for
  709.     the adapter, initializes the adapter's block, registers resources
  710.     with the wrapper and initializes the physical adapter.
  711.  
  712. Arguments:
  713.  
  714.     Adapter - The adapter structure.
  715.  
  716.     ConfigurationHandle - Handle passed to UM9008Initialize.
  717.  
  718.     ConfigError - Was there an error during configuration reading.
  719.  
  720.     ConfigErrorValue - Value to log if there is an error.
  721.  
  722. Return Value:
  723.  
  724.     Indicates the success or failure of the registration.
  725.  
  726. --*/
  727.  
  728. {
  729.  
  730.     //
  731.     // Temporary looping variable.
  732.     //
  733.     UINT i;
  734.  
  735.     //
  736.     // General purpose return from NDIS calls
  737.     //
  738.     NDIS_STATUS status;
  739.     // Check Valid IOPort or not
  740.     UINT  IoBaseAddr1;
  741.     CCHAR INData;
  742.     UINT  INPort;
  743.     CCHAR InterruptNumber;
  744.  
  745.  
  746.     //
  747.     // check that NumBuffers <= MAX_XMIT_BUFS
  748.     //
  749.  
  750.     if (Adapter->NumBuffers > MAX_XMIT_BUFS)
  751.         return(NDIS_STATUS_RESOURCES);
  752.  
  753.     //
  754.     // Check for a configuration error
  755.     //
  756.     if (ConfigError)
  757.     {
  758.         //
  759.         // Log Error and exit.
  760.         //
  761.         NdisWriteErrorLogEntry(
  762.             Adapter->MiniportAdapterHandle,
  763.             NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  764.             1,
  765.             ConfigErrorValue
  766.             );
  767.  
  768.         return(NDIS_STATUS_FAILURE);
  769.     }
  770.  
  771.  
  772.  
  773.  
  774.     //
  775.     // Inform the wrapper of the physical attributes of this adapter.
  776.     //
  777.     NdisMSetAttributes(
  778.         Adapter->MiniportAdapterHandle,
  779.         (NDIS_HANDLE)Adapter,
  780.         FALSE,
  781.         Adapter->BusType
  782.     );
  783.  
  784. #if  NDIS_NT
  785.     InterruptNumber = Adapter->InterruptNumber;
  786.     #ifdef TTT
  787.        if (NdisMRegisterIoPortRange(
  788.                  (PVOID *)(&(Adapter->IoPAddr)),
  789.                  Adapter->MiniportAdapterHandle,
  790.                  (ULONG)Adapter->IoBaseAddr,
  791.                  0x20
  792.              ) == NDIS_STATUS_SUCCESS) {
  793.                 NdisMDeregisterIoPortRange(
  794.                    Adapter->MiniportAdapterHandle,
  795.                    (ULONG) Adapter->IoBaseAddr,
  796.                    0x20,
  797.                    (PVOID) Adapter->IoPAddr);
  798.     #endif
  799.  
  800.                 NdisImmediateWritePortUchar(ConfigurationHandle, \
  801.                      (ULONG) Adapter->IoBaseAddr, (CCHAR) 0x21);
  802.                 NdisImmediateReadPortUchar(ConfigurationHandle, \
  803.                      (ULONG) Adapter->IoBaseAddr, &INData);
  804.                 if ((INData & 0xF9) == 0x21) {
  805.                    NdisImmediateReadPortUchar(ConfigurationHandle, \
  806.                      (ULONG) Adapter->IoBaseAddr+0xa, &INData);
  807.                    if ((INData & 0xf) > 7) {
  808.                       INPort = 0x200 + (UINT) ((INData & 0x7) << 5);
  809.                    } else {
  810.                       INPort = 0x300 + (UINT) ((INData & 0x7) << 5);
  811.                    }
  812.                    if ((PVOID)INPort == Adapter->IoBaseAddr) {
  813.                       InterruptNumber = IRQTab[(INData & 0x70) >> 4];
  814.                       INData = (CCHAR) 0xff;
  815.                    } else {
  816.                       INData = 0;
  817.                    }
  818.                 } else {
  819.                    INData = 0;
  820.                 }
  821.  
  822.     #ifdef TTT
  823.         } else {
  824.            INData = 0;
  825.         }
  826.     #endif
  827.  
  828.         if (INData == 0) {
  829.            for (IoBaseAddr1 = 0x200; IoBaseAddr1 < 0x400 ; IoBaseAddr1 += 0x20) {
  830.               if ((PVOID) IoBaseAddr1 == Adapter->IoBaseAddr) {
  831.                  INData = 0;
  832.                  continue;
  833.               }
  834.      #ifdef TTT
  835.               if (NdisMRegisterIoPortRange(
  836.                        (PVOID *)(&Adapter->IoPAddr),
  837.                        Adapter->MiniportAdapterHandle,
  838.                        (ULONG)IoBaseAddr1,
  839.                        0x20
  840.                    ) == NDIS_STATUS_SUCCESS) {
  841.                  NdisMDeregisterIoPortRange(
  842.                     Adapter->MiniportAdapterHandle,
  843.                     IoBaseAddr1,
  844.                     0x20,
  845.                     (PVOID) Adapter->IoPAddr);
  846.      #endif
  847.  
  848.                  NdisImmediateWritePortUchar(ConfigurationHandle, \
  849.                    (ULONG) IoBaseAddr1, (CCHAR) 0x21);
  850.                  NdisImmediateReadPortUchar(ConfigurationHandle, \
  851.                    (ULONG) IoBaseAddr1, &INData);
  852.                  if ((INData & 0xF9) == 0x21) {
  853.                     NdisImmediateReadPortUchar(ConfigurationHandle, \
  854.                     (ULONG) IoBaseAddr1+0xa, &INData);
  855.                     if ((INData & 0xf) > 7) {
  856.                        INPort = 0x200 + (UINT) ((INData & 0x7) << 5);
  857.                     } else {
  858.                        INPort = 0x300 + (UINT) ((INData & 0x7) << 5);
  859.                     }
  860.                     if (INPort == (UINT)IoBaseAddr1) {
  861.                        InterruptNumber = IRQTab[(INData & 0x70) >> 4];
  862.                        INData = (CCHAR)0xff;
  863.                        break;
  864.                     } else {
  865.                        INData = 0;
  866.                     }
  867.                  } else {
  868.                     INData = 0;
  869.                  }
  870.         #ifdef     TTT
  871.               } else {
  872.                  INData = 0;
  873.               }
  874.         #endif
  875.            }
  876.  
  877.            if (INData) {
  878.               Adapter->IoBaseAddr = (PVOID) IoBaseAddr1;
  879.            }
  880.         }
  881.  
  882.    Adapter->InterruptNumber = InterruptNumber;
  883. #endif
  884.  
  885.  
  886.  
  887.     //
  888.     // Register the port addresses.
  889.     //
  890.     status = NdisMRegisterIoPortRange(
  891.                  (PVOID *)(&(Adapter->IoPAddr)),
  892.                  Adapter->MiniportAdapterHandle,
  893.                  (ULONG)Adapter->IoBaseAddr,
  894.                  0x20
  895.              );
  896.  
  897.     if (status != NDIS_STATUS_SUCCESS)
  898.         return(status);
  899.  
  900.     if (UM9008_ISA == Adapter->CardType)
  901.     {
  902.         //
  903.         // Check that the IoBaseAddress seems to be correct.
  904.         //
  905.         IF_VERY_LOUD( DbgPrint("Checking Parameters\n"); )
  906.  
  907.         if (!CardCheckParameters(Adapter))
  908.         {
  909.             //
  910.             // The card does not seem to be there, fail silently.
  911.             //
  912.             IF_VERY_LOUD( DbgPrint("  -- Failed\n"); )
  913.  
  914.             NdisWriteErrorLogEntry(
  915.                 Adapter->MiniportAdapterHandle,
  916.                 NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  917.                 0
  918.             );
  919.  
  920.             status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  921.  
  922.             goto fail2;
  923.         }
  924.  
  925.         IF_VERY_LOUD( DbgPrint("  -- Success\n"); )
  926.     }
  927.  
  928.     //
  929.     // Initialize the card.
  930.     //
  931.     IF_VERY_LOUD( DbgPrint("CardInitialize\n"); )
  932.  
  933.     if (!CardInitialize(Adapter))
  934.     {
  935.         //
  936.         // Card seems to have failed.
  937.         //
  938.  
  939.         IF_VERY_LOUD( DbgPrint("  -- Failed\n"); )
  940.  
  941.         NdisWriteErrorLogEntry(
  942.             Adapter->MiniportAdapterHandle,
  943.             NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  944.             0
  945.         );
  946.  
  947.         status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  948.  
  949.         goto fail2;
  950.     }
  951.  
  952.     IF_VERY_LOUD( DbgPrint("  -- Success\n"); )
  953.  
  954.     //
  955.     //
  956.     // For programmed I/O, we will refer to transmit/receive memory in
  957.     // terms of offsets in the card's 64K address space.
  958.     //
  959.     Adapter->XmitStart = Adapter->RamBase;
  960.  
  961.     //
  962.     // For the NicXXX fields, always use the addressing system
  963.     // containing the MSB only).
  964.     //
  965.     Adapter->NicXmitStart = (UCHAR)(((ULONG)Adapter->XmitStart) >> 8);
  966.  
  967.     //
  968.     // The start of the receive space.
  969.     //
  970.     Adapter->PageStart = Adapter->XmitStart +
  971.             (Adapter->NumBuffers * TX_BUF_SIZE);
  972.  
  973.     Adapter->NicPageStart = Adapter->NicXmitStart +
  974.             (UCHAR)(Adapter->NumBuffers * BUFS_PER_TX);
  975.  
  976.     ASSERT(Adapter->PageStart < (Adapter->RamBase + Adapter->RamSize));
  977.  
  978.     //
  979.     // The end of the receive space.
  980.     //
  981.     Adapter->PageStop = Adapter->XmitStart + Adapter->RamSize;
  982.     Adapter->NicPageStop = Adapter->NicXmitStart + (UCHAR)(Adapter->RamSize >> 8);
  983.  
  984.     ASSERT(Adapter->PageStop <= (Adapter->RamBase + Adapter->RamSize));
  985.  
  986.     IF_LOUD( DbgPrint("Xmit Start (0x%x, 0x%x) : Rcv Start (0x%x, 0x%x) : Rcv End (0x%x, 0x%x)\n",
  987.               Adapter->XmitStart,
  988.               Adapter->NicXmitStart,
  989.               Adapter->PageStart,
  990.               Adapter->NicPageStart,
  991.               (ULONG)Adapter->PageStop,
  992.               Adapter->NicPageStop
  993.              );
  994.        )
  995.  
  996.  
  997.     //
  998.     // Initialize the receive variables.
  999.     //
  1000.     Adapter->NicReceiveConfig = RCR_REJECT_ERR;
  1001.  
  1002.     //
  1003.     // Initialize the transmit buffer control.
  1004.     //
  1005.     Adapter->CurBufXmitting = (XMIT_BUF)-1;
  1006.  
  1007.     //
  1008.     // Initialize the transmit buffer states.
  1009.     //
  1010.     for (i = 0; i < Adapter->NumBuffers; i++)
  1011.         Adapter->BufferStatus[i] = EMPTY;
  1012.  
  1013.     //
  1014.     // Read the Ethernet address off of the PROM.
  1015.     //
  1016.     if (!CardReadEthernetAddress(Adapter))
  1017.     {
  1018.         IF_LOUD(DbgPrint("Could not read the ethernet address\n");)
  1019.  
  1020.         NdisWriteErrorLogEntry(
  1021.             Adapter->MiniportAdapterHandle,
  1022.             NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  1023.             0
  1024.             );
  1025.  
  1026.         status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  1027.  
  1028.         goto fail2;
  1029.     }
  1030.  
  1031.     //
  1032.     // Now initialize the NIC and Gate Array registers.
  1033.     //
  1034.     Adapter->NicInterruptMask = IMR_RCV | IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
  1035.  
  1036.     //
  1037.     // Link us on to the chain of adapters for this driver.
  1038.     //
  1039.     Adapter->NextAdapter = UM9008MiniportBlock.AdapterQueue;
  1040.     UM9008MiniportBlock.AdapterQueue = Adapter;
  1041.  
  1042.  
  1043.     //
  1044.     // Setup the card based on the initialization information
  1045.     //
  1046.  
  1047.     IF_VERY_LOUD( DbgPrint("Setup\n"); )
  1048.  
  1049.     if (!CardSetup(Adapter))
  1050.     {
  1051.         //
  1052.         // The NIC could not be written to.
  1053.         //
  1054.  
  1055.         NdisWriteErrorLogEntry(
  1056.             Adapter->MiniportAdapterHandle,
  1057.             NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  1058.             0
  1059.         );
  1060.  
  1061.         IF_VERY_LOUD( DbgPrint("  -- Failed\n"); )
  1062.  
  1063.         status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  1064.  
  1065.         goto fail3;
  1066.     }
  1067.  
  1068.     IF_VERY_LOUD( DbgPrint("  -- Success\n"); )
  1069.  
  1070.     //
  1071.     // Initialize the interrupt.
  1072.     //
  1073.     status = NdisMRegisterInterrupt(
  1074.                  &Adapter->Interrupt,
  1075.                  Adapter->MiniportAdapterHandle,
  1076.                  Adapter->InterruptNumber,
  1077.                  Adapter->InterruptNumber,
  1078.                  FALSE,
  1079.                  FALSE,
  1080.                  NdisInterruptLatched
  1081.              );
  1082.  
  1083.     if (status != NDIS_STATUS_SUCCESS)
  1084.     {
  1085.         NdisWriteErrorLogEntry(
  1086.             Adapter->MiniportAdapterHandle,
  1087.             NDIS_ERROR_CODE_INTERRUPT_CONNECT,
  1088.             0
  1089.         );
  1090.  
  1091.         goto fail3;
  1092.     }
  1093.  
  1094.     IF_LOUD( DbgPrint("Interrupt Connected\n");)
  1095.  
  1096.     //
  1097.     // Start up the adapter.
  1098.     //
  1099.     CardStart(Adapter);
  1100.  
  1101.     //
  1102.     // Initialization completed successfully.
  1103.     //
  1104.     IF_LOUD( DbgPrint(" [ UM9008 ] : OK\n");)
  1105.  
  1106.     return(NDIS_STATUS_SUCCESS);
  1107.  
  1108.     //
  1109.     // Code to unwind what has already been set up when a part of
  1110.     // initialization fails, which is jumped into at various
  1111.     // points based on where the failure occured. Jumping to
  1112.     // a higher-numbered failure point will execute the code
  1113.     // for that block and all lower-numbered ones.
  1114.     //
  1115.  
  1116. fail3:
  1117.  
  1118.     //
  1119.     // Take us out of the AdapterQueue.
  1120.     //
  1121.  
  1122.     if (UM9008MiniportBlock.AdapterQueue == Adapter)
  1123.     {
  1124.         UM9008MiniportBlock.AdapterQueue = Adapter->NextAdapter;
  1125.     }
  1126.     else
  1127.     {
  1128.         PUM9008_ADAPTER TmpAdapter = UM9008MiniportBlock.AdapterQueue;
  1129.  
  1130.         while (TmpAdapter->NextAdapter != Adapter)
  1131.         {
  1132.             TmpAdapter = TmpAdapter->NextAdapter;
  1133.         }
  1134.  
  1135.         TmpAdapter->NextAdapter = TmpAdapter->NextAdapter->NextAdapter;
  1136.     }
  1137.  
  1138.     //
  1139.     // We already enabled the interrupt on the card, so
  1140.     // turn it off.
  1141.     //
  1142.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND, CR_STOP);
  1143.  
  1144. fail2:
  1145.  
  1146.     NdisMDeregisterIoPortRange(
  1147.         Adapter->MiniportAdapterHandle,
  1148.         (ULONG)Adapter->IoBaseAddr,
  1149.         0x20,
  1150.         (PVOID)Adapter->IoPAddr
  1151.     );
  1152.  
  1153.     return(status);
  1154. }
  1155.  
  1156.  
  1157. extern
  1158. VOID
  1159. UM9008Halt(
  1160.     IN NDIS_HANDLE MiniportAdapterContext
  1161.     )
  1162.  
  1163. /*++
  1164.  
  1165. Routine Description:
  1166.  
  1167.     UM9008Halt removes an adapter that was previously initialized.
  1168.  
  1169. Arguments:
  1170.  
  1171.     MiniportAdapterContext - The context value that the Miniport returned
  1172.         from UM9008Initialize; actually as pointer to an UM9008_ADAPTER.
  1173.  
  1174. Return Value:
  1175.  
  1176.     None.
  1177.  
  1178. --*/
  1179.  
  1180. {
  1181.     PUM9008_ADAPTER Adapter;
  1182.  
  1183.     Adapter = PUM9008_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  1184.  
  1185.     //
  1186.     // Shut down the chip.
  1187.     //
  1188.     CardStop(Adapter);
  1189.  
  1190.     //
  1191.     // Disconnect the interrupt line.
  1192.     //
  1193.     NdisMDeregisterInterrupt(&Adapter->Interrupt);
  1194.  
  1195.     //
  1196.     // Pause, waiting for any DPC stuff to clear.
  1197.     //
  1198.     NdisStallExecution(250000);
  1199.  
  1200.     NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle,
  1201.                                (ULONG)Adapter->IoBaseAddr,
  1202.                                0x20,
  1203.                                (PVOID)Adapter->IoPAddr
  1204.                                );
  1205.  
  1206.     //
  1207.     // Remove the adapter from the global queue of adapters.
  1208.     //
  1209.     if (UM9008MiniportBlock.AdapterQueue == Adapter) {
  1210.  
  1211.         UM9008MiniportBlock.AdapterQueue = Adapter->NextAdapter;
  1212.  
  1213.     } else {
  1214.  
  1215.         PUM9008_ADAPTER TmpAdapter = UM9008MiniportBlock.AdapterQueue;
  1216.  
  1217.         while (TmpAdapter->NextAdapter != Adapter) {
  1218.  
  1219.             TmpAdapter = TmpAdapter->NextAdapter;
  1220.  
  1221.         }
  1222.  
  1223.         TmpAdapter->NextAdapter = TmpAdapter->NextAdapter->NextAdapter;
  1224.     }
  1225.  
  1226.     //
  1227.     // Free up the memory
  1228.     //
  1229.     NdisFreeMemory(Adapter, sizeof(UM9008_ADAPTER), 0);
  1230.  
  1231.     return;
  1232.  
  1233. }
  1234.  
  1235.  
  1236.  
  1237.  
  1238. NDIS_STATUS
  1239. UM9008Reset(
  1240.     OUT PBOOLEAN AddressingReset,
  1241.     IN NDIS_HANDLE MiniportAdapterContext
  1242.     )
  1243. /*++
  1244.  
  1245. Routine Description:
  1246.  
  1247.     The UM9008Reset request instructs the Miniport to issue a hardware reset
  1248.     to the network adapter.  The driver also resets its software state.  See
  1249.     the description of NdisMReset for a detailed description of this request.
  1250.  
  1251. Arguments:
  1252.  
  1253.     AddressingReset - Does the adapter need the addressing information reloaded.
  1254.  
  1255.     MiniportAdapterContext - Pointer to the adapter structure.
  1256.  
  1257. Return Value:
  1258.  
  1259.     The function value is the status of the operation.
  1260.  
  1261. --*/
  1262.  
  1263. {
  1264.  
  1265.     //
  1266.     // Pointer to the adapter structure.
  1267.     //
  1268.     PUM9008_ADAPTER Adapter = (PUM9008_ADAPTER)MiniportAdapterContext;
  1269.  
  1270.     //
  1271.     // Temporary looping variable
  1272.     //
  1273.     UINT i;
  1274.  
  1275.     //
  1276.     // Clear the values for transmits, they will be reset these for after
  1277.     // the reset is completed.
  1278.     //
  1279.     Adapter->NextBufToFill = 0;
  1280.     Adapter->NextBufToXmit = 0;
  1281.     Adapter->CurBufXmitting = (XMIT_BUF)-1;
  1282.  
  1283.     Adapter->FirstPacket = NULL;
  1284.     Adapter->LastPacket = NULL;
  1285.  
  1286.     for (i=0; i<Adapter->NumBuffers; i++) {
  1287.             Adapter->BufferStatus[i] = EMPTY;
  1288.     }
  1289.  
  1290.     //
  1291.     // Physically reset the card.
  1292.     //
  1293.     Adapter->NicInterruptMask = IMR_RCV | IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
  1294.  
  1295.     return (CardReset(Adapter) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
  1296. }
  1297.  
  1298. NDIS_STATUS
  1299. UM9008QueryInformation(
  1300.     IN NDIS_HANDLE MiniportAdapterContext,
  1301.     IN NDIS_OID Oid,
  1302.     IN PVOID InformationBuffer,
  1303.     IN ULONG InformationBufferLength,
  1304.     OUT PULONG BytesWritten,
  1305.     OUT PULONG BytesNeeded
  1306. )
  1307.  
  1308. /*++
  1309.  
  1310. Routine Description:
  1311.  
  1312.     The UM9008QueryInformation process a Query request for
  1313.     NDIS_OIDs that are specific about the Driver.
  1314.  
  1315. Arguments:
  1316.  
  1317.     MiniportAdapterContext - a pointer to the adapter.
  1318.  
  1319.     Oid - the NDIS_OID to process.
  1320.  
  1321.     InformationBuffer -  a pointer into the
  1322.     NdisRequest->InformationBuffer into which store the result of the query.
  1323.  
  1324.     InformationBufferLength - a pointer to the number of bytes left in the
  1325.     InformationBuffer.
  1326.  
  1327.     BytesWritten - a pointer to the number of bytes written into the
  1328.     InformationBuffer.
  1329.  
  1330.     BytesNeeded - If there is not enough room in the information buffer
  1331.     then this will contain the number of bytes needed to complete the
  1332.     request.
  1333.  
  1334. Return Value:
  1335.  
  1336.     The function value is the status of the operation.
  1337.  
  1338. --*/
  1339. {
  1340.  
  1341.     //
  1342.     // Pointer to the adapter structure.
  1343.     //
  1344.     PUM9008_ADAPTER Adapter = (PUM9008_ADAPTER)MiniportAdapterContext;
  1345.  
  1346.     //
  1347.     //   General Algorithm:
  1348.     //
  1349.     //      Switch(Request)
  1350.     //         Get requested information
  1351.     //         Store results in a common variable.
  1352.     //      default:
  1353.     //         Try protocol query information
  1354.     //         If that fails, fail query.
  1355.     //
  1356.     //      Copy result in common variable to result buffer.
  1357.     //   Finish processing
  1358.  
  1359.     UINT BytesLeft = InformationBufferLength;
  1360.     PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1361.     NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1362.     NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  1363.     NDIS_MEDIUM Medium = NdisMedium802_3;
  1364.  
  1365.     //
  1366.     // This variable holds result of query
  1367.     //
  1368.     ULONG GenericULong;
  1369.     USHORT GenericUShort;
  1370.     UCHAR GenericArray[6];
  1371.     UINT MoveBytes = sizeof(ULONG);
  1372.     PVOID MoveSource = (PVOID)(&GenericULong);
  1373.  
  1374.     //
  1375.     // Make sure that int is 4 bytes.  Else GenericULong must change
  1376.     // to something of size 4.
  1377.     //
  1378.     ASSERT(sizeof(ULONG) == 4);
  1379.  
  1380.     //
  1381.     // Switch on request type
  1382.     //
  1383.  
  1384.     switch (Oid) {
  1385.  
  1386.     case OID_GEN_MAC_OPTIONS:
  1387.  
  1388.         GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND  |
  1389.                                NDIS_MAC_OPTION_RECEIVE_SERIALIZED  |
  1390.                                NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
  1391.                                NDIS_MAC_OPTION_NO_LOOPBACK
  1392.                                );
  1393.  
  1394.         break;
  1395.  
  1396.     case OID_GEN_SUPPORTED_LIST:
  1397.  
  1398.         MoveSource = (PVOID)(UM9008SupportedOids);
  1399.         MoveBytes = sizeof(UM9008SupportedOids);
  1400.         break;
  1401.  
  1402.     case OID_GEN_HARDWARE_STATUS:
  1403.  
  1404.         HardwareStatus = NdisHardwareStatusReady;
  1405.         MoveSource = (PVOID)(&HardwareStatus);
  1406.         MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
  1407.  
  1408.         break;
  1409.  
  1410.     case OID_GEN_MEDIA_SUPPORTED:
  1411.     case OID_GEN_MEDIA_IN_USE:
  1412.  
  1413.         MoveSource = (PVOID) (&Medium);
  1414.         MoveBytes = sizeof(NDIS_MEDIUM);
  1415.         break;
  1416.  
  1417.     case OID_GEN_MAXIMUM_LOOKAHEAD:
  1418.  
  1419.         GenericULong = UM9008_MAX_LOOKAHEAD;
  1420.  
  1421.         break;
  1422.  
  1423.  
  1424.     case OID_GEN_MAXIMUM_FRAME_SIZE:
  1425.  
  1426.         GenericULong = (ULONG)(1514 - UM9008_HEADER_SIZE);
  1427.  
  1428.         break;
  1429.  
  1430.  
  1431.     case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1432.  
  1433.         GenericULong = (ULONG)(1514);
  1434.  
  1435.         break;
  1436.  
  1437.  
  1438.     case OID_GEN_LINK_SPEED:
  1439.  
  1440.         GenericULong = (ULONG)(100000);
  1441.  
  1442.         break;
  1443.  
  1444.  
  1445.     case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1446.  
  1447.         GenericULong = (ULONG)(Adapter->NumBuffers * TX_BUF_SIZE);
  1448.  
  1449.         break;
  1450.  
  1451.     case OID_GEN_RECEIVE_BUFFER_SPACE:
  1452.  
  1453.         GenericULong = (ULONG)(0x2000 - (Adapter->NumBuffers * TX_BUF_SIZE));
  1454.  
  1455.         break;
  1456.  
  1457.     case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1458.  
  1459.         GenericULong = (ULONG)(TX_BUF_SIZE);
  1460.  
  1461.         break;
  1462.  
  1463.     case OID_GEN_RECEIVE_BLOCK_SIZE:
  1464.  
  1465.         GenericULong = (ULONG)(256);
  1466.  
  1467.         break;
  1468.  
  1469. #ifdef UM9008
  1470.  
  1471.     case OID_GEN_VENDOR_ID:
  1472.  
  1473.         NdisMoveMemory(
  1474.             (PVOID)&GenericULong,
  1475.             Adapter->PermanentAddress,
  1476.             3
  1477.             );
  1478.         GenericULong &= 0xFFFFFF00;
  1479.         MoveSource = (PVOID)(&GenericULong);
  1480.         MoveBytes = sizeof(GenericULong);
  1481.         break;
  1482.  
  1483.     case OID_GEN_VENDOR_DESCRIPTION:
  1484.  
  1485.         MoveSource = (PVOID)"UMC UM9008 Adapter.";
  1486.         MoveBytes = 20;
  1487.  
  1488.         break;
  1489.  
  1490. #else
  1491.  
  1492.     case OID_GEN_VENDOR_ID:
  1493.  
  1494.         NdisMoveMemory(
  1495.             (PVOID)&GenericULong,
  1496.             Adapter->PermanentAddress,
  1497.             3
  1498.             );
  1499.         GenericULong &= 0xFFFFFF00;
  1500.         GenericULong |= 0x01;
  1501.         MoveSource = (PVOID)(&GenericULong);
  1502.         MoveBytes = sizeof(GenericULong);
  1503.         break;
  1504.  
  1505.     case OID_GEN_VENDOR_DESCRIPTION:
  1506.  
  1507.         MoveSource = (PVOID)"UMC UM9008 Adapter.";
  1508.         MoveBytes = 20;
  1509.  
  1510.         break;
  1511.  
  1512. #endif
  1513.  
  1514.     case OID_GEN_DRIVER_VERSION:
  1515.  
  1516.         GenericUShort = ((USHORT)UM9008_NDIS_MAJOR_VERSION << 8) |
  1517.                 UM9008_NDIS_MINOR_VERSION;
  1518.  
  1519.         MoveSource = (PVOID)(&GenericUShort);
  1520.         MoveBytes = sizeof(GenericUShort);
  1521.         break;
  1522.  
  1523.     case OID_GEN_CURRENT_LOOKAHEAD:
  1524.  
  1525.         GenericULong = (ULONG)(Adapter->MaxLookAhead);
  1526.         break;
  1527.  
  1528.     case OID_802_3_PERMANENT_ADDRESS:
  1529.  
  1530.         UM9008_MOVE_MEM((PCHAR)GenericArray,
  1531.                     Adapter->PermanentAddress,
  1532.                     UM9008_LENGTH_OF_ADDRESS);
  1533.  
  1534.         MoveSource = (PVOID)(GenericArray);
  1535.         MoveBytes = sizeof(Adapter->PermanentAddress);
  1536.  
  1537.         break;
  1538.  
  1539.     case OID_802_3_CURRENT_ADDRESS:
  1540.  
  1541.         UM9008_MOVE_MEM((PCHAR)GenericArray,
  1542.                     Adapter->StationAddress,
  1543.                     UM9008_LENGTH_OF_ADDRESS);
  1544.  
  1545.         MoveSource = (PVOID)(GenericArray);
  1546.         MoveBytes = sizeof(Adapter->StationAddress);
  1547.  
  1548.         break;
  1549.  
  1550.     case OID_802_3_MAXIMUM_LIST_SIZE:
  1551.  
  1552.         GenericULong = (ULONG) (Adapter->MulticastListMax);
  1553.         break;
  1554.  
  1555.     case OID_GEN_XMIT_OK:
  1556.  
  1557.         GenericULong = (UINT)(Adapter->FramesXmitGood);
  1558.         break;
  1559.  
  1560.     case OID_GEN_RCV_OK:
  1561.  
  1562.         GenericULong = (UINT)(Adapter->FramesRcvGood);
  1563.         break;
  1564.  
  1565.     case OID_GEN_XMIT_ERROR:
  1566.  
  1567.         GenericULong = (UINT)(Adapter->FramesXmitBad);
  1568.         break;
  1569.  
  1570.     case OID_GEN_RCV_ERROR:
  1571.  
  1572.         GenericULong = (UINT)(Adapter->CrcErrors);
  1573.         break;
  1574.  
  1575.     case OID_GEN_RCV_NO_BUFFER:
  1576.  
  1577.         GenericULong = (UINT)(Adapter->MissedPackets);
  1578.         break;
  1579.  
  1580.     case OID_802_3_RCV_ERROR_ALIGNMENT:
  1581.  
  1582.         GenericULong = (UINT)(Adapter->FrameAlignmentErrors);
  1583.         break;
  1584.  
  1585.     case OID_802_3_XMIT_ONE_COLLISION:
  1586.  
  1587.         GenericULong = (UINT)(Adapter->FramesXmitOneCollision);
  1588.         break;
  1589.  
  1590.     case OID_802_3_XMIT_MORE_COLLISIONS:
  1591.  
  1592.         GenericULong = (UINT)(Adapter->FramesXmitManyCollisions);
  1593.         break;
  1594.  
  1595.     default:
  1596.  
  1597.         StatusToReturn = NDIS_STATUS_INVALID_OID;
  1598.         break;
  1599.  
  1600.     }
  1601.  
  1602.  
  1603.     if (StatusToReturn == NDIS_STATUS_SUCCESS) {
  1604.  
  1605.         if (MoveBytes > BytesLeft) {
  1606.  
  1607.             //
  1608.             // Not enough room in InformationBuffer. Punt
  1609.             //
  1610.  
  1611.             *BytesNeeded = MoveBytes;
  1612.  
  1613.             StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1614.  
  1615.         } else {
  1616.  
  1617.             //
  1618.             // Store result.
  1619.             //
  1620.  
  1621.             UM9008_MOVE_MEM(InfoBuffer, MoveSource, MoveBytes);
  1622.  
  1623.             (*BytesWritten) += MoveBytes;
  1624.  
  1625.         }
  1626.     }
  1627.  
  1628.     return StatusToReturn;
  1629. }
  1630.  
  1631. extern
  1632. NDIS_STATUS
  1633. UM9008SetInformation(
  1634.     IN NDIS_HANDLE MiniportAdapterContext,
  1635.     IN NDIS_OID Oid,
  1636.     IN PVOID InformationBuffer,
  1637.     IN ULONG InformationBufferLength,
  1638.     OUT PULONG BytesRead,
  1639.     OUT PULONG BytesNeeded
  1640.     )
  1641.  
  1642. /*++
  1643.  
  1644. Routine Description:
  1645.  
  1646.     UM9008SetInformation handles a set operation for a
  1647.     single OID.
  1648.  
  1649. Arguments:
  1650.  
  1651.     MiniportAdapterContext - Context registered with the wrapper, really
  1652.         a pointer to the adapter.
  1653.  
  1654.     Oid - The OID of the set.
  1655.  
  1656.     InformationBuffer - Holds the data to be set.
  1657.  
  1658.     InformationBufferLength - The length of InformationBuffer.
  1659.  
  1660.     BytesRead - If the call is successful, returns the number
  1661.         of bytes read from InformationBuffer.
  1662.  
  1663.     BytesNeeded - If there is not enough data in InformationBuffer
  1664.         to satisfy the OID, returns the amount of storage needed.
  1665.  
  1666. Return Value:
  1667.  
  1668.     NDIS_STATUS_SUCCESS
  1669.     NDIS_STATUS_PENDING
  1670.     NDIS_STATUS_INVALID_LENGTH
  1671.     NDIS_STATUS_INVALID_OID
  1672.  
  1673. --*/
  1674. {
  1675.     //
  1676.     // Pointer to the adapter structure.
  1677.     //
  1678.     PUM9008_ADAPTER Adapter = (PUM9008_ADAPTER)MiniportAdapterContext;
  1679.  
  1680.     //
  1681.     // General Algorithm:
  1682.     //
  1683.     //     Verify length
  1684.     //     Switch(Request)
  1685.     //        Process Request
  1686.     //
  1687.  
  1688.     UINT BytesLeft = InformationBufferLength;
  1689.     PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1690.  
  1691.     //
  1692.     // Variables for a particular request
  1693.     //
  1694.     UINT OidLength;
  1695.  
  1696.     //
  1697.     // Variables for holding the new values to be used.
  1698.     //
  1699.     ULONG LookAhead;
  1700.     ULONG Filter;
  1701.  
  1702.     //
  1703.     // Status of the operation.
  1704.     //
  1705.     NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1706.  
  1707.  
  1708.     IF_LOUD( DbgPrint("In SetInfo\n");)
  1709.  
  1710.     //
  1711.     // Get Oid and Length of request
  1712.     //
  1713.     OidLength = BytesLeft;
  1714.  
  1715.     switch (Oid) {
  1716.  
  1717.     case OID_802_3_MULTICAST_LIST:
  1718.  
  1719.         //
  1720.         // Verify length
  1721.         //
  1722.         if ((OidLength % UM9008_LENGTH_OF_ADDRESS) != 0){
  1723.  
  1724.             StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1725.  
  1726.             *BytesRead = 0;
  1727.             *BytesNeeded = 0;
  1728.  
  1729.             break;
  1730.  
  1731.         }
  1732.  
  1733.         //
  1734.         // Set the new list on the adapter.
  1735.         //
  1736.         NdisMoveMemory(Adapter->Addresses, InfoBuffer, OidLength);
  1737.  
  1738.         //
  1739.         //  If we are currently receiving all multicast or
  1740.         //  we are promsicuous then we DO NOT call this, or
  1741.         //  it will reset thoes settings.
  1742.         //
  1743.         if
  1744.         (
  1745.             !(Adapter->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST |
  1746.                                        NDIS_PACKET_TYPE_PROMISCUOUS))
  1747.         )
  1748.         {
  1749.             StatusToReturn = DispatchSetMulticastAddressList(Adapter);
  1750.         }
  1751.         else
  1752.         {
  1753.             //
  1754.             //  Our list of multicast addresses is kept by the
  1755.             //  wrapper.
  1756.             //
  1757.             StatusToReturn = NDIS_STATUS_SUCCESS;
  1758.         }
  1759.  
  1760.         break;
  1761.  
  1762.     case OID_GEN_CURRENT_PACKET_FILTER:
  1763.  
  1764.         //
  1765.         // Verify length
  1766.         //
  1767.  
  1768.         if (OidLength != 4 ) {
  1769.  
  1770.             StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1771.  
  1772.             *BytesRead = 0;
  1773.             *BytesNeeded = 0;
  1774.  
  1775.             break;
  1776.  
  1777.         }
  1778.  
  1779.         UM9008_MOVE_MEM(&Filter, InfoBuffer, 4);
  1780.  
  1781.         //
  1782.         // Verify bits
  1783.         //
  1784.  
  1785.         if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
  1786.               NDIS_PACKET_TYPE_SMT |
  1787.               NDIS_PACKET_TYPE_MAC_FRAME |
  1788.               NDIS_PACKET_TYPE_FUNCTIONAL |
  1789.               NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
  1790.               NDIS_PACKET_TYPE_GROUP
  1791.              )) {
  1792.  
  1793.             StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  1794.  
  1795.             *BytesRead = 4;
  1796.             *BytesNeeded = 0;
  1797.  
  1798.             break;
  1799.  
  1800.         }
  1801.  
  1802.         //
  1803.         // Set the new value on the adapter.
  1804.         //
  1805.         Adapter->PacketFilter = Filter;
  1806.         StatusToReturn = DispatchSetPacketFilter(Adapter);
  1807.         break;
  1808.  
  1809.     case OID_GEN_CURRENT_LOOKAHEAD:
  1810.  
  1811.         //
  1812.         // Verify length
  1813.         //
  1814.  
  1815.         if (OidLength != 4) {
  1816.  
  1817.             StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1818.  
  1819.             *BytesRead = 0;
  1820.             *BytesNeeded = 0;
  1821.  
  1822.             break;
  1823.  
  1824.         }
  1825.  
  1826.         //
  1827.         // Store the new value.
  1828.         //
  1829.  
  1830.         UM9008_MOVE_MEM(&LookAhead, InfoBuffer, 4);
  1831.  
  1832.         if (LookAhead <= UM9008_MAX_LOOKAHEAD) {
  1833.             Adapter->MaxLookAhead = LookAhead;
  1834.         } else {
  1835.             StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  1836.         }
  1837.  
  1838.         break;
  1839.  
  1840.     default:
  1841.  
  1842.         StatusToReturn = NDIS_STATUS_INVALID_OID;
  1843.  
  1844.         *BytesRead = 0;
  1845.         *BytesNeeded = 0;
  1846.  
  1847.         break;
  1848.  
  1849.     }
  1850.  
  1851.  
  1852.     if (StatusToReturn == NDIS_STATUS_SUCCESS) {
  1853.  
  1854.         *BytesRead = BytesLeft;
  1855.         *BytesNeeded = 0;
  1856.  
  1857.     }
  1858.  
  1859.     return(StatusToReturn);
  1860. }
  1861.  
  1862. NDIS_STATUS
  1863. DispatchSetPacketFilter(
  1864.     IN PUM9008_ADAPTER Adapter
  1865.     )
  1866.  
  1867. /*++
  1868.  
  1869. Routine Description:
  1870.  
  1871.     Sets the appropriate bits in the adapter filters
  1872.     and modifies the card Receive Configuration Register if needed.
  1873.  
  1874. Arguments:
  1875.  
  1876.     Adapter - Pointer to the adapter block
  1877.  
  1878. Return Value:
  1879.  
  1880.     The final status (always NDIS_STATUS_SUCCESS).
  1881.  
  1882. Notes:
  1883.  
  1884.   - Note that to receive all multicast packets the multicast
  1885.     registers on the card must be filled with 1's. To be
  1886.     promiscuous that must be done as well as setting the
  1887.     promiscuous physical flag in the RCR. This must be done
  1888.     as long as ANY protocol bound to this adapter has their
  1889.     filter set accordingly.
  1890.  
  1891. --*/
  1892.  
  1893.  
  1894. {
  1895.     //
  1896.     // See what has to be put on the card.
  1897.     //
  1898.  
  1899.     if
  1900.     (
  1901.         Adapter->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST |
  1902.                                  NDIS_PACKET_TYPE_PROMISCUOUS)
  1903.     )
  1904.     {
  1905.         //
  1906.         // need "all multicast" now.
  1907.         //
  1908.         CardSetAllMulticast(Adapter);    // fills it with 1's
  1909.     }
  1910.     else
  1911.     {
  1912.         //
  1913.         // No longer need "all multicast".
  1914.         //
  1915.         DispatchSetMulticastAddressList(Adapter);
  1916.     }
  1917.  
  1918.     //
  1919.     // The multicast bit in the RCR should be on if ANY protocol wants
  1920.     // multicast/all multicast packets (or is promiscuous).
  1921.     //
  1922.     if
  1923.     (
  1924.         Adapter->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST |
  1925.                                  NDIS_PACKET_TYPE_MULTICAST |
  1926.                                  NDIS_PACKET_TYPE_PROMISCUOUS)
  1927.     )
  1928.     {
  1929.         Adapter->NicReceiveConfig |= RCR_MULTICAST;
  1930.     }
  1931.     else
  1932.     {
  1933.         Adapter->NicReceiveConfig &= ~RCR_MULTICAST;
  1934.     }
  1935.  
  1936.     //
  1937.     // The promiscuous physical bit in the RCR should be on if ANY
  1938.     // protocol wants to be promiscuous.
  1939.     //
  1940.     if (Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
  1941.     {
  1942.         Adapter->NicReceiveConfig |= RCR_ALL_PHYS;
  1943.     }
  1944.     else
  1945.     {
  1946.         Adapter->NicReceiveConfig &= ~RCR_ALL_PHYS;
  1947.     }
  1948.  
  1949.     //
  1950.     // The broadcast bit in the RCR should be on if ANY protocol wants
  1951.     // broadcast packets (or is promiscuous).
  1952.     //
  1953.     if
  1954.     (
  1955.         Adapter->PacketFilter & (NDIS_PACKET_TYPE_BROADCAST |
  1956.                                  NDIS_PACKET_TYPE_PROMISCUOUS)
  1957.     )
  1958.     {
  1959.         Adapter->NicReceiveConfig |= RCR_BROADCAST;
  1960.     }
  1961.     else
  1962.     {
  1963.         Adapter->NicReceiveConfig &= ~RCR_BROADCAST;
  1964.     }
  1965.  
  1966.     CardSetReceiveConfig(Adapter);
  1967.  
  1968.     return(NDIS_STATUS_SUCCESS);
  1969. }
  1970.  
  1971.  
  1972.  
  1973. NDIS_STATUS
  1974. DispatchSetMulticastAddressList(
  1975.     IN PUM9008_ADAPTER Adapter
  1976.     )
  1977.  
  1978. /*++
  1979.  
  1980. Routine Description:
  1981.  
  1982.     Sets the multicast list for this open
  1983.  
  1984. Arguments:
  1985.  
  1986.     Adapter - Pointer to the adapter block
  1987.  
  1988. Return Value:
  1989.  
  1990.     NDIS_STATUS_SUCESS
  1991.  
  1992. Implementation Note:
  1993.  
  1994.     When invoked, we are to make it so that the multicast list in the filter
  1995.     package becomes the multicast list for the adapter. To do this, we
  1996.     determine the required contents of the NIC multicast registers and
  1997.     update them.
  1998.  
  1999.  
  2000. --*/
  2001. {
  2002.     //
  2003.     // Update the local copy of the NIC multicast regs and copy them to the NIC
  2004.     //
  2005.     CardFillMulticastRegs(Adapter);
  2006.     CardCopyMulticastRegs(Adapter);
  2007.  
  2008.     return NDIS_STATUS_SUCCESS;
  2009. }
  2010.