Annotation of ntddk/src/network/sonic/sonic.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990-1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     sonic.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This is the main file for the National Semiconductor SONIC
        !            12:     Ethernet controller.  This driver conforms to the NDIS 3.0 interface.
        !            13: 
        !            14:     The overall structure and much of the code is taken from
        !            15:     the Lance NDIS driver by Tony Ercolano.
        !            16: 
        !            17: Author:
        !            18: 
        !            19:     Anthony V. Ercolano (Tonye) 20-Jul-1990
        !            20:     Adam Barr (adamba) 14-Nov-1990
        !            21: 
        !            22: Environment:
        !            23: 
        !            24:     Kernel Mode - Or whatever is the equivalent.
        !            25: 
        !            26: Revision History:
        !            27: 
        !            28: 
        !            29: --*/
        !            30: 
        !            31: #include <ndis.h>
        !            32: 
        !            33: 
        !            34: #include <efilter.h>
        !            35: #include <sonichrd.h>
        !            36: #include <sonicsft.h>
        !            37: 
        !            38: 
        !            39: 
        !            40: //
        !            41: // This variable is used to control debug output.
        !            42: //
        !            43: 
        !            44: #if DBG
        !            45: INT SonicDbg = 0;
        !            46: #endif
        !            47: 
        !            48: 
        !            49: STATIC
        !            50: VOID
        !            51: SonicShutdown(
        !            52:     IN PVOID ShutdownContext
        !            53:     );
        !            54: 
        !            55: STATIC
        !            56: NDIS_STATUS
        !            57: SonicOpenAdapter(
        !            58:     OUT PNDIS_STATUS OpenErrorStatus,
        !            59:     OUT NDIS_HANDLE *MacBindingHandle,
        !            60:     OUT PUINT SelectedMediumIndex,
        !            61:     IN PNDIS_MEDIUM MediumArray,
        !            62:     IN UINT MediumArraySize,
        !            63:     IN NDIS_HANDLE NdisBindingContext,
        !            64:     IN NDIS_HANDLE MacAdapterContext,
        !            65:     IN UINT OpenOptions,
        !            66:     IN PSTRING AddressingInformation OPTIONAL
        !            67:     );
        !            68: 
        !            69: STATIC
        !            70: NDIS_STATUS
        !            71: SonicCloseAdapter(
        !            72:     IN NDIS_HANDLE MacBindingHandle
        !            73:     );
        !            74: 
        !            75: 
        !            76: STATIC
        !            77: VOID
        !            78: SonicUnload(
        !            79:     IN NDIS_HANDLE MacMacContext
        !            80:     );
        !            81: 
        !            82: STATIC
        !            83: NDIS_STATUS
        !            84: SonicAddAdapter(
        !            85:     IN NDIS_HANDLE MacMacContext,
        !            86:     IN NDIS_HANDLE ConfigurationHandle,
        !            87:     IN PNDIS_STRING AdapterName
        !            88:     );
        !            89: 
        !            90: STATIC
        !            91: VOID
        !            92: SonicRemoveAdapter(
        !            93:     IN NDIS_HANDLE MacAdapterContext
        !            94:     );
        !            95: 
        !            96: STATIC
        !            97: NDIS_STATUS
        !            98: SonicReset(
        !            99:     IN NDIS_HANDLE MacBindingHandle
        !           100:     );
        !           101: 
        !           102: #if 0
        !           103: STATIC
        !           104: UINT
        !           105: CalculateCRC(
        !           106:     IN UINT NumberOfBytes,
        !           107:     IN PCHAR Input
        !           108:     );
        !           109: #endif
        !           110: 
        !           111: STATIC
        !           112: BOOLEAN
        !           113: SonicSynchClearIsr(
        !           114:     IN PVOID Context
        !           115:     );
        !           116: 
        !           117: STATIC
        !           118: VOID
        !           119: SonicStopChip(
        !           120:     IN PSONIC_ADAPTER Adapter
        !           121:     );
        !           122: 
        !           123: STATIC
        !           124: BOOLEAN
        !           125: SetupRegistersAndInit(
        !           126:     IN PSONIC_ADAPTER Adapter
        !           127:     );
        !           128: 
        !           129: STATIC
        !           130: BOOLEAN
        !           131: SonicInitialInit(
        !           132:     IN PSONIC_ADAPTER Adapter
        !           133:     );
        !           134: 
        !           135: #ifdef NDIS_NT
        !           136: 
        !           137: NTSTATUS
        !           138: DriverEntry(
        !           139:     IN PDRIVER_OBJECT DriverObject,
        !           140:     IN PUNICODE_STRING RegistryPath
        !           141:     );
        !           142: 
        !           143: #else
        !           144: 
        !           145: NDIS_STATUS
        !           146: DriverEntry(
        !           147:     VOID
        !           148:     );
        !           149: 
        !           150: #endif
        !           151: 
        !           152: STATIC
        !           153: NDIS_STATUS
        !           154: SonicRegisterAdapter(
        !           155:     IN NDIS_HANDLE NdisMacHandle,
        !           156:     IN NDIS_HANDLE ConfigurationHandle,
        !           157:     IN PNDIS_STRING DeviceName,
        !           158:     IN PUCHAR NetworkAddress,
        !           159:     IN UCHAR AdapterType,
        !           160:     IN UINT SlotNumber,
        !           161:     IN UINT Controller,
        !           162:     IN UINT MultifunctionAdapter,
        !           163:     IN UINT SonicInterruptVector,
        !           164:     IN UINT SonicInterruptLevel,
        !           165:     IN NDIS_INTERRUPT_MODE SonicInterruptMode,
        !           166:     IN UINT MaximumOpenAdapters
        !           167:     );
        !           168: 
        !           169: typedef enum {
        !           170:     SonicHardwareOk,
        !           171:     SonicHardwareChecksum,
        !           172:     SonicHardwareConfig
        !           173: } SONIC_HARDWARE_STATUS;
        !           174: 
        !           175: STATIC
        !           176: SONIC_HARDWARE_STATUS
        !           177: SonicHardwareGetDetails(
        !           178:     IN PSONIC_ADAPTER Adapter,
        !           179:     IN UINT SlotNumber,
        !           180:     IN UINT Controller,
        !           181:     IN UINT MultifunctionAdapter,
        !           182:     OUT PULONG InitialPort,
        !           183:     OUT PULONG NumberOfPorts,
        !           184:     IN OUT PUINT InterruptVector,
        !           185:     IN OUT PUINT InterruptLevel,
        !           186:     OUT ULONG ErrorLogData[3]
        !           187:     );
        !           188: 
        !           189: STATIC
        !           190: BOOLEAN
        !           191: SonicHardwareGetAddress(
        !           192:     IN PSONIC_ADAPTER Adapter,
        !           193:     OUT ULONG ErrorLogData[3]
        !           194:     );
        !           195: 
        !           196: #ifdef SONIC_INTERNAL
        !           197: 
        !           198: //
        !           199: // These routines are support reading the address for the
        !           200: // sonic internal implementation on the R4000 motherboards.
        !           201: //
        !           202: 
        !           203: STATIC
        !           204: NTSTATUS
        !           205: SonicHardwareSaveInformation(
        !           206:     IN PWSTR ValueName,
        !           207:     IN ULONG ValueType,
        !           208:     IN PVOID ValueData,
        !           209:     IN ULONG ValueLength,
        !           210:     IN PVOID Context,
        !           211:     IN PVOID EntryContext
        !           212:     );
        !           213: 
        !           214: STATIC
        !           215: BOOLEAN
        !           216: SonicHardwareVerifyChecksum(
        !           217:     IN PSONIC_ADAPTER Adapter,
        !           218:     IN PUCHAR EthernetAddress,
        !           219:     OUT ULONG ErrorLogData[3]
        !           220:     );
        !           221: 
        !           222: #endif
        !           223: 
        !           224: 
        !           225: //
        !           226: // Use the alloc_text pragma to specify the driver initialization routines
        !           227: // (they can be paged out).
        !           228: //
        !           229: 
        !           230: #ifdef ALLOC_PRAGMA
        !           231: #pragma alloc_text(init,DriverEntry)
        !           232: #pragma alloc_text(init,SonicRegisterAdapter)
        !           233: #pragma alloc_text(init,SonicInitialInit)
        !           234: #pragma alloc_text(init,SonicAddAdapter)
        !           235: #pragma alloc_text(init,SonicHardwareGetDetails)
        !           236: #pragma alloc_text(init,SonicHardwareGetAddress)
        !           237: #ifdef SONIC_INTERNAL
        !           238: #pragma alloc_text(init,SonicHardwareSaveInformation)
        !           239: #pragma alloc_text(init,SonicHardwareVerifyChecksum)
        !           240: #endif
        !           241: #endif
        !           242: 
        !           243: 
        !           244: 
        !           245: NTSTATUS
        !           246: DriverEntry(
        !           247:     IN PDRIVER_OBJECT DriverObject,
        !           248:     IN PUNICODE_STRING RegistryPath
        !           249:     )
        !           250: 
        !           251: /*++
        !           252: 
        !           253: Routine Description:
        !           254: 
        !           255:     This is the primary initialization routine for the sonic driver.
        !           256:     It is simply responsible for the intializing the wrapper and registering
        !           257:     the MAC.  It then calls a system and architecture specific routine that
        !           258:     will initialize and register each adapter.
        !           259: 
        !           260: Arguments:
        !           261: 
        !           262:     DriverObject - Pointer to driver object created by the system.
        !           263: 
        !           264: Return Value:
        !           265: 
        !           266:     The status of the operation.
        !           267: 
        !           268: --*/
        !           269: 
        !           270: {
        !           271: 
        !           272:     //
        !           273:     // Receives the status of the NdisRegisterMac operation.
        !           274:     //
        !           275:     NDIS_STATUS Status;
        !           276: 
        !           277:     PSONIC_MAC SonicMac;
        !           278: 
        !           279:     NDIS_HANDLE SonicWrapperHandle;
        !           280: 
        !           281:     static const NDIS_STRING MacName = NDIS_STRING_CONST("SONIC");
        !           282:     NDIS_MAC_CHARACTERISTICS SonicChar;
        !           283: 
        !           284: 
        !           285:     //
        !           286:     // Initialize the wrapper.
        !           287:     //
        !           288: 
        !           289:     NdisInitializeWrapper(
        !           290:                 &SonicWrapperHandle,
        !           291:                 DriverObject,
        !           292:                 RegistryPath,
        !           293:                 NULL
        !           294:                 );
        !           295: 
        !           296:     //
        !           297:     // Now allocate memory for our global structure.
        !           298:     //
        !           299: 
        !           300:     SONIC_ALLOC_MEMORY(&Status, &SonicMac, sizeof(SONIC_MAC));
        !           301: 
        !           302:     if (Status != NDIS_STATUS_SUCCESS) {
        !           303: 
        !           304:          return NDIS_STATUS_RESOURCES;
        !           305: 
        !           306:     }
        !           307: 
        !           308:     SonicMac->WrapperHandle = SonicWrapperHandle;
        !           309: 
        !           310:     //
        !           311:     // Initialize the MAC characteristics for the call to
        !           312:     // NdisRegisterMac.
        !           313:     //
        !           314: 
        !           315:     SonicChar.MajorNdisVersion = SONIC_NDIS_MAJOR_VERSION;
        !           316:     SonicChar.MinorNdisVersion = SONIC_NDIS_MINOR_VERSION;
        !           317:     SonicChar.OpenAdapterHandler = SonicOpenAdapter;
        !           318:     SonicChar.CloseAdapterHandler = SonicCloseAdapter;
        !           319:     SonicChar.SendHandler = SonicSend;
        !           320:     SonicChar.TransferDataHandler = SonicTransferData;
        !           321:     SonicChar.ResetHandler = SonicReset;
        !           322:     SonicChar.RequestHandler = SonicRequest;
        !           323:     SonicChar.QueryGlobalStatisticsHandler = SonicQueryGlobalStatistics;
        !           324:     SonicChar.UnloadMacHandler = SonicUnload;
        !           325:     SonicChar.AddAdapterHandler = SonicAddAdapter;
        !           326:     SonicChar.RemoveAdapterHandler = SonicRemoveAdapter;
        !           327:     SonicChar.Name = MacName;
        !           328: 
        !           329: 
        !           330:     NdisRegisterMac(
        !           331:         &Status,
        !           332:         &SonicMac->MacHandle,
        !           333:         SonicWrapperHandle,
        !           334:         (NDIS_HANDLE)SonicMac,                   // MacMacContext
        !           335:         &SonicChar,
        !           336:         sizeof(SonicChar)
        !           337:         );
        !           338: 
        !           339:     if (Status == NDIS_STATUS_SUCCESS) {
        !           340: 
        !           341:         return NDIS_STATUS_SUCCESS;
        !           342: 
        !           343:     }
        !           344: 
        !           345: 
        !           346:     //
        !           347:     // We can only get here if something went wrong with registering
        !           348:     // the mac or *all* of the adapters.
        !           349:     //
        !           350: 
        !           351:     NdisTerminateWrapper(SonicWrapperHandle, NULL);
        !           352: 
        !           353:     return NDIS_STATUS_FAILURE;
        !           354: 
        !           355: }
        !           356: 
        !           357: #if DBG
        !           358: //
        !           359: // Save this to retrieve it in the debugger.
        !           360: //
        !           361: 
        !           362: PVOID SonicAdapterAddress;
        !           363: #endif
        !           364: 
        !           365: 
        !           366: STATIC
        !           367: NDIS_STATUS
        !           368: SonicRegisterAdapter(
        !           369:     IN NDIS_HANDLE NdisMacHandle,
        !           370:     IN NDIS_HANDLE ConfigurationHandle,
        !           371:     IN PNDIS_STRING DeviceName,
        !           372:     IN PUCHAR NetworkAddress,
        !           373:     IN UCHAR AdapterType,
        !           374:     IN UINT SlotNumber,
        !           375:     IN UINT Controller,
        !           376:     IN UINT MultifunctionAdapter,
        !           377:     IN UINT SonicInterruptVector,
        !           378:     IN UINT SonicInterruptLevel,
        !           379:     IN NDIS_INTERRUPT_MODE SonicInterruptMode,
        !           380:     IN UINT MaximumOpenAdapters
        !           381:     )
        !           382: 
        !           383: /*++
        !           384: 
        !           385: Routine Description:
        !           386: 
        !           387:     This routine (and its interface) are not portable.  They are
        !           388:     defined by the OS, the architecture, and the particular SONIC
        !           389:     implementation.
        !           390: 
        !           391:     This routine is responsible for the allocation of the datastructures
        !           392:     for the driver as well as any hardware specific details necessary
        !           393:     to talk with the device.
        !           394: 
        !           395: Arguments:
        !           396: 
        !           397:     NdisMacHandle - The handle given back to the mac from ndis when
        !           398:     the mac registered itself.
        !           399: 
        !           400:     ConfigurationHandle - Config handle passed to MacAddAdapter.
        !           401: 
        !           402:     DeviceName - The string containing the name to give to the
        !           403:     device adapter.
        !           404: 
        !           405:     NetworkAddress - The network address, or NULL if the default
        !           406:     should be used.
        !           407: 
        !           408:     AdapterType - The type of the adapter; currently SONIC_ADAPTER_TYPE_EISA
        !           409:     and SONIC_ADAPTER_TYPE_INTERNAL are supported,
        !           410: 
        !           411:     SlotNumber - The slot number for the EISA card.
        !           412: 
        !           413:     Controller - The controller number for INTERNAL chips.
        !           414: 
        !           415:     MultifunctionAdapter - The INTERNAL bus number for INTERNAL chips.
        !           416: 
        !           417:     SonicInterruptVector - The interrupt vector to use for the adapter.
        !           418: 
        !           419:     SonicInterruptLevel - The interrupt request level to use for this
        !           420:     adapter.
        !           421: 
        !           422:     SonicInterruptMode - The interrupt mode to be use for this adapter.
        !           423: 
        !           424:     MaximumOpenAdapters - The maximum number of opens at any one time.
        !           425: 
        !           426: Return Value:
        !           427: 
        !           428:     Returns a failure status if anything occurred that prevents the
        !           429:     initialization of the adapter.
        !           430: 
        !           431: --*/
        !           432: 
        !           433: {
        !           434: 
        !           435:     //
        !           436:     // Pointer for the adapter root.
        !           437:     //
        !           438:     PSONIC_ADAPTER Adapter;
        !           439: 
        !           440:     //
        !           441:     // Status of various NDIS calls.
        !           442:     //
        !           443:     NDIS_STATUS Status;
        !           444: 
        !           445:     //
        !           446:     // Holds information needed when registering the adapter.
        !           447:     //
        !           448:     NDIS_ADAPTER_INFORMATION AdapterInformation;
        !           449: 
        !           450:     //
        !           451:     // Number of ports needed
        !           452:     //
        !           453:     ULONG InitialPort;
        !           454:     ULONG NumberOfPorts;
        !           455: 
        !           456:     //
        !           457:     // Returned from SonicHardwareGetDetails; if it failed,
        !           458:     // we log an error and exit.
        !           459:     //
        !           460:     SONIC_HARDWARE_STATUS HardwareDetailsStatus;
        !           461: 
        !           462:     //
        !           463:     // Used to store error log data from SonicHardwareGetDetails.
        !           464:     //
        !           465:     ULONG ErrorLogData[3];
        !           466: 
        !           467:     //
        !           468:     // We put in this assertion to make sure that ushort are 2 bytes.
        !           469:     // if they aren't then the initialization block definition needs
        !           470:     // to be changed.
        !           471:     //
        !           472:     // Also all of the logic that deals with status registers assumes
        !           473:     // that control registers are only 2 bytes.
        !           474:     //
        !           475: 
        !           476:     ASSERT(sizeof(USHORT) == 2);
        !           477: 
        !           478:     //
        !           479:     // The Sonic uses four bytes four physical addresses, so we
        !           480:     // must ensure that this is the case (SONIC_PHYSICAL_ADDRESS)
        !           481:     // is defined as a ULONG).
        !           482:     //
        !           483: 
        !           484:     ASSERT(sizeof(SONIC_PHYSICAL_ADDRESS) == 4);
        !           485: 
        !           486:     //
        !           487:     // Allocate the Adapter block.
        !           488:     //
        !           489: 
        !           490:     SONIC_ALLOC_MEMORY(&Status, &Adapter, sizeof(SONIC_ADAPTER));
        !           491: 
        !           492:     if (Status == NDIS_STATUS_SUCCESS) {
        !           493: #if DBG
        !           494:         SonicAdapterAddress = Adapter;
        !           495: #endif
        !           496: 
        !           497:         SONIC_ZERO_MEMORY(
        !           498:             Adapter,
        !           499:             sizeof(SONIC_ADAPTER)
        !           500:             );
        !           501: 
        !           502: 
        !           503:         Adapter->AdapterType = AdapterType;
        !           504:         if (SonicInterruptMode == NdisInterruptLatched) {
        !           505:             Adapter->InterruptLatched = TRUE;
        !           506:         }
        !           507:         Adapter->PermanentAddressValid = FALSE;
        !           508: 
        !           509:         //
        !           510:         // Set up the AdapterInformation structure; zero it out
        !           511:         // first using sizeof (in case any fields are added).
        !           512:         //
        !           513: 
        !           514:         SONIC_ZERO_MEMORY (&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
        !           515:         AdapterInformation.DmaChannel = 0;
        !           516:         AdapterInformation.Master = TRUE;
        !           517:         AdapterInformation.PhysicalMapRegistersNeeded =
        !           518:             SONIC_MAX_FRAGMENTS * SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
        !           519:         AdapterInformation.MaximumPhysicalMapping =
        !           520:                              SONIC_LARGE_BUFFER_SIZE;
        !           521: 
        !           522:         //
        !           523:         // This returns the I/O ports used by the Sonic and may
        !           524:         // modify SonicInterruptVector and SonicInterruptLevel,
        !           525:         // as well as modiying some fields in Adapter.
        !           526:         //
        !           527: 
        !           528:         if ((HardwareDetailsStatus =
        !           529:               SonicHardwareGetDetails(
        !           530:                  Adapter,
        !           531:                  SlotNumber,
        !           532:                  Controller,
        !           533:                  MultifunctionAdapter,
        !           534:                  &InitialPort,
        !           535:                  &NumberOfPorts,
        !           536:                  &SonicInterruptVector,
        !           537:                  &SonicInterruptLevel,
        !           538:                  ErrorLogData)) != SonicHardwareOk) {
        !           539: 
        !           540:             //
        !           541:             // If it fails, we call NdisRegisterAdapter anyway
        !           542:             // (so we can log an error using the NdisAdapterHandle),
        !           543:             // then return failure.
        !           544:             //
        !           545: 
        !           546:             AdapterInformation.NumberOfPortDescriptors = 0;
        !           547: 
        !           548:         } else {
        !           549: 
        !           550:             AdapterInformation.NumberOfPortDescriptors = 1;
        !           551:             AdapterInformation.PortDescriptors[0].InitialPort = InitialPort;
        !           552:             AdapterInformation.PortDescriptors[0].NumberOfPorts = NumberOfPorts;
        !           553:             AdapterInformation.PortDescriptors[0].PortOffset = (PVOID *)(&(Adapter->SonicPortAddress));
        !           554: 
        !           555:         }
        !           556: 
        !           557:         if (AdapterType == SONIC_ADAPTER_TYPE_EISA) {
        !           558:             AdapterInformation.AdapterType = NdisInterfaceEisa;
        !           559:         } else {
        !           560:             AdapterInformation.AdapterType = NdisInterfaceInternal;
        !           561:         }
        !           562: 
        !           563:         //
        !           564:         // Register the adapter with NDIS.
        !           565:         //
        !           566: 
        !           567:         if ((Status = NdisRegisterAdapter(
        !           568:                 &Adapter->NdisAdapterHandle,
        !           569:                 NdisMacHandle,
        !           570:                 Adapter,
        !           571:                 ConfigurationHandle,
        !           572:                 DeviceName,
        !           573:                 &AdapterInformation
        !           574:                 )) == NDIS_STATUS_SUCCESS) {
        !           575: 
        !           576:             if (HardwareDetailsStatus != SonicHardwareOk) {
        !           577: 
        !           578:                 //
        !           579:                 // Log an error and exit.
        !           580:                 //
        !           581: 
        !           582:                 if (HardwareDetailsStatus == SonicHardwareChecksum) {
        !           583: 
        !           584:                     NdisWriteErrorLogEntry(
        !           585:                         Adapter->NdisAdapterHandle,
        !           586:                         NDIS_ERROR_CODE_NETWORK_ADDRESS,
        !           587:                         6,
        !           588:                         hardwareDetails,
        !           589:                         SONIC_ERRMSG_HARDWARE_ADDRESS,
        !           590:                         NDIS_STATUS_FAILURE,
        !           591:                         ErrorLogData[0],
        !           592:                         ErrorLogData[1],
        !           593:                         ErrorLogData[2]
        !           594:                         );
        !           595: 
        !           596:                 } else {
        !           597: 
        !           598:                     NdisWriteErrorLogEntry(
        !           599:                         Adapter->NdisAdapterHandle,
        !           600:                         NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
        !           601:                         0
        !           602:                         );
        !           603: 
        !           604:                 }
        !           605: 
        !           606:                 NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           607:                 SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           608:                 return NDIS_STATUS_FAILURE;
        !           609: 
        !           610:             }
        !           611: 
        !           612: 
        !           613:             //
        !           614:             // Allocate memory for all of the adapter structures.
        !           615:             //
        !           616: 
        !           617:             Adapter->NumberOfTransmitDescriptors =
        !           618:                                 SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
        !           619:             Adapter->NumberOfReceiveBuffers =
        !           620:                                 SONIC_NUMBER_OF_RECEIVE_BUFFERS;
        !           621:             Adapter->NumberOfReceiveDescriptors =
        !           622:                                 SONIC_NUMBER_OF_RECEIVE_DESCRIPTORS;
        !           623: 
        !           624: 
        !           625:             if (AllocateAdapterMemory(Adapter)) {
        !           626: 
        !           627:                 //
        !           628:                 // Get the network address. This writes
        !           629:                 // an error log entry if it fails. This routine
        !           630:                 // may do nothing on some systems, if
        !           631:                 // SonicHardwareGetDetails has already determined
        !           632:                 // the network address.
        !           633:                 //
        !           634: 
        !           635:                 if (!SonicHardwareGetAddress(Adapter, ErrorLogData)) {
        !           636: 
        !           637:                     NdisWriteErrorLogEntry(
        !           638:                         Adapter->NdisAdapterHandle,
        !           639:                         NDIS_ERROR_CODE_NETWORK_ADDRESS,
        !           640:                         6,
        !           641:                         hardwareDetails,
        !           642:                         SONIC_ERRMSG_HARDWARE_ADDRESS,
        !           643:                         NDIS_STATUS_FAILURE,
        !           644:                         ErrorLogData[0],
        !           645:                         ErrorLogData[1],
        !           646:                         ErrorLogData[2]
        !           647:                         );
        !           648: 
        !           649:                     DeleteAdapterMemory(Adapter);
        !           650:                     NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           651:                     SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           652:                     return NDIS_STATUS_FAILURE;
        !           653: 
        !           654:                 }
        !           655: 
        !           656:                 //
        !           657:                 // Initialize the current hardware address.
        !           658:                 //
        !           659: 
        !           660:                 SONIC_MOVE_MEMORY(
        !           661:                     Adapter->CurrentNetworkAddress,
        !           662:                     (NetworkAddress != NULL) ?
        !           663:                         NetworkAddress :
        !           664:                         Adapter->PermanentNetworkAddress,
        !           665:                     ETH_LENGTH_OF_ADDRESS);
        !           666: 
        !           667: 
        !           668:                 InitializeListHead(&Adapter->OpenBindings);
        !           669:                 Adapter->OpenCount = 0;
        !           670:                 Adapter->Removed = FALSE;
        !           671:                 InitializeListHead(&Adapter->CloseList);
        !           672:                 NdisAllocateSpinLock(&Adapter->Lock);
        !           673: 
        !           674: 
        !           675:                 Adapter->LastTransmitDescriptor =
        !           676:                             Adapter->TransmitDescriptorArea +
        !           677:                             (Adapter->NumberOfTransmitDescriptors-1);
        !           678:                 Adapter->NumberOfAvailableDescriptors =
        !           679:                             Adapter->NumberOfTransmitDescriptors;
        !           680:                 Adapter->AllocateableDescriptor =
        !           681:                             Adapter->TransmitDescriptorArea;
        !           682:                 Adapter->TransmittingDescriptor =
        !           683:                             Adapter->TransmitDescriptorArea;
        !           684:                 Adapter->FirstUncommittedDescriptor =
        !           685:                             Adapter->TransmitDescriptorArea;
        !           686:                 Adapter->PacketsSinceLastInterrupt = 0;
        !           687: 
        !           688:                 Adapter->CurrentReceiveBufferIndex = 0;
        !           689:                 Adapter->CurrentReceiveDescriptorIndex = 0;
        !           690:                 Adapter->LastReceiveDescriptor =
        !           691:                             &Adapter->ReceiveDescriptorArea[
        !           692:                                 Adapter->NumberOfReceiveDescriptors-1];
        !           693: 
        !           694:                 Adapter->InterruptMaskRegister = SONIC_INT_DEFAULT_VALUE;
        !           695:                 Adapter->ReceiveDescriptorsExhausted = FALSE;
        !           696:                 Adapter->ReceiveBuffersExhausted = FALSE;
        !           697:                 Adapter->ReceiveControlRegister = SONIC_RCR_DEFAULT_VALUE;
        !           698: 
        !           699:                 Adapter->ProcessingReceiveInterrupt = FALSE;
        !           700:                 Adapter->ProcessingGeneralInterrupt = FALSE;
        !           701:                 Adapter->ProcessingDeferredOperations = FALSE;
        !           702:                 Adapter->FirstLoopBack = NULL;
        !           703:                 Adapter->LastLoopBack = NULL;
        !           704:                 Adapter->FirstFinishTransmit = NULL;
        !           705:                 Adapter->LastFinishTransmit = NULL;
        !           706:                 Adapter->SendStageOpen = TRUE;
        !           707:                 Adapter->AlreadyProcessingSendStage = FALSE;
        !           708:                 Adapter->FirstSendStagePacket = NULL;
        !           709:                 Adapter->LastSendStagePacket = NULL;
        !           710: 
        !           711:                 Adapter->References = 1;
        !           712: 
        !           713:                 Adapter->ResetInProgress = FALSE;
        !           714:                 Adapter->IndicatingResetStart = FALSE;
        !           715:                 Adapter->IndicatingResetEnd = FALSE;
        !           716:                 Adapter->ResettingOpen = NULL;
        !           717:                 Adapter->FirstInitialization = TRUE;
        !           718: 
        !           719:                 SONIC_ZERO_MEMORY (&Adapter->GeneralMandatory, GM_ARRAY_SIZE * sizeof(ULONG));
        !           720:                 SONIC_ZERO_MEMORY (&Adapter->GeneralOptionalByteCount, GO_COUNT_ARRAY_SIZE * sizeof(SONIC_LARGE_INTEGER));
        !           721:                 SONIC_ZERO_MEMORY (&Adapter->GeneralOptionalFrameCount, GO_COUNT_ARRAY_SIZE * sizeof(ULONG));
        !           722:                 SONIC_ZERO_MEMORY (&Adapter->GeneralOptional, (GO_ARRAY_SIZE - GO_ARRAY_START) * sizeof(ULONG));
        !           723:                 SONIC_ZERO_MEMORY (&Adapter->MediaMandatory, MM_ARRAY_SIZE * sizeof(ULONG));
        !           724:                 SONIC_ZERO_MEMORY (&Adapter->MediaOptional, MO_ARRAY_SIZE * sizeof(ULONG));
        !           725: 
        !           726:                 //
        !           727:                 // Initialize the CAM and associated things.
        !           728:                 // At the beginning nothing is enabled since
        !           729:                 // our filter is 0, although we do store
        !           730:                 // our network address in the first slot.
        !           731:                 //
        !           732: 
        !           733:                 Adapter->MulticastCamEnableBits = 0x0000;
        !           734:                 Adapter->CurrentPacketFilter = 0;
        !           735:                 Adapter->CamDescriptorArea->CamEnable = 0x0000;
        !           736:                 Adapter->CamDescriptorsUsed = 0x0001;
        !           737:                 Adapter->CamDescriptorAreaSize = 1;
        !           738: 
        !           739:                 NdisInitializeTimer(
        !           740:                     &Adapter->DeferredTimer,
        !           741:                     SonicTimerProcess,
        !           742:                     (PVOID)Adapter);
        !           743: 
        !           744:                 SONIC_LOAD_CAM_FRAGMENT(
        !           745:                     &Adapter->CamDescriptorArea->CamFragments[0],
        !           746:                     0,
        !           747:                     Adapter->CurrentNetworkAddress
        !           748:                     );
        !           749: 
        !           750: 
        !           751:                 if (!EthCreateFilter(
        !           752:                          SONIC_CAM_ENTRIES-1,    // maximum MC addresses
        !           753:                          SonicChangeAddresses,
        !           754:                          SonicChangeClass,
        !           755:                          SonicCloseAction,
        !           756:                          Adapter->CurrentNetworkAddress,
        !           757:                          &Adapter->Lock,
        !           758:                          &Adapter->FilterDB
        !           759:                          )) {
        !           760: 
        !           761:                     NdisWriteErrorLogEntry(
        !           762:                         Adapter->NdisAdapterHandle,
        !           763:                         NDIS_ERROR_CODE_OUT_OF_RESOURCES,
        !           764:                         2,
        !           765:                         registerAdapter,
        !           766:                         SONIC_ERRMSG_CREATE_FILTER
        !           767:                         );
        !           768: 
        !           769:                     DeleteAdapterMemory(Adapter);
        !           770:                     NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           771:                     NdisFreeSpinLock(&Adapter->Lock);
        !           772:                     SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           773:                     return NDIS_STATUS_RESOURCES;
        !           774: 
        !           775:                 } else {
        !           776: 
        !           777:                     //
        !           778:                     // Initialize the interrupt.
        !           779:                     //
        !           780: 
        !           781:                     NdisInitializeInterrupt(
        !           782:                         &Status,
        !           783:                         &Adapter->Interrupt,
        !           784:                         Adapter->NdisAdapterHandle,
        !           785:                         SonicInterruptService,
        !           786:                         Adapter,
        !           787:                         SonicDeferredProcessing,
        !           788:                         SonicInterruptVector,
        !           789:                         SonicInterruptLevel,
        !           790:                         TRUE,
        !           791:                         SonicInterruptMode
        !           792:                         );
        !           793: 
        !           794: 
        !           795:                     if (Status != NDIS_STATUS_SUCCESS) {
        !           796: 
        !           797:                         NdisWriteErrorLogEntry(
        !           798:                             Adapter->NdisAdapterHandle,
        !           799:                             NDIS_ERROR_CODE_INTERRUPT_CONNECT,
        !           800:                             2,
        !           801:                             registerAdapter,
        !           802:                             SONIC_ERRMSG_INIT_INTERRUPT
        !           803:                             );
        !           804: 
        !           805:                         EthDeleteFilter(Adapter->FilterDB);
        !           806:                         DeleteAdapterMemory(Adapter);
        !           807:                         NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           808:                         NdisFreeSpinLock(&Adapter->Lock);
        !           809:                         SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           810:                         return Status;
        !           811: 
        !           812:                     }
        !           813: 
        !           814:                     //
        !           815:                     // Start the card up. This writes an error
        !           816:                     // log entry if it fails.
        !           817:                     //
        !           818: 
        !           819:                     if (!SonicInitialInit(Adapter)) {
        !           820: 
        !           821:                         NdisRemoveInterrupt(&Adapter->Interrupt);
        !           822:                         EthDeleteFilter(Adapter->FilterDB);
        !           823:                         DeleteAdapterMemory(Adapter);
        !           824:                         NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           825:                         NdisFreeSpinLock(&Adapter->Lock);
        !           826:                         SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           827:                         return NDIS_STATUS_FAILURE;
        !           828: 
        !           829:                     } else {
        !           830: 
        !           831:                         //
        !           832:                         // Initialize the wake up timer to catch interrupts that
        !           833:                         // don't complete. It fires continuously
        !           834:                         // every 5 seconds, and we check if there are any
        !           835:                         // uncompleted operations from the previous 5 second
        !           836:                         // period.
        !           837:                         //
        !           838: 
        !           839:                         Adapter->WakeUpDpc = (PVOID)SonicWakeUpDpc;
        !           840: 
        !           841:                         NdisInitializeTimer(&Adapter->WakeUpTimer,
        !           842:                                             (PVOID)(Adapter->WakeUpDpc),
        !           843:                                             Adapter );
        !           844: 
        !           845:                         NdisSetTimer(
        !           846:                             &Adapter->WakeUpTimer,
        !           847:                             5000
        !           848:                             );
        !           849: 
        !           850:                         NdisRegisterAdapterShutdownHandler(
        !           851:                             Adapter->NdisAdapterHandle,
        !           852:                             (PVOID)Adapter,
        !           853:                             SonicShutdown
        !           854:                             );
        !           855: 
        !           856:                         return NDIS_STATUS_SUCCESS;
        !           857: 
        !           858:                     }
        !           859: 
        !           860:                 }
        !           861: 
        !           862: 
        !           863:             } else {
        !           864: 
        !           865:                 //
        !           866:                 // Call to AllocateAdapterMemory failed.
        !           867:                 //
        !           868: 
        !           869:                 NdisWriteErrorLogEntry(
        !           870:                     Adapter->NdisAdapterHandle,
        !           871:                     NDIS_ERROR_CODE_OUT_OF_RESOURCES,
        !           872:                     2,
        !           873:                     registerAdapter,
        !           874:                     SONIC_ERRMSG_ALLOC_MEMORY
        !           875:                     );
        !           876: 
        !           877:                 DeleteAdapterMemory(Adapter);
        !           878:                 NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !           879:                 SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           880:                 return NDIS_STATUS_RESOURCES;
        !           881: 
        !           882:             }
        !           883: 
        !           884:         } else {
        !           885: 
        !           886:             //
        !           887:             // Call to NdisRegisterAdapter failed.
        !           888:             //
        !           889: 
        !           890:             SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !           891:             return Status;
        !           892: 
        !           893:         }
        !           894: 
        !           895:     } else {
        !           896: 
        !           897:         //
        !           898:         // Couldn't allocate adapter object.
        !           899:         //
        !           900: 
        !           901:         return Status;
        !           902: 
        !           903:     }
        !           904: 
        !           905: }
        !           906: 
        !           907: extern
        !           908: BOOLEAN
        !           909: SonicInitialInit(
        !           910:     IN PSONIC_ADAPTER Adapter
        !           911:     )
        !           912: 
        !           913: /*++
        !           914: 
        !           915: Routine Description:
        !           916: 
        !           917:     This routine sets up the initial init of the driver.
        !           918: 
        !           919: Arguments:
        !           920: 
        !           921:     Adapter - The adapter for the hardware.
        !           922: 
        !           923: Return Value:
        !           924: 
        !           925:     None.
        !           926: 
        !           927: --*/
        !           928: 
        !           929: {
        !           930: 
        !           931:     UINT Time = 50;
        !           932: 
        !           933:     //
        !           934:     // First we make sure that the device is stopped.
        !           935:     //
        !           936: 
        !           937:     SonicStopChip(Adapter);
        !           938: 
        !           939:     //
        !           940:     // Set up the registers.
        !           941:     //
        !           942: 
        !           943:     if (!SetupRegistersAndInit(Adapter)) {
        !           944: 
        !           945:         NdisWriteErrorLogEntry(
        !           946:             Adapter->NdisAdapterHandle,
        !           947:             NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
        !           948:             3,
        !           949:             registerAdapter,
        !           950:             SONIC_ERRMSG_INITIAL_INIT
        !           951:             );
        !           952: 
        !           953:         return FALSE;
        !           954: 
        !           955:     }
        !           956: 
        !           957: 
        !           958:     //
        !           959:     // Delay execution for 1/2 second to give the sonic
        !           960:     // time to initialize.
        !           961:     //
        !           962: 
        !           963:     while (Time > 0) {
        !           964: 
        !           965:         if (!Adapter->FirstInitialization) {
        !           966:             break;
        !           967:         }
        !           968: 
        !           969:         NdisStallExecution(10000);
        !           970:         Time--;
        !           971: 
        !           972:     }
        !           973: 
        !           974: 
        !           975:     //
        !           976:     // The only way that first initialization could have
        !           977:     // been turned off is if we actually initialized.
        !           978:     //
        !           979: 
        !           980:     if (!Adapter->FirstInitialization) {
        !           981: 
        !           982:         //
        !           983:         // We actually did get the initialization.
        !           984:         //
        !           985:         // We can start the chip.  We may not
        !           986:         // have any bindings to indicate to but this
        !           987:         // is unimportant.
        !           988:         //
        !           989: 
        !           990:         SonicStartChip(Adapter);
        !           991: 
        !           992:         return TRUE;
        !           993: 
        !           994: 
        !           995:     } else {
        !           996: 
        !           997:         NdisWriteErrorLogEntry(
        !           998:             Adapter->NdisAdapterHandle,
        !           999:             NDIS_ERROR_CODE_TIMEOUT,
        !          1000:             2,
        !          1001:             registerAdapter,
        !          1002:             SONIC_ERRMSG_INITIAL_INIT
        !          1003:             );
        !          1004: 
        !          1005:         return FALSE;
        !          1006: 
        !          1007:     }
        !          1008: 
        !          1009: }
        !          1010: 
        !          1011: STATIC
        !          1012: BOOLEAN
        !          1013: SonicSynchClearIsr(
        !          1014:     IN PVOID Context
        !          1015:     )
        !          1016: 
        !          1017: /*++
        !          1018: 
        !          1019: Routine Description:
        !          1020: 
        !          1021:     This routine is used during a reset. It ensures that no
        !          1022:     interrupts will come through, and that any DPRs that run
        !          1023:     will find no interrupts to process.
        !          1024: 
        !          1025: Arguments:
        !          1026: 
        !          1027:     Context - A pointer to a SONIC_ADAPTER structure.
        !          1028: 
        !          1029: Return Value:
        !          1030: 
        !          1031:     Always returns true.
        !          1032: 
        !          1033: --*/
        !          1034: 
        !          1035: {
        !          1036: 
        !          1037:     PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)Context;
        !          1038: 
        !          1039:     SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_STATUS, 0xffff);
        !          1040:     Adapter->IsrValue = 0;
        !          1041: 
        !          1042:     return TRUE;
        !          1043: 
        !          1044: }
        !          1045: 
        !          1046: extern
        !          1047: VOID
        !          1048: SonicStartChip(
        !          1049:     IN PSONIC_ADAPTER Adapter
        !          1050:     )
        !          1051: 
        !          1052: /*++
        !          1053: 
        !          1054: Routine Description:
        !          1055: 
        !          1056:     This routine is used to start an already initialized sonic.
        !          1057: 
        !          1058: Arguments:
        !          1059: 
        !          1060:     Adapter - The adapter for the SONIC to start.
        !          1061: 
        !          1062: Return Value:
        !          1063: 
        !          1064:     None.
        !          1065: 
        !          1066: --*/
        !          1067: 
        !          1068: {
        !          1069: 
        !          1070:     //
        !          1071:     // Take us out of reset mode if we are in it.
        !          1072:     //
        !          1073: 
        !          1074:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          1075:         0x0000
        !          1076:         );
        !          1077: 
        !          1078:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          1079:         SONIC_CR_RECEIVER_ENABLE
        !          1080:         );
        !          1081: 
        !          1082: }
        !          1083: 
        !          1084: STATIC
        !          1085: VOID
        !          1086: SonicStopChip(
        !          1087:     IN PSONIC_ADAPTER Adapter
        !          1088:     )
        !          1089: 
        !          1090: /*++
        !          1091: 
        !          1092: Routine Description:
        !          1093: 
        !          1094:     This routine is used to stop a sonic.
        !          1095: 
        !          1096:     This routine is *not* portable.  It is specific to the 386
        !          1097:     implementation of the sonic.  On the bus master card the ACON bit
        !          1098:     must be set in csr3, whereas on the decstation, csr3 remains clear.
        !          1099: 
        !          1100: Arguments:
        !          1101: 
        !          1102:     Adapter - The adapter for the SONIC to stop.
        !          1103: 
        !          1104: Return Value:
        !          1105: 
        !          1106:     None.
        !          1107: 
        !          1108: --*/
        !          1109: 
        !          1110: {
        !          1111: 
        !          1112:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          1113:         SONIC_CR_RECEIVER_DISABLE |
        !          1114:         SONIC_CR_SOFTWARE_RESET
        !          1115:         );
        !          1116: 
        !          1117: }
        !          1118: 
        !          1119: extern
        !          1120: VOID
        !          1121: SonicStartCamReload(
        !          1122:     IN PSONIC_ADAPTER Adapter
        !          1123:     )
        !          1124: 
        !          1125: /*++
        !          1126: 
        !          1127: Routine Description:
        !          1128: 
        !          1129:     This routine starts a CAM reload, which will cause an
        !          1130:     interrupt when it is done.
        !          1131: 
        !          1132: Arguments:
        !          1133: 
        !          1134:     Adapter - The adapter for the SONIC to reload.
        !          1135: 
        !          1136: Return Value:
        !          1137: 
        !          1138:     None.
        !          1139: 
        !          1140: --*/
        !          1141: 
        !          1142: {
        !          1143: 
        !          1144:     //
        !          1145:     // Move CAM Enable into the appropriate spot.
        !          1146:     //
        !          1147: 
        !          1148:     SONIC_LOAD_CAM_ENABLE(
        !          1149:         &Adapter->CamDescriptorArea->CamFragments[
        !          1150:                                         Adapter->CamDescriptorAreaSize],
        !          1151:         Adapter->CamDescriptorArea->CamEnable
        !          1152:         );
        !          1153: 
        !          1154: 
        !          1155:     //
        !          1156:     // Flush the CAM before we start the reload.
        !          1157:     //
        !          1158: 
        !          1159:     SONIC_FLUSH_WRITE_BUFFER(Adapter->CamDescriptorAreaFlushBuffer);
        !          1160: 
        !          1161: 
        !          1162:     SONIC_WRITE_PORT(Adapter, SONIC_CAM_DESCRIPTOR,
        !          1163:         SONIC_GET_LOW_PART_ADDRESS(Adapter->CamDescriptorAreaPhysical)
        !          1164:         );
        !          1165: 
        !          1166:     SONIC_WRITE_PORT(Adapter, SONIC_CAM_DESCRIPTOR_COUNT,
        !          1167:         (USHORT)Adapter->CamDescriptorAreaSize
        !          1168:         );
        !          1169: 
        !          1170: 
        !          1171:     //
        !          1172:     // Start the Load CAM, which will cause an interrupt
        !          1173:     // when it is done.
        !          1174:     //
        !          1175: 
        !          1176:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          1177:         SONIC_CR_LOAD_CAM
        !          1178:         );
        !          1179: 
        !          1180: }
        !          1181: 
        !          1182: STATIC
        !          1183: NDIS_STATUS
        !          1184: SonicOpenAdapter(
        !          1185:     OUT PNDIS_STATUS OpenErrorStatus,
        !          1186:     OUT NDIS_HANDLE *MacBindingHandle,
        !          1187:     OUT PUINT SelectedMediumIndex,
        !          1188:     IN PNDIS_MEDIUM MediumArray,
        !          1189:     IN UINT MediumArraySize,
        !          1190:     IN NDIS_HANDLE NdisBindingContext,
        !          1191:     IN NDIS_HANDLE MacAdapterContext,
        !          1192:     IN UINT OpenOptions,
        !          1193:     IN PSTRING AddressingInformation OPTIONAL
        !          1194:     )
        !          1195: 
        !          1196: /*++
        !          1197: 
        !          1198: Routine Description:
        !          1199: 
        !          1200:     This routine is used to create an open instance of an adapter, in effect
        !          1201:     creating a binding between an upper-level module and the MAC module over
        !          1202:     the adapter.
        !          1203: 
        !          1204: Arguments:
        !          1205: 
        !          1206:     OpenErrorStatus - Returns more information in some cases.
        !          1207: 
        !          1208:     MacBindingHandle - A pointer to a location in which the MAC stores
        !          1209:     a context value that it uses to represent this binding.
        !          1210: 
        !          1211:     SelectedMediumIndex - A pointer to a location in which the MAC stores
        !          1212:     the medium selected out of MediumArray.
        !          1213: 
        !          1214:     MediumArray - An array of media that the protocol can support.
        !          1215: 
        !          1216:     MediumArraySize - The number of elements in MediumArray.
        !          1217: 
        !          1218:     NdisBindingContext - A value to be recorded by the MAC and passed as
        !          1219:     context whenever an indication is delivered by the MAC for this binding.
        !          1220: 
        !          1221:     MacAdapterContext - The value associated with the adapter that is being
        !          1222:     opened when the MAC registered the adapter with NdisRegisterAdapter.
        !          1223: 
        !          1224:     OpenOptions - A bit mask containing flags with information about this
        !          1225:     binding.
        !          1226: 
        !          1227:     AddressingInformation - An optional pointer to a variable length string
        !          1228:     containing hardware-specific information that can be used to program the
        !          1229:     device.  (This is not used by this MAC.)
        !          1230: 
        !          1231: Return Value:
        !          1232: 
        !          1233:     The function value is the status of the operation.  If the MAC does not
        !          1234:     complete this request synchronously, the value would be
        !          1235:     NDIS_STATUS_PENDING.
        !          1236: 
        !          1237: 
        !          1238: --*/
        !          1239: 
        !          1240: {
        !          1241: 
        !          1242:     //
        !          1243:     // The SONIC_ADAPTER that this open binding should belong too.
        !          1244:     //
        !          1245:     PSONIC_ADAPTER Adapter;
        !          1246: 
        !          1247:     //
        !          1248:     // Holds the status that should be returned to the caller.
        !          1249:     //
        !          1250:     NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
        !          1251: 
        !          1252:     //
        !          1253:     // Simple iteration variable, for scanning the medium array.
        !          1254:     //
        !          1255:     UINT i;
        !          1256: 
        !          1257:     //
        !          1258:     // Pointer to the space allocated for the binding.
        !          1259:     //
        !          1260:     PSONIC_OPEN NewOpen;
        !          1261: 
        !          1262:     //
        !          1263:     // Points to the MacReserved section of NewOpen->OpenCloseRequest.
        !          1264:     //
        !          1265:     PSONIC_REQUEST_RESERVED Reserved;
        !          1266: 
        !          1267: 
        !          1268:     //
        !          1269:     // If we are being removed, don't allow new opens.
        !          1270:     //
        !          1271: 
        !          1272:     Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
        !          1273: 
        !          1274:     if (Adapter->Removed) {
        !          1275:         return NDIS_STATUS_FAILURE;
        !          1276:     }
        !          1277: 
        !          1278: 
        !          1279:     //
        !          1280:     // Search for the 802.3 media type
        !          1281:     //
        !          1282: 
        !          1283:     for (i=0; i<MediumArraySize; i++) {
        !          1284: 
        !          1285:         if (MediumArray[i] == NdisMedium802_3) {
        !          1286:             break;
        !          1287:         }
        !          1288: 
        !          1289:     }
        !          1290: 
        !          1291:     if (i == MediumArraySize) {
        !          1292: 
        !          1293:         return NDIS_STATUS_UNSUPPORTED_MEDIA;
        !          1294: 
        !          1295:     }
        !          1296: 
        !          1297:     *SelectedMediumIndex = i;
        !          1298: 
        !          1299: 
        !          1300:     NdisAcquireSpinLock(&Adapter->Lock);
        !          1301:     Adapter->References++;
        !          1302: 
        !          1303:     NdisReleaseSpinLock(&Adapter->Lock);
        !          1304: 
        !          1305:     //
        !          1306:     // Allocate the space for the open binding.  Fill in the fields.
        !          1307:     //
        !          1308: 
        !          1309:     SONIC_ALLOC_MEMORY(&StatusToReturn, &NewOpen, sizeof(SONIC_OPEN));
        !          1310: 
        !          1311:     if (StatusToReturn == NDIS_STATUS_SUCCESS) {
        !          1312: 
        !          1313:         *MacBindingHandle = BINDING_HANDLE_FROM_PSONIC_OPEN(NewOpen);
        !          1314:         InitializeListHead(&NewOpen->OpenList);
        !          1315:         NewOpen->NdisBindingContext = NdisBindingContext;
        !          1316:         NewOpen->References = 1;
        !          1317:         NewOpen->BindingShuttingDown = FALSE;
        !          1318:         NewOpen->OwningSonic = Adapter;
        !          1319: 
        !          1320:         NewOpen->OpenCloseRequest.RequestType = NdisRequestOpen;
        !          1321:         Reserved = PSONIC_RESERVED_FROM_REQUEST(&NewOpen->OpenCloseRequest);
        !          1322:         Reserved->OpenBlock = NewOpen;
        !          1323:         Reserved->Next = (PNDIS_REQUEST)NULL;
        !          1324: 
        !          1325:         NdisAcquireSpinLock(&Adapter->Lock);
        !          1326: 
        !          1327:         SonicQueueRequest(Adapter, &NewOpen->OpenCloseRequest);
        !          1328: 
        !          1329:         StatusToReturn = NDIS_STATUS_PENDING;
        !          1330: 
        !          1331:     } else {
        !          1332: 
        !          1333:         NdisWriteErrorLogEntry(
        !          1334:             Adapter->NdisAdapterHandle,
        !          1335:             NDIS_ERROR_CODE_OUT_OF_RESOURCES,
        !          1336:             2,
        !          1337:             openAdapter,
        !          1338:             SONIC_ERRMSG_ALLOC_OPEN
        !          1339:             );
        !          1340: 
        !          1341: 
        !          1342:         NdisAcquireSpinLock(&Adapter->Lock);
        !          1343: 
        !          1344:     }
        !          1345: 
        !          1346: 
        !          1347:     //
        !          1348:     // This macro assumes it is called with the lock held,
        !          1349:     // and releases it.
        !          1350:     //
        !          1351: 
        !          1352:     SONIC_DO_DEFERRED(Adapter);
        !          1353:     return StatusToReturn;
        !          1354: }
        !          1355: 
        !          1356: STATIC
        !          1357: NDIS_STATUS
        !          1358: SonicCloseAdapter(
        !          1359:     IN NDIS_HANDLE MacBindingHandle
        !          1360:     )
        !          1361: 
        !          1362: /*++
        !          1363: 
        !          1364: Routine Description:
        !          1365: 
        !          1366:     This routine causes the MAC to close an open handle (binding).
        !          1367: 
        !          1368: Arguments:
        !          1369: 
        !          1370:     MacBindingHandle - The context value returned by the MAC when the
        !          1371:     adapter was opened.  In reality it is a PSONIC_OPEN.
        !          1372: 
        !          1373: Return Value:
        !          1374: 
        !          1375:     The function value is the status of the operation.
        !          1376: 
        !          1377: 
        !          1378: --*/
        !          1379: 
        !          1380: {
        !          1381: 
        !          1382:     //
        !          1383:     // The SONIC_ADAPTER that this open binding should belong too.
        !          1384:     //
        !          1385:     PSONIC_ADAPTER Adapter;
        !          1386: 
        !          1387:     //
        !          1388:     // Holds the status that should be returned to the caller.
        !          1389:     //
        !          1390:     NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
        !          1391: 
        !          1392:     //
        !          1393:     // Pointer to the space allocated for the binding.
        !          1394:     //
        !          1395:     PSONIC_OPEN Open;
        !          1396: 
        !          1397: 
        !          1398:     Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1399: 
        !          1400:     //
        !          1401:     // Hold the lock while we update the reference counts for the
        !          1402:     // adapter and the open.
        !          1403:     //
        !          1404: 
        !          1405:     NdisAcquireSpinLock(&Adapter->Lock);
        !          1406:     Adapter->References++;
        !          1407: 
        !          1408:     Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1409: 
        !          1410:     //
        !          1411:     // Don't do anything if this binding is already closing.
        !          1412:     //
        !          1413: 
        !          1414:     if (!Open->BindingShuttingDown) {
        !          1415: 
        !          1416:         PSONIC_REQUEST_RESERVED Reserved = PSONIC_RESERVED_FROM_REQUEST(&Open->OpenCloseRequest);
        !          1417: 
        !          1418:         Open->OpenCloseRequest.RequestType = NdisRequestClose;
        !          1419:         Reserved->OpenBlock = Open;
        !          1420:         Reserved->Next = (PNDIS_REQUEST)NULL;
        !          1421: 
        !          1422:         ++Open->References;
        !          1423: 
        !          1424:         SonicQueueRequest(Adapter, &Open->OpenCloseRequest);
        !          1425: 
        !          1426:         //
        !          1427:         // Remove the creation reference.
        !          1428:         //
        !          1429: 
        !          1430:         --Open->References;
        !          1431: 
        !          1432:         StatusToReturn = NDIS_STATUS_PENDING;
        !          1433: 
        !          1434:     } else {
        !          1435: 
        !          1436:         StatusToReturn = NDIS_STATUS_CLOSING;
        !          1437: 
        !          1438:     }
        !          1439: 
        !          1440:     //
        !          1441:     // This macro assumes it is called with the lock held,
        !          1442:     // and releases it.
        !          1443:     //
        !          1444: 
        !          1445:     SONIC_DO_DEFERRED(Adapter);
        !          1446:     return StatusToReturn;
        !          1447: 
        !          1448: }
        !          1449: 
        !          1450: STATIC
        !          1451: VOID
        !          1452: SonicUnload(
        !          1453:     IN NDIS_HANDLE MacMacContext
        !          1454:     )
        !          1455: 
        !          1456: /*++
        !          1457: 
        !          1458: Routine Description:
        !          1459: 
        !          1460:     SonicUnload is called when the MAC is to unload itself.
        !          1461: 
        !          1462: Arguments:
        !          1463: 
        !          1464:     None.
        !          1465: 
        !          1466: Return Value:
        !          1467: 
        !          1468:     None.
        !          1469: 
        !          1470: --*/
        !          1471: 
        !          1472: {
        !          1473: 
        !          1474:     NDIS_STATUS Status;
        !          1475: 
        !          1476:     PSONIC_MAC SonicMac = (PSONIC_MAC)MacMacContext;
        !          1477: 
        !          1478: 
        !          1479:     NdisDeregisterMac(
        !          1480:         &Status,
        !          1481:         SonicMac->MacHandle
        !          1482:         );
        !          1483: 
        !          1484:     NdisTerminateWrapper(
        !          1485:         SonicMac->WrapperHandle,
        !          1486:         NULL
        !          1487:         );
        !          1488: 
        !          1489:     return;
        !          1490: 
        !          1491: }
        !          1492: 
        !          1493: 
        !          1494: STATIC
        !          1495: NDIS_STATUS
        !          1496: SonicAddAdapter(
        !          1497:     IN NDIS_HANDLE MacMacContext,
        !          1498:     IN NDIS_HANDLE ConfigurationHandle,
        !          1499:     IN PNDIS_STRING AdapterName
        !          1500:     )
        !          1501: 
        !          1502: /*++
        !          1503: 
        !          1504: Routine Description:
        !          1505: 
        !          1506:     SonicAddAdapter adds an adapter to the list supported
        !          1507:     by this MAC.
        !          1508: 
        !          1509: Arguments:
        !          1510: 
        !          1511:     MacMacContext - The context passed to NdisRegisterMac (will be NULL).
        !          1512: 
        !          1513:     ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
        !          1514: 
        !          1515:     AdapterName - The name to register with via NdisRegisterAdapter.
        !          1516: 
        !          1517: Return Value:
        !          1518: 
        !          1519:     NDIS_STATUS_SUCCESS
        !          1520:     NDIS_STATUS_PENDING
        !          1521: 
        !          1522: --*/
        !          1523: 
        !          1524: {
        !          1525: 
        !          1526:     NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
        !          1527:     PSONIC_MAC SonicMac = (PSONIC_MAC)MacMacContext;
        !          1528:     NDIS_HANDLE ConfigHandle;
        !          1529:     NDIS_STRING AdapterTypeString = NDIS_STRING_CONST("AdapterType");
        !          1530: #ifdef SONIC_INTERNAL
        !          1531:     NDIS_STRING MultifunctionAdapterString = NDIS_STRING_CONST("MultifunctionAdapter");
        !          1532:     NDIS_STRING NetworkControllerString = NDIS_STRING_CONST("NetworkController");
        !          1533: #endif
        !          1534:     PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
        !          1535:     PUCHAR NetworkAddress;
        !          1536:     UINT NetworkAddressLength;
        !          1537:     UCHAR AdapterType;
        !          1538:     UINT InterruptVector;
        !          1539:     UINT InterruptLevel;
        !          1540:     NDIS_INTERRUPT_MODE InterruptMode;
        !          1541:     UINT SlotNumber;
        !          1542:     UINT Controller = 0;
        !          1543:     UINT MultifunctionAdapter = 0;
        !          1544: 
        !          1545:     //
        !          1546:     // Open the configuration info.
        !          1547:     //
        !          1548: 
        !          1549:     NdisOpenConfiguration(
        !          1550:                     &Status,
        !          1551:                     &ConfigHandle,
        !          1552:                     ConfigurationHandle
        !          1553:                     );
        !          1554: 
        !          1555:     if (Status != NDIS_STATUS_SUCCESS) {
        !          1556:         return Status;
        !          1557:     }
        !          1558: 
        !          1559: 
        !          1560:     //
        !          1561:     // Check that adapter type is supported.
        !          1562:     // The default depends on the processor type.
        !          1563:     //
        !          1564: 
        !          1565:     AdapterType = SONIC_ADAPTER_TYPE_DEFAULT;
        !          1566: 
        !          1567:     NdisReadConfiguration(
        !          1568:                     &Status,
        !          1569:                     &ReturnedValue,
        !          1570:                     ConfigHandle,
        !          1571:                     &AdapterTypeString,
        !          1572:                     NdisParameterInteger
        !          1573:                     );
        !          1574: 
        !          1575:     if (Status == NDIS_STATUS_SUCCESS) {
        !          1576: 
        !          1577:         //
        !          1578:         // See if the adapter type is valid. We skip to AdapterTypeRecognized
        !          1579:         // if the AdapterType is known to this driver.
        !          1580:         //
        !          1581: 
        !          1582: #ifdef SONIC_EISA
        !          1583:         if (ReturnedValue->ParameterData.IntegerData == SONIC_ADAPTER_TYPE_EISA) {
        !          1584:             goto AdapterTypeRecognized;
        !          1585:         }
        !          1586: #endif
        !          1587: 
        !          1588: #ifdef SONIC_INTERNAL
        !          1589:         if (ReturnedValue->ParameterData.IntegerData == SONIC_ADAPTER_TYPE_INTERNAL) {
        !          1590:             goto AdapterTypeRecognized;
        !          1591:         }
        !          1592: #endif
        !          1593: 
        !          1594:         //
        !          1595:         // Card type not supported by this driver
        !          1596:         //
        !          1597: 
        !          1598: #if DBG
        !          1599:         DbgPrint("SONIC: Error in adapter type: %lx\n", ReturnedValue->ParameterData.IntegerData);
        !          1600: #endif
        !          1601:         NdisCloseConfiguration(ConfigHandle);
        !          1602:         return NDIS_STATUS_FAILURE;
        !          1603: 
        !          1604: 
        !          1605: AdapterTypeRecognized:
        !          1606: 
        !          1607:         AdapterType = (UCHAR)ReturnedValue->ParameterData.IntegerData;
        !          1608:     }
        !          1609: 
        !          1610:     switch (AdapterType) {
        !          1611: 
        !          1612: #ifdef SONIC_EISA
        !          1613: 
        !          1614:     case SONIC_ADAPTER_TYPE_EISA:
        !          1615:     {
        !          1616: 
        !          1617:         NDIS_EISA_FUNCTION_INFORMATION EisaData;
        !          1618:         USHORT Portzc88;
        !          1619:         UCHAR zc88Value;
        !          1620:         UCHAR Mask;
        !          1621:         UCHAR InitType;
        !          1622:         UCHAR PortValue;
        !          1623:         USHORT PortAddress;
        !          1624:         PUCHAR CurrentChar;
        !          1625:         BOOLEAN LastEntry;
        !          1626: 
        !          1627:         NdisReadEisaSlotInformation(
        !          1628:                                 &Status,
        !          1629:                                 ConfigurationHandle,
        !          1630:                                 &SlotNumber,
        !          1631:                                 &EisaData
        !          1632:                                 );
        !          1633: 
        !          1634:         if (Status != NDIS_STATUS_SUCCESS) {
        !          1635: 
        !          1636: #if DBG
        !          1637:             DbgPrint("SONIC: Could not read EISA data\n");
        !          1638: #endif
        !          1639:             NdisCloseConfiguration(ConfigHandle);
        !          1640:             return NDIS_STATUS_FAILURE;
        !          1641: 
        !          1642:         }
        !          1643: 
        !          1644:         CurrentChar = EisaData.InitializationData;
        !          1645: 
        !          1646:         Portzc88 = (SlotNumber << 12) + 0xc88;
        !          1647: 
        !          1648:         LastEntry = FALSE;
        !          1649:         while (!LastEntry) {
        !          1650:             InitType = *(CurrentChar++);
        !          1651:             PortAddress = *((USHORT UNALIGNED *)CurrentChar);
        !          1652:             CurrentChar += sizeof(USHORT);
        !          1653: 
        !          1654:             if ((InitType & 0x80) == 0) {
        !          1655:                 LastEntry = TRUE;
        !          1656:             }
        !          1657: 
        !          1658:             PortValue = *(CurrentChar++);
        !          1659: 
        !          1660:             if (InitType & 0x40) {
        !          1661:                 Mask = *(CurrentChar++);
        !          1662:             } else {
        !          1663:                 Mask = 0;
        !          1664:             }
        !          1665: 
        !          1666:             //
        !          1667:             // The only port we care about is zc88 (z is the
        !          1668:             // slot number) since it has the interrupt in it.
        !          1669:             //
        !          1670: 
        !          1671:             if (PortAddress != Portzc88) {
        !          1672:                 continue;
        !          1673:             }
        !          1674: 
        !          1675:             zc88Value &= Mask;
        !          1676:             zc88Value |= PortValue;
        !          1677: 
        !          1678:         }
        !          1679: 
        !          1680:         switch ((zc88Value & 0x06) >> 1) {
        !          1681:         case 0:
        !          1682:             InterruptVector = 5; break;
        !          1683:         case 1:
        !          1684:             InterruptVector = 9; break;
        !          1685:         case 2:
        !          1686:             InterruptVector = 10; break;
        !          1687:         case 3:
        !          1688:             InterruptVector = 11; break;
        !          1689:         }
        !          1690: 
        !          1691:         InterruptLevel = InterruptVector;
        !          1692: 
        !          1693:         if ((zc88Value & 0x01) != 0) {
        !          1694:             InterruptMode = NdisInterruptLatched;
        !          1695:         } else {
        !          1696:             InterruptMode = NdisInterruptLevelSensitive;
        !          1697:         }
        !          1698: 
        !          1699:         break;
        !          1700: 
        !          1701:     }
        !          1702: 
        !          1703: #endif  // SONIC_EISA
        !          1704: 
        !          1705: #ifdef SONIC_INTERNAL
        !          1706: 
        !          1707:     case SONIC_ADAPTER_TYPE_INTERNAL:
        !          1708:     {
        !          1709: 
        !          1710:         //
        !          1711:         // For the internal adapter, we read the MultifunctionAdapter number
        !          1712:         // and NetworkController number, which are both optional. For
        !          1713:         // passing to SonicRegisterAdapter.
        !          1714:         //
        !          1715: 
        !          1716:         NdisReadConfiguration(
        !          1717:                         &Status,
        !          1718:                         &ReturnedValue,
        !          1719:                         ConfigHandle,
        !          1720:                         &MultifunctionAdapterString,
        !          1721:                         NdisParameterInteger
        !          1722:                         );
        !          1723: 
        !          1724:         if (Status == NDIS_STATUS_SUCCESS) {
        !          1725: 
        !          1726:             MultifunctionAdapter =  ReturnedValue->ParameterData.IntegerData;
        !          1727: 
        !          1728:         }
        !          1729: 
        !          1730:         NdisReadConfiguration(
        !          1731:                         &Status,
        !          1732:                         &ReturnedValue,
        !          1733:                         ConfigHandle,
        !          1734:                         &NetworkControllerString,
        !          1735:                         NdisParameterInteger
        !          1736:                         );
        !          1737: 
        !          1738:         if (Status == NDIS_STATUS_SUCCESS) {
        !          1739: 
        !          1740:             Controller =  ReturnedValue->ParameterData.IntegerData;
        !          1741: 
        !          1742:         }
        !          1743: 
        !          1744:         //
        !          1745:         // These are filled in by SonicHardwareGetDetails.
        !          1746:         //
        !          1747: 
        !          1748:         InterruptVector = 0;
        !          1749:         InterruptLevel = 0;
        !          1750: 
        !          1751:         //
        !          1752:         // The internal adapter is level-sensitive.
        !          1753:         //
        !          1754: 
        !          1755:         InterruptMode = NdisInterruptLevelSensitive;
        !          1756: 
        !          1757:         break;
        !          1758: 
        !          1759:     }
        !          1760: 
        !          1761: #endif  // SONIC_INTERNAL
        !          1762: 
        !          1763:     default:
        !          1764: 
        !          1765:         ASSERT(FALSE);
        !          1766:         break;
        !          1767: 
        !          1768:     }
        !          1769: 
        !          1770: 
        !          1771:     //
        !          1772:     // Read network address
        !          1773:     //
        !          1774: 
        !          1775:     NdisReadNetworkAddress(
        !          1776:         &Status,
        !          1777:         (PVOID *)&NetworkAddress,
        !          1778:         &NetworkAddressLength,
        !          1779:         ConfigHandle);
        !          1780: 
        !          1781: 
        !          1782:     //
        !          1783:     // Make sure that the address is the right length asnd
        !          1784:     // at least one of the bytes is non-zero.
        !          1785:     //
        !          1786: 
        !          1787:     if ((Status == NDIS_STATUS_SUCCESS) &&
        !          1788:         (NetworkAddressLength == ETH_LENGTH_OF_ADDRESS) &&
        !          1789:         ((NetworkAddress[0] |
        !          1790:           NetworkAddress[1] |
        !          1791:           NetworkAddress[2] |
        !          1792:           NetworkAddress[3] |
        !          1793:           NetworkAddress[4] |
        !          1794:           NetworkAddress[5]) != 0)) {
        !          1795: 
        !          1796: #if DBG
        !          1797:         if (SonicDbg) {
        !          1798:             DbgPrint("SONIC: New Address = %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n",
        !          1799:                                     NetworkAddress[0],
        !          1800:                                     NetworkAddress[1],
        !          1801:                                     NetworkAddress[2],
        !          1802:                                     NetworkAddress[3],
        !          1803:                                     NetworkAddress[4],
        !          1804:                                     NetworkAddress[5]);
        !          1805:         }
        !          1806: #endif
        !          1807: 
        !          1808:     } else {
        !          1809: 
        !          1810:         //
        !          1811:         // Tells SonicRegisterAdapter to use the
        !          1812:         // burned-in address.
        !          1813:         //
        !          1814: 
        !          1815:         NetworkAddress = NULL;
        !          1816: 
        !          1817:     }
        !          1818: 
        !          1819:     //
        !          1820:     // Used passed-in adapter name to register.
        !          1821:     //
        !          1822: 
        !          1823:     Status = SonicRegisterAdapter(
        !          1824:                  SonicMac->MacHandle,
        !          1825:                  ConfigurationHandle,
        !          1826:                  AdapterName,
        !          1827:                  NetworkAddress,
        !          1828:                  AdapterType,
        !          1829:                  SlotNumber,
        !          1830:                  Controller,
        !          1831:                  MultifunctionAdapter,
        !          1832:                  InterruptVector,
        !          1833:                  InterruptLevel,
        !          1834:                  InterruptMode,
        !          1835:                  32);
        !          1836: 
        !          1837: 
        !          1838:     NdisCloseConfiguration(ConfigHandle);
        !          1839: 
        !          1840: 
        !          1841:     return Status;           // should be NDIS_STATUS_SUCCESS
        !          1842: 
        !          1843: }
        !          1844: 
        !          1845: STATIC
        !          1846: VOID
        !          1847: SonicRemoveAdapter(
        !          1848:     IN NDIS_HANDLE MacAdapterContext
        !          1849:     )
        !          1850: 
        !          1851: /*++
        !          1852: 
        !          1853: Routine Description:
        !          1854: 
        !          1855:     SonicRemoveAdapter removes an adapter previously registered
        !          1856:     with NdisRegisterAdapter.
        !          1857: 
        !          1858: Arguments:
        !          1859: 
        !          1860:     MacAdapterContext - The context value that the MAC passed
        !          1861:         to NdisRegisterAdapter; actually as pointer to a
        !          1862:         SONIC_ADAPTER.
        !          1863: 
        !          1864: Return Value:
        !          1865: 
        !          1866:     None.
        !          1867: 
        !          1868: --*/
        !          1869: 
        !          1870: {
        !          1871:     PSONIC_ADAPTER Adapter;
        !          1872:     BOOLEAN Canceled;
        !          1873: 
        !          1874:     Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
        !          1875: 
        !          1876:     Adapter->Removed = TRUE;
        !          1877: 
        !          1878:     //
        !          1879:     // Stop the chip.
        !          1880:     //
        !          1881: 
        !          1882:     SonicStopChip (Adapter);
        !          1883: 
        !          1884:     NdisDeregisterAdapterShutdownHandler(Adapter->NdisAdapterHandle);
        !          1885: 
        !          1886:     ASSERT (Adapter->OpenCount == 0);
        !          1887: 
        !          1888:     //
        !          1889:     // There are no opens left, so remove ourselves.
        !          1890:     //
        !          1891: 
        !          1892:     //
        !          1893:     // Stop the deadman timer
        !          1894:     //
        !          1895: 
        !          1896:     NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
        !          1897: 
        !          1898:     if ( !Canceled ) {
        !          1899:         NdisStallExecution(500000);
        !          1900:     }
        !          1901: 
        !          1902:     NdisRemoveInterrupt(&Adapter->Interrupt);
        !          1903: 
        !          1904:     EthDeleteFilter(Adapter->FilterDB);
        !          1905: 
        !          1906:     DeleteAdapterMemory(Adapter);
        !          1907:     NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
        !          1908: 
        !          1909:     NdisFreeSpinLock(&Adapter->Lock);
        !          1910:     SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
        !          1911: 
        !          1912: }
        !          1913: 
        !          1914: STATIC
        !          1915: NDIS_STATUS
        !          1916: SonicReset(
        !          1917:     IN NDIS_HANDLE MacBindingHandle
        !          1918:     )
        !          1919: 
        !          1920: /*++
        !          1921: 
        !          1922: Routine Description:
        !          1923: 
        !          1924:     The SonicReset request instructs the MAC to issue a hardware reset
        !          1925:     to the network adapter.  The MAC also resets its software state.  See
        !          1926:     the description of NdisReset for a detailed description of this request.
        !          1927: 
        !          1928: Arguments:
        !          1929: 
        !          1930:     MacBindingHandle - The context value returned by the MAC  when the
        !          1931:     adapter was opened.  In reality, it is a pointer to SONIC_OPEN.
        !          1932: 
        !          1933: Return Value:
        !          1934: 
        !          1935:     The function value is the status of the operation.
        !          1936: 
        !          1937: 
        !          1938: --*/
        !          1939: 
        !          1940: {
        !          1941: 
        !          1942:     //
        !          1943:     // Holds the status that should be returned to the caller.
        !          1944:     //
        !          1945:     NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
        !          1946: 
        !          1947:     PSONIC_ADAPTER Adapter =
        !          1948:         PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1949: 
        !          1950:     //
        !          1951:     // Hold the locks while we update the reference counts on the
        !          1952:     // adapter and the open.
        !          1953:     //
        !          1954: 
        !          1955:     if (Adapter->Removed) {
        !          1956: 
        !          1957:         return(NDIS_STATUS_FAILURE);
        !          1958: 
        !          1959:     }
        !          1960: 
        !          1961:     NdisAcquireSpinLock(&Adapter->Lock);
        !          1962: 
        !          1963:     Adapter->References++;
        !          1964: 
        !          1965:     if (!Adapter->ResetInProgress && !Adapter->IndicatingResetStart) {
        !          1966: 
        !          1967:         PSONIC_OPEN Open;
        !          1968: 
        !          1969:         Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1970: 
        !          1971:         if (!Open->BindingShuttingDown) {
        !          1972: 
        !          1973:             Adapter->IndicatingResetStart = TRUE;
        !          1974: 
        !          1975:             if (!Adapter->IndicatingResetEnd) {
        !          1976: 
        !          1977:                 //
        !          1978:                 // Loop through, indicating RESET_START; we
        !          1979:                 // don't bother with the StatusComplete
        !          1980:                 // indication until RESET_END is indicated.
        !          1981:                 //
        !          1982: 
        !          1983:                 PSONIC_OPEN Open;
        !          1984:                 PLIST_ENTRY CurrentLink;
        !          1985: 
        !          1986:                 CurrentLink = Adapter->OpenBindings.Flink;
        !          1987: 
        !          1988:                 while (CurrentLink != &Adapter->OpenBindings) {
        !          1989: 
        !          1990:                     Open = CONTAINING_RECORD(
        !          1991:                              CurrentLink,
        !          1992:                              SONIC_OPEN,
        !          1993:                              OpenList
        !          1994:                              );
        !          1995: 
        !          1996:                     Open->References++;
        !          1997:                     NdisReleaseSpinLock(&Adapter->Lock);
        !          1998: 
        !          1999:                     NdisIndicateStatus(
        !          2000:                         Open->NdisBindingContext,
        !          2001:                         NDIS_STATUS_RESET_START,
        !          2002:                         NULL,
        !          2003:                         0
        !          2004:                         );
        !          2005: 
        !          2006:                     NdisAcquireSpinLock(&Adapter->Lock);
        !          2007:                     Open->References--;
        !          2008: 
        !          2009:                     CurrentLink = CurrentLink->Flink;
        !          2010: 
        !          2011:                 }
        !          2012: 
        !          2013: 
        !          2014:                 Adapter->IndicatingResetStart = FALSE;
        !          2015: 
        !          2016:                 SetupForReset(
        !          2017:                     Adapter,
        !          2018:                     PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)
        !          2019:                     );
        !          2020:             }
        !          2021: 
        !          2022:             Open->References++;
        !          2023:             Adapter->ResettingOpen = Open;
        !          2024: 
        !          2025:             StatusToReturn = NDIS_STATUS_PENDING;
        !          2026: 
        !          2027:         } else {
        !          2028: 
        !          2029:             StatusToReturn = NDIS_STATUS_CLOSING;
        !          2030: 
        !          2031:         }
        !          2032: 
        !          2033:     } else {
        !          2034: 
        !          2035:         StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
        !          2036: 
        !          2037:     }
        !          2038: 
        !          2039: 
        !          2040:     //
        !          2041:     // This macro assumes it is called with the lock held,
        !          2042:     // and releases it.
        !          2043:     //
        !          2044: 
        !          2045:     SONIC_DO_DEFERRED(Adapter);
        !          2046:     return StatusToReturn;
        !          2047: 
        !          2048: }
        !          2049: 
        !          2050: #if 0
        !          2051: STATIC
        !          2052: UINT
        !          2053: CalculateCRC(
        !          2054:     IN UINT NumberOfBytes,
        !          2055:     IN PCHAR Input
        !          2056:     )
        !          2057: 
        !          2058: /*++
        !          2059: 
        !          2060: Routine Description:
        !          2061: 
        !          2062:     Calculates a 32 bit crc value over the input number of bytes.
        !          2063: 
        !          2064:     NOTE: This routine assumes UINTs are 32 bits.
        !          2065: 
        !          2066: Arguments:
        !          2067: 
        !          2068:     NumberOfBytes - The number of bytes in the input.
        !          2069: 
        !          2070:     Input - An input "string" to calculate a CRC over.
        !          2071: 
        !          2072: Return Value:
        !          2073: 
        !          2074:     A 32 bit crc value.
        !          2075: 
        !          2076: 
        !          2077: --*/
        !          2078: 
        !          2079: {
        !          2080: 
        !          2081:     const UINT POLY = 0x04c11db6;
        !          2082:     UINT CRCValue = 0xffffffff;
        !          2083: 
        !          2084:     ASSERT(sizeof(UINT) == 4);
        !          2085: 
        !          2086:     for (
        !          2087:         ;
        !          2088:         NumberOfBytes;
        !          2089:         NumberOfBytes--
        !          2090:         ) {
        !          2091: 
        !          2092:         UINT CurrentBit;
        !          2093:         UCHAR CurrentByte = *Input;
        !          2094:         Input++;
        !          2095: 
        !          2096:         for (
        !          2097:             CurrentBit = 8;
        !          2098:             CurrentBit;
        !          2099:             CurrentBit--
        !          2100:             ) {
        !          2101: 
        !          2102:             UINT CurrentCRCHigh = CRCValue >> 31;
        !          2103: 
        !          2104:             CRCValue <<= 1;
        !          2105: 
        !          2106:             if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
        !          2107: 
        !          2108:                 CRCValue ^= POLY;
        !          2109:                 CRCValue |= 0x00000001;
        !          2110: 
        !          2111:             }
        !          2112: 
        !          2113:             CurrentByte >>= 1;
        !          2114: 
        !          2115:         }
        !          2116: 
        !          2117:     }
        !          2118: 
        !          2119:     return CRCValue;
        !          2120: 
        !          2121: }
        !          2122: #endif
        !          2123: 
        !          2124: extern
        !          2125: VOID
        !          2126: StartAdapterReset(
        !          2127:     IN PSONIC_ADAPTER Adapter
        !          2128:     )
        !          2129: 
        !          2130: /*++
        !          2131: 
        !          2132: Routine Description:
        !          2133: 
        !          2134:     This is the first phase of resetting the adapter hardware.
        !          2135: 
        !          2136:     It makes the following assumptions:
        !          2137: 
        !          2138:     1) That the hardware has been stopped.
        !          2139: 
        !          2140:     2) That it can not be preempted.
        !          2141: 
        !          2142:     3) That no other adapter activity can occur.
        !          2143: 
        !          2144:     When this routine is finished all of the adapter information
        !          2145:     will be as if the driver was just initialized.
        !          2146: 
        !          2147: Arguments:
        !          2148: 
        !          2149:     Adapter - The adapter whose hardware is to be reset.
        !          2150: 
        !          2151: Return Value:
        !          2152: 
        !          2153:     None.
        !          2154: 
        !          2155: --*/
        !          2156: {
        !          2157: 
        !          2158:     //
        !          2159:     // These are used for cleaning the rings.
        !          2160:     //
        !          2161: 
        !          2162:     PSONIC_RECEIVE_DESCRIPTOR CurrentReceiveDescriptor;
        !          2163:     PSONIC_TRANSMIT_DESCRIPTOR CurrentTransmitDescriptor;
        !          2164:     UINT i;
        !          2165:     SONIC_PHYSICAL_ADDRESS SonicPhysicalAdr;
        !          2166: 
        !          2167: 
        !          2168:     //
        !          2169:     // Shut down the chip.  We won't be doing any more work until
        !          2170:     // the reset is complete.
        !          2171:     //
        !          2172: 
        !          2173:     SonicStopChip(Adapter);
        !          2174: 
        !          2175:     //
        !          2176:     // Once the chip is stopped we can't get any more interrupts.
        !          2177:     // Any interrupts that are "queued" for processing could
        !          2178:     // only possibly service this reset.  It is therefore safe for
        !          2179:     // us to clear the adapter global csr value.
        !          2180:     //
        !          2181:     Adapter->IsrValue = 0;
        !          2182: 
        !          2183: 
        !          2184:     Adapter->LastTransmitDescriptor =
        !          2185:                 Adapter->TransmitDescriptorArea +
        !          2186:                 (Adapter->NumberOfTransmitDescriptors-1);
        !          2187:     Adapter->NumberOfAvailableDescriptors =
        !          2188:                 Adapter->NumberOfTransmitDescriptors;
        !          2189:     Adapter->AllocateableDescriptor =
        !          2190:                 Adapter->TransmitDescriptorArea;
        !          2191:     Adapter->TransmittingDescriptor =
        !          2192:                 Adapter->TransmitDescriptorArea;
        !          2193:     Adapter->FirstUncommittedDescriptor =
        !          2194:                 Adapter->TransmitDescriptorArea;
        !          2195:     Adapter->PacketsSinceLastInterrupt = 0;
        !          2196: 
        !          2197:     Adapter->CurrentReceiveBufferIndex = 0;
        !          2198:     Adapter->CurrentReceiveDescriptorIndex = 0;
        !          2199:     Adapter->LastReceiveDescriptor =
        !          2200:                 &Adapter->ReceiveDescriptorArea[
        !          2201:                     Adapter->NumberOfReceiveDescriptors-1];
        !          2202: 
        !          2203:     Adapter->InterruptMaskRegister = SONIC_INT_DEFAULT_VALUE;
        !          2204:     Adapter->ReceiveDescriptorsExhausted = FALSE;
        !          2205:     Adapter->ReceiveBuffersExhausted = FALSE;
        !          2206:     Adapter->ReceiveControlRegister = SONIC_RCR_DEFAULT_VALUE;
        !          2207: 
        !          2208:     Adapter->SendStageOpen = TRUE;
        !          2209: 
        !          2210:     Adapter->AlreadyProcessingSendStage = FALSE;
        !          2211: 
        !          2212:     //
        !          2213:     // Clean the receive descriptors and initialize the link
        !          2214:     // fields.
        !          2215:     //
        !          2216: 
        !          2217:     SONIC_ZERO_MEMORY(
        !          2218:         Adapter->ReceiveDescriptorArea,
        !          2219:         (sizeof(SONIC_RECEIVE_DESCRIPTOR)*Adapter->NumberOfReceiveDescriptors)
        !          2220:         );
        !          2221: 
        !          2222:     for (
        !          2223:         i = 0, CurrentReceiveDescriptor = Adapter->ReceiveDescriptorArea;
        !          2224:         i < Adapter->NumberOfReceiveDescriptors;
        !          2225:         i++,CurrentReceiveDescriptor++
        !          2226:         ) {
        !          2227: 
        !          2228:         CurrentReceiveDescriptor->InUse = SONIC_OWNED_BY_SONIC;
        !          2229: 
        !          2230:         SonicPhysicalAdr = NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical) +
        !          2231:                         (i * sizeof(SONIC_RECEIVE_DESCRIPTOR));
        !          2232: 
        !          2233:         if (i == 0) {
        !          2234: 
        !          2235:             Adapter->ReceiveDescriptorArea[
        !          2236:                 Adapter->NumberOfReceiveDescriptors-1].Link =
        !          2237:                         SonicPhysicalAdr | SONIC_END_OF_LIST;
        !          2238: 
        !          2239:         } else {
        !          2240: 
        !          2241:             Adapter->ReceiveDescriptorArea[i-1].Link = SonicPhysicalAdr;
        !          2242: 
        !          2243:         }
        !          2244: 
        !          2245:     }
        !          2246: 
        !          2247: 
        !          2248:     //
        !          2249:     // Clean the transmit descriptors and initialize the link
        !          2250:     // fields.
        !          2251:     //
        !          2252: 
        !          2253:     SONIC_ZERO_MEMORY(
        !          2254:         Adapter->TransmitDescriptorArea,
        !          2255:         (sizeof(SONIC_TRANSMIT_DESCRIPTOR)*Adapter->NumberOfTransmitDescriptors)
        !          2256:         );
        !          2257: 
        !          2258:     for (
        !          2259:         i = 0, CurrentTransmitDescriptor = Adapter->TransmitDescriptorArea;
        !          2260:         i < Adapter->NumberOfTransmitDescriptors;
        !          2261:         i++,CurrentTransmitDescriptor++
        !          2262:         ) {
        !          2263: 
        !          2264:         SonicPhysicalAdr = NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical) +
        !          2265:                         (i * sizeof(SONIC_TRANSMIT_DESCRIPTOR));
        !          2266: 
        !          2267:         if (i == 0) {
        !          2268: 
        !          2269:             Adapter->TransmitDescriptorArea[Adapter->NumberOfTransmitDescriptors-1].Link = SonicPhysicalAdr;
        !          2270: 
        !          2271:         } else {
        !          2272: 
        !          2273:             (CurrentTransmitDescriptor-1)->Link = SonicPhysicalAdr;
        !          2274: 
        !          2275:         }
        !          2276: 
        !          2277:     }
        !          2278: 
        !          2279: 
        !          2280:     //
        !          2281:     // Recover all of the adapter buffers.
        !          2282:     //
        !          2283: 
        !          2284:     {
        !          2285: 
        !          2286:         UINT i;
        !          2287: 
        !          2288:         for (
        !          2289:             i = 0;
        !          2290:             i < (SONIC_NUMBER_OF_SMALL_BUFFERS +
        !          2291:                  SONIC_NUMBER_OF_MEDIUM_BUFFERS +
        !          2292:                  SONIC_NUMBER_OF_LARGE_BUFFERS);
        !          2293:             i++
        !          2294:             ) {
        !          2295: 
        !          2296:             Adapter->SonicBuffers[i].Next = i+1;
        !          2297: 
        !          2298:         }
        !          2299: 
        !          2300:         Adapter->SonicBufferListHeads[0] = -1;
        !          2301:         Adapter->SonicBufferListHeads[1] = 0;
        !          2302:         Adapter->SonicBuffers[SONIC_NUMBER_OF_SMALL_BUFFERS-1].Next = -1;
        !          2303:         Adapter->SonicBufferListHeads[2] = SONIC_NUMBER_OF_SMALL_BUFFERS;
        !          2304:         Adapter->SonicBuffers[(SONIC_NUMBER_OF_SMALL_BUFFERS+
        !          2305:                                SONIC_NUMBER_OF_MEDIUM_BUFFERS)-1].Next = -1;
        !          2306:         Adapter->SonicBufferListHeads[3] = SONIC_NUMBER_OF_SMALL_BUFFERS +
        !          2307:                                            SONIC_NUMBER_OF_MEDIUM_BUFFERS;
        !          2308:         Adapter->SonicBuffers[(SONIC_NUMBER_OF_SMALL_BUFFERS+
        !          2309:                                SONIC_NUMBER_OF_MEDIUM_BUFFERS+
        !          2310:                                SONIC_NUMBER_OF_LARGE_BUFFERS)-1].Next = -1;
        !          2311: 
        !          2312:     }
        !          2313: 
        !          2314:     //
        !          2315:     // Go through the various transmit lists and abort every packet.
        !          2316:     //
        !          2317: 
        !          2318:     {
        !          2319: 
        !          2320:         UINT i;
        !          2321:         PNDIS_PACKET Packet;
        !          2322:         PSONIC_PACKET_RESERVED Reserved;
        !          2323:         PSONIC_OPEN Open;
        !          2324:         PNDIS_PACKET Next;
        !          2325: 
        !          2326:         for (
        !          2327:             i = 0;
        !          2328:             i < 3;
        !          2329:             i++
        !          2330:             ) {
        !          2331: 
        !          2332:             switch (i) {
        !          2333: 
        !          2334:                 case 0:
        !          2335:                     Next = Adapter->FirstLoopBack;
        !          2336:                     break;
        !          2337:                 case 1:
        !          2338:                     Next = Adapter->FirstFinishTransmit;
        !          2339:                     break;
        !          2340:                 case 2:
        !          2341:                     Next = Adapter->FirstSendStagePacket;
        !          2342:                     break;
        !          2343: 
        !          2344:             }
        !          2345: 
        !          2346: 
        !          2347:             while (Next) {
        !          2348: 
        !          2349:                 Packet = Next;
        !          2350:                 Reserved = PSONIC_RESERVED_FROM_PACKET(Packet);
        !          2351:                 Next = Reserved->Next;
        !          2352:                 Open =
        !          2353:                   PSONIC_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
        !          2354: 
        !          2355:                 //
        !          2356:                 // The completion of the packet is one less reason
        !          2357:                 // to keep the open around.
        !          2358:                 //
        !          2359: 
        !          2360:                 ASSERT(Open->References);
        !          2361: 
        !          2362:                 NdisCompleteSend(
        !          2363:                     Open->NdisBindingContext,
        !          2364:                     Packet,
        !          2365:                     NDIS_STATUS_REQUEST_ABORTED
        !          2366:                     );
        !          2367: 
        !          2368:                 Open->References--;
        !          2369: 
        !          2370:             }
        !          2371: 
        !          2372:         }
        !          2373: 
        !          2374:         Adapter->FirstLoopBack = NULL;
        !          2375:         Adapter->LastLoopBack = NULL;
        !          2376:         Adapter->FirstFinishTransmit = NULL;
        !          2377:         Adapter->LastFinishTransmit = NULL;
        !          2378:         Adapter->FirstSendStagePacket = NULL;
        !          2379:         Adapter->LastSendStagePacket = NULL;
        !          2380:         Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH - GO_ARRAY_START] = 0;
        !          2381: 
        !          2382:     }
        !          2383: 
        !          2384:     (VOID)SetupRegistersAndInit(Adapter);
        !          2385: 
        !          2386: }
        !          2387: 
        !          2388: STATIC
        !          2389: BOOLEAN
        !          2390: SetupRegistersAndInit(
        !          2391:     IN PSONIC_ADAPTER Adapter
        !          2392:     )
        !          2393: 
        !          2394: /*++
        !          2395: 
        !          2396: Routine Description:
        !          2397: 
        !          2398:     It is this routines responsibility to make sure that the
        !          2399:     initialization block is filled and the chip is initialized
        !          2400:     *but not* started.
        !          2401: 
        !          2402:     NOTE: This routine assumes that it is called with the lock
        !          2403:     acquired OR that only a single thread of execution is working
        !          2404:     with this particular adapter.
        !          2405: 
        !          2406: Arguments:
        !          2407: 
        !          2408:     Adapter - The adapter whose hardware is to be initialized.
        !          2409: 
        !          2410: Return Value:
        !          2411: 
        !          2412:     TRUE if the registers are initialized successfully.
        !          2413: 
        !          2414: --*/
        !          2415: {
        !          2416: 
        !          2417:     USHORT CommandRegister;
        !          2418:     UINT Time;
        !          2419: 
        !          2420: 
        !          2421:     SONIC_WRITE_PORT(Adapter, SONIC_DATA_CONFIGURATION,
        !          2422:             Adapter->DataConfigurationRegister
        !          2423:             );
        !          2424: 
        !          2425:     SONIC_WRITE_PORT(Adapter, SONIC_RECEIVE_CONTROL,
        !          2426:             Adapter->ReceiveControlRegister
        !          2427:             );
        !          2428: 
        !          2429:     SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
        !          2430:             Adapter->InterruptMaskRegister
        !          2431:             );
        !          2432: 
        !          2433:     SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_STATUS,
        !          2434:             (USHORT)0xffff
        !          2435:             );
        !          2436: 
        !          2437: 
        !          2438: 
        !          2439:     SONIC_WRITE_PORT(Adapter, SONIC_UPPER_TRANSMIT_DESCRIPTOR,
        !          2440:             SONIC_GET_HIGH_PART_ADDRESS(
        !          2441:                 NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical))
        !          2442:             );
        !          2443: 
        !          2444:     SONIC_WRITE_PORT(Adapter, SONIC_CURR_TRANSMIT_DESCRIPTOR,
        !          2445:             SONIC_GET_LOW_PART_ADDRESS(
        !          2446:                 NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical))
        !          2447:             );
        !          2448: 
        !          2449: 
        !          2450:     SONIC_WRITE_PORT(Adapter, SONIC_UPPER_RECEIVE_DESCRIPTOR,
        !          2451:             SONIC_GET_HIGH_PART_ADDRESS(
        !          2452:                 NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical))
        !          2453:             );
        !          2454: 
        !          2455:     SONIC_WRITE_PORT(Adapter, SONIC_CURR_RECEIVE_DESCRIPTOR,
        !          2456:             SONIC_GET_LOW_PART_ADDRESS(
        !          2457:                 NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical))
        !          2458:             );
        !          2459: 
        !          2460: 
        !          2461:     //
        !          2462:     // The EOBC value cannot be odd (since the card register
        !          2463:     // wants it in words); in addition it appears that the
        !          2464:     // value in the register must be even, so this number
        !          2465:     // has to be a multiple of 4.
        !          2466:     //
        !          2467:     ASSERT((SONIC_END_OF_BUFFER_COUNT & 0x3) == 0);
        !          2468: 
        !          2469:     switch (Adapter->AdapterType) {
        !          2470: 
        !          2471: #ifdef SONIC_EISA
        !          2472: 
        !          2473:     case SONIC_ADAPTER_TYPE_EISA:
        !          2474: 
        !          2475:         //
        !          2476:         // For the EISA card, set EOBC to 2 words more than real
        !          2477:         // size.
        !          2478:         //
        !          2479: 
        !          2480:         SONIC_WRITE_PORT(Adapter, SONIC_END_OF_BUFFER_WORD_COUNT,
        !          2481:                 (SONIC_END_OF_BUFFER_COUNT / 2) + 2
        !          2482:                 );
        !          2483:         break;
        !          2484: 
        !          2485: #endif  // SONIC_EISA
        !          2486: 
        !          2487: #ifdef SONIC_INTERNAL
        !          2488: 
        !          2489:     case SONIC_ADAPTER_TYPE_INTERNAL:
        !          2490: 
        !          2491:         SONIC_WRITE_PORT(Adapter, SONIC_END_OF_BUFFER_WORD_COUNT,
        !          2492:                 SONIC_END_OF_BUFFER_COUNT / 2
        !          2493:                 );
        !          2494:         break;
        !          2495: 
        !          2496: #endif  // SONIC_INTERNAL
        !          2497: 
        !          2498:     default:
        !          2499: 
        !          2500:         ASSERT(FALSE);
        !          2501:         break;
        !          2502: 
        !          2503:     }
        !          2504: 
        !          2505: 
        !          2506:     SONIC_WRITE_PORT(Adapter, SONIC_UPPER_RECEIVE_RESOURCE,
        !          2507:             SONIC_GET_HIGH_PART_ADDRESS(
        !          2508:                 NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
        !          2509:             );
        !          2510: 
        !          2511:     SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_START,
        !          2512:             SONIC_GET_LOW_PART_ADDRESS(
        !          2513:                 NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
        !          2514:             );
        !          2515: 
        !          2516:     SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_END,
        !          2517:             (USHORT)(SONIC_GET_LOW_PART_ADDRESS(
        !          2518:                 NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical)) +
        !          2519:                 sizeof(SONIC_RECEIVE_RESOURCE) *
        !          2520:                 Adapter->NumberOfReceiveBuffers)
        !          2521:             );
        !          2522: 
        !          2523:     SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_READ,
        !          2524:             SONIC_GET_LOW_PART_ADDRESS(
        !          2525:                 NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
        !          2526:             );
        !          2527: 
        !          2528:     SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_WRITE,
        !          2529:             SONIC_GET_LOW_PART_ADDRESS(
        !          2530:                 NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
        !          2531:             );
        !          2532: 
        !          2533: 
        !          2534:     //
        !          2535:     // Now take us out of reset mode...
        !          2536:     //
        !          2537: 
        !          2538:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          2539:         0x0000
        !          2540:         );
        !          2541: 
        !          2542:     //
        !          2543:     // ...and issue the Read RRA command.
        !          2544:     //
        !          2545: 
        !          2546:     SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
        !          2547:         SONIC_CR_READ_RRA
        !          2548:         );
        !          2549: 
        !          2550: 
        !          2551: 
        !          2552:     //
        !          2553:     // Wait for 1/5 second for Read RRA to finish.
        !          2554:     //
        !          2555: 
        !          2556:     Time = 20;
        !          2557: 
        !          2558:     while (Time > 0) {
        !          2559: 
        !          2560:         NdisStallExecution(10000);
        !          2561: 
        !          2562:         SONIC_READ_PORT(Adapter, SONIC_COMMAND, &CommandRegister);
        !          2563:         if ((CommandRegister & SONIC_CR_READ_RRA) == 0) {
        !          2564:             break;
        !          2565:         }
        !          2566: 
        !          2567:         Time--;
        !          2568: 
        !          2569:     }
        !          2570: 
        !          2571:     if (Time == 0) {
        !          2572: 
        !          2573: #if DBG
        !          2574:         DbgPrint("SONIC: Could not read RRA\n");
        !          2575: #endif
        !          2576:         return FALSE;
        !          2577: 
        !          2578:     }
        !          2579: 
        !          2580: 
        !          2581:     //
        !          2582:     // This will cause a LOAD_CAM interrupt when it is done.
        !          2583:     //
        !          2584: 
        !          2585:     SonicStartCamReload(Adapter);
        !          2586: 
        !          2587:     return TRUE;
        !          2588: 
        !          2589: }
        !          2590: 
        !          2591: extern
        !          2592: VOID
        !          2593: SetupForReset(
        !          2594:     IN PSONIC_ADAPTER Adapter,
        !          2595:     IN PSONIC_OPEN Open
        !          2596:     )
        !          2597: 
        !          2598: /*++
        !          2599: 
        !          2600: Routine Description:
        !          2601: 
        !          2602:     This routine is used to fill in the who and why a reset is
        !          2603:     being set up as well as setting the appropriate fields in the
        !          2604:     adapter.
        !          2605: 
        !          2606:     NOTE: This routine must be called with the lock acquired.
        !          2607: 
        !          2608: Arguments:
        !          2609: 
        !          2610:     Adapter - The adapter whose hardware is to be initialized.
        !          2611: 
        !          2612:     Open - A pointer to an sonic open structure.
        !          2613: 
        !          2614: Return Value:
        !          2615: 
        !          2616:     None.
        !          2617: 
        !          2618: --*/
        !          2619: {
        !          2620: 
        !          2621:     PNDIS_REQUEST CurrentRequest;
        !          2622:     PNDIS_REQUEST * CurrentNextLocation;
        !          2623:     PSONIC_OPEN TmpOpen;
        !          2624: 
        !          2625:     PSONIC_REQUEST_RESERVED Reserved;
        !          2626: 
        !          2627:     //
        !          2628:     // Shut down the chip.  We won't be doing any more work until
        !          2629:     // the reset is complete. We take it out of reset mode, however.
        !          2630:     //
        !          2631: 
        !          2632:     SonicStopChip(Adapter);
        !          2633: 
        !          2634: 
        !          2635:     //
        !          2636:     // Once the chip is stopped we can't get any more interrupts.
        !          2637:     // This call ensures that any ISR which is just about to run
        !          2638:     // will find no bits in the ISR, and any DPR which fires will
        !          2639:     // find nothing queued to do.
        !          2640:     //
        !          2641: 
        !          2642:     NdisSynchronizeWithInterrupt(
        !          2643:         &Adapter->Interrupt,
        !          2644:         SonicSynchClearIsr,
        !          2645:         (PVOID)Adapter);
        !          2646: 
        !          2647: 
        !          2648:     Adapter->ResetInProgress = TRUE;
        !          2649: 
        !          2650:     //
        !          2651:     // Shut down all of the transmit queues so that the
        !          2652:     // transmit portion of the chip will eventually calm down.
        !          2653:     //
        !          2654: 
        !          2655:     Adapter->SendStageOpen = FALSE;
        !          2656: 
        !          2657:     //
        !          2658:     // If there is a close at the top of the queue, then
        !          2659:     // it may be in two states:
        !          2660:     //
        !          2661:     // 1- Has interrupted, and the InterruptDpc got the
        !          2662:     // interrupt out of Adapter->IsrValue before we zeroed it.
        !          2663:     //
        !          2664:     // 2- Has interrupted, but we zeroed Adapter->IsrValue
        !          2665:     // before it read it, OR has not yet interrupted.
        !          2666:     //
        !          2667:     // In case 1, the interrupt will be processed and the
        !          2668:     // close will complete without our intervention. In
        !          2669:     // case 2, the open will not complete. In that case
        !          2670:     // the CAM will have been updated for that open, so
        !          2671:     // all that remains is for us to dereference the open
        !          2672:     // as would have been done in the interrupt handler.
        !          2673:     //
        !          2674:     // Closes that are not at the top of the queue we
        !          2675:     // leave in place; when we restart the queue after
        !          2676:     // the reset, they will get processed.
        !          2677:     //
        !          2678: 
        !          2679:     CurrentRequest = Adapter->FirstRequest;
        !          2680: 
        !          2681:     if (CurrentRequest) {
        !          2682: 
        !          2683:         Reserved = PSONIC_RESERVED_FROM_REQUEST(CurrentRequest);
        !          2684: 
        !          2685:         //
        !          2686:         // If the first request is a close, take it off the
        !          2687:         // queue, and "complete" it.
        !          2688:         //
        !          2689: 
        !          2690:         if (CurrentRequest->RequestType == NdisRequestClose) {
        !          2691:             Adapter->FirstRequest = Reserved->Next;
        !          2692:             --(Reserved->OpenBlock)->References;
        !          2693:             CurrentRequest = Adapter->FirstRequest;
        !          2694:         }
        !          2695: 
        !          2696:         CurrentNextLocation = &(Adapter->FirstRequest);
        !          2697: 
        !          2698:         while (CurrentRequest) {
        !          2699: 
        !          2700:             Reserved = PSONIC_RESERVED_FROM_REQUEST(CurrentRequest);
        !          2701: 
        !          2702:             if ((CurrentRequest->RequestType == NdisRequestClose) ||
        !          2703:                 (CurrentRequest->RequestType == NdisRequestOpen)) {
        !          2704: 
        !          2705:                 //
        !          2706:                 // Opens are inoffensive, we just leave them
        !          2707:                 // on the list. Closes that were not at the
        !          2708:                 // head of the list were not processing and
        !          2709:                 // can be left on also.
        !          2710:                 //
        !          2711: 
        !          2712:                 CurrentNextLocation = &(Reserved->Next);
        !          2713: 
        !          2714:             } else {
        !          2715: 
        !          2716:                 //
        !          2717:                 // Not a close, remove it from the list and
        !          2718:                 // fail it.
        !          2719:                 //
        !          2720: 
        !          2721:                 *CurrentNextLocation = Reserved->Next;
        !          2722:                 TmpOpen = Reserved->OpenBlock;
        !          2723: 
        !          2724:                 NdisReleaseSpinLock(&Adapter->Lock);
        !          2725: 
        !          2726:                 NdisCompleteRequest(
        !          2727:                     TmpOpen->NdisBindingContext,
        !          2728:                     CurrentRequest,
        !          2729:                     NDIS_STATUS_RESET_IN_PROGRESS
        !          2730:                     );
        !          2731: 
        !          2732:                 NdisAcquireSpinLock(&Adapter->Lock);
        !          2733: 
        !          2734:                 --TmpOpen->References;
        !          2735: 
        !          2736:             }
        !          2737: 
        !          2738:             CurrentRequest = *CurrentNextLocation;
        !          2739: 
        !          2740:         }
        !          2741: 
        !          2742:         Adapter->RequestInProgress = FALSE;
        !          2743: 
        !          2744:     }
        !          2745: 
        !          2746: }
        !          2747: 
        !          2748: #ifdef SONIC_INTERNAL
        !          2749: 
        !          2750: //
        !          2751: // The next routines are to support reading the registry to
        !          2752: // obtain information about the internal sonic on the
        !          2753: // MIPS R4000 motherboards.
        !          2754: //
        !          2755: 
        !          2756: //
        !          2757: // This structure is used as the Context in the callbacks
        !          2758: // to SonicHardwareSaveInformation.
        !          2759: //
        !          2760: 
        !          2761: typedef struct _SONIC_HARDWARE_INFO {
        !          2762: 
        !          2763:     //
        !          2764:     // These are read out of the "Configuration Data"
        !          2765:     // data.
        !          2766:     //
        !          2767: 
        !          2768:     CCHAR InterruptVector;
        !          2769:     KIRQL InterruptLevel;
        !          2770:     USHORT DataConfigurationRegister;
        !          2771:     LARGE_INTEGER PortAddress;
        !          2772:     BOOLEAN DataValid;
        !          2773:     UCHAR EthernetAddress[8];
        !          2774:     BOOLEAN AddressValid;
        !          2775: 
        !          2776:     //
        !          2777:     // This is set to TRUE if "Identifier" is equal to
        !          2778:     // "SONIC".
        !          2779:     //
        !          2780: 
        !          2781:     BOOLEAN SonicIdentifier;
        !          2782: 
        !          2783: } SONIC_HARDWARE_INFO, *PSONIC_HARDWARE_INFO;
        !          2784: 
        !          2785: 
        !          2786: STATIC
        !          2787: NTSTATUS
        !          2788: SonicHardwareSaveInformation(
        !          2789:     IN PWSTR ValueName,
        !          2790:     IN ULONG ValueType,
        !          2791:     IN PVOID ValueData,
        !          2792:     IN ULONG ValueLength,
        !          2793:     IN PVOID Context,
        !          2794:     IN PVOID EntryContext
        !          2795:     )
        !          2796: 
        !          2797: /*++
        !          2798: 
        !          2799: Routine Description:
        !          2800: 
        !          2801:     This routine is a callback routine for RtlQueryRegistryValues.
        !          2802:     It is called back with the data for the "Identifier" value
        !          2803:     and verifies that it is "SONIC", then is called back with
        !          2804:     the resource list and records the ports, interrupt number,
        !          2805:     and DCR value.
        !          2806: 
        !          2807: Arguments:
        !          2808: 
        !          2809:     ValueName - The name of the value ("Identifier" or "Configuration
        !          2810:         Data").
        !          2811: 
        !          2812:     ValueType - The type of the value (REG_SZ or REG_BINARY).
        !          2813: 
        !          2814:     ValueData - The null-terminated data for the value.
        !          2815: 
        !          2816:     ValueLength - The length of ValueData (ignored).
        !          2817: 
        !          2818:     Context - A pointer to the SONIC_HARDWARE_INFO structure.
        !          2819: 
        !          2820:     EntryContext - FALSE for "Identifier", TRUE for "Configuration Data".
        !          2821: 
        !          2822: Return Value:
        !          2823: 
        !          2824:     STATUS_SUCCESS
        !          2825: 
        !          2826: --*/
        !          2827: 
        !          2828: {
        !          2829:     PSONIC_HARDWARE_INFO HardwareInfo = (PSONIC_HARDWARE_INFO)Context;
        !          2830: 
        !          2831:     if ((BOOLEAN)EntryContext) {
        !          2832: 
        !          2833:         //
        !          2834:         // This is the "Configuration Data" callback.
        !          2835:         //
        !          2836: 
        !          2837:         if ((ValueType == REG_BINARY || ValueType == REG_FULL_RESOURCE_DESCRIPTOR) &&
        !          2838:             (ValueLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))) {
        !          2839: 
        !          2840:             BOOLEAN InterruptRead = FALSE;
        !          2841:             BOOLEAN PortAddressRead = FALSE;
        !          2842:             BOOLEAN DeviceSpecificRead = FALSE;
        !          2843:             UINT i;
        !          2844: 
        !          2845:             PCM_PARTIAL_RESOURCE_LIST ResourceList;
        !          2846:             PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
        !          2847:             PCM_SONIC_DEVICE_DATA SonicDeviceData;
        !          2848: 
        !          2849:             ResourceList =
        !          2850:                &((PCM_FULL_RESOURCE_DESCRIPTOR)ValueData)->PartialResourceList;
        !          2851: 
        !          2852:             for (i = 0; i < ResourceList->Count; i++) {
        !          2853: 
        !          2854:                 ResourceDescriptor = &(ResourceList->PartialDescriptors[i]);
        !          2855: 
        !          2856:                 switch (ResourceDescriptor->Type) {
        !          2857: 
        !          2858:                 case CmResourceTypePort:
        !          2859: 
        !          2860:                     HardwareInfo->PortAddress = ResourceDescriptor->u.Port.Start;
        !          2861:                     PortAddressRead = TRUE;
        !          2862:                     break;
        !          2863: 
        !          2864:                 case CmResourceTypeInterrupt:
        !          2865: 
        !          2866:                     HardwareInfo->InterruptVector = (CCHAR)ResourceDescriptor->u.Interrupt.Vector;
        !          2867:                     HardwareInfo->InterruptLevel = (KIRQL)ResourceDescriptor->u.Interrupt.Level;
        !          2868:                     InterruptRead = TRUE;
        !          2869:                     break;
        !          2870: 
        !          2871:                 case CmResourceTypeDeviceSpecific:
        !          2872: 
        !          2873:                     if (i == ResourceList->Count-1) {
        !          2874: 
        !          2875:                         SonicDeviceData = (PCM_SONIC_DEVICE_DATA)
        !          2876:                             &(ResourceList->PartialDescriptors[ResourceList->Count]);
        !          2877: 
        !          2878:                         //
        !          2879:                         // Make sure we have enough room for each element we read.
        !          2880:                         //
        !          2881: 
        !          2882:                         if (ResourceDescriptor->u.DeviceSpecificData.DataSize >=
        !          2883:                             (ULONG)(FIELD_OFFSET (CM_SONIC_DEVICE_DATA, EthernetAddress[0]))) {
        !          2884: 
        !          2885:                             HardwareInfo->DataConfigurationRegister =
        !          2886:                                 SonicDeviceData->DataConfigurationRegister;
        !          2887:                             DeviceSpecificRead = TRUE;
        !          2888: 
        !          2889:                             //
        !          2890:                             // Version.Revision later than 0.0 means that
        !          2891:                             // the ethernet address is there too.
        !          2892:                             //
        !          2893: 
        !          2894:                             if ((SonicDeviceData->Version != 0) ||
        !          2895:                                 (SonicDeviceData->Revision != 0)) {
        !          2896: 
        !          2897:                                 if (ResourceDescriptor->u.DeviceSpecificData.DataSize >=
        !          2898:                                     (ULONG)(FIELD_OFFSET (CM_SONIC_DEVICE_DATA, EthernetAddress[0]) + 8)) {
        !          2899: 
        !          2900:                                     SONIC_MOVE_MEMORY(
        !          2901:                                         HardwareInfo->EthernetAddress,
        !          2902:                                         SonicDeviceData->EthernetAddress,
        !          2903:                                         8);
        !          2904: 
        !          2905:                                     HardwareInfo->AddressValid = TRUE;
        !          2906: 
        !          2907:                                 }
        !          2908: 
        !          2909:                             }
        !          2910: 
        !          2911:                         }
        !          2912: 
        !          2913:                     }
        !          2914: 
        !          2915:                     break;
        !          2916: 
        !          2917:                 }
        !          2918: 
        !          2919:             }
        !          2920: 
        !          2921:             //
        !          2922:             // Make sure we got all we wanted.
        !          2923:             //
        !          2924: 
        !          2925:             if (PortAddressRead && InterruptRead && DeviceSpecificRead) {
        !          2926:                 HardwareInfo->DataValid = TRUE;
        !          2927:             }
        !          2928: 
        !          2929:         }
        !          2930: 
        !          2931:     } else {
        !          2932: 
        !          2933:         static const WCHAR SonicString[] = L"SONIC";
        !          2934: 
        !          2935:         //
        !          2936:         // This is the "Identifier" callback.
        !          2937:         //
        !          2938: 
        !          2939:         if ((ValueType == REG_SZ) &&
        !          2940:             (ValueLength >= sizeof(SonicString)) &&
        !          2941:             (RtlCompareMemory (ValueData, (PVOID)&SonicString, sizeof(SonicString)) == sizeof(SonicString))) {
        !          2942: 
        !          2943:             HardwareInfo->SonicIdentifier = TRUE;
        !          2944: 
        !          2945:         }
        !          2946: 
        !          2947:     }
        !          2948: 
        !          2949:     return STATUS_SUCCESS;
        !          2950: 
        !          2951: }
        !          2952: 
        !          2953: 
        !          2954: STATIC
        !          2955: BOOLEAN
        !          2956: SonicHardwareVerifyChecksum(
        !          2957:     IN PSONIC_ADAPTER Adapter,
        !          2958:     IN PUCHAR EthernetAddress,
        !          2959:     OUT ULONG ErrorLogData[3]
        !          2960:     )
        !          2961: 
        !          2962: /*++
        !          2963: 
        !          2964: Routine Description:
        !          2965: 
        !          2966:     This routine verifies that the checksum on the address
        !          2967:     for an internal sonic on a MIPS R4000 system is correct.
        !          2968: 
        !          2969: Arguments:
        !          2970: 
        !          2971:     Adapter - The adapter which is being verified.
        !          2972: 
        !          2973:     EthernetAddress - A pointer to the address, with the checksum
        !          2974:         following it.
        !          2975: 
        !          2976:     ErrorLogData - If the checksum is bad, returns the address
        !          2977:         and the checksum we expected.
        !          2978: 
        !          2979: Return Value:
        !          2980: 
        !          2981:     TRUE if the checksum is correct.
        !          2982: 
        !          2983: --*/
        !          2984: 
        !          2985: {
        !          2986: 
        !          2987:     //
        !          2988:     // Iteration variable.
        !          2989:     //
        !          2990:     UINT i;
        !          2991: 
        !          2992:     //
        !          2993:     // Holds the checksum value.
        !          2994:     //
        !          2995:     USHORT CheckSum = 0;
        !          2996: 
        !          2997: 
        !          2998:     //
        !          2999:     // The network address is stored in the first 6 bytes of
        !          3000:     // EthernetAddress. Following that is a zero byte followed
        !          3001:     // by a value such that the sum of a checksum on the six
        !          3002:     // bytes and this value is 0xff. The checksum is computed
        !          3003:     // by adding together the six bytes, with the carry being
        !          3004:     // wrapped back to the first byte.
        !          3005:     //
        !          3006: 
        !          3007:     for (i=0; i<6; i++) {
        !          3008: 
        !          3009:         CheckSum += EthernetAddress[i];
        !          3010:         if (CheckSum > 0xff) {
        !          3011:             CheckSum -= 0xff;
        !          3012:         }
        !          3013: 
        !          3014:     }
        !          3015: 
        !          3016: 
        !          3017:     if ((EthernetAddress[6] != 0x00)  ||
        !          3018:         ((EthernetAddress[7] + CheckSum) != 0xff)) {
        !          3019: 
        !          3020:         ErrorLogData[0] = ((ULONG)(EthernetAddress[3]) << 24) +
        !          3021:                           ((ULONG)(EthernetAddress[2]) << 16) +
        !          3022:                           ((ULONG)(EthernetAddress[1]) << 8) +
        !          3023:                           ((ULONG)(EthernetAddress[0]));
        !          3024:         ErrorLogData[1] = ((ULONG)(EthernetAddress[7]) << 24) +
        !          3025:                           ((ULONG)(EthernetAddress[6]) << 16) +
        !          3026:                           ((ULONG)(EthernetAddress[5]) << 8) +
        !          3027:                           ((ULONG)(EthernetAddress[4]));
        !          3028:         ErrorLogData[2] = 0xff - CheckSum;
        !          3029: 
        !          3030:         return FALSE;
        !          3031: 
        !          3032:     }
        !          3033: 
        !          3034:     return TRUE;
        !          3035: 
        !          3036: }
        !          3037: 
        !          3038: #endif  // SONIC_INTERNAL
        !          3039: 
        !          3040: 
        !          3041: STATIC
        !          3042: SONIC_HARDWARE_STATUS
        !          3043: SonicHardwareGetDetails(
        !          3044:     IN PSONIC_ADAPTER Adapter,
        !          3045:     IN UINT SlotNumber,
        !          3046:     IN UINT Controller,
        !          3047:     IN UINT MultifunctionAdapter,
        !          3048:     OUT PULONG InitialPort,
        !          3049:     OUT PULONG NumberOfPorts,
        !          3050:     IN OUT PUINT InterruptVector,
        !          3051:     IN OUT PUINT InterruptLevel,
        !          3052:     OUT ULONG ErrorLogData[3]
        !          3053:     )
        !          3054: 
        !          3055: /*++
        !          3056: 
        !          3057: Routine Description:
        !          3058: 
        !          3059:     This routine gets the initial port and number of ports for
        !          3060:     the Sonic. It also sets Adapter->PortShift. The ports are
        !          3061:     numbered 0, 1, 2, etc. but may appear as 16- or 32-bit
        !          3062:     ports, so PortShift will be 1 or 2 depending on how wide
        !          3063:     the ports are.
        !          3064: 
        !          3065:     It also sets the value of Adapter->DataConfigurationRegister,
        !          3066:     and may modify InterruptVector, InterruptLevel, and
        !          3067:     Adapter->PermanentNetworkAddress.
        !          3068: 
        !          3069: Arguments:
        !          3070: 
        !          3071:     Adapter - The adapter in question.
        !          3072: 
        !          3073:     SlotNumber - For the EISA card this is the slot number that the
        !          3074:         card is in.
        !          3075: 
        !          3076:     Controller - For the internal version, it is the
        !          3077:         NetworkController number.
        !          3078: 
        !          3079:     MultifunctionAdapter - For the internal version, it is the adapter number.
        !          3080: 
        !          3081:     InitialPort - The base of the Sonic ports.
        !          3082: 
        !          3083:     NumberOfPorts - The number of bytes of ports to map.
        !          3084: 
        !          3085:     InterruptVector - A pointer to the interrupt vector. Depending
        !          3086:         on the card type, this may be passed in or returned by
        !          3087:         this function.
        !          3088: 
        !          3089:     InterruptLevel - A pointer to the interrupt level. Depending
        !          3090:         on the card type, this may be passed in or returned by
        !          3091:         this function.
        !          3092: 
        !          3093:     ErrorLogData - If the return status is SonicHardwareChecksum,
        !          3094:         this returns 3 longwords to be included in the error log.
        !          3095: 
        !          3096: Return Value:
        !          3097: 
        !          3098:     SonicHardwareOk if successful, SonicHardwareChecksum if the
        !          3099:     checksum is bad, SonicHardwareConfig for other problems.
        !          3100: 
        !          3101: --*/
        !          3102: 
        !          3103: {
        !          3104: 
        !          3105:     switch (Adapter->AdapterType) {
        !          3106: 
        !          3107: #ifdef SONIC_EISA
        !          3108: 
        !          3109:     case SONIC_ADAPTER_TYPE_EISA:
        !          3110: 
        !          3111:         *InitialPort = (SlotNumber << 12);
        !          3112:         *NumberOfPorts = 0xD00;
        !          3113:         Adapter->PortShift = 1;
        !          3114:         Adapter->DataConfigurationRegister =
        !          3115:             SONIC_DCR_PROGRAMMABLE_OUTPUT_1 |
        !          3116:             SONIC_DCR_USER_DEFINABLE_1 |
        !          3117:             SONIC_DCR_3_WAIT_STATE |
        !          3118:             SONIC_DCR_BLOCK_MODE_DMA |
        !          3119:             SONIC_DCR_32_BIT_DATA_WIDTH |
        !          3120:             SONIC_DCR_8_WORD_RECEIVE_FIFO |
        !          3121:             SONIC_DCR_8_WORD_TRANSMIT_FIFO;
        !          3122: 
        !          3123:         return SonicHardwareOk;
        !          3124:         break;
        !          3125: 
        !          3126: #endif  // SONIC_EISA
        !          3127: 
        !          3128: #ifdef SONIC_INTERNAL
        !          3129: 
        !          3130:     case SONIC_ADAPTER_TYPE_INTERNAL:
        !          3131:     {
        !          3132: 
        !          3133:         //
        !          3134:         // For MIPS R4000 systems, we have to query the registry to obtain
        !          3135:         // information about ports, interrupts, and the value to be
        !          3136:         // stored in the DCR register.
        !          3137:         //
        !          3138: 
        !          3139:         //
        !          3140:         // NOTE: The following code is NT-specific, since that is
        !          3141:         // currently the only system that runs on the MIPS R4000 hardware.
        !          3142:         //
        !          3143:         // We initialize an RTL_QUERY_TABLE to retrieve the Identifer
        !          3144:         // and ConfigurationData strings from the registry.
        !          3145:         //
        !          3146: 
        !          3147:         PWSTR ConfigDataPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter\\#\\NetworkController\\#";
        !          3148:         PWSTR IdentifierString = L"Identifier";
        !          3149:         PWSTR ConfigDataString = L"Configuration Data";
        !          3150:         RTL_QUERY_REGISTRY_TABLE QueryTable[4];
        !          3151:         SONIC_HARDWARE_INFO SonicHardwareInfo;
        !          3152:         NTSTATUS Status;
        !          3153: 
        !          3154: 
        !          3155:         //
        !          3156:         // Set up QueryTable to do the following:
        !          3157:         //
        !          3158: 
        !          3159:         //
        !          3160:         // 1) Call SonicSaveHardwareInformation for the "Identifier"
        !          3161:         // value.
        !          3162:         //
        !          3163: 
        !          3164:         QueryTable[0].QueryRoutine = SonicHardwareSaveInformation;
        !          3165:         QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
        !          3166:         QueryTable[0].Name = IdentifierString;
        !          3167:         QueryTable[0].EntryContext = (PVOID)FALSE;
        !          3168:         QueryTable[0].DefaultType = REG_NONE;
        !          3169: 
        !          3170:         //
        !          3171:         // 2) Call SonicSaveHardwareInformation for the "Configuration Data"
        !          3172:         // value.
        !          3173:         //
        !          3174: 
        !          3175:         QueryTable[1].QueryRoutine = SonicHardwareSaveInformation;
        !          3176:         QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
        !          3177:         QueryTable[1].Name = ConfigDataString;
        !          3178:         QueryTable[1].EntryContext = (PVOID)TRUE;
        !          3179:         QueryTable[1].DefaultType = REG_NONE;
        !          3180: 
        !          3181:         //
        !          3182:         // 3) Stop
        !          3183:         //
        !          3184: 
        !          3185:         QueryTable[2].QueryRoutine = NULL;
        !          3186:         QueryTable[2].Flags = 0;
        !          3187:         QueryTable[2].Name = NULL;
        !          3188: 
        !          3189: 
        !          3190:         //
        !          3191:         // Modify ConfigDataPath to replace the two # symbols with
        !          3192:         // the MultifunctionAdapter number and NetworkController number.
        !          3193:         //
        !          3194: 
        !          3195:         ConfigDataPath[67] = (WCHAR)('0' + MultifunctionAdapter);
        !          3196:         ConfigDataPath[87] = (WCHAR)('0' + Controller);
        !          3197: 
        !          3198:         SonicHardwareInfo.DataValid = FALSE;
        !          3199:         SonicHardwareInfo.AddressValid = FALSE;
        !          3200:         SonicHardwareInfo.SonicIdentifier = FALSE;
        !          3201: 
        !          3202:         Status = RtlQueryRegistryValues(
        !          3203:                      RTL_REGISTRY_ABSOLUTE,
        !          3204:                      ConfigDataPath,
        !          3205:                      QueryTable,
        !          3206:                      (PVOID)&SonicHardwareInfo,
        !          3207:                      NULL);
        !          3208: 
        !          3209:         if (!NT_SUCCESS(Status)) {
        !          3210: #if DBG
        !          3211:             DbgPrint ("SONIC: Could not read hardware information\n");
        !          3212: #endif
        !          3213:             return SonicHardwareConfig;
        !          3214:         }
        !          3215: 
        !          3216:         if (SonicHardwareInfo.DataValid && SonicHardwareInfo.SonicIdentifier) {
        !          3217: 
        !          3218:             *InterruptVector = (UINT)SonicHardwareInfo.InterruptVector;
        !          3219:             *InterruptLevel = (UINT)SonicHardwareInfo.InterruptLevel;
        !          3220:             *InitialPort = SonicHardwareInfo.PortAddress.LowPart;
        !          3221:             *NumberOfPorts = 192;
        !          3222:             Adapter->PortShift = 2;
        !          3223:             Adapter->DataConfigurationRegister =
        !          3224:                 SonicHardwareInfo.DataConfigurationRegister;
        !          3225: 
        !          3226:             if (SonicHardwareInfo.AddressValid) {
        !          3227: 
        !          3228:                 if (!SonicHardwareVerifyChecksum(Adapter, SonicHardwareInfo.EthernetAddress, ErrorLogData)) {
        !          3229: #if DBG
        !          3230:                     DbgPrint("SONIC: Invalid registry network address checksum!!\n");
        !          3231: #endif
        !          3232:                     return SonicHardwareChecksum;
        !          3233:                 }
        !          3234: 
        !          3235:                 SONIC_MOVE_MEMORY(
        !          3236:                     Adapter->PermanentNetworkAddress,
        !          3237:                     SonicHardwareInfo.EthernetAddress,
        !          3238:                     8);
        !          3239:                 Adapter->PermanentAddressValid = TRUE;
        !          3240: 
        !          3241:             }
        !          3242: 
        !          3243:             return SonicHardwareOk;
        !          3244: 
        !          3245:         } else {
        !          3246: 
        !          3247: #if DBG
        !          3248:             DbgPrint ("SONIC: Incorrect registry hardware information\n");
        !          3249: #endif
        !          3250:             return SonicHardwareConfig;
        !          3251: 
        !          3252:         }
        !          3253: 
        !          3254:         break;
        !          3255: 
        !          3256:     }
        !          3257: 
        !          3258: #endif  // SONIC_INTERNAL
        !          3259: 
        !          3260:     default:
        !          3261: 
        !          3262:         ASSERT(FALSE);
        !          3263:         break;
        !          3264: 
        !          3265:     }
        !          3266: 
        !          3267:     return SonicHardwareConfig;
        !          3268: 
        !          3269: }
        !          3270: 
        !          3271: 
        !          3272: STATIC
        !          3273: BOOLEAN
        !          3274: SonicHardwareGetAddress(
        !          3275:     IN PSONIC_ADAPTER Adapter,
        !          3276:     IN ULONG ErrorLogData[3]
        !          3277:     )
        !          3278: 
        !          3279: /*++
        !          3280: 
        !          3281: Routine Description:
        !          3282: 
        !          3283:     This routine gets the network address from the hardware.
        !          3284: 
        !          3285: Arguments:
        !          3286: 
        !          3287:     Adapter - Where to store the network address.
        !          3288: 
        !          3289:     ErrorLogData - If the checksum is bad, returns the address
        !          3290:         and the checksum we expected.
        !          3291: 
        !          3292: Return Value:
        !          3293: 
        !          3294:     TRUE if successful.
        !          3295: 
        !          3296: --*/
        !          3297: 
        !          3298: {
        !          3299: #define NVRAM_READ_ONLY_BASE 0x8000b000
        !          3300: 
        !          3301:     //
        !          3302:     // Iteration variable.
        !          3303:     //
        !          3304:     UINT i;
        !          3305: 
        !          3306: 
        !          3307:     switch (Adapter->AdapterType) {
        !          3308: 
        !          3309: #ifdef SONIC_EISA
        !          3310: 
        !          3311:     case SONIC_ADAPTER_TYPE_EISA:
        !          3312: 
        !          3313:         //
        !          3314:         // The EISA card has the address stored at ports xC90 to xC95,
        !          3315:         // where x is the slot number.
        !          3316:         //
        !          3317: 
        !          3318:         for (i = 0; i < 6; i++) {
        !          3319: 
        !          3320:             NdisRawReadPortUchar(
        !          3321:                 Adapter->SonicPortAddress + 0xc90 + i,
        !          3322:                 &Adapter->PermanentNetworkAddress[i]);
        !          3323: 
        !          3324:         }
        !          3325: 
        !          3326:         break;
        !          3327: 
        !          3328: #endif  // SONIC_EISA
        !          3329: 
        !          3330: #ifdef SONIC_INTERNAL
        !          3331: 
        !          3332:     case SONIC_ADAPTER_TYPE_INTERNAL:
        !          3333:     {
        !          3334: 
        !          3335:         NDIS_STATUS Status;
        !          3336:         USHORT SiliconRevision;
        !          3337: 
        !          3338:         if (!Adapter->PermanentAddressValid) {
        !          3339: 
        !          3340:             //
        !          3341:             // Physical addresses for call to NdisMapIoSpace.
        !          3342:             //
        !          3343: 
        !          3344:             NDIS_PHYSICAL_ADDRESS NvRamPhysical =
        !          3345:                                 NDIS_PHYSICAL_ADDRESS_CONST(NVRAM_READ_ONLY_BASE, 0);
        !          3346: 
        !          3347:             //
        !          3348:             // Temporarily maps the NVRAM into our address space.
        !          3349:             //
        !          3350:             PVOID NvRamMapping;
        !          3351: 
        !          3352: 
        !          3353: 
        !          3354:             //
        !          3355:             // If PermanentAddressValid is still FALSE then the address
        !          3356:             // was not read by SonicHardwareGetDetails, so we must do it
        !          3357:             // here.
        !          3358:             //
        !          3359: 
        !          3360:             NdisMapIoSpace (
        !          3361:                   &Status,
        !          3362:                   &NvRamMapping,
        !          3363:                   Adapter->NdisAdapterHandle,
        !          3364:                   NvRamPhysical,
        !          3365:                   8
        !          3366:                   );
        !          3367: 
        !          3368:             if (Status != NDIS_STATUS_SUCCESS) {
        !          3369: 
        !          3370:                 NdisWriteErrorLogEntry(
        !          3371:                     Adapter->NdisAdapterHandle,
        !          3372:                     NDIS_ERROR_CODE_RESOURCE_CONFLICT,
        !          3373:                     0
        !          3374:                     );
        !          3375: 
        !          3376:                 return(FALSE);
        !          3377: 
        !          3378:             }
        !          3379: 
        !          3380:             //
        !          3381:             // Verify that the checksum matches.
        !          3382:             //
        !          3383: 
        !          3384:             if (!SonicHardwareVerifyChecksum(Adapter, (PUCHAR)NvRamMapping, ErrorLogData)) {
        !          3385: 
        !          3386: #if DBG
        !          3387:                 DbgPrint("SONIC: Invalid NVRAM network address checksum!!\n");
        !          3388: #endif
        !          3389:                 NdisUnmapIoSpace(Adapter->NdisAdapterHandle, NvRamMapping, 8);
        !          3390:                 return FALSE;
        !          3391: 
        !          3392:             }
        !          3393: 
        !          3394:             //
        !          3395:             // Checksum is OK, save the address.
        !          3396:             //
        !          3397: 
        !          3398:             for (i=0; i<6; i++) {
        !          3399:                 Adapter->PermanentNetworkAddress[i] = *((PUCHAR)NvRamMapping+i);
        !          3400:             }
        !          3401:             Adapter->PermanentAddressValid = TRUE;
        !          3402: 
        !          3403:             NdisUnmapIoSpace(Adapter->NdisAdapterHandle, NvRamMapping, 8);
        !          3404: 
        !          3405:         }
        !          3406: 
        !          3407:         //
        !          3408:         // The Data Configuration Register is already set up, but we
        !          3409:         // change the FIFO initialization for old revisions.
        !          3410:         //
        !          3411: 
        !          3412:         SONIC_READ_PORT(Adapter, SONIC_SILICON_REVISION, &SiliconRevision);
        !          3413: 
        !          3414:         if (SiliconRevision < 4) {
        !          3415: 
        !          3416:             Adapter->DataConfigurationRegister =
        !          3417:                 (Adapter->DataConfigurationRegister & SONIC_DCR_FIFO_MASK) |
        !          3418:                 SONIC_DCR_8_WORD_RECEIVE_FIFO |
        !          3419:                 SONIC_DCR_8_WORD_TRANSMIT_FIFO;
        !          3420: 
        !          3421:         }
        !          3422: 
        !          3423:         break;
        !          3424: 
        !          3425:     }
        !          3426: 
        !          3427: #endif  // SONIC_INTERNAL
        !          3428: 
        !          3429:     default:
        !          3430: 
        !          3431:         ASSERT(FALSE);
        !          3432:         break;
        !          3433: 
        !          3434:     }
        !          3435: 
        !          3436: 
        !          3437: #if DBG
        !          3438:     if (SonicDbg) {
        !          3439:         DbgPrint("SONIC: ");
        !          3440:         DbgPrint("[ %x-%x-%x-%x-%x-%x ]\n",
        !          3441:             (UCHAR)Adapter->PermanentNetworkAddress[0],
        !          3442:             (UCHAR)Adapter->PermanentNetworkAddress[1],
        !          3443:             (UCHAR)Adapter->PermanentNetworkAddress[2],
        !          3444:             (UCHAR)Adapter->PermanentNetworkAddress[3],
        !          3445:             (UCHAR)Adapter->PermanentNetworkAddress[4],
        !          3446:             (UCHAR)Adapter->PermanentNetworkAddress[5]);
        !          3447:         DbgPrint("\n");
        !          3448:     }
        !          3449: #endif
        !          3450: 
        !          3451:     return TRUE;
        !          3452: 
        !          3453: }
        !          3454: 
        !          3455: 
        !          3456: VOID
        !          3457: SonicShutdown(
        !          3458:     IN PVOID ShutdownContext
        !          3459:     )
        !          3460: 
        !          3461: /*++
        !          3462: 
        !          3463: Routine Description:
        !          3464: 
        !          3465:     Turns off the card during a powerdown of the system.
        !          3466: 
        !          3467: Arguments:
        !          3468: 
        !          3469:     ShutdownContext - Really a pointer to the adapter structure.
        !          3470: 
        !          3471: Return Value:
        !          3472: 
        !          3473:     None.
        !          3474: 
        !          3475: --*/
        !          3476: 
        !          3477: {
        !          3478:     PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)(ShutdownContext);
        !          3479: 
        !          3480:     NdisAcquireSpinLock(&Adapter->Lock);
        !          3481: 
        !          3482:     //
        !          3483:     // Set the flag
        !          3484:     //
        !          3485: 
        !          3486:     Adapter->Removed = TRUE;
        !          3487: 
        !          3488:     //
        !          3489:     // Shut down the chip.  We won't be doing any more work until
        !          3490:     // the reset is complete.
        !          3491:     //
        !          3492: 
        !          3493:     SonicStopChip(Adapter);
        !          3494: 
        !          3495:     NdisStallExecution(250000);
        !          3496: 
        !          3497:     NdisReleaseSpinLock(&Adapter->Lock);
        !          3498: 
        !          3499: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.