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

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990-1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     request.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This is the cose to handle NdisRequestss for the National Semiconductor
        !            12:     SONIC 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 macro determines if the directed address
        !            42: // filtering in the CAM is actually necessary given
        !            43: // the current filter.
        !            44: //
        !            45: 
        !            46: #define CAM_DIRECTED_SIGNIFICANT(_Filter) \
        !            47:     ((((_Filter) & NDIS_PACKET_TYPE_DIRECTED) && \
        !            48:     (!((_Filter) & NDIS_PACKET_TYPE_PROMISCUOUS))) ? 1 : 0)
        !            49: 
        !            50: 
        !            51: //
        !            52: // This macro determines if the multicast filtering in
        !            53: // the CAM are actually necessary given the current filter.
        !            54: //
        !            55: 
        !            56: #define CAM_MULTICAST_SIGNIFICANT(_Filter) \
        !            57:     ((((_Filter) & NDIS_PACKET_TYPE_MULTICAST) && \
        !            58:     (!((_Filter) & (NDIS_PACKET_TYPE_ALL_MULTICAST | \
        !            59:                     NDIS_PACKET_TYPE_PROMISCUOUS)))) ? 1 : 0)
        !            60: 
        !            61: 
        !            62: STATIC
        !            63: NDIS_STATUS
        !            64: SonicQueryInformation(
        !            65:     IN PSONIC_ADAPTER Adapter,
        !            66:     IN PSONIC_OPEN Open,
        !            67:     IN NDIS_OID Oid,
        !            68:     IN PVOID InformationBuffer,
        !            69:     IN UINT InformationBufferLength,
        !            70:     IN PUINT BytesWritten,
        !            71:     IN PUINT BytesNeeded,
        !            72:     IN BOOLEAN Global
        !            73:     );
        !            74: 
        !            75: STATIC
        !            76: NDIS_STATUS
        !            77: SonicSetInformation(
        !            78:     IN PSONIC_ADAPTER Adapter,
        !            79:     IN PSONIC_OPEN Open,
        !            80:     IN NDIS_OID Oid,
        !            81:     IN PVOID InformationBuffer,
        !            82:     IN UINT InformationBufferLength,
        !            83:     IN PUINT BytesRead,
        !            84:     IN PUINT BytesNeeded
        !            85:     );
        !            86: 
        !            87: STATIC
        !            88: MULTICAST_STATUS
        !            89: ChangeClassDispatch(
        !            90:     IN PSONIC_ADAPTER Adapter,
        !            91:     IN UINT OldFilterClasses,
        !            92:     IN UINT NewFilterClasses,
        !            93:     IN BOOLEAN Set
        !            94:     );
        !            95: 
        !            96: STATIC
        !            97: MULTICAST_STATUS
        !            98: ChangeAddressDispatch(
        !            99:     IN PSONIC_ADAPTER Adapter,
        !           100:     IN UINT AddressCount,
        !           101:     IN CHAR Addresses[][ETH_LENGTH_OF_ADDRESS],
        !           102:     IN BOOLEAN Set
        !           103:     );
        !           104: 
        !           105: 
        !           106: 
        !           107: 
        !           108: extern
        !           109: NDIS_STATUS
        !           110: SonicRequest(
        !           111:     IN NDIS_HANDLE MacBindingHandle,
        !           112:     IN PNDIS_REQUEST NdisRequest
        !           113:     )
        !           114: 
        !           115: /*++
        !           116: 
        !           117: Routine Description:
        !           118: 
        !           119:     The SonicRequest function handles general requests from the
        !           120:     protocol. Currently these include SetInformation and
        !           121:     QueryInformation, more may be added in the future.
        !           122: 
        !           123: Arguments:
        !           124: 
        !           125:     MacBindingHandle - The context value returned by the MAC  when the
        !           126:     adapter was opened.  In reality, it is a pointer to SONIC_OPEN.
        !           127: 
        !           128:     NdisRequest - A structure describing the request. In the case
        !           129:     of asynchronous completion, this pointer will be used to
        !           130:     identify the request that is completing.
        !           131: 
        !           132: Return Value:
        !           133: 
        !           134:     The function value is the status of the operation.
        !           135: 
        !           136: 
        !           137: --*/
        !           138: 
        !           139: {
        !           140:     //
        !           141:     // This holds the status we will return.
        !           142:     //
        !           143:     NDIS_STATUS StatusOfRequest;
        !           144: 
        !           145:     //
        !           146:     // Points to the adapter that this request is coming through.
        !           147:     //
        !           148:     PSONIC_ADAPTER Adapter;
        !           149: 
        !           150:     //
        !           151:     // Points to the MacReserved section of the request.
        !           152:     //
        !           153:     PSONIC_REQUEST_RESERVED Reserved = PSONIC_RESERVED_FROM_REQUEST(NdisRequest);
        !           154: 
        !           155: 
        !           156:     Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !           157: 
        !           158:     NdisAcquireSpinLock(&Adapter->Lock);
        !           159:     Adapter->References++;
        !           160: 
        !           161:     if (!Adapter->ResetInProgress) {
        !           162: 
        !           163:         PSONIC_OPEN Open;
        !           164: 
        !           165:         Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !           166: 
        !           167:         if (!Open->BindingShuttingDown) {
        !           168: 
        !           169:             switch (NdisRequest->RequestType) {
        !           170: 
        !           171:             case NdisRequestSetInformation:
        !           172:             case NdisRequestQueryInformation:
        !           173: 
        !           174:                 //
        !           175:                 // This is a valid request, queue it.
        !           176:                 //
        !           177: 
        !           178:                 Open->References++;
        !           179: 
        !           180:                 Reserved->OpenBlock = Open;
        !           181:                 Reserved->Next = (PNDIS_REQUEST)NULL;
        !           182: 
        !           183:                 SonicQueueRequest (Adapter, NdisRequest);
        !           184: 
        !           185:                 StatusOfRequest = NDIS_STATUS_PENDING;
        !           186:                 break;
        !           187: 
        !           188:             default:
        !           189: 
        !           190:                 //
        !           191:                 // Unknown request
        !           192:                 //
        !           193: 
        !           194:                 StatusOfRequest = NDIS_STATUS_NOT_SUPPORTED;
        !           195:                 break;
        !           196: 
        !           197:             }
        !           198: 
        !           199:         } else {
        !           200: 
        !           201:             StatusOfRequest = NDIS_STATUS_CLOSING;
        !           202: 
        !           203:         }
        !           204: 
        !           205:     } else {
        !           206: 
        !           207:         StatusOfRequest = NDIS_STATUS_RESET_IN_PROGRESS;
        !           208: 
        !           209:     }
        !           210: 
        !           211: 
        !           212:     //
        !           213:     // This macro assumes it is called with the lock held,
        !           214:     // and releases it.
        !           215:     //
        !           216: 
        !           217:     SONIC_DO_DEFERRED(Adapter);
        !           218:     return StatusOfRequest;
        !           219: }
        !           220: 
        !           221: extern
        !           222: VOID
        !           223: SonicQueueRequest(
        !           224:     IN PSONIC_ADAPTER Adapter,
        !           225:     IN PNDIS_REQUEST NdisRequest
        !           226:     )
        !           227: 
        !           228: /*++
        !           229: 
        !           230: Routine Description:
        !           231: 
        !           232:     SonicQueueRequest takes an NDIS_REQUEST and ensures that it
        !           233:     gets processed and completed. It processes the
        !           234:     request immediately if nothing else is in progress, otherwise
        !           235:     it queues it for later processing.
        !           236: 
        !           237:     THIS ROUTINE IS CALLED WITH THE LOCK HELD.
        !           238: 
        !           239: Arguments:
        !           240: 
        !           241:     Adapter - The adapter that the request is for.
        !           242: 
        !           243:     NdisRequest - The NDIS_REQUEST structure describing the request.
        !           244:         The SonicReserved section is partially filled in, except
        !           245:         for the queueing and current offset fields.
        !           246: 
        !           247: Return Value:
        !           248: 
        !           249:     NDIS_STATUS_PENDING if the request was queued.
        !           250:     Otherwise, the return code from SonicProcessRequestQueue.
        !           251:     This will be NDIS_STATUS_PENDING if the request was queued
        !           252:     to the adapter, otherwise the status of the request.
        !           253: 
        !           254: 
        !           255: --*/
        !           256: 
        !           257: {
        !           258: 
        !           259:     //
        !           260:     // Queue the request.
        !           261:     //
        !           262: 
        !           263:     if (Adapter->FirstRequest != (PNDIS_REQUEST)NULL) {
        !           264: 
        !           265:         //
        !           266:         // Something else on the queue, just queue it.
        !           267:         //
        !           268: 
        !           269:         PSONIC_RESERVED_FROM_REQUEST(Adapter->LastRequest)->Next = NdisRequest;
        !           270:         Adapter->LastRequest = NdisRequest;
        !           271: 
        !           272:     } else {
        !           273: 
        !           274:         //
        !           275:         // The queue if empty; if nothing is in progress, if we
        !           276:         // are not resetting, then process this request; if
        !           277:         // we are resetting, then after the reset the queue
        !           278:         // will be restarted.
        !           279:         //
        !           280: 
        !           281:         Adapter->FirstRequest = NdisRequest;
        !           282:         Adapter->LastRequest = NdisRequest;
        !           283: 
        !           284:         if (!Adapter->RequestInProgress) {
        !           285: 
        !           286:             SonicProcessRequestQueue(Adapter);
        !           287: 
        !           288:         }
        !           289: 
        !           290: 
        !           291:     }
        !           292: }
        !           293: 
        !           294: extern
        !           295: VOID
        !           296: SonicProcessRequestQueue(
        !           297:     IN PSONIC_ADAPTER Adapter
        !           298:     )
        !           299: 
        !           300: /*++
        !           301: 
        !           302: Routine Description:
        !           303: 
        !           304:     SonicProcessRequestQueue takes the requests on the queue
        !           305:     and processes them as much as possible. It will complete
        !           306:     any requests that it fully processes. It will stop when
        !           307:     the queue is empty or it finds a request that has to pend.
        !           308: 
        !           309:     THIS ROUTINE IS CALLED WITH THE LOCK HELD.
        !           310: 
        !           311: Arguments:
        !           312: 
        !           313:     Adapter - The adapter that the request is for.
        !           314: 
        !           315: Return Value:
        !           316: 
        !           317:     NDIS_STATUS_PENDING (probably should be VOID...)
        !           318: 
        !           319: 
        !           320: --*/
        !           321: {
        !           322:     PNDIS_REQUEST Request;
        !           323:     PSONIC_REQUEST_RESERVED Reserved;
        !           324:     NDIS_STATUS Status;
        !           325:     PSONIC_OPEN Open;
        !           326: 
        !           327: 
        !           328:     Request = Adapter->FirstRequest;
        !           329: 
        !           330:     for (;;) {
        !           331: 
        !           332:         //
        !           333:         // Loop until we exit, which happens when a
        !           334:         // request pends, or we empty the queue.
        !           335:         //
        !           336: 
        !           337:         if (Request == (PNDIS_REQUEST)NULL) {
        !           338:             Adapter->RequestInProgress = FALSE;
        !           339:             break;
        !           340:         }
        !           341: 
        !           342:         if (Adapter->ResetInProgress) {
        !           343:             Adapter->RequestInProgress = FALSE;
        !           344:             break;
        !           345:         }
        !           346: 
        !           347:         Adapter->RequestInProgress = TRUE;
        !           348: 
        !           349:         Reserved = PSONIC_RESERVED_FROM_REQUEST(Request);
        !           350:         switch (Request->RequestType) {
        !           351: 
        !           352:         case NdisRequestClose:
        !           353: 
        !           354: #if DBG
        !           355:             if (SonicDbg) {
        !           356:                 DbgPrint("Processing Close request\n");
        !           357:             }
        !           358: #endif
        !           359: 
        !           360:             Open = Reserved->OpenBlock;
        !           361: 
        !           362:             Status = EthDeleteFilterOpenAdapter(
        !           363:                              Adapter->FilterDB,
        !           364:                              Open->NdisFilterHandle,
        !           365:                              NULL
        !           366:                              );
        !           367: 
        !           368: 
        !           369:             //
        !           370:             // If the status is successful that merely implies that
        !           371:             // we were able to delete the reference to the open binding
        !           372:             // from the filtering code.
        !           373:             //
        !           374:             // The delete filter routine can return a "special" status
        !           375:             // that indicates that there is a current NdisIndicateReceive
        !           376:             // on this binding.  See below.
        !           377:             //
        !           378: 
        !           379:             if (Status == NDIS_STATUS_SUCCESS) {
        !           380: 
        !           381:                 //
        !           382:                 // Account for the filter's reference to this open.
        !           383:                 //
        !           384: 
        !           385:                 Open->References--;
        !           386: 
        !           387:             } else if (Status == NDIS_STATUS_PENDING) {
        !           388: 
        !           389:                 //
        !           390:                 // This means that a CAM reload is needed; the
        !           391:                 // dispatch routines defer this for a close,
        !           392:                 // so we need to do it now.
        !           393:                 //
        !           394: 
        !           395:                 SonicStartCamReload(Adapter);
        !           396: 
        !           397:                 //
        !           398:                 // When the request completes we will dereference the
        !           399:                 // open to account for the filter package's reference.
        !           400:                 //
        !           401: 
        !           402:             } else if (Status == NDIS_STATUS_CLOSING_INDICATING) {
        !           403: 
        !           404:                 //
        !           405:                 // When we have this status it indicates that the filtering
        !           406:                 // code was currently doing an NdisIndicateReceive. Our
        !           407:                 // close action routine will get called when the filter
        !           408:                 // is done with us, we reload the CAM there to get
        !           409:                 // queue processing going again.
        !           410:                 //
        !           411: 
        !           412:                 Status = NDIS_STATUS_PENDING;
        !           413: 
        !           414:                 ;
        !           415: 
        !           416:             } else {
        !           417: 
        !           418:                 ASSERT(0);
        !           419: 
        !           420:             }
        !           421: 
        !           422:             //
        !           423:             // This flag prevents further requests on this binding.
        !           424:             //
        !           425: 
        !           426:             Open->BindingShuttingDown = TRUE;
        !           427: 
        !           428:             //
        !           429:             // Remove the reference kept for the fact that we
        !           430:             // had something queued.
        !           431:             //
        !           432: 
        !           433:             Open->References--;
        !           434: 
        !           435:             //
        !           436:             // Remove the open from the open list and put it on
        !           437:             // the closing list. This list is checked after every
        !           438:             // request, and when the reference count goes to zero
        !           439:             // the close is completed.
        !           440:             //
        !           441: 
        !           442:             RemoveEntryList(&Open->OpenList);
        !           443:             InsertTailList(&Adapter->CloseList,&Open->OpenList);
        !           444: 
        !           445:             break;
        !           446: 
        !           447:          case NdisRequestOpen:
        !           448: 
        !           449:             Open = Reserved->OpenBlock;
        !           450: 
        !           451: #if DBG
        !           452:             if (SonicDbg) {
        !           453:                 DbgPrint("Processing Open request\n");
        !           454:             }
        !           455: #endif
        !           456: 
        !           457:             if (!EthNoteFilterOpenAdapter(
        !           458:                     Open->OwningSonic->FilterDB,
        !           459:                     Open,
        !           460:                     Open->NdisBindingContext,
        !           461:                     &Open->NdisFilterHandle
        !           462:                     )) {
        !           463: 
        !           464:                 NdisReleaseSpinLock(&Adapter->Lock);
        !           465: 
        !           466:                 NdisCompleteOpenAdapter(
        !           467:                     Open->NdisBindingContext,
        !           468:                     NDIS_STATUS_FAILURE,
        !           469:                     0);
        !           470: 
        !           471: 
        !           472:                 NdisWriteErrorLogEntry(
        !           473:                     Adapter->NdisAdapterHandle,
        !           474:                     NDIS_ERROR_CODE_OUT_OF_RESOURCES,
        !           475:                     2,
        !           476:                     openAdapter,
        !           477:                     SONIC_ERRMSG_OPEN_DB
        !           478:                     );
        !           479: 
        !           480:                 SONIC_FREE_MEMORY(Open, sizeof(SONIC_OPEN));
        !           481: 
        !           482:                 NdisAcquireSpinLock(&Adapter->Lock);
        !           483: 
        !           484:             } else {
        !           485: 
        !           486:                 //
        !           487:                 // Everything has been filled in.  Synchronize access to the
        !           488:                 // adapter block and link the new open adapter in and increment
        !           489:                 // the opens reference count to account for the fact that the
        !           490:                 // filter routines have a "reference" to the open.
        !           491:                 //
        !           492: 
        !           493:                 InsertTailList(&Adapter->OpenBindings,&Open->OpenList);
        !           494:                 Adapter->OpenCount++;
        !           495:                 Open->References++;
        !           496: 
        !           497:                 NdisReleaseSpinLock(&Adapter->Lock);
        !           498: 
        !           499:                 NdisCompleteOpenAdapter(
        !           500:                     Open->NdisBindingContext,
        !           501:                     NDIS_STATUS_SUCCESS,
        !           502:                     0);
        !           503: 
        !           504:                 NdisAcquireSpinLock(&Adapter->Lock);
        !           505: 
        !           506:             }
        !           507: 
        !           508:             //
        !           509:             // Set this, since we want to continue processing
        !           510:             // the queue.
        !           511:             //
        !           512: 
        !           513:             Status = NDIS_STATUS_SUCCESS;
        !           514: 
        !           515:             break;
        !           516: 
        !           517:         case NdisRequestQueryInformation:
        !           518: 
        !           519: #if DBG
        !           520:             if (SonicDbg) {
        !           521:                 DbgPrint("Processing Query request\n");
        !           522:             }
        !           523: #endif
        !           524: 
        !           525:             Status = SonicQueryInformation(
        !           526:                          Adapter,
        !           527:                          Reserved->OpenBlock,
        !           528:                          Request->DATA.QUERY_INFORMATION.Oid,
        !           529:                          Request->DATA.QUERY_INFORMATION.InformationBuffer,
        !           530:                          Request->DATA.QUERY_INFORMATION.InformationBufferLength,
        !           531:                          &(Request->DATA.QUERY_INFORMATION.BytesWritten),
        !           532:                          &(Request->DATA.QUERY_INFORMATION.BytesNeeded),
        !           533:                          FALSE);
        !           534: 
        !           535:             break;
        !           536: 
        !           537:         case NdisRequestQueryStatistics:
        !           538: 
        !           539:             Status = SonicQueryInformation(
        !           540:                          Adapter,
        !           541:                          Reserved->OpenBlock,
        !           542:                          Request->DATA.QUERY_INFORMATION.Oid,
        !           543:                          Request->DATA.QUERY_INFORMATION.InformationBuffer,
        !           544:                          Request->DATA.QUERY_INFORMATION.InformationBufferLength,
        !           545:                          &(Request->DATA.QUERY_INFORMATION.BytesWritten),
        !           546:                          &(Request->DATA.QUERY_INFORMATION.BytesNeeded),
        !           547:                          TRUE);
        !           548: 
        !           549:             break;
        !           550: 
        !           551:         case NdisRequestSetInformation:
        !           552: 
        !           553: #if DBG
        !           554:             if (SonicDbg) {
        !           555:                 DbgPrint("Processing Set request\n");
        !           556:             }
        !           557: #endif
        !           558: 
        !           559:             Status = SonicSetInformation(
        !           560:                          Adapter,
        !           561:                          Reserved->OpenBlock,
        !           562:                          Request->DATA.SET_INFORMATION.Oid,
        !           563:                          Request->DATA.SET_INFORMATION.InformationBuffer,
        !           564:                          Request->DATA.SET_INFORMATION.InformationBufferLength,
        !           565:                          &(Request->DATA.SET_INFORMATION.BytesRead),
        !           566:                          &(Request->DATA.SET_INFORMATION.BytesNeeded));
        !           567: 
        !           568:             break;
        !           569: 
        !           570:         }
        !           571: 
        !           572: 
        !           573:         //
        !           574:         // If the operation pended, then stop processing the queue.
        !           575:         //
        !           576: 
        !           577:         if (Status == NDIS_STATUS_PENDING) {
        !           578:             return;
        !           579:         }
        !           580: 
        !           581: 
        !           582:         //
        !           583:         // If we fall through here, we are done with this request.
        !           584:         //
        !           585: 
        !           586:         Adapter->FirstRequest = Reserved->Next;
        !           587: 
        !           588:         if ((Request->RequestType == NdisRequestQueryInformation) ||
        !           589:             (Request->RequestType == NdisRequestSetInformation)) {
        !           590: 
        !           591:             Open = Reserved->OpenBlock;
        !           592: 
        !           593:             NdisReleaseSpinLock(&Adapter->Lock);
        !           594: 
        !           595:             NdisCompleteRequest(
        !           596:                 Open->NdisBindingContext,
        !           597:                 Request,
        !           598:                 Status);
        !           599: 
        !           600:             NdisAcquireSpinLock(&Adapter->Lock);
        !           601: 
        !           602:             --Open->References;
        !           603: 
        !           604:         } else if (Request->RequestType == NdisRequestQueryStatistics) {
        !           605: 
        !           606:             NdisReleaseSpinLock(&Adapter->Lock);
        !           607: 
        !           608:             NdisCompleteQueryStatistics(
        !           609:                 Adapter->NdisAdapterHandle,
        !           610:                 Request,
        !           611:                 Status);
        !           612: 
        !           613:             NdisAcquireSpinLock(&Adapter->Lock);
        !           614: 
        !           615:             --Adapter->References;
        !           616: 
        !           617:         }
        !           618: 
        !           619:         Request = Adapter->FirstRequest;
        !           620: 
        !           621:         //
        !           622:         // Now loop and continue on with the next request.
        !           623:         //
        !           624: 
        !           625:     }
        !           626: 
        !           627: }
        !           628: 
        !           629: extern
        !           630: NDIS_STATUS
        !           631: SonicQueryGlobalStatistics(
        !           632:     IN NDIS_HANDLE MacAdapterContext,
        !           633:     IN PNDIS_REQUEST NdisRequest
        !           634:     )
        !           635: 
        !           636: /*++
        !           637: 
        !           638: Routine Description:
        !           639: 
        !           640:     SonicQueryGlobalStatistics handles a per-adapter query
        !           641:     for statistics. It is similar to SonicQueryInformation,
        !           642:     which is per-binding.
        !           643: 
        !           644: Arguments:
        !           645: 
        !           646:     MacAdapterContext - The context value that the MAC passed
        !           647:         to NdisRegisterAdapter; actually as pointer to a
        !           648:         SONIC_ADAPTER.
        !           649: 
        !           650:     NdisRequest - Describes the query request.
        !           651: 
        !           652: Return Value:
        !           653: 
        !           654:     NDIS_STATUS_SUCCESS
        !           655:     NDIS_STATUS_PENDING
        !           656: 
        !           657: --*/
        !           658: 
        !           659: {
        !           660:     //
        !           661:     // This holds the status we will return.
        !           662:     //
        !           663: 
        !           664:     NDIS_STATUS StatusOfRequest;
        !           665: 
        !           666:     //
        !           667:     // Points to the adapter that this request is coming through.
        !           668:     //
        !           669:     PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)MacAdapterContext;
        !           670: 
        !           671:     PSONIC_REQUEST_RESERVED Reserved = PSONIC_RESERVED_FROM_REQUEST(NdisRequest);
        !           672: 
        !           673:     NdisAcquireSpinLock(&Adapter->Lock);
        !           674:     Adapter->References++;
        !           675: 
        !           676:     if (!Adapter->ResetInProgress) {
        !           677: 
        !           678:         switch (NdisRequest->RequestType) {
        !           679: 
        !           680:         case NdisRequestQueryStatistics:
        !           681: 
        !           682:             //
        !           683:             // Valid request.
        !           684:             //
        !           685: 
        !           686:             Reserved->OpenBlock = (PSONIC_OPEN)NULL;
        !           687:             Reserved->Next = (PNDIS_REQUEST)NULL;
        !           688: 
        !           689:             Adapter->References++;
        !           690: 
        !           691:             SonicQueueRequest (Adapter, NdisRequest);
        !           692: 
        !           693:             StatusOfRequest = NDIS_STATUS_PENDING;
        !           694:             break;
        !           695: 
        !           696:         default:
        !           697: 
        !           698:             //
        !           699:             // Unknown request
        !           700:             //
        !           701: 
        !           702:             StatusOfRequest = NDIS_STATUS_NOT_SUPPORTED;
        !           703:             break;
        !           704: 
        !           705:         }
        !           706: 
        !           707:     } else {
        !           708: 
        !           709:         StatusOfRequest = NDIS_STATUS_RESET_IN_PROGRESS;
        !           710: 
        !           711:     }
        !           712: 
        !           713: 
        !           714:     //
        !           715:     // This macro assumes it is called with the lock held,
        !           716:     // and releases it.
        !           717:     //
        !           718: 
        !           719:     SONIC_DO_DEFERRED(Adapter);
        !           720:     return StatusOfRequest;
        !           721: }
        !           722: 
        !           723: STATIC
        !           724: NDIS_STATUS
        !           725: SonicQueryInformation(
        !           726:     IN PSONIC_ADAPTER Adapter,
        !           727:     IN PSONIC_OPEN Open,
        !           728:     IN NDIS_OID Oid,
        !           729:     IN PVOID InformationBuffer,
        !           730:     IN UINT InformationBufferLength,
        !           731:     IN PUINT BytesWritten,
        !           732:     IN PUINT BytesNeeded,
        !           733:     IN BOOLEAN Global
        !           734:     )
        !           735: 
        !           736: /*++
        !           737: 
        !           738: Routine Description:
        !           739: 
        !           740:     SonicQueryInformation handles a query operation for a
        !           741:     single OID.
        !           742: 
        !           743:     THIS ROUTINE IS CALLED WITH THE LOCK HELD.
        !           744: 
        !           745: Arguments:
        !           746: 
        !           747:     Adapter - The adapter that the query is for.
        !           748: 
        !           749:     Open - The binding that the query is for.
        !           750: 
        !           751:     Oid - The OID of the query.
        !           752: 
        !           753:     InformationBuffer - Holds the result of the query.
        !           754: 
        !           755:     InformationBufferLength - The length of InformationBuffer.
        !           756: 
        !           757:     BytesWritten - If the call is successful, returns the number
        !           758:         of bytes written to InformationBuffer.
        !           759: 
        !           760:     BytesNeeded - If there is not enough room in InformationBuffer
        !           761:         to satisfy the OID, returns the amount of storage needed.
        !           762: 
        !           763:     Global - TRUE if this is for a QueryGlobalInformation, FALSE for
        !           764:         a protocol QueryInformation.
        !           765: 
        !           766: Return Value:
        !           767: 
        !           768:     NDIS_STATUS_SUCCESS
        !           769:     NDIS_STATUS_PENDING
        !           770:     NDIS_STATUS_INVALID_LENGTH
        !           771:     NDIS_STATUS_INVALID_OID
        !           772: 
        !           773: --*/
        !           774: 
        !           775: {
        !           776: 
        !           777:     INT i;
        !           778:     PNDIS_OID SupportedOidArray;
        !           779:     INT SupportedOids;
        !           780:     NDIS_OID MaskOid;
        !           781:     PVOID SourceBuffer;
        !           782:     ULONG SourceBufferLength;
        !           783:     ULONG GenericUlong;
        !           784:     USHORT GenericUshort;
        !           785:     UINT MulticastAddresses;
        !           786:     NDIS_STATUS Status;
        !           787:     UCHAR VendorId[4];
        !           788: #ifdef SONIC_EISA
        !           789:     static const UCHAR EisaDescriptor[] = "SONIC EISA Bus Master Ethernet Adapter (DP83932EB-EISA)";
        !           790: #endif
        !           791: #ifdef SONIC_INTERNAL
        !           792:     static const UCHAR InternalDescriptor[] = "MIPS R4000 on-board network controller";
        !           793: #endif
        !           794: 
        !           795:     static const NDIS_OID SonicGlobalSupportedOids[] = {
        !           796:         OID_GEN_SUPPORTED_LIST,
        !           797:         OID_GEN_HARDWARE_STATUS,
        !           798:         OID_GEN_MEDIA_SUPPORTED,
        !           799:         OID_GEN_MEDIA_IN_USE,
        !           800:         OID_GEN_MAXIMUM_LOOKAHEAD,
        !           801:         OID_GEN_MAXIMUM_FRAME_SIZE,
        !           802:         OID_GEN_MAXIMUM_TOTAL_SIZE,
        !           803:         OID_GEN_MAC_OPTIONS,
        !           804:         OID_GEN_PROTOCOL_OPTIONS,
        !           805:         OID_GEN_LINK_SPEED,
        !           806:         OID_GEN_TRANSMIT_BUFFER_SPACE,
        !           807:         OID_GEN_RECEIVE_BUFFER_SPACE,
        !           808:         OID_GEN_TRANSMIT_BLOCK_SIZE,
        !           809:         OID_GEN_RECEIVE_BLOCK_SIZE,
        !           810:         OID_GEN_VENDOR_ID,
        !           811:         OID_GEN_VENDOR_DESCRIPTION,
        !           812:         OID_GEN_DRIVER_VERSION,
        !           813:         OID_GEN_CURRENT_PACKET_FILTER,
        !           814:         OID_GEN_CURRENT_LOOKAHEAD,
        !           815:         OID_GEN_XMIT_OK,
        !           816:         OID_GEN_RCV_OK,
        !           817:         OID_GEN_XMIT_ERROR,
        !           818:         OID_GEN_RCV_ERROR,
        !           819:         OID_GEN_RCV_NO_BUFFER,
        !           820:         OID_GEN_DIRECTED_BYTES_XMIT,
        !           821:         OID_GEN_DIRECTED_FRAMES_XMIT,
        !           822:         OID_GEN_MULTICAST_BYTES_XMIT,
        !           823:         OID_GEN_MULTICAST_FRAMES_XMIT,
        !           824:         OID_GEN_BROADCAST_BYTES_XMIT,
        !           825:         OID_GEN_BROADCAST_FRAMES_XMIT,
        !           826:         OID_GEN_DIRECTED_BYTES_RCV,
        !           827:         OID_GEN_DIRECTED_FRAMES_RCV,
        !           828:         OID_GEN_MULTICAST_BYTES_RCV,
        !           829:         OID_GEN_MULTICAST_FRAMES_RCV,
        !           830:         OID_GEN_BROADCAST_BYTES_RCV,
        !           831:         OID_GEN_BROADCAST_FRAMES_RCV,
        !           832:         OID_GEN_RCV_CRC_ERROR,
        !           833:         OID_GEN_TRANSMIT_QUEUE_LENGTH,
        !           834:         OID_802_3_PERMANENT_ADDRESS,
        !           835:         OID_802_3_CURRENT_ADDRESS,
        !           836:         OID_802_3_MULTICAST_LIST,
        !           837:         OID_802_3_MAXIMUM_LIST_SIZE,
        !           838:         OID_802_3_RCV_ERROR_ALIGNMENT,
        !           839:         OID_802_3_XMIT_ONE_COLLISION,
        !           840:         OID_802_3_XMIT_MORE_COLLISIONS,
        !           841:         OID_802_3_XMIT_DEFERRED,
        !           842:         OID_802_3_XMIT_MAX_COLLISIONS,
        !           843:         OID_802_3_RCV_OVERRUN,
        !           844:         OID_802_3_XMIT_UNDERRUN,
        !           845:         OID_802_3_XMIT_HEARTBEAT_FAILURE,
        !           846:         OID_802_3_XMIT_TIMES_CRS_LOST,
        !           847:         OID_802_3_XMIT_LATE_COLLISIONS
        !           848:         };
        !           849: 
        !           850:     static const NDIS_OID SonicProtocolSupportedOids[] = {
        !           851:         OID_GEN_SUPPORTED_LIST,
        !           852:         OID_GEN_HARDWARE_STATUS,
        !           853:         OID_GEN_MEDIA_SUPPORTED,
        !           854:         OID_GEN_MEDIA_IN_USE,
        !           855:         OID_GEN_MAXIMUM_LOOKAHEAD,
        !           856:         OID_GEN_MAXIMUM_FRAME_SIZE,
        !           857:         OID_GEN_MAXIMUM_TOTAL_SIZE,
        !           858:         OID_GEN_MAC_OPTIONS,
        !           859:         OID_GEN_PROTOCOL_OPTIONS,
        !           860:         OID_GEN_LINK_SPEED,
        !           861:         OID_GEN_TRANSMIT_BUFFER_SPACE,
        !           862:         OID_GEN_RECEIVE_BUFFER_SPACE,
        !           863:         OID_GEN_TRANSMIT_BLOCK_SIZE,
        !           864:         OID_GEN_RECEIVE_BLOCK_SIZE,
        !           865:         OID_GEN_VENDOR_ID,
        !           866:         OID_GEN_VENDOR_DESCRIPTION,
        !           867:         OID_GEN_DRIVER_VERSION,
        !           868:         OID_GEN_CURRENT_PACKET_FILTER,
        !           869:         OID_GEN_CURRENT_LOOKAHEAD,
        !           870:         OID_GEN_TRANSMIT_QUEUE_LENGTH,
        !           871:         OID_802_3_PERMANENT_ADDRESS,
        !           872:         OID_802_3_CURRENT_ADDRESS,
        !           873:         OID_802_3_MULTICAST_LIST,
        !           874:         OID_802_3_MAXIMUM_LIST_SIZE
        !           875:         };
        !           876: 
        !           877:     //
        !           878:     // Check that the OID is valid.
        !           879:     //
        !           880: 
        !           881:     if (Global) {
        !           882:         SupportedOidArray = (PNDIS_OID)SonicGlobalSupportedOids;
        !           883:         SupportedOids = sizeof(SonicGlobalSupportedOids)/sizeof(ULONG);
        !           884:     } else {
        !           885:         SupportedOidArray = (PNDIS_OID)SonicProtocolSupportedOids;
        !           886:         SupportedOids = sizeof(SonicProtocolSupportedOids)/sizeof(ULONG);
        !           887:     }
        !           888: 
        !           889:     for (i=0; i<SupportedOids; i++) {
        !           890:         if (Oid == SupportedOidArray[i]) {
        !           891:             break;
        !           892:         }
        !           893:     }
        !           894: 
        !           895:     if (i == SupportedOids) {
        !           896:         *BytesWritten = 0;
        !           897:         return NDIS_STATUS_INVALID_OID;
        !           898:     }
        !           899: 
        !           900:     //
        !           901:     // Initialize these once, since this is the majority
        !           902:     // of cases.
        !           903:     //
        !           904: 
        !           905:     SourceBuffer = &GenericUlong;
        !           906:     SourceBufferLength = sizeof(ULONG);
        !           907: 
        !           908:     switch (Oid & OID_TYPE_MASK) {
        !           909: 
        !           910:     case OID_TYPE_GENERAL_OPERATIONAL:
        !           911: 
        !           912:         switch (Oid) {
        !           913: 
        !           914:         case OID_GEN_MAC_OPTIONS:
        !           915: 
        !           916:             GenericUlong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND   |
        !           917:                                    NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA  |
        !           918:                                    NDIS_MAC_OPTION_RECEIVE_SERIALIZED
        !           919:                                   );
        !           920: 
        !           921:             break;
        !           922: 
        !           923:         case OID_GEN_SUPPORTED_LIST:
        !           924: 
        !           925:             SourceBuffer =  SupportedOidArray;
        !           926:             SourceBufferLength = SupportedOids * sizeof(ULONG);
        !           927:             break;
        !           928: 
        !           929:         case OID_GEN_HARDWARE_STATUS:
        !           930: 
        !           931:             GenericUlong = NdisHardwareStatusReady;
        !           932:             break;
        !           933: 
        !           934:         case OID_GEN_MEDIA_SUPPORTED:
        !           935: 
        !           936:             GenericUlong = NdisMedium802_3;
        !           937:             break;
        !           938: 
        !           939:         case OID_GEN_MEDIA_IN_USE:
        !           940: 
        !           941:             GenericUlong = NdisMedium802_3;
        !           942:             if (Global) {
        !           943:                 if (Adapter->OpenCount == 0) {
        !           944:                     SourceBufferLength = 0;
        !           945:                 }
        !           946:             }
        !           947:             break;
        !           948: 
        !           949:         case OID_GEN_MAXIMUM_LOOKAHEAD:
        !           950: 
        !           951:             GenericUlong = (SONIC_INDICATE_MAXIMUM-14 < SONIC_LOOPBACK_MAXIMUM) ?
        !           952:                             SONIC_INDICATE_MAXIMUM-14 : SONIC_LOOPBACK_MAXIMUM;
        !           953:             break;
        !           954: 
        !           955:         case OID_GEN_MAXIMUM_FRAME_SIZE:
        !           956: 
        !           957:             GenericUlong = 1500;
        !           958:             break;
        !           959: 
        !           960:         case OID_GEN_MAXIMUM_TOTAL_SIZE:
        !           961: 
        !           962:             GenericUlong = 1514;
        !           963:             break;
        !           964: 
        !           965:         case OID_GEN_LINK_SPEED:
        !           966: 
        !           967:             GenericUlong = 100000;    // 10 Mbps in 100 bps units
        !           968:             break;
        !           969: 
        !           970:         case OID_GEN_TRANSMIT_BUFFER_SPACE:
        !           971: 
        !           972:             GenericUlong = SONIC_LARGE_BUFFER_SIZE * SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
        !           973:             break;
        !           974: 
        !           975:         case OID_GEN_RECEIVE_BUFFER_SPACE:
        !           976: 
        !           977:             GenericUlong = SONIC_LARGE_BUFFER_SIZE * SONIC_NUMBER_OF_RECEIVE_DESCRIPTORS;
        !           978:             break;
        !           979: 
        !           980:         case OID_GEN_TRANSMIT_BLOCK_SIZE:
        !           981: 
        !           982:             GenericUlong = SONIC_LARGE_BUFFER_SIZE;
        !           983:             break;
        !           984: 
        !           985:         case OID_GEN_RECEIVE_BLOCK_SIZE:
        !           986: 
        !           987:             GenericUlong = SONIC_LARGE_BUFFER_SIZE;
        !           988:             break;
        !           989: 
        !           990:         case OID_GEN_VENDOR_ID:
        !           991: 
        !           992:             SONIC_MOVE_MEMORY(VendorId, Adapter->PermanentNetworkAddress, 3);
        !           993:             VendorId[3] = 0x0;
        !           994:             SourceBuffer = VendorId;
        !           995:             SourceBufferLength = sizeof(VendorId);
        !           996:             break;
        !           997: 
        !           998:         case OID_GEN_VENDOR_DESCRIPTION:
        !           999: 
        !          1000:             switch (Adapter->AdapterType) {
        !          1001: #ifdef SONIC_EISA
        !          1002:             case SONIC_ADAPTER_TYPE_EISA:
        !          1003:                 SourceBuffer = (PVOID)EisaDescriptor;
        !          1004:                 SourceBufferLength = sizeof(EisaDescriptor);
        !          1005:                 break;
        !          1006: #endif
        !          1007: #ifdef SONIC_INTERNAL
        !          1008:             case SONIC_ADAPTER_TYPE_INTERNAL:
        !          1009:                 SourceBuffer = (PVOID)InternalDescriptor;
        !          1010:                 SourceBufferLength = sizeof(InternalDescriptor);
        !          1011:                 break;
        !          1012: #endif
        !          1013:             default:
        !          1014:                 ASSERT(FALSE);
        !          1015:                 break;
        !          1016:             }
        !          1017:             break;
        !          1018: 
        !          1019:         case OID_GEN_DRIVER_VERSION:
        !          1020: 
        !          1021:             GenericUshort = (SONIC_NDIS_MAJOR_VERSION << 8) + SONIC_NDIS_MINOR_VERSION;
        !          1022:             SourceBuffer = &GenericUshort;
        !          1023:             SourceBufferLength = sizeof(USHORT);
        !          1024:             break;
        !          1025: 
        !          1026:         case OID_GEN_CURRENT_PACKET_FILTER:
        !          1027: 
        !          1028:             if (Global) {
        !          1029:                 GenericUlong = Adapter->CurrentPacketFilter;
        !          1030:             } else {
        !          1031:                 GenericUlong = ETH_QUERY_PACKET_FILTER (Adapter->FilterDB, Open->NdisFilterHandle);
        !          1032:             }
        !          1033:             break;
        !          1034: 
        !          1035:         case OID_GEN_CURRENT_LOOKAHEAD:
        !          1036: 
        !          1037:             GenericUlong = (SONIC_INDICATE_MAXIMUM-14 < SONIC_LOOPBACK_MAXIMUM) ?
        !          1038:                             SONIC_INDICATE_MAXIMUM-14 : SONIC_LOOPBACK_MAXIMUM;
        !          1039:             break;
        !          1040: 
        !          1041:         default:
        !          1042: 
        !          1043:             ASSERT(FALSE);
        !          1044:             break;
        !          1045: 
        !          1046:         }
        !          1047: 
        !          1048:         break;
        !          1049: 
        !          1050:     case OID_TYPE_GENERAL_STATISTICS:
        !          1051: 
        !          1052:         MaskOid = (Oid & OID_INDEX_MASK) - 1;
        !          1053: 
        !          1054:         switch (Oid & OID_REQUIRED_MASK) {
        !          1055: 
        !          1056:         case OID_REQUIRED_MANDATORY:
        !          1057: 
        !          1058:             ASSERT (MaskOid < GM_ARRAY_SIZE);
        !          1059: 
        !          1060:             if (MaskOid == GM_RECEIVE_NO_BUFFER) {
        !          1061: 
        !          1062:                 //
        !          1063:                 // This one is read off the card, update unless our
        !          1064:                 // counter is more (which indicates an imminent
        !          1065:                 // overflow interrupt, so we don't update).
        !          1066:                 //
        !          1067: 
        !          1068:                 USHORT MissedPacket;
        !          1069:                 SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &MissedPacket);
        !          1070: 
        !          1071:                 if ((Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] & 0xffff) <
        !          1072:                         MissedPacket) {
        !          1073: 
        !          1074:                     Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] =
        !          1075:                         (Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] & 0xffff0000) +
        !          1076:                         MissedPacket;
        !          1077: 
        !          1078:                 }
        !          1079:             }
        !          1080: 
        !          1081:             GenericUlong = Adapter->GeneralMandatory[MaskOid];
        !          1082:             break;
        !          1083: 
        !          1084:         case OID_REQUIRED_OPTIONAL:
        !          1085: 
        !          1086:             ASSERT (MaskOid < GO_ARRAY_SIZE);
        !          1087: 
        !          1088:             if (MaskOid == GO_RECEIVE_CRC) {
        !          1089: 
        !          1090:                 //
        !          1091:                 // This one is read off the card, update unless our
        !          1092:                 // counter is more (which indicates an imminent
        !          1093:                 // overflow interrupt, so we don't update).
        !          1094:                 //
        !          1095: 
        !          1096:                 USHORT CrcError;
        !          1097:                 SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &CrcError);
        !          1098: 
        !          1099:                 if ((Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] & 0xffff) <
        !          1100:                         CrcError) {
        !          1101: 
        !          1102:                     Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] =
        !          1103:                         (Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] & 0xffff0000) +
        !          1104:                         CrcError;
        !          1105: 
        !          1106:                 }
        !          1107:             }
        !          1108: 
        !          1109:             if ((MaskOid / 2) < GO_COUNT_ARRAY_SIZE) {
        !          1110: 
        !          1111:                 if (MaskOid & 0x01) {
        !          1112:                     // Frame count
        !          1113:                     GenericUlong = Adapter->GeneralOptionalFrameCount[MaskOid / 2];
        !          1114:                 } else {
        !          1115:                     // Byte count
        !          1116:                     SourceBuffer = &Adapter->GeneralOptionalByteCount[MaskOid / 2];
        !          1117:                     SourceBufferLength = sizeof(LARGE_INTEGER);
        !          1118:                 }
        !          1119: 
        !          1120:             } else {
        !          1121: 
        !          1122:                 GenericUlong = Adapter->GeneralOptional[MaskOid - GO_ARRAY_START];
        !          1123: 
        !          1124:             }
        !          1125: 
        !          1126:             break;
        !          1127: 
        !          1128:         default:
        !          1129: 
        !          1130:             ASSERT(FALSE);
        !          1131:             break;
        !          1132: 
        !          1133:         }
        !          1134: 
        !          1135:         break;
        !          1136: 
        !          1137:     case OID_TYPE_802_3_OPERATIONAL:
        !          1138: 
        !          1139:         switch (Oid) {
        !          1140: 
        !          1141:         case OID_802_3_PERMANENT_ADDRESS:
        !          1142: 
        !          1143:             SourceBuffer = Adapter->PermanentNetworkAddress;
        !          1144:             SourceBufferLength = 6;
        !          1145:             break;
        !          1146: 
        !          1147:         case OID_802_3_CURRENT_ADDRESS:
        !          1148: 
        !          1149:             SourceBuffer = Adapter->CurrentNetworkAddress;
        !          1150:             SourceBufferLength = 6;
        !          1151:             break;
        !          1152: 
        !          1153:         case OID_802_3_MULTICAST_LIST:
        !          1154: 
        !          1155:             if (Global) {
        !          1156: 
        !          1157:                 EthQueryGlobalFilterAddresses(
        !          1158:                     &Status,
        !          1159:                     Adapter->FilterDB,
        !          1160:                     InformationBufferLength,
        !          1161:                     &MulticastAddresses,
        !          1162:                     (PVOID)InformationBuffer);
        !          1163: 
        !          1164:                 SourceBuffer = (PVOID)InformationBuffer;
        !          1165:                 SourceBufferLength = MulticastAddresses * ETH_LENGTH_OF_ADDRESS;
        !          1166: 
        !          1167:             } else {
        !          1168: 
        !          1169:                 EthQueryOpenFilterAddresses(
        !          1170:                     &Status,
        !          1171:                     Adapter->FilterDB,
        !          1172:                     Open->NdisFilterHandle,
        !          1173:                     InformationBufferLength,
        !          1174:                     &MulticastAddresses,
        !          1175:                     (PVOID)InformationBuffer);
        !          1176: 
        !          1177:                 if (Status == NDIS_STATUS_SUCCESS) {
        !          1178:                     SourceBuffer = (PVOID)InformationBuffer;
        !          1179:                     SourceBufferLength = MulticastAddresses * ETH_LENGTH_OF_ADDRESS;
        !          1180:                 } else {
        !          1181:                     SourceBuffer = (PVOID)InformationBuffer;
        !          1182:                     SourceBufferLength = ETH_LENGTH_OF_ADDRESS *
        !          1183:                         EthNumberOfOpenFilterAddresses(
        !          1184:                             Adapter->FilterDB,
        !          1185:                             Open->NdisFilterHandle);
        !          1186:                 }
        !          1187: 
        !          1188:             }
        !          1189: 
        !          1190:             break;
        !          1191: 
        !          1192:         case OID_802_3_MAXIMUM_LIST_SIZE:
        !          1193: 
        !          1194:             GenericUlong = SONIC_CAM_ENTRIES - 1;
        !          1195:             break;
        !          1196: 
        !          1197:         default:
        !          1198: 
        !          1199:             ASSERT(FALSE);
        !          1200:             break;
        !          1201: 
        !          1202:         }
        !          1203: 
        !          1204:         break;
        !          1205: 
        !          1206:     case OID_TYPE_802_3_STATISTICS:
        !          1207: 
        !          1208:         MaskOid = (Oid & OID_INDEX_MASK) - 1;
        !          1209: 
        !          1210:         switch (Oid & OID_REQUIRED_MASK) {
        !          1211: 
        !          1212:         case OID_REQUIRED_MANDATORY:
        !          1213: 
        !          1214:             ASSERT (MaskOid < MM_ARRAY_SIZE);
        !          1215: 
        !          1216:             if (MaskOid == MM_RECEIVE_ERROR_ALIGNMENT) {
        !          1217: 
        !          1218:                 //
        !          1219:                 // This one is read off the card, update unless our
        !          1220:                 // counter is more (which indicates an imminent
        !          1221:                 // overflow interrupt, so we don't update).
        !          1222:                 //
        !          1223: 
        !          1224:                 USHORT FaError;
        !          1225:                 SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &FaError);
        !          1226: 
        !          1227:                 if ((Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] & 0xffff) <
        !          1228:                         FaError) {
        !          1229: 
        !          1230:                     Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] =
        !          1231:                         (Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] & 0xffff0000) +
        !          1232:                         FaError;
        !          1233: 
        !          1234:                 }
        !          1235:             }
        !          1236: 
        !          1237:             GenericUlong = Adapter->MediaMandatory[MaskOid];
        !          1238:             break;
        !          1239: 
        !          1240:         case OID_REQUIRED_OPTIONAL:
        !          1241: 
        !          1242:             ASSERT (MaskOid < MO_ARRAY_SIZE);
        !          1243:             GenericUlong = Adapter->MediaOptional[MaskOid];
        !          1244:             break;
        !          1245: 
        !          1246:         default:
        !          1247: 
        !          1248:             ASSERT(FALSE);
        !          1249:             break;
        !          1250: 
        !          1251:         }
        !          1252: 
        !          1253:         break;
        !          1254: 
        !          1255:     }
        !          1256: 
        !          1257:     if (SourceBufferLength > InformationBufferLength) {
        !          1258:         *BytesNeeded = SourceBufferLength;
        !          1259:         return NDIS_STATUS_INVALID_LENGTH;
        !          1260:     }
        !          1261: 
        !          1262:     SONIC_MOVE_MEMORY (InformationBuffer, SourceBuffer, SourceBufferLength);
        !          1263:     *BytesWritten = SourceBufferLength;
        !          1264: 
        !          1265:     return NDIS_STATUS_SUCCESS;
        !          1266: 
        !          1267: }
        !          1268: 
        !          1269: 
        !          1270: STATIC
        !          1271: NDIS_STATUS
        !          1272: SonicSetInformation(
        !          1273:     IN PSONIC_ADAPTER Adapter,
        !          1274:     IN PSONIC_OPEN Open,
        !          1275:     IN NDIS_OID Oid,
        !          1276:     IN PVOID InformationBuffer,
        !          1277:     IN UINT InformationBufferLength,
        !          1278:     IN PUINT BytesRead,
        !          1279:     IN PUINT BytesNeeded
        !          1280:     )
        !          1281: 
        !          1282: /*++
        !          1283: 
        !          1284: Routine Description:
        !          1285: 
        !          1286:     SonicQueryInformation handles a set operation for a
        !          1287:     single OID.
        !          1288: 
        !          1289:     THIS ROUTINE IS CALLED WITH THE LOCK HELD.
        !          1290: 
        !          1291: Arguments:
        !          1292: 
        !          1293:     Adapter - The adapter that the set is for.
        !          1294: 
        !          1295:     Open - The binding that the set is for.
        !          1296: 
        !          1297:     Oid - The OID of the set.
        !          1298: 
        !          1299:     InformationBuffer - Holds the data to be set.
        !          1300: 
        !          1301:     InformationBufferLength - The length of InformationBuffer.
        !          1302: 
        !          1303:     BytesRead - If the call is successful, returns the number
        !          1304:         of bytes read from InformationBuffer.
        !          1305: 
        !          1306:     BytesNeeded - If there is not enough data in InformationBuffer
        !          1307:         to satisfy the OID, returns the amount of storage needed.
        !          1308: 
        !          1309: Return Value:
        !          1310: 
        !          1311:     NDIS_STATUS_SUCCESS
        !          1312:     NDIS_STATUS_PENDING
        !          1313:     NDIS_STATUS_INVALID_LENGTH
        !          1314:     NDIS_STATUS_INVALID_OID
        !          1315: 
        !          1316: --*/
        !          1317: 
        !          1318: {
        !          1319: 
        !          1320:     NDIS_STATUS Status;
        !          1321:     ULONG PacketFilter;
        !          1322: 
        !          1323:     //
        !          1324:     // Now check for the most common OIDs
        !          1325:     //
        !          1326: 
        !          1327:     switch (Oid) {
        !          1328: 
        !          1329:     case OID_802_3_MULTICAST_LIST:
        !          1330: 
        !          1331:         if (InformationBufferLength % ETH_LENGTH_OF_ADDRESS != 0) {
        !          1332: 
        !          1333:             //
        !          1334:             // The data must be a multiple of the Ethernet
        !          1335:             // address size.
        !          1336:             //
        !          1337: 
        !          1338:             return NDIS_STATUS_INVALID_DATA;
        !          1339: 
        !          1340:         }
        !          1341: #if DBG
        !          1342:             if (SonicDbg) {
        !          1343:                 DbgPrint("Processing Change Multicast List request\n");
        !          1344:             }
        !          1345: #endif
        !          1346: 
        !          1347: 
        !          1348:         //
        !          1349:         // Now call the filter package to set up the addresses.
        !          1350:         //
        !          1351: 
        !          1352:         Status = EthChangeFilterAddresses(
        !          1353:                      Adapter->FilterDB,
        !          1354:                      Open->NdisFilterHandle,
        !          1355:                      (PNDIS_REQUEST)NULL,
        !          1356:                      InformationBufferLength / ETH_LENGTH_OF_ADDRESS,
        !          1357:                      InformationBuffer,
        !          1358:                      TRUE
        !          1359:                      );
        !          1360: 
        !          1361:         *BytesRead = InformationBufferLength;
        !          1362: 
        !          1363:         return Status;
        !          1364: 
        !          1365:         break;
        !          1366: 
        !          1367:     case OID_GEN_CURRENT_PACKET_FILTER:
        !          1368: 
        !          1369:         if (InformationBufferLength != 4) {
        !          1370: 
        !          1371:            *BytesNeeded = 4;
        !          1372:            return NDIS_STATUS_INVALID_LENGTH;
        !          1373: 
        !          1374:         }
        !          1375: 
        !          1376: #if DBG
        !          1377:             if (SonicDbg) {
        !          1378:                 DbgPrint("Processing Change Packet Filter request\n");
        !          1379:             }
        !          1380: #endif
        !          1381: 
        !          1382:         //
        !          1383:         // Now call the filter package to set the packet filter.
        !          1384:         //
        !          1385: 
        !          1386:         SONIC_MOVE_MEMORY ((PVOID)&PacketFilter, InformationBuffer, sizeof(ULONG));
        !          1387: 
        !          1388:         //
        !          1389:         // Verify bits
        !          1390:         //
        !          1391: 
        !          1392:         if (PacketFilter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
        !          1393:                             NDIS_PACKET_TYPE_SMT |
        !          1394:                             NDIS_PACKET_TYPE_MAC_FRAME |
        !          1395:                             NDIS_PACKET_TYPE_FUNCTIONAL |
        !          1396:                             NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
        !          1397:                             NDIS_PACKET_TYPE_GROUP
        !          1398:                            )) {
        !          1399: 
        !          1400:             *BytesRead = 4;
        !          1401:             *BytesNeeded = 0;
        !          1402: 
        !          1403:             return NDIS_STATUS_NOT_SUPPORTED;
        !          1404: 
        !          1405:         }
        !          1406: 
        !          1407:         Status = EthFilterAdjust(
        !          1408:                      Adapter->FilterDB,
        !          1409:                      Open->NdisFilterHandle,
        !          1410:                      (PNDIS_REQUEST)NULL,
        !          1411:                      PacketFilter,
        !          1412:                      TRUE
        !          1413:                      );
        !          1414: 
        !          1415:         *BytesRead = 4;
        !          1416:         return Status;
        !          1417: 
        !          1418:         break;
        !          1419: 
        !          1420:     case OID_GEN_CURRENT_LOOKAHEAD:
        !          1421: 
        !          1422:         //
        !          1423:         // No need to record requested lookahead length since we
        !          1424:         // always indicate the whole packet.
        !          1425:         //
        !          1426: 
        !          1427:         *BytesRead = 4;
        !          1428:         return NDIS_STATUS_SUCCESS;
        !          1429:         break;
        !          1430: 
        !          1431:     case OID_GEN_PROTOCOL_OPTIONS:
        !          1432: 
        !          1433:         *BytesRead = 4;
        !          1434:         return NDIS_STATUS_SUCCESS;
        !          1435:         break;
        !          1436: 
        !          1437:     default:
        !          1438: 
        !          1439:         return NDIS_STATUS_INVALID_OID;
        !          1440:         break;
        !          1441: 
        !          1442:     }
        !          1443: 
        !          1444: }
        !          1445: 
        !          1446: extern
        !          1447: NDIS_STATUS
        !          1448: SonicChangeClass(
        !          1449:     IN UINT OldFilterClasses,
        !          1450:     IN UINT NewFilterClasses,
        !          1451:     IN NDIS_HANDLE MacBindingHandle,
        !          1452:     IN PNDIS_REQUEST NdisRequest,
        !          1453:     IN BOOLEAN Set
        !          1454:     )
        !          1455: 
        !          1456: /*++
        !          1457: 
        !          1458: Routine Description:
        !          1459: 
        !          1460:     Action routine that will get called when a particular filter
        !          1461:     class is first used or last cleared.
        !          1462: 
        !          1463:     NOTE: This routine assumes that it is called with the lock
        !          1464:     acquired.
        !          1465: 
        !          1466: Arguments:
        !          1467: 
        !          1468:     OldFilterClasses - The values of the class filter before it
        !          1469:     was changed.
        !          1470: 
        !          1471:     NewFilterClasses - The current value of the class filter
        !          1472: 
        !          1473:     MacBindingHandle - The context value returned by the MAC  when the
        !          1474:     adapter was opened.  In reality, it is a pointer to SONIC_OPEN.
        !          1475: 
        !          1476:     RequestHandle - A value supplied by the NDIS interface that the MAC
        !          1477:     must use when completing this request with the NdisCompleteRequest
        !          1478:     service, if the MAC completes this request asynchronously.
        !          1479: 
        !          1480:     Set - If true the change resulted from a set, otherwise the
        !          1481:     change resulted from a open closing.
        !          1482: 
        !          1483: Return Value:
        !          1484: 
        !          1485:     None.
        !          1486: 
        !          1487: 
        !          1488: --*/
        !          1489: 
        !          1490: {
        !          1491: 
        !          1492: 
        !          1493:     PSONIC_ADAPTER Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1494: 
        !          1495:     //
        !          1496:     // The open that made this request.
        !          1497:     //
        !          1498:     PSONIC_OPEN Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1499: 
        !          1500:     //
        !          1501:     // Holds the change that should be returned to the filtering package.
        !          1502:     //
        !          1503:     NDIS_STATUS StatusOfChange;
        !          1504: 
        !          1505: 
        !          1506:     if (Adapter->ResetInProgress) {
        !          1507: 
        !          1508:         StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
        !          1509: 
        !          1510:     } else {
        !          1511: 
        !          1512:         //
        !          1513:         // The whole purpose of this routine is to determine whether
        !          1514:         // the filtering changes need to result in the hardware being
        !          1515:         // reset.
        !          1516:         //
        !          1517: 
        !          1518:         ASSERT(OldFilterClasses != NewFilterClasses);
        !          1519: 
        !          1520: 
        !          1521:         if (ChangeClassDispatch(Adapter,
        !          1522:                 OldFilterClasses,
        !          1523:                 NewFilterClasses,
        !          1524:                 Set
        !          1525:                 ) == CAM_LOADED) {
        !          1526: 
        !          1527: 
        !          1528: #if DBG
        !          1529:             if (SonicDbg) {
        !          1530:                 DbgPrint("Processing Filter request pended\n");
        !          1531:             }
        !          1532: #endif
        !          1533: 
        !          1534:             StatusOfChange = NDIS_STATUS_PENDING;
        !          1535: 
        !          1536:         } else {
        !          1537: 
        !          1538: #if DBG
        !          1539:             if (SonicDbg) {
        !          1540:                 DbgPrint("Processing Filter request succeeded\n");
        !          1541:             }
        !          1542: #endif
        !          1543: 
        !          1544:             StatusOfChange = NDIS_STATUS_SUCCESS;
        !          1545: 
        !          1546:         }
        !          1547: 
        !          1548:     }
        !          1549: 
        !          1550:     return StatusOfChange;
        !          1551: 
        !          1552: }
        !          1553: 
        !          1554: STATIC
        !          1555: MULTICAST_STATUS
        !          1556: ChangeClassDispatch(
        !          1557:     IN PSONIC_ADAPTER Adapter,
        !          1558:     IN UINT OldFilterClasses,
        !          1559:     IN UINT NewFilterClasses,
        !          1560:     IN BOOLEAN Set
        !          1561:     )
        !          1562: 
        !          1563: /*++
        !          1564: 
        !          1565: Routine Description:
        !          1566: 
        !          1567:     Modifies the Receive Control Register and Cam Enable registers,
        !          1568:     then re-loads the CAM if necessary.
        !          1569: 
        !          1570: Arguments:
        !          1571: 
        !          1572:     Adapter - The adapter.
        !          1573: 
        !          1574:     Address - The address to load.
        !          1575: 
        !          1576:     CamIndex - The index of this address in the CAM.
        !          1577: 
        !          1578:     Set - TRUE if the dispatch is due to a Set, not a close.
        !          1579: 
        !          1580: Return Value:
        !          1581: 
        !          1582:     CAM_LOADED - if the CAM was reloaded.
        !          1583:     CAM_NOT_LOADED - otherwise.
        !          1584: 
        !          1585: --*/
        !          1586: 
        !          1587: {
        !          1588: 
        !          1589:     MULTICAST_STATUS DispatchStatus;
        !          1590: 
        !          1591:     //
        !          1592:     // Is a CAM re-load necessary.
        !          1593:     //
        !          1594:     BOOLEAN CamReloadNeeded;
        !          1595: 
        !          1596:     //
        !          1597:     // The new value for the RCR.
        !          1598:     //
        !          1599:     USHORT NewReceiveControl = SONIC_RCR_DEFAULT_VALUE;
        !          1600: 
        !          1601: 
        !          1602:     //
        !          1603:     // First take care of the Receive Control Register.
        !          1604:     //
        !          1605: 
        !          1606:     if (NewFilterClasses & NDIS_PACKET_TYPE_PROMISCUOUS) {
        !          1607: 
        !          1608:         NewReceiveControl |= SONIC_RCR_PROMISCUOUS_PHYSICAL |
        !          1609:                              SONIC_RCR_ACCEPT_BROADCAST |
        !          1610:                              SONIC_RCR_ACCEPT_ALL_MULTICAST;
        !          1611: 
        !          1612:     } else {
        !          1613: 
        !          1614:         if (NewFilterClasses & NDIS_PACKET_TYPE_ALL_MULTICAST) {
        !          1615: 
        !          1616:             NewReceiveControl |= SONIC_RCR_ACCEPT_ALL_MULTICAST;
        !          1617: 
        !          1618:         }
        !          1619: 
        !          1620:         if (NewFilterClasses & NDIS_PACKET_TYPE_BROADCAST) {
        !          1621: 
        !          1622:             NewReceiveControl |= SONIC_RCR_ACCEPT_BROADCAST;
        !          1623: 
        !          1624:         }
        !          1625: 
        !          1626:     }
        !          1627: 
        !          1628:     Adapter->ReceiveControlRegister = NewReceiveControl;
        !          1629:     SONIC_WRITE_PORT(Adapter, SONIC_RECEIVE_CONTROL,
        !          1630:             Adapter->ReceiveControlRegister
        !          1631:             );
        !          1632: 
        !          1633: 
        !          1634:     //
        !          1635:     // Now see if CamEnable has to be modified and the
        !          1636:     // CAM re-loaded.
        !          1637:     //
        !          1638: 
        !          1639:     CamReloadNeeded = FALSE;
        !          1640: 
        !          1641:     if (CAM_DIRECTED_SIGNIFICANT(OldFilterClasses) !=
        !          1642:         CAM_DIRECTED_SIGNIFICANT(NewFilterClasses)) {
        !          1643: 
        !          1644:         //
        !          1645:         // The NDIS_PACKET_TYPE_DIRECTED bit has changed.
        !          1646:         //
        !          1647: 
        !          1648:         CamReloadNeeded = TRUE;
        !          1649: 
        !          1650:         if (CAM_DIRECTED_SIGNIFICANT(NewFilterClasses)) {
        !          1651: 
        !          1652:             Adapter->CamDescriptorArea->CamEnable |= 1;
        !          1653: 
        !          1654:         } else {
        !          1655: 
        !          1656:             Adapter->CamDescriptorArea->CamEnable &= ~1;
        !          1657: 
        !          1658:         }
        !          1659: 
        !          1660:     }
        !          1661: 
        !          1662:     if (CAM_MULTICAST_SIGNIFICANT(OldFilterClasses) !=
        !          1663:         CAM_MULTICAST_SIGNIFICANT(NewFilterClasses)) {
        !          1664: 
        !          1665:         CamReloadNeeded = TRUE;
        !          1666: 
        !          1667:         if (CAM_MULTICAST_SIGNIFICANT(NewFilterClasses)) {
        !          1668: 
        !          1669:             Adapter->CamDescriptorArea->CamEnable |=
        !          1670:                                     Adapter->MulticastCamEnableBits;
        !          1671: 
        !          1672:         } else {
        !          1673: 
        !          1674:             Adapter->CamDescriptorArea->CamEnable &= 1;
        !          1675: 
        !          1676:         }
        !          1677: 
        !          1678:     }
        !          1679: 
        !          1680: 
        !          1681:     if (CamReloadNeeded) {
        !          1682: 
        !          1683:         //
        !          1684:         // This will cause a LOAD_CAM interrupt when it is done.
        !          1685:         //
        !          1686: 
        !          1687:         if (Set) {
        !          1688:             SonicStartCamReload(Adapter);
        !          1689:         }
        !          1690: 
        !          1691:         DispatchStatus = CAM_LOADED;
        !          1692: 
        !          1693:     } else {
        !          1694: 
        !          1695:         DispatchStatus = CAM_NOT_LOADED;
        !          1696: 
        !          1697:     }
        !          1698: 
        !          1699: 
        !          1700:     Adapter->CurrentPacketFilter = NewFilterClasses;
        !          1701: 
        !          1702:     return DispatchStatus;
        !          1703: 
        !          1704: }
        !          1705: 
        !          1706: extern
        !          1707: NDIS_STATUS
        !          1708: SonicChangeAddresses(
        !          1709:     IN UINT OldAddressCount,
        !          1710:     IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
        !          1711:     IN UINT NewAddressCount,
        !          1712:     IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
        !          1713:     IN NDIS_HANDLE MacBindingHandle,
        !          1714:     IN PNDIS_REQUEST NdisRequest,
        !          1715:     IN BOOLEAN Set
        !          1716:     )
        !          1717: 
        !          1718: /*++
        !          1719: 
        !          1720: Routine Description:
        !          1721: 
        !          1722:     Action routine that will get called when the multicast address
        !          1723:     list has changed.
        !          1724: 
        !          1725:     NOTE: This routine assumes that it is called with the lock
        !          1726:     acquired.
        !          1727: 
        !          1728: Arguments:
        !          1729: 
        !          1730:     OldAddressCount - The number of addresses in OldAddresses.
        !          1731: 
        !          1732:     OldAddresses - The old multicast address list.
        !          1733: 
        !          1734:     NewAddressCount - The number of addresses in NewAddresses.
        !          1735: 
        !          1736:     NewAddresses - The new multicast address list.
        !          1737: 
        !          1738:     MacBindingHandle - The context value returned by the MAC  when the
        !          1739:     adapter was opened.  In reality, it is a pointer to SONIC_OPEN.
        !          1740: 
        !          1741:     RequestHandle - A value supplied by the NDIS interface that the MAC
        !          1742:     must use when completing this request with the NdisCompleteRequest
        !          1743:     service, if the MAC completes this request asynchronously.
        !          1744: 
        !          1745:     Set - If true the change resulted from a set, otherwise the
        !          1746:     change resulted from a open closing.
        !          1747: 
        !          1748: Return Value:
        !          1749: 
        !          1750:     None.
        !          1751: 
        !          1752: 
        !          1753: --*/
        !          1754: 
        !          1755: {
        !          1756: 
        !          1757: 
        !          1758:     PSONIC_ADAPTER Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1759: 
        !          1760:     //
        !          1761:     // The open that made this request.
        !          1762:     //
        !          1763:     PSONIC_OPEN Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !          1764: 
        !          1765:     //
        !          1766:     // Holds the change that should be returned to the filtering package.
        !          1767:     //
        !          1768:     NDIS_STATUS StatusOfChange;
        !          1769: 
        !          1770: 
        !          1771:     if (Adapter->ResetInProgress) {
        !          1772: 
        !          1773:         StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
        !          1774: 
        !          1775:     } else {
        !          1776: 
        !          1777:         //
        !          1778:         // The whole purpose of this routine is to determine whether
        !          1779:         // the filtering changes need to result in the hardware being
        !          1780:         // reset.
        !          1781:         //
        !          1782: 
        !          1783:         if (ChangeAddressDispatch(Adapter,
        !          1784:                 NewAddressCount,
        !          1785:                 NewAddresses,
        !          1786:                 Set
        !          1787:                 ) == CAM_LOADED) {
        !          1788: 
        !          1789: 
        !          1790: #if DBG
        !          1791:             if (SonicDbg) {
        !          1792:                 DbgPrint("Processing Address request pended\n");
        !          1793:             }
        !          1794: #endif
        !          1795: 
        !          1796:             StatusOfChange = NDIS_STATUS_PENDING;
        !          1797: 
        !          1798:         } else {
        !          1799: 
        !          1800:             StatusOfChange = NDIS_STATUS_SUCCESS;
        !          1801: 
        !          1802:         }
        !          1803: 
        !          1804:     }
        !          1805: 
        !          1806:     return StatusOfChange;
        !          1807: 
        !          1808: }
        !          1809: 
        !          1810: STATIC
        !          1811: MULTICAST_STATUS
        !          1812: ChangeAddressDispatch(
        !          1813:     IN PSONIC_ADAPTER Adapter,
        !          1814:     IN UINT AddressCount,
        !          1815:     IN CHAR Addresses[][ETH_LENGTH_OF_ADDRESS],
        !          1816:     IN BOOLEAN Set
        !          1817:     )
        !          1818: 
        !          1819: /*++
        !          1820: 
        !          1821: Routine Description:
        !          1822: 
        !          1823:     Modifies the Receive Control Register and Cam Enable registers,
        !          1824:     then re-loads the CAM if necessary.
        !          1825: 
        !          1826: Arguments:
        !          1827: 
        !          1828:     Adapter - The adapter.
        !          1829: 
        !          1830:     AddressCount - The number of addresses in Addresses
        !          1831: 
        !          1832:     Addresses - The new multicast address list.
        !          1833: 
        !          1834:     Set - TRUE if the change is due to a Set, not a close.
        !          1835: 
        !          1836: Return Value:
        !          1837: 
        !          1838:     CAM_LOADED - if the CAM was reloaded.
        !          1839:     CAM_NOT_LOADED - otherwise.
        !          1840: 
        !          1841: --*/
        !          1842: 
        !          1843: {
        !          1844: 
        !          1845:     ULONG EnableBit;
        !          1846:     MULTICAST_STATUS DispatchStatus;
        !          1847:     UINT i;
        !          1848: 
        !          1849:     //
        !          1850:     // The first entry in the CAM is for our address.
        !          1851:     //
        !          1852: 
        !          1853:     Adapter->MulticastCamEnableBits = 1;
        !          1854:     EnableBit = 1;
        !          1855: 
        !          1856:     //
        !          1857:     // Loop through, copying the addresses into the CAM.
        !          1858:     //
        !          1859: 
        !          1860:     for (i=0; i<AddressCount; i++) {
        !          1861: 
        !          1862:         EnableBit <<= 1;
        !          1863:         Adapter->MulticastCamEnableBits |= EnableBit;
        !          1864: 
        !          1865:         SONIC_LOAD_CAM_FRAGMENT(
        !          1866:             &Adapter->CamDescriptorArea->CamFragments[i+1],
        !          1867:             i+1,
        !          1868:             Addresses[i]
        !          1869:             );
        !          1870: 
        !          1871:     }
        !          1872: 
        !          1873:     Adapter->CamDescriptorAreaSize = AddressCount + 1;
        !          1874: 
        !          1875:     //
        !          1876:     // Now see if we have to worry about re-loading the
        !          1877:     // CAM also.
        !          1878:     //
        !          1879: 
        !          1880:     if (CAM_MULTICAST_SIGNIFICANT(Adapter->CurrentPacketFilter)) {
        !          1881: 
        !          1882:         Adapter->CamDescriptorArea->CamEnable = Adapter->MulticastCamEnableBits;
        !          1883: 
        !          1884:         //
        !          1885:         // This will cause a LOAD_CAM interrupt when it is done.
        !          1886:         //
        !          1887: 
        !          1888:         if (Set) {
        !          1889:             SonicStartCamReload(Adapter);
        !          1890:         }
        !          1891: 
        !          1892: #if DBG
        !          1893:             if (SonicDbg) {
        !          1894:                 DbgPrint("Processing Address request pended\n");
        !          1895:             }
        !          1896: #endif
        !          1897: 
        !          1898: 
        !          1899:         DispatchStatus = CAM_LOADED;
        !          1900: 
        !          1901:     } else {
        !          1902: 
        !          1903: #if DBG
        !          1904:             if (SonicDbg) {
        !          1905:                 DbgPrint("Processing Address request succeeded\n");
        !          1906:             }
        !          1907: #endif
        !          1908: 
        !          1909:         DispatchStatus = CAM_NOT_LOADED;
        !          1910: 
        !          1911:     }
        !          1912: 
        !          1913:     return DispatchStatus;
        !          1914: 
        !          1915: }
        !          1916: 
        !          1917: extern
        !          1918: VOID
        !          1919: SonicCloseAction(
        !          1920:     IN NDIS_HANDLE MacBindingHandle
        !          1921:     )
        !          1922: 
        !          1923: /*++
        !          1924: 
        !          1925: Routine Description:
        !          1926: 
        !          1927:     Action routine that will get called when a particular binding
        !          1928:     was closed while it was indicating through NdisIndicateReceive
        !          1929: 
        !          1930:     This routine starts a CAM reload (even though nothing may
        !          1931:     have changed) so that queue processing is restarted in the
        !          1932:     completion handler).
        !          1933: 
        !          1934:     NOTE: This routine assumes that it is called with the lock acquired.
        !          1935: 
        !          1936: Arguments:
        !          1937: 
        !          1938:     MacBindingHandle - The context value returned by the MAC  when the
        !          1939:     adapter was opened.  In reality, it is a pointer to SONIC_OPEN.
        !          1940: 
        !          1941: Return Value:
        !          1942: 
        !          1943:     None.
        !          1944: 
        !          1945: 
        !          1946: --*/
        !          1947: 
        !          1948: {
        !          1949: 
        !          1950:     SonicStartCamReload(PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle));
        !          1951: 
        !          1952: }

unix.superglobalmegacorp.com

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