Annotation of ntddk/src/network/sonic/request.c, revision 1.1.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.