|
|
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.