|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.