|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990 Microsoft Corporation
4:
5: Module Name:
6:
7: lance.c
8:
9: Abstract:
10:
11: This is the main file for the Advanced Micro Devices LANCE (Am 7990)
12: Ethernet controller. This driver conforms to the NDIS 3.0 interface.
13:
14: The idea for handling loopback and sends simultaneously is largely
15: adapted from the EtherLink II NDIS driver by Adam Barr.
16:
17: Author:
18:
19: Anthony V. Ercolano (Tonye) 20-Jul-1990
20:
21: Environment:
22:
23: Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
24:
25: Revision History:
26:
27: 31-Jul-1992 R.D. Lanser:
28:
29: Changed DECST card type to DECTC for the DEC TurboChannel option
30: PMAD-AA (Lance ethernet). This option will be available for all
31: TurboChannel systems regardless of CPU type or system.
32:
33: Removed UsedLanceBuffer conditional (always true).
34:
35: Added InterruptRequestLevel to the _LANCE_ADAPTER structure because
36: 'lance.c' was passing the InterruptVector as the IRQL to the interrupt
37: connect routine which is not correct. This works on JAZZ because the
38: JAZZ HalGetInterruptVector is hardcoded to return a fixed IRQL for
39: EISA devices.
40:
41: Remove hardcoded configuration information and added gets from the
42: registry for the base address, interrupt vector, and interrupt
43: request level.
44:
45:
46: --*/
47:
48: #include <ndis.h>
49: #include <efilter.h>
50: #include "lancehrd.h"
51: #include "lancesft.h"
52: #include "dectc.h"
53:
54: #if DBG
55: #define STATIC
56: #else
57: #define STATIC static
58: #endif
59:
60:
61: #if DBG
62:
63: UCHAR LanceSendFails[256];
64: UCHAR LanceSendFailPlace = 0;
65:
66: #endif
67:
68:
69: NDIS_HANDLE LanceNdisWrapperHandle;
70: NDIS_HANDLE LanceMacHandle;
71: PDRIVER_OBJECT LanceDriverObject;
72:
73: //
74: // This constant is used for places where NdisAllocateMemory
75: // needs to be called and the HighestAcceptableAddress does
76: // not matter.
77: //
78:
79: NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
80: NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
81:
82:
83: #if LANCELOG
84:
85: NDIS_TIMER LogTimer;
86: BOOLEAN LogTimerRunning = FALSE;
87:
88: UCHAR Log[LOG_SIZE];
89:
90: UCHAR LogPlace = 0;
91: UCHAR LogWrapped = 0;
92:
93: UCHAR LancePrintLog = 0;
94:
95: void
96: LogDpc(
97: IN PVOID SystemSpecific1,
98: PVOID Context,
99: IN PVOID SystemSpecific2,
100: IN PVOID SystemSpecific3
101: )
102: {
103:
104: UNREFERENCED_PARAMETER(Context);
105: UNREFERENCED_PARAMETER(SystemSpecific1);
106: UNREFERENCED_PARAMETER(SystemSpecific2);
107: UNREFERENCED_PARAMETER(SystemSpecific3);
108:
109: LOG(TIMER);
110:
111: NdisSetTimer(&LogTimer, 1000);
112:
113: }
114:
115:
116: #endif
117:
118:
119:
120:
121: #define MAX_MULTICAST_ADDRESS ((UINT)32)
122:
123: //
124: // Used for accessing the filter package multicast address list.
125: //
126:
127: static CHAR MulticastAddresses[MAX_MULTICAST_ADDRESS][ETH_LENGTH_OF_ADDRESS];
128:
129:
130:
131: //
132: // If you add to this, make sure to add the
133: // a case in LanceFillInGlobalData() and in
134: // LanceQueryGlobalStatistics() if global
135: // information only or
136: // LanceQueryProtocolStatistics() if it is
137: // protocol queriable information.
138: //
139: UINT LanceGlobalSupportedOids[] = {
140: OID_GEN_SUPPORTED_LIST,
141: OID_GEN_HARDWARE_STATUS,
142: OID_GEN_MEDIA_SUPPORTED,
143: OID_GEN_MEDIA_IN_USE,
144: OID_GEN_MAXIMUM_LOOKAHEAD,
145: OID_GEN_MAXIMUM_FRAME_SIZE,
146: OID_GEN_MAXIMUM_TOTAL_SIZE,
147: OID_GEN_MAC_OPTIONS,
148: OID_GEN_PROTOCOL_OPTIONS,
149: OID_GEN_LINK_SPEED,
150: OID_GEN_TRANSMIT_BUFFER_SPACE,
151: OID_GEN_RECEIVE_BUFFER_SPACE,
152: OID_GEN_TRANSMIT_BLOCK_SIZE,
153: OID_GEN_RECEIVE_BLOCK_SIZE,
154: OID_GEN_VENDOR_ID,
155: OID_GEN_VENDOR_DESCRIPTION,
156: OID_GEN_DRIVER_VERSION,
157: OID_GEN_CURRENT_PACKET_FILTER,
158: OID_GEN_CURRENT_LOOKAHEAD,
159: OID_GEN_XMIT_OK,
160: OID_GEN_RCV_OK,
161: OID_GEN_XMIT_ERROR,
162: OID_GEN_RCV_ERROR,
163: OID_GEN_RCV_NO_BUFFER,
164: OID_802_3_PERMANENT_ADDRESS,
165: OID_802_3_CURRENT_ADDRESS,
166: OID_802_3_MULTICAST_LIST,
167: OID_802_3_MAXIMUM_LIST_SIZE,
168: OID_802_3_RCV_ERROR_ALIGNMENT,
169: OID_802_3_XMIT_ONE_COLLISION,
170: OID_802_3_XMIT_MORE_COLLISIONS
171: };
172:
173: //
174: // If you add to this, make sure to add the
175: // a case in LanceQueryGlobalStatistics() and in
176: // LanceQueryProtocolInformation()
177: //
178: UINT LanceProtocolSupportedOids[] = {
179: OID_GEN_SUPPORTED_LIST,
180: OID_GEN_HARDWARE_STATUS,
181: OID_GEN_MEDIA_SUPPORTED,
182: OID_GEN_MEDIA_IN_USE,
183: OID_GEN_MAXIMUM_LOOKAHEAD,
184: OID_GEN_MAXIMUM_FRAME_SIZE,
185: OID_GEN_MAXIMUM_TOTAL_SIZE,
186: OID_GEN_MAC_OPTIONS,
187: OID_GEN_PROTOCOL_OPTIONS,
188: OID_GEN_LINK_SPEED,
189: OID_GEN_TRANSMIT_BUFFER_SPACE,
190: OID_GEN_RECEIVE_BUFFER_SPACE,
191: OID_GEN_TRANSMIT_BLOCK_SIZE,
192: OID_GEN_RECEIVE_BLOCK_SIZE,
193: OID_GEN_VENDOR_ID,
194: OID_GEN_VENDOR_DESCRIPTION,
195: OID_GEN_DRIVER_VERSION,
196: OID_GEN_CURRENT_PACKET_FILTER,
197: OID_GEN_CURRENT_LOOKAHEAD,
198: OID_802_3_PERMANENT_ADDRESS,
199: OID_802_3_CURRENT_ADDRESS,
200: OID_802_3_MULTICAST_LIST,
201: OID_802_3_MAXIMUM_LIST_SIZE
202: };
203:
204:
205:
206: //
207: // This macro is to synchronize execution with interrupts. It
208: // gets the stored value of the CSR 0 and clears the old value.
209: //
210: #define GET_CSR0_SINCE_LAST_PROCESSED(A,V) \
211: { \
212: PLANCE_ADAPTER _A = A; \
213: LANCE_SYNCH_CONTEXT _C; \
214: _C.Adapter = _A; \
215: _C.LocalRead = (V); \
216: NdisSynchronizeWithInterrupt( \
217: &(_A)->Interrupt, \
218: LanceInterruptSynch, \
219: &_C \
220: ); \
221: }
222:
223: //
224: // We define a constant csr0 value that is useful for initializing
225: // an already stopped LANCE.
226: //
227: // This also enables the chip for interrupts.
228: //
229: #define LANCE_CSR0_INIT_CHIP ((USHORT)0x41)
230:
231: //
232: // We define a constant csr0 value that is useful for clearing all of
233: // the interesting bits that *could* be set on an interrupt.
234: //
235: #define LANCE_CSR0_CLEAR_INTERRUPT_BITS ((USHORT)0x7f00)
236:
237: STATIC
238: NDIS_STATUS
239: LanceOpenAdapter(
240: OUT PNDIS_STATUS OpenErrorStatus,
241: OUT NDIS_HANDLE *MacBindingHandle,
242: OUT PUINT SelectedMediumIndex,
243: IN PNDIS_MEDIUM MediumArray,
244: IN UINT MediumArraySize,
245: IN NDIS_HANDLE NdisBindingContext,
246: IN NDIS_HANDLE MacAdapterContext,
247: IN UINT OpenOptions,
248: IN PSTRING AddressingInformation OPTIONAL
249: );
250:
251:
252: VOID
253: LanceUnload(
254: IN NDIS_HANDLE MacMacContext
255: );
256:
257: STATIC
258: NDIS_STATUS
259: LanceCloseAdapter(
260: IN NDIS_HANDLE MacBindingHandle
261: );
262:
263:
264: STATIC
265: NDIS_STATUS
266: LanceRequest(
267: IN NDIS_HANDLE MacBindingHandle,
268: IN PNDIS_REQUEST NdisRequest
269: );
270:
271: NDIS_STATUS
272: LanceQueryProtocolInformation(
273: IN PLANCE_ADAPTER Adapter,
274: IN PLANCE_OPEN Open,
275: IN NDIS_OID Oid,
276: IN BOOLEAN GlobalMode,
277: IN PVOID InfoBuffer,
278: IN UINT BytesLeft,
279: OUT PUINT BytesNeeded,
280: OUT PUINT BytesWritten
281: );
282:
283: NDIS_STATUS
284: LanceQueryInformation(
285: IN PLANCE_ADAPTER Adapter,
286: IN PLANCE_OPEN Open,
287: IN PNDIS_REQUEST NdisRequest
288: );
289:
290: NDIS_STATUS
291: LanceSetInformation(
292: IN PLANCE_ADAPTER Adapter,
293: IN PLANCE_OPEN Open,
294: IN PNDIS_REQUEST NdisRequest
295: );
296:
297: STATIC
298: NDIS_STATUS
299: LanceReset(
300: IN NDIS_HANDLE MacBindingHandle
301: );
302:
303:
304: STATIC
305: NDIS_STATUS
306: LanceSetPacketFilter(
307: IN PLANCE_ADAPTER Adapter,
308: IN PLANCE_OPEN Open,
309: IN PNDIS_REQUEST NdisRequest,
310: IN UINT PacketFilter
311: );
312:
313:
314: NDIS_STATUS
315: LanceFillInGlobalData(
316: IN PLANCE_ADAPTER Adapter,
317: IN PNDIS_REQUEST NdisRequest
318: );
319:
320:
321: STATIC
322: NDIS_STATUS
323: LanceQueryGlobalStatistics(
324: IN NDIS_HANDLE MacAdapterContext,
325: IN PNDIS_REQUEST NdisRequest
326: );
327:
328: NDIS_STATUS
329: LanceChangeMulticastAddresses(
330: IN UINT OldFilterCount,
331: IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
332: IN UINT NewFilterCount,
333: IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
334: IN NDIS_HANDLE MacBindingHandle,
335: IN PNDIS_REQUEST NdisRequest,
336: IN BOOLEAN Set
337: );
338:
339: STATIC
340: NDIS_STATUS
341: LanceChangeFilterClasses(
342: IN UINT OldFilterClasses,
343: IN UINT NewFilterClasses,
344: IN NDIS_HANDLE MacBindingHandle,
345: IN PNDIS_REQUEST NdisRequest,
346: IN BOOLEAN Set
347: );
348:
349: STATIC
350: VOID
351: LanceCloseAction(
352: IN NDIS_HANDLE MacBindingHandle
353: );
354:
355: STATIC
356: BOOLEAN
357: AllocateAdapterMemory(
358: IN PLANCE_ADAPTER Adapter
359: );
360:
361: STATIC
362: VOID
363: DeleteAdapterMemory(
364: IN PLANCE_ADAPTER Adapter
365: );
366:
367: STATIC
368: VOID
369: ReturnAdapterResources(
370: IN PLANCE_ADAPTER Adapter,
371: IN UINT BufferIndex
372: );
373:
374: STATIC
375: VOID
376: RelinquishReceivePacket(
377: IN PLANCE_ADAPTER Adapter,
378: IN UINT StartingIndex,
379: IN UINT NumberOfBuffers
380: );
381:
382: STATIC
383: BOOLEAN
384: ProcessReceiveInterrupts(
385: IN PLANCE_ADAPTER Adapter
386: );
387:
388: STATIC
389: BOOLEAN
390: ProcessTransmitInterrupts(
391: IN PLANCE_ADAPTER Adapter
392: );
393:
394: STATIC
395: VOID
396: LanceStandardInterruptDPC(
397: IN PVOID SystemSpecific,
398: IN PVOID Context,
399: IN PVOID SystemArgument1,
400: IN PVOID SystemArgument2
401: );
402:
403:
404: extern
405: BOOLEAN
406: LanceISR(
407: IN PVOID Context
408: );
409:
410: STATIC
411: BOOLEAN
412: LanceInterruptSynch(
413: IN PVOID Context
414: );
415:
416: STATIC
417: UINT
418: CalculateCRC(
419: IN UINT NumberOfBytes,
420: IN PCHAR Input
421: );
422:
423: STATIC
424: VOID
425: ProcessInterrupt(
426: IN PLANCE_ADAPTER Adapter
427: );
428:
429: STATIC
430: VOID
431: LanceStartChip(
432: IN PLANCE_ADAPTER Adapter
433: );
434:
435: STATIC
436: VOID
437: LanceSetInitializationBlock(
438: IN PLANCE_ADAPTER Adapter
439: );
440:
441: STATIC
442: VOID
443: SetInitBlockAndInit(
444: IN PLANCE_ADAPTER Adapter
445: );
446:
447: STATIC
448: VOID
449: StartAdapterReset(
450: IN PLANCE_ADAPTER Adapter
451: );
452:
453: STATIC
454: VOID
455: SetupForReset(
456: IN PLANCE_ADAPTER Adapter,
457: IN PLANCE_OPEN Open,
458: IN PNDIS_REQUEST NdisRequest,
459: IN NDIS_REQUEST_TYPE RequestType
460: );
461:
462: STATIC
463: NDIS_STATUS
464: LanceInitialInit(
465: IN PLANCE_ADAPTER Adapter
466: );
467:
468:
469: STATIC
470: VOID
471: FinishPendOp(
472: IN PLANCE_ADAPTER Adapter,
473: IN BOOLEAN Successful
474: );
475:
476:
477: //
478: // Non portable interface.
479: //
480:
481: NTSTATUS
482: DriverEntry(
483: IN PDRIVER_OBJECT DriverObject,
484: IN PUNICODE_STRING RegistryPath
485: )
486:
487: /*++
488:
489: Routine Description:
490:
491: This is the primary initialization routine for the lance driver.
492: It is simply responsible for the intializing the wrapper and registering
493: the MAC. It then calls a system and architecture specific routine that
494: will initialize and register each adapter.
495:
496: Arguments:
497:
498: DriverObject - Pointer to driver object created by the system.
499:
500: Return Value:
501:
502: The status of the operation.
503:
504: --*/
505:
506: {
507:
508:
509: //
510: // Receives the status of the NdisRegisterMac operation.
511: //
512: NDIS_STATUS InitStatus;
513:
514: NDIS_HANDLE NdisMacHandle;
515:
516: NDIS_HANDLE NdisWrapperHandle;
517:
518: char Tmp[sizeof(NDIS_MAC_CHARACTERISTICS)];
519: PNDIS_MAC_CHARACTERISTICS LanceChar = (PNDIS_MAC_CHARACTERISTICS)Tmp;
520:
521: NDIS_STRING MacName = NDIS_STRING_CONST("Lance");
522:
523: //
524: // Initialize the wrapper.
525: //
526:
527: NdisInitializeWrapper(&NdisWrapperHandle,
528: DriverObject,
529: RegistryPath,
530: NULL
531: );
532:
533: //
534: // Initialize the MAC characteristics for the call to
535: // NdisRegisterMac.
536: //
537:
538: LanceChar->MajorNdisVersion = LANCE_NDIS_MAJOR_VERSION;
539: LanceChar->MinorNdisVersion = LANCE_NDIS_MINOR_VERSION;
540: LanceChar->OpenAdapterHandler = LanceOpenAdapter;
541: LanceChar->CloseAdapterHandler = LanceCloseAdapter;
542: LanceChar->SendHandler = LanceSend;
543: LanceChar->TransferDataHandler = LanceTransferData;
544: LanceChar->ResetHandler = LanceReset;
545: LanceChar->RequestHandler = LanceRequest;
546: LanceChar->AddAdapterHandler = LanceAddAdapter;
547: LanceChar->UnloadMacHandler = LanceUnload;
548: LanceChar->RemoveAdapterHandler = LanceRemoveAdapter;
549: LanceChar->QueryGlobalStatisticsHandler = LanceQueryGlobalStatistics;
550:
551: LanceChar->Name = MacName;
552:
553: LanceDriverObject = DriverObject;
554: LanceNdisWrapperHandle = NdisWrapperHandle;
555:
556: NdisRegisterMac(
557: &InitStatus,
558: &NdisMacHandle,
559: NdisWrapperHandle,
560: &NdisMacHandle,
561: LanceChar,
562: sizeof(*LanceChar)
563: );
564:
565: LanceMacHandle = NdisMacHandle;
566:
567: if (InitStatus == NDIS_STATUS_SUCCESS) {
568:
569: return NDIS_STATUS_SUCCESS;
570:
571: }
572:
573: NdisTerminateWrapper(NdisWrapperHandle, NULL);
574:
575: return NDIS_STATUS_FAILURE;
576:
577: }
578:
579: NDIS_STATUS
580: LanceAddAdapter(
581: IN NDIS_HANDLE MacMacContext,
582: IN NDIS_HANDLE ConfigurationHandle,
583: IN PNDIS_STRING AdapterName
584: )
585: /*++
586: Routine Description:
587:
588: This is the Wd MacAddAdapter routine. The system calls this routine
589: to add support for a particular WD adapter. This routine extracts
590: configuration information from the configuration data base and registers
591: the adapter with NDIS.
592:
593: Arguments:
594:
595: see NDIS 3.0 spec...
596:
597: Return Value:
598:
599: NDIS_STATUS_SUCCESS - Adapter was successfully added.
600: NDIS_STATUS_FAILURE - Adapter was not added, also MAC deregistered.
601:
602: --*/
603: {
604: //
605: // Pointer for the adapter root.
606: //
607: PLANCE_ADAPTER Adapter;
608:
609:
610: NDIS_HANDLE ConfigHandle;
611: PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
612: NDIS_STRING IoAddressStr = NDIS_STRING_CONST("IoBaseAddress");
613: NDIS_STRING MaxMulticastListStr = NDIS_STRING_CONST("MaximumMulticastList");
614: NDIS_STRING NetworkAddressStr = NDIS_STRING_CONST("NetworkAddress");
615: NDIS_STRING InterruptStr = NDIS_STRING_CONST("InterruptNumber");
616: NDIS_STRING CardStr = NDIS_STRING_CONST("CardType");
617: NDIS_STRING MemoryBaseAddrStr = NDIS_STRING_CONST("MemoryMappedBaseAddress");
618:
619: NDIS_HANDLE NdisMacHandle = (NDIS_HANDLE)(*((PNDIS_HANDLE)MacMacContext));
620:
621: NDIS_STATUS Status;
622:
623: NDIS_ADAPTER_INFORMATION AdapterInformation; // needed to register adapter
624: NDIS_EISA_FUNCTION_INFORMATION EisaData;
625: USHORT ConfigValue = 0;
626: UCHAR HiBaseValue = 0;
627:
628: UINT MaxMulticastList = 32;
629: PVOID NetAddress;
630: UINT Length;
631:
632: USHORT RegUshort;
633: UCHAR RegUchar;
634: UINT LanceSlot = 1;
635:
636: BOOLEAN ConfigError = FALSE;
637: NDIS_STATUS ConfigErrorCode;
638:
639:
640: //
641: // Allocate the Adapter block.
642: //
643:
644: LANCE_ALLOC_PHYS(&Adapter, sizeof(LANCE_ADAPTER));
645:
646: if (Adapter == NULL){
647:
648: return NDIS_STATUS_RESOURCES;
649:
650: }
651:
652: LANCE_ZERO_MEMORY(
653: Adapter,
654: sizeof(LANCE_ADAPTER)
655: );
656:
657: Adapter->NdisMacHandle = NdisMacHandle;
658:
659:
660: //
661: // Start with the default card
662: //
663:
664: Adapter->LanceCard = LANCE_DE201;
665:
666: Adapter->RAP = LANCE_DE201_PRI_RAP_ADDRESS;
667: Adapter->RDP = LANCE_DE201_PRI_RDP_ADDRESS;
668: Adapter->Nicsr = LANCE_DE201_PRI_NICSR_ADDRESS;
669: Adapter->NicsrDefaultValue = 0;
670: Adapter->NetworkHardwareAddress = LANCE_DE201_PRI_NETWORK_ADDRESS;
671: Adapter->HardwareBaseAddr = LANCE_DE201_BASE;
672: Adapter->AmountOfHardwareMemory = LANCE_DE201_HARDWARE_MEMORY;
673: Adapter->InterruptNumber = LANCE_DE201_INTERRUPT_VECTOR;
674: Adapter->InterruptRequestLevel = LANCE_DE201_INTERRUPT_VECTOR;
675:
676: NdisOpenConfiguration(
677: &Status,
678: &ConfigHandle,
679: ConfigurationHandle
680: );
681:
682: if (Status != NDIS_STATUS_SUCCESS) {
683:
684: return NDIS_STATUS_FAILURE;
685:
686: }
687:
688: //
689: // Read Card Type
690: //
691:
692: NdisReadConfiguration(
693: &Status,
694: &ReturnedValue,
695: ConfigHandle,
696: &CardStr,
697: NdisParameterInteger
698: );
699:
700: if (Status == NDIS_STATUS_SUCCESS) {
701:
702: if (ReturnedValue->ParameterData.IntegerData == 2) {
703:
704: Adapter->LanceCard = LANCE_DE201;
705:
706: } else if (ReturnedValue->ParameterData.IntegerData == 1) {
707:
708: Adapter->LanceCard = LANCE_DE100;
709:
710: } else if (ReturnedValue->ParameterData.IntegerData == 3) {
711:
712: Adapter->LanceCard = LANCE_DEPCA;
713:
714: #ifndef i386
715: } else if (ReturnedValue->ParameterData.IntegerData == 4) {
716:
717: Adapter->LanceCard = LANCE_DECTC;
718:
719: ConfigErrorCode = LanceDecTcGetConfiguration(ConfigHandle, Adapter);
720:
721: if ( ConfigErrorCode != NDIS_STATUS_SUCCESS ) {
722: ConfigError = TRUE;
723: }
724: #endif // i386
725:
726: } else if (ReturnedValue->ParameterData.IntegerData == 5) {
727:
728: Adapter->LanceCard = LANCE_DE422;
729:
730: } else if (ReturnedValue->ParameterData.IntegerData == 6) {
731:
732: //
733: // This is the De200, but it operates exactly like the 201.
734: //
735:
736: Adapter->LanceCard = LANCE_DE201;
737:
738: } else if (ReturnedValue->ParameterData.IntegerData == 7) {
739:
740: //
741: // This is the De101, but it operates exactly like the 100.
742: //
743:
744: Adapter->LanceCard = LANCE_DE100;
745:
746: } else {
747:
748: ConfigError = TRUE;
749: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
750:
751: goto RegisterAdapter;
752: }
753:
754: }
755:
756: //
757: // Read MaxMulticastList
758: //
759:
760: NdisReadConfiguration(
761: &Status,
762: &ReturnedValue,
763: ConfigHandle,
764: &MaxMulticastListStr,
765: NdisParameterInteger
766: );
767:
768: if (Status == NDIS_STATUS_SUCCESS) {
769:
770: MaxMulticastList = ReturnedValue->ParameterData.IntegerData;
771:
772: }
773:
774: //
775: // Read net address
776: //
777:
778: NdisReadNetworkAddress(
779: &Status,
780: &NetAddress,
781: &Length,
782: ConfigHandle
783: );
784:
785: if ((Length == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
786:
787: ETH_COPY_NETWORK_ADDRESS(
788: Adapter->CurrentNetworkAddress,
789: NetAddress
790: );
791:
792: }
793:
794: if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100)) {
795:
796: //
797: // Read IoAddress
798: //
799:
800: NdisReadConfiguration(
801: &Status,
802: &ReturnedValue,
803: ConfigHandle,
804: &IoAddressStr,
805: NdisParameterInteger
806: );
807:
808: if (Status == NDIS_STATUS_SUCCESS) {
809:
810: if (ReturnedValue->ParameterData.IntegerData == 1) {
811:
812: Adapter->RAP = LANCE_DE201_PRI_RAP_ADDRESS;
813:
814: Adapter->RDP = LANCE_DE201_PRI_RDP_ADDRESS;
815:
816: Adapter->Nicsr = LANCE_DE201_PRI_NICSR_ADDRESS;
817:
818: Adapter->NetworkHardwareAddress = LANCE_DE201_PRI_NETWORK_ADDRESS;
819:
820: } else if (ReturnedValue->ParameterData.IntegerData == 2) {
821:
822: Adapter->RAP = LANCE_DE201_SEC_RAP_ADDRESS;
823:
824: Adapter->RDP = LANCE_DE201_SEC_RDP_ADDRESS;
825:
826: Adapter->Nicsr = LANCE_DE201_SEC_NICSR_ADDRESS;
827:
828: Adapter->NetworkHardwareAddress = LANCE_DE201_SEC_NETWORK_ADDRESS;
829:
830: } else {
831:
832: ConfigError = TRUE;
833: ConfigErrorCode = NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS;
834:
835: goto RegisterAdapter;
836: }
837:
838: }
839:
840:
841:
842:
843: //
844: // Read Interrupt
845: //
846:
847: NdisReadConfiguration(
848: &Status,
849: &ReturnedValue,
850: ConfigHandle,
851: &InterruptStr,
852: NdisParameterInteger
853: );
854:
855: if (Status == NDIS_STATUS_SUCCESS) {
856:
857: Adapter->InterruptNumber = (CCHAR)(ReturnedValue->ParameterData.IntegerData);
858: Adapter->InterruptRequestLevel = Adapter->InterruptNumber;
859:
860: if (Adapter->LanceCard == LANCE_DE201) {
861:
862: if (!((Adapter->InterruptNumber == 5) ||
863: (Adapter->InterruptNumber == 9) ||
864: (Adapter->InterruptNumber == 10) ||
865: (Adapter->InterruptNumber == 11) ||
866: (Adapter->InterruptNumber == 15))) {
867:
868: ConfigError = TRUE;
869: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
870:
871: goto RegisterAdapter;
872:
873: }
874:
875: } else {
876:
877: if (!((Adapter->InterruptNumber == 2) ||
878: (Adapter->InterruptNumber == 3) ||
879: (Adapter->InterruptNumber == 4) ||
880: (Adapter->InterruptNumber == 5) ||
881: (Adapter->InterruptNumber == 7))) {
882:
883: ConfigError = TRUE;
884: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
885:
886: goto RegisterAdapter;
887:
888: }
889:
890: }
891:
892: }
893:
894:
895:
896: //
897: // Read MemoryBaseAddress
898: //
899:
900:
901: NdisReadConfiguration(
902: &Status,
903: &ReturnedValue,
904: ConfigHandle,
905: &MemoryBaseAddrStr,
906: NdisParameterHexInteger
907: );
908:
909: if (Status == NDIS_STATUS_SUCCESS) {
910:
911: Adapter->HardwareBaseAddr = (PVOID)(ReturnedValue->ParameterData.IntegerData);
912:
913: if (!((Adapter->HardwareBaseAddr == (PVOID)0xC0000) ||
914: (Adapter->HardwareBaseAddr == (PVOID)0xC8000) ||
915: (Adapter->HardwareBaseAddr == (PVOID)0xD0000) ||
916: (Adapter->HardwareBaseAddr == (PVOID)0xD8000) ||
917: (Adapter->HardwareBaseAddr == (PVOID)0xE0000) ||
918: (Adapter->HardwareBaseAddr == (PVOID)0xE8000))) {
919:
920: ConfigError = TRUE;
921: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
922:
923: goto RegisterAdapter;
924:
925: }
926:
927: }
928:
929:
930: if (((ULONG)Adapter->HardwareBaseAddr) & 0x8000) {
931:
932: Adapter->AmountOfHardwareMemory = 0x8000;
933: Adapter->HardwareBaseOffset = 0x8000;
934:
935: } else {
936:
937: Adapter->AmountOfHardwareMemory = 0x10000;
938: Adapter->HardwareBaseOffset = 0x0;
939:
940: }
941:
942: } else if (Adapter->LanceCard == LANCE_DEPCA) {
943:
944: Adapter->NetworkHardwareAddress = LANCE_DEPCA_EPROM_ADDRESS;
945: Adapter->InterruptNumber = LANCE_DEPCA_INTERRUPT_VECTOR;
946: Adapter->InterruptRequestLevel = LANCE_DEPCA_INTERRUPT_VECTOR;
947: Adapter->RAP = LANCE_DEPCA_RAP_ADDRESS;
948: Adapter->RDP = LANCE_DEPCA_RDP_ADDRESS;
949: Adapter->AmountOfHardwareMemory = LANCE_DEPCA_HARDWARE_MEMORY;
950: Adapter->HardwareBaseAddr = LANCE_DEPCA_BASE;
951: Adapter->Nicsr = LANCE_DEPCA_NICSR_ADDRESS;
952: Adapter->LanceCard = LANCE_DE100;
953:
954: } else if (Adapter->LanceCard == LANCE_DE422) {
955:
956: PUCHAR CurrentChar;
957: BOOLEAN LastEntry;
958: UCHAR InitType;
959: USHORT PortAddress, PortValue, Mask;
960:
961: NdisReadEisaSlotInformation(
962: &Status,
963: ConfigurationHandle,
964: &Adapter->SlotNumber,
965: &EisaData
966: );
967:
968: if (Status != NDIS_STATUS_SUCCESS) {
969:
970: ConfigError = TRUE;
971: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
972:
973: goto RegisterAdapter;
974:
975: }
976:
977: //
978: // Setup Ports
979: //
980:
981: Adapter->RAP = (((ULONG)Adapter->SlotNumber) << 12) +
982: LANCE_DE422_RAP_ADDRESS;
983:
984: Adapter->RDP = (((ULONG)Adapter->SlotNumber) << 12) +
985: LANCE_DE422_RDP_ADDRESS;
986:
987: Adapter->Nicsr = (((ULONG)Adapter->SlotNumber) << 12) +
988: LANCE_DE422_NICSR_ADDRESS;
989:
990: Adapter->NetworkHardwareAddress = (((ULONG)Adapter->SlotNumber) << 12) +
991: LANCE_DE422_NETWORK_ADDRESS;
992:
993: CurrentChar = (PUCHAR) (EisaData.InitializationData);
994: LastEntry = FALSE;
995:
996: while (!LastEntry) {
997:
998: InitType = *(CurrentChar++);
999: PortAddress = *((USHORT UNALIGNED *) CurrentChar++);
1000:
1001: CurrentChar++;
1002:
1003: if ((InitType & 0x80) == 0) {
1004: LastEntry = TRUE;
1005: }
1006:
1007:
1008:
1009: if (PortAddress == (USHORT)(Adapter->NetworkHardwareAddress)) {
1010:
1011: PortValue = *((USHORT UNALIGNED *) CurrentChar++);
1012:
1013: } else if (PortAddress == ((Adapter->SlotNumber << 12) +
1014: LANCE_DE422_EXTENDED_MEMORY_BASE_ADDRESS)) {
1015:
1016: PortValue = (USHORT)(*(CurrentChar++));
1017:
1018: } else {
1019:
1020: continue;
1021:
1022: }
1023:
1024:
1025:
1026: if (InitType & 0x40) {
1027:
1028: if (PortAddress == Adapter->NetworkHardwareAddress) {
1029:
1030: Mask = *((USHORT UNALIGNED *) CurrentChar++);
1031:
1032: } else {
1033:
1034: Mask = (USHORT)(*(CurrentChar++));
1035:
1036: }
1037:
1038: } else {
1039:
1040: Mask = 0;
1041:
1042: }
1043:
1044: if (PortAddress == Adapter->NetworkHardwareAddress) {
1045:
1046: ConfigValue &= Mask;
1047: ConfigValue |= PortValue;
1048:
1049: } else {
1050:
1051: HiBaseValue &= (UCHAR)Mask;
1052: HiBaseValue |= (UCHAR)PortValue;
1053:
1054: }
1055:
1056: }
1057:
1058: //
1059: // Interpret values
1060: //
1061:
1062: switch (ConfigValue & 0x78) {
1063:
1064: case 0x40:
1065:
1066: Adapter->InterruptNumber = 11;
1067: break;
1068:
1069: case 0x20:
1070:
1071: Adapter->InterruptNumber = 10;
1072: break;
1073:
1074: case 0x10:
1075:
1076: Adapter->InterruptNumber = 9;
1077: break;
1078:
1079: case 0x08:
1080:
1081: Adapter->InterruptNumber = 5;
1082: break;
1083:
1084: default:
1085:
1086: ConfigError = TRUE;
1087: ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
1088:
1089: goto RegisterAdapter;
1090:
1091: }
1092:
1093: Adapter->InterruptRequestLevel = Adapter->InterruptNumber;
1094: //
1095: // We postpone the rest of the processing since we have to read from
1096: // the NICSR to get the amount of hardware memory and cannot do that
1097: // until after we have called NdisRegisterAdater.
1098: //
1099:
1100: }
1101:
1102: RegisterAdapter:
1103:
1104: NdisCloseConfiguration(ConfigHandle);
1105:
1106: //
1107: // The adapter is initialized, register it with NDIS.
1108: // This must occur before interrupts are enabled since the
1109: // InitializeInterrupt routine requires the NdisAdapterHandle
1110: //
1111:
1112: //
1113: // Set up the AdapterInformation structure; zero it
1114: // first in case it is extended later.
1115: //
1116:
1117: LANCE_ZERO_MEMORY(&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
1118:
1119: if (Adapter->LanceCard & (LANCE_DE100 | LANCE_DE201)) {
1120:
1121: AdapterInformation.AdapterType = NdisInterfaceIsa;
1122:
1123: } else if (Adapter->LanceCard == LANCE_DE422) {
1124:
1125: AdapterInformation.AdapterType = NdisInterfaceEisa;
1126:
1127: }
1128:
1129: AdapterInformation.NumberOfPortDescriptors = 1;
1130:
1131: #ifndef i386
1132:
1133: if (Adapter->LanceCard == LANCE_DECTC) {
1134:
1135: Status = LanceDecTcGetInformation(Adapter, &AdapterInformation);
1136: if (Status != NDIS_STATUS_SUCCESS) {
1137: return Status;
1138: }
1139:
1140: } else
1141:
1142: #endif
1143:
1144: if (Adapter->LanceCard & (LANCE_DE100 | LANCE_DE201)) {
1145:
1146: AdapterInformation.PortDescriptors[0].InitialPort = (ULONG)Adapter->Nicsr;
1147: AdapterInformation.PortDescriptors[0].NumberOfPorts = 0x10;
1148:
1149: } else if (Adapter->LanceCard == LANCE_DE422) {
1150:
1151: AdapterInformation.PortDescriptors[0].InitialPort = (ULONG)(Adapter->Nicsr);
1152: AdapterInformation.PortDescriptors[0].NumberOfPorts = 0x90;
1153:
1154: }
1155:
1156: if ((Status = NdisRegisterAdapter(
1157: &Adapter->NdisAdapterHandle,
1158: Adapter->NdisMacHandle,
1159: Adapter,
1160: ConfigurationHandle,
1161: AdapterName,
1162: &AdapterInformation
1163: )) != NDIS_STATUS_SUCCESS) {
1164:
1165: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1166:
1167: return Status;
1168:
1169: }
1170:
1171:
1172: if (ConfigError) {
1173:
1174: NdisWriteErrorLogEntry(
1175: Adapter->NdisAdapterHandle,
1176: ConfigErrorCode,
1177: 0
1178: );
1179:
1180: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1181:
1182: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1183:
1184: return NDIS_STATUS_FAILURE;
1185:
1186: }
1187:
1188: //
1189: // Now we get the rest of the information necessary for the DE422.
1190: //
1191:
1192: if (Adapter->LanceCard == LANCE_DE422) {
1193:
1194: //
1195: // Verify card is a DE422
1196: //
1197:
1198: NdisReadPortUshort(Adapter->NdisAdapterHandle,
1199: (((ULONG)(Adapter->SlotNumber)) << 12) +
1200: LANCE_DE422_EISA_IDENTIFICATION,
1201: &RegUshort
1202: );
1203:
1204: if (RegUshort != 0xA310) {
1205:
1206: //
1207: // Not a DE422 card
1208: //
1209:
1210: NdisWriteErrorLogEntry(
1211: Adapter->NdisAdapterHandle,
1212: NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
1213: 0
1214: );
1215:
1216: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1217:
1218: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1219:
1220: return NDIS_STATUS_FAILURE;
1221:
1222: }
1223:
1224: NdisReadPortUshort(Adapter->NdisAdapterHandle,
1225: (((ULONG)(Adapter->SlotNumber)) << 12) +
1226: LANCE_DE422_EISA_IDENTIFICATION + 2,
1227: &RegUshort
1228: );
1229:
1230: if (RegUshort != 0x2042) {
1231:
1232: //
1233: // Not a DE422 card
1234: //
1235:
1236: NdisWriteErrorLogEntry(
1237: Adapter->NdisAdapterHandle,
1238: NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
1239: 0
1240: );
1241:
1242: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1243:
1244: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1245:
1246: return NDIS_STATUS_FAILURE;
1247:
1248: }
1249:
1250: //
1251: // Check that the card is enabled.
1252: //
1253:
1254: NdisReadPortUchar(Adapter->NdisAdapterHandle,
1255: (((ULONG)(Adapter->SlotNumber)) << 12) +
1256: LANCE_DE422_EISA_CONTROL,
1257: &RegUchar
1258: );
1259:
1260: if (!(RegUchar & 0x1)) {
1261:
1262: NdisWriteErrorLogEntry(
1263: Adapter->NdisAdapterHandle,
1264: NDIS_ERROR_CODE_ADAPTER_DISABLED,
1265: 0
1266: );
1267:
1268: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1269:
1270: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1271:
1272: return NDIS_STATUS_FAILURE;
1273:
1274: }
1275:
1276: //
1277: // Get Memory size
1278: //
1279:
1280: NdisReadPortUshort(Adapter->NdisAdapterHandle,
1281: Adapter->Nicsr,
1282: &RegUshort
1283: );
1284:
1285: if (RegUshort & LANCE_NICSR_BUFFER_SIZE) {
1286:
1287: Adapter->AmountOfHardwareMemory = 0x8000;
1288:
1289: } else if (RegUshort & LANCE_NICSR_128K) {
1290:
1291: Adapter->AmountOfHardwareMemory = 0x20000;
1292: Adapter->NicsrDefaultValue = LANCE_NICSR_128K;
1293:
1294: } else {
1295:
1296: Adapter->AmountOfHardwareMemory = 0x10000;
1297:
1298: }
1299:
1300: //
1301: // Get Base memory address
1302: //
1303:
1304: switch (Adapter->AmountOfHardwareMemory) {
1305:
1306: case 0x8000:
1307:
1308: switch (ConfigValue & 0x07) {
1309:
1310: case 0x04:
1311:
1312: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC8000);
1313: Adapter->HardwareBaseOffset = 0x8000;
1314: break;
1315:
1316: case 0x05:
1317:
1318: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xE8000);
1319: Adapter->HardwareBaseOffset = 0x8000;
1320: break;
1321:
1322: case 0x06:
1323:
1324: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD8000);
1325: Adapter->HardwareBaseOffset = 0x8000;
1326: break;
1327:
1328: case 0x07:
1329:
1330: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xF8000);
1331: Adapter->HardwareBaseOffset = 0x8000;
1332: break;
1333:
1334: default:
1335:
1336: NdisWriteErrorLogEntry(
1337: Adapter->NdisAdapterHandle,
1338: NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
1339: 0
1340: );
1341:
1342: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1343:
1344: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1345:
1346: return NDIS_STATUS_FAILURE;
1347:
1348: }
1349: break;
1350:
1351: case 0x10000:
1352:
1353: switch (ConfigValue & 0x07) {
1354:
1355: case 0x00:
1356:
1357: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC0000);
1358: Adapter->HardwareBaseOffset = 0x0000;
1359: break;
1360:
1361: case 0x01:
1362:
1363: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xE0000);
1364: Adapter->HardwareBaseOffset = 0x0000;
1365: break;
1366:
1367: case 0x02:
1368:
1369: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD0000);
1370: Adapter->HardwareBaseOffset = 0x0000;
1371: break;
1372:
1373: case 0x03:
1374:
1375: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xF0000);
1376: Adapter->HardwareBaseOffset = 0x0000;
1377: break;
1378:
1379: default:
1380:
1381: NdisWriteErrorLogEntry(
1382: Adapter->NdisAdapterHandle,
1383: NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
1384: 0
1385: );
1386:
1387: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1388:
1389: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1390:
1391: return NDIS_STATUS_FAILURE;
1392:
1393: }
1394: break;
1395:
1396: case 0x20000:
1397:
1398: switch (ConfigValue & 0x07) {
1399:
1400: case 0x00:
1401:
1402: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xC0000);
1403: Adapter->HardwareBaseOffset = 0x0000;
1404: break;
1405:
1406: case 0x01:
1407:
1408: Adapter->HardwareBaseAddr = (PVOID)((HiBaseValue << 24) + 0xD0000);
1409: Adapter->HardwareBaseOffset = 0x0000;
1410: break;
1411:
1412: default:
1413:
1414: NdisWriteErrorLogEntry(
1415: Adapter->NdisAdapterHandle,
1416: NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
1417: 0
1418: );
1419:
1420: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1421:
1422: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1423:
1424: return NDIS_STATUS_FAILURE;
1425:
1426: }
1427:
1428: break;
1429:
1430: }
1431:
1432: }
1433:
1434: //
1435: // Set the port addresses and the network address.
1436: //
1437:
1438: Adapter->InterruptsStopped = FALSE;
1439: Adapter->MaxMulticastList = MaxMulticastList;
1440:
1441: Status = LanceRegisterAdapter(
1442: Adapter
1443: );
1444:
1445: if (Status != NDIS_STATUS_SUCCESS) {
1446:
1447:
1448:
1449: //
1450: // LanceRegisterAdapter failed.
1451: //
1452:
1453: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1454:
1455: LANCE_FREE_PHYS(Adapter, sizeof(LANCE_ADAPTER));
1456:
1457: return NDIS_STATUS_FAILURE;
1458:
1459: }
1460:
1461: return NDIS_STATUS_SUCCESS;
1462: }
1463:
1464:
1465: VOID
1466: LanceRemoveAdapter(
1467: IN PVOID MacAdapterContext
1468: )
1469: /*++
1470:
1471: Routine Description:
1472:
1473: LanceRemoveAdapter removes an adapter previously registered
1474: with NdisRegisterAdapter.
1475:
1476: Arguments:
1477:
1478: MacAdapterContext - The context value that the MAC passed
1479: to NdisRegisterAdapter; actually as pointer to an
1480: LANCE_ADAPTER.
1481:
1482: Return Value:
1483:
1484: None.
1485:
1486: --*/
1487: {
1488:
1489: PLANCE_ADAPTER Adapter;
1490: BOOLEAN Canceled;
1491:
1492: Adapter = PLANCE_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
1493:
1494: //
1495: // There are no opens left, so remove ourselves.
1496: //
1497:
1498: #if LANCELOG
1499: if (LogTimerRunning) {
1500: NdisCancelTimer(&LogTimer, &Canceled);
1501: LogTimerRunning = FALSE;
1502: }
1503: #endif
1504:
1505: NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
1506:
1507: if ( !Canceled ) {
1508:
1509: NdisStallExecution(500000);
1510: }
1511:
1512: NdisRemoveInterrupt(&(Adapter->Interrupt));
1513:
1514: NdisUnmapIoSpace(
1515: Adapter->NdisAdapterHandle,
1516: Adapter->MmMappedBaseAddr,
1517: Adapter->AmountOfHardwareMemory
1518: );
1519:
1520: EthDeleteFilter(Adapter->FilterDB);
1521:
1522: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1523:
1524: NdisFreeSpinLock(&Adapter->Lock);
1525:
1526: NdisFreeMemory(Adapter, sizeof(LANCE_ADAPTER), 0);
1527:
1528: return;
1529: }
1530:
1531: VOID
1532: LanceUnload(
1533: IN NDIS_HANDLE MacMacContext
1534: )
1535:
1536: /*++
1537:
1538: Routine Description:
1539:
1540: LanceUnload is called when the MAC is to unload itself.
1541:
1542: Arguments:
1543:
1544: MacMacContext - not used.
1545:
1546: Return Value:
1547:
1548: None.
1549:
1550: --*/
1551:
1552: {
1553: NDIS_STATUS InitStatus;
1554:
1555: UNREFERENCED_PARAMETER(MacMacContext);
1556:
1557: NdisDeregisterMac(
1558: &InitStatus,
1559: LanceMacHandle
1560: );
1561:
1562: NdisTerminateWrapper(
1563: LanceNdisWrapperHandle,
1564: NULL
1565: );
1566:
1567: return;
1568: }
1569:
1570: LanceRegisterAdapter(
1571: IN PLANCE_ADAPTER Adapter
1572: )
1573:
1574: /*++
1575:
1576: Routine Description:
1577:
1578: This routine (and its interface) are not portable. They are
1579: defined by the OS, the architecture, and the particular LANCE
1580: implementation.
1581:
1582: This routine is responsible for the allocation of the datastructures
1583: for the driver as well as any hardware specific details necessary
1584: to talk with the device.
1585:
1586: Arguments:
1587:
1588: Adapter - Pointer to the adapter block.
1589:
1590: Return Value:
1591:
1592: Returns false if anything occurred that prevents the initialization
1593: of the adapter.
1594:
1595: --*/
1596: {
1597:
1598: //
1599: // Result of Ndis Calls.
1600: //
1601: NDIS_STATUS Status;
1602:
1603:
1604: //
1605: // We put in this assertion to make sure that ushort are 2 bytes.
1606: // if they aren't then the initialization block definition needs
1607: // to be changed.
1608: //
1609: // Also all of the logic that deals with status registers assumes
1610: // that control registers are only 2 bytes.
1611: //
1612:
1613: ASSERT(sizeof(USHORT) == 2);
1614:
1615: //
1616: // This assertion checks that the network address in the initialization
1617: // block does start on the third byte of the initalization block.
1618: //
1619: // If this is true then other fields in the initialization block
1620: // and the send and receive descriptors should be at their correct
1621: // locations.
1622: //
1623:
1624: ASSERT(FIELD_OFFSET(LANCE_INITIALIZATION_BLOCK,PhysicalAddress[0]) == 2);
1625:
1626:
1627: //
1628: // Allocate memory for all of the adapter structures.
1629: //
1630:
1631: Adapter->NumberOfTransmitRings = LANCE_NUMBER_OF_TRANSMIT_RINGS;
1632: Adapter->LogNumberTransmitRings = LANCE_LOG_TRANSMIT_RINGS;
1633:
1634: #ifndef i386
1635:
1636: if (Adapter->LanceCard == LANCE_DECTC) {
1637:
1638: Status = LanceDecTcSoftwareDetails(Adapter);
1639: if (Status != NDIS_STATUS_SUCCESS) {
1640: return Status;
1641: }
1642:
1643: } else
1644:
1645:
1646: #endif
1647:
1648: {
1649:
1650: if (Adapter->AmountOfHardwareMemory == 0x20000) {
1651:
1652: ASSERT(Adapter->LanceCard == LANCE_DE422);
1653:
1654: Adapter->SizeOfReceiveBuffer = LANCE_128K_SIZE_OF_RECEIVE_BUFFERS;
1655: Adapter->NumberOfSmallBuffers = LANCE_128K_NUMBER_OF_SMALL_BUFFERS;
1656: Adapter->NumberOfMediumBuffers= LANCE_128K_NUMBER_OF_MEDIUM_BUFFERS;
1657: Adapter->NumberOfLargeBuffers = LANCE_128K_NUMBER_OF_LARGE_BUFFERS;
1658:
1659: Adapter->NumberOfReceiveRings = LANCE_128K_NUMBER_OF_RECEIVE_RINGS;
1660: Adapter->LogNumberReceiveRings = LANCE_128K_LOG_RECEIVE_RINGS;
1661:
1662: } else if (Adapter->AmountOfHardwareMemory == 0x10000) {
1663:
1664: Adapter->NumberOfReceiveRings = LANCE_64K_NUMBER_OF_RECEIVE_RINGS;
1665: Adapter->LogNumberReceiveRings = LANCE_64K_LOG_RECEIVE_RINGS;
1666:
1667: Adapter->SizeOfReceiveBuffer = LANCE_64K_SIZE_OF_RECEIVE_BUFFERS;
1668: Adapter->NumberOfSmallBuffers = LANCE_64K_NUMBER_OF_SMALL_BUFFERS;
1669: Adapter->NumberOfMediumBuffers= LANCE_64K_NUMBER_OF_MEDIUM_BUFFERS;
1670: Adapter->NumberOfLargeBuffers = LANCE_64K_NUMBER_OF_LARGE_BUFFERS;
1671:
1672: } else {
1673:
1674: Adapter->NumberOfReceiveRings = LANCE_32K_NUMBER_OF_RECEIVE_RINGS;
1675: Adapter->LogNumberReceiveRings = LANCE_32K_LOG_RECEIVE_RINGS;
1676:
1677: Adapter->SizeOfReceiveBuffer = LANCE_32K_SIZE_OF_RECEIVE_BUFFERS;
1678: Adapter->NumberOfSmallBuffers = LANCE_32K_NUMBER_OF_SMALL_BUFFERS;
1679: Adapter->NumberOfMediumBuffers= LANCE_32K_NUMBER_OF_MEDIUM_BUFFERS;
1680: Adapter->NumberOfLargeBuffers = LANCE_32K_NUMBER_OF_LARGE_BUFFERS;
1681:
1682: }
1683:
1684: }
1685:
1686: #ifndef i386
1687:
1688: if (((Adapter->LanceCard == LANCE_DECTC) &&
1689: (LanceDecTcHardwareDetails(Adapter) == NDIS_STATUS_SUCCESS)) ||
1690: LanceHardwareDetails(Adapter)) {
1691:
1692: #else
1693:
1694: if (LanceHardwareDetails(Adapter)) {
1695:
1696: #endif
1697:
1698: NDIS_PHYSICAL_ADDRESS PhysicalAddress;
1699:
1700: //
1701: // Get hold of the RAP and RDP address as well
1702: // as filling in the hardware assigned network
1703: // address.
1704: //
1705:
1706: if ((Adapter->CurrentNetworkAddress[0] == 0x00) &&
1707: (Adapter->CurrentNetworkAddress[1] == 0x00) &&
1708: (Adapter->CurrentNetworkAddress[2] == 0x00) &&
1709: (Adapter->CurrentNetworkAddress[3] == 0x00) &&
1710: (Adapter->CurrentNetworkAddress[4] == 0x00) &&
1711: (Adapter->CurrentNetworkAddress[5] == 0x00)) {
1712:
1713: Adapter->CurrentNetworkAddress[0] = Adapter->NetworkAddress[0];
1714: Adapter->CurrentNetworkAddress[1] = Adapter->NetworkAddress[1];
1715: Adapter->CurrentNetworkAddress[2] = Adapter->NetworkAddress[2];
1716: Adapter->CurrentNetworkAddress[3] = Adapter->NetworkAddress[3];
1717: Adapter->CurrentNetworkAddress[4] = Adapter->NetworkAddress[4];
1718: Adapter->CurrentNetworkAddress[5] = Adapter->NetworkAddress[5];
1719:
1720: }
1721:
1722: NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
1723: NdisSetPhysicalAddressLow(PhysicalAddress, (ULONG)(Adapter->HardwareBaseAddr));
1724:
1725: NdisMapIoSpace(
1726: &Status,
1727: &(Adapter->MmMappedBaseAddr),
1728: Adapter->NdisAdapterHandle,
1729: PhysicalAddress,
1730: Adapter->AmountOfHardwareMemory
1731: );
1732:
1733: if (Status != NDIS_STATUS_SUCCESS) {
1734:
1735: NdisWriteErrorLogEntry(
1736: Adapter->NdisAdapterHandle,
1737: NDIS_ERROR_CODE_RESOURCE_CONFLICT,
1738: 0
1739: );
1740:
1741: return(Status);
1742:
1743: }
1744:
1745: Adapter->CurrentMemoryFirstFree = Adapter->MmMappedBaseAddr;
1746:
1747:
1748: Adapter->MemoryFirstUnavailable =
1749: (PUCHAR)(Adapter->CurrentMemoryFirstFree) +
1750: Adapter->AmountOfHardwareMemory;
1751:
1752: if (!AllocateAdapterMemory(Adapter)) {
1753:
1754: NdisWriteErrorLogEntry(
1755: Adapter->NdisAdapterHandle,
1756: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
1757: 0
1758: );
1759:
1760: return( NDIS_STATUS_ADAPTER_NOT_FOUND );
1761:
1762: }
1763:
1764: InitializeListHead(&Adapter->OpenBindings);
1765: InitializeListHead(&Adapter->CloseList);
1766:
1767: NdisAllocateSpinLock(&Adapter->Lock);
1768:
1769: Adapter->InterruptDPC = (PVOID)LanceStandardInterruptDPC;
1770: Adapter->LoopbackDPC = (PVOID)LanceStandardInterruptDPC;
1771:
1772:
1773: Adapter->AllocateableRing = Adapter->TransmitRing;
1774: Adapter->TransmittingRing = Adapter->TransmitRing;
1775: Adapter->FirstUncommittedRing = Adapter->TransmitRing;
1776: Adapter->NumberOfAvailableRings = Adapter->NumberOfTransmitRings;
1777: Adapter->LastTransmitRingEntry = Adapter->TransmitRing +
1778: (Adapter->NumberOfTransmitRings-1);
1779:
1780: Adapter->FirstLoopBack = NULL;
1781: Adapter->LastLoopBack = NULL;
1782: Adapter->FirstFinishTransmit = NULL;
1783: Adapter->LastFinishTransmit = NULL;
1784: Adapter->StageOpen = TRUE;
1785: Adapter->AlreadyProcessingStage = FALSE;
1786: Adapter->FirstStage1Packet = NULL;
1787: Adapter->LastStage1Packet = NULL;
1788: Adapter->CurrentReceiveIndex = 0;
1789: Adapter->OutOfReceiveBuffers = 0;
1790: Adapter->CRCError = 0;
1791: Adapter->FramingError = 0;
1792: Adapter->RetryFailure = 0;
1793: Adapter->LostCarrier = 0;
1794: Adapter->LateCollision = 0;
1795: Adapter->UnderFlow = 0;
1796: Adapter->Deferred = 0;
1797: Adapter->OneRetry = 0;
1798: Adapter->MoreThanOneRetry = 0;
1799: Adapter->ResetInProgress = FALSE;
1800: Adapter->ResetInitStarted = FALSE;
1801: Adapter->ResettingOpen = NULL;
1802: Adapter->FirstInitialization = TRUE;
1803: Adapter->HardwareFailure = FALSE;
1804: Adapter->PendQueue = NULL;
1805: Adapter->PendQueueTail = NULL;
1806:
1807: //
1808: // First we make sure that the device is stopped. We call
1809: // directly since we don't have an Interrupt object yet.
1810: //
1811:
1812: LanceSyncStopChip(Adapter);
1813:
1814:
1815: //
1816: // Initialize the interrupt.
1817: //
1818:
1819: NdisInitializeInterrupt(
1820: &Status,
1821: &Adapter->Interrupt,
1822: Adapter->NdisAdapterHandle,
1823: (PNDIS_INTERRUPT_SERVICE)LanceISR,
1824: Adapter,
1825: (PNDIS_DEFERRED_PROCESSING)Adapter->InterruptDPC,
1826: Adapter->InterruptNumber,
1827: Adapter->InterruptRequestLevel,
1828: FALSE,
1829: NdisInterruptLatched
1830: );
1831:
1832: if (Status != NDIS_STATUS_SUCCESS){
1833:
1834: NdisWriteErrorLogEntry(
1835: Adapter->NdisAdapterHandle,
1836: NDIS_ERROR_CODE_INTERRUPT_CONNECT,
1837: 0
1838: );
1839:
1840: NdisUnmapIoSpace(
1841: Adapter->NdisAdapterHandle,
1842: Adapter->MmMappedBaseAddr,
1843: Adapter->AmountOfHardwareMemory);
1844:
1845: DeleteAdapterMemory(Adapter);
1846:
1847: return Status;
1848: }
1849:
1850:
1851: if (!EthCreateFilter(
1852: Adapter->MaxMulticastList,
1853: LanceChangeMulticastAddresses,
1854: LanceChangeFilterClasses,
1855: LanceCloseAction,
1856: Adapter->CurrentNetworkAddress,
1857: &Adapter->Lock,
1858: &Adapter->FilterDB
1859: )) {
1860:
1861: NdisWriteErrorLogEntry(
1862: Adapter->NdisAdapterHandle,
1863: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
1864: 0
1865: );
1866:
1867: NdisUnmapIoSpace(
1868: Adapter->NdisAdapterHandle,
1869: Adapter->MmMappedBaseAddr,
1870: Adapter->AmountOfHardwareMemory);
1871:
1872: DeleteAdapterMemory(Adapter);
1873:
1874: NdisRemoveInterrupt(&Adapter->Interrupt);
1875:
1876: return NDIS_STATUS_RESOURCES;
1877:
1878: }
1879:
1880: if ((Status = LanceInitialInit(Adapter)) != NDIS_STATUS_SUCCESS) {
1881:
1882:
1883: NdisWriteErrorLogEntry(
1884: Adapter->NdisAdapterHandle,
1885: NDIS_ERROR_CODE_HARDWARE_FAILURE,
1886: 0
1887: );
1888:
1889: EthDeleteFilter(Adapter->FilterDB);
1890:
1891: NdisUnmapIoSpace(
1892: Adapter->NdisAdapterHandle,
1893: Adapter->MmMappedBaseAddr,
1894: Adapter->AmountOfHardwareMemory);
1895:
1896: DeleteAdapterMemory(Adapter);
1897:
1898: NdisRemoveInterrupt(&Adapter->Interrupt);
1899:
1900: return Status;
1901:
1902: }
1903:
1904: //
1905: // Initialize the wake up timer to catch interrupts that
1906: // don't complete. It fires continuously
1907: // every 5 seconds, and we check if there are any
1908: // uncompleted operations from the previous two-second
1909: // period.
1910: //
1911:
1912: Adapter->WakeUpDpc = (PVOID)LanceWakeUpDpc;
1913:
1914: NdisInitializeTimer(&Adapter->WakeUpTimer,
1915: (PVOID)(Adapter->WakeUpDpc),
1916: Adapter );
1917:
1918: NdisSetTimer(
1919: &Adapter->WakeUpTimer,
1920: 5000
1921: );
1922:
1923: return Status;
1924:
1925: } else {
1926:
1927: NdisWriteErrorLogEntry(
1928: Adapter->NdisAdapterHandle,
1929: NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
1930: 0
1931: );
1932:
1933: return NDIS_STATUS_FAILURE;
1934:
1935: }
1936:
1937: }
1938:
1939: extern
1940: NDIS_STATUS
1941: LanceInitialInit(
1942: IN PLANCE_ADAPTER Adapter
1943: )
1944:
1945: /*++
1946:
1947: Routine Description:
1948:
1949: This routine sets up the initial init of the driver.
1950:
1951: Arguments:
1952:
1953: Adapter - The adapter for the hardware.
1954:
1955: Return Value:
1956:
1957: None.
1958:
1959: --*/
1960:
1961: {
1962:
1963: if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) {
1964:
1965: //
1966: // Allow interrupts
1967: //
1968:
1969: Adapter->InterruptsStopped = FALSE;
1970:
1971: LOG(UNPEND);
1972:
1973: LANCE_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
1974:
1975: }
1976:
1977: SetInitBlockAndInit(Adapter);
1978:
1979: //
1980: // Delay execution for 1/2 second to give the lance
1981: // time to initialize.
1982: //
1983:
1984:
1985: NdisStallExecution( 500000 );
1986:
1987: NdisAcquireSpinLock(&Adapter->Lock);
1988:
1989: //
1990: // The only way that first initialization could have
1991: // been turned off is if we actually initialized.
1992: //
1993:
1994: if (!Adapter->FirstInitialization) {
1995:
1996: //
1997: // Initialize the Deferred processing timer.
1998: //
1999:
2000: NdisInitializeTimer(&Adapter->DeferredTimer,
2001: Adapter->LoopbackDPC,
2002: Adapter);
2003:
2004: #if LANCELOG
2005:
2006: if (!LogTimerRunning) {
2007:
2008: NdisInitializeTimer(&LogTimer,
2009: (PVOID)LogDpc,
2010: (PVOID)(&LogTimer)
2011: );
2012:
2013: NdisSetTimer(&LogTimer,1000);
2014:
2015: LogTimerRunning = TRUE;
2016:
2017: }
2018:
2019: #endif
2020:
2021: //
2022: // We actually did get the initialization.
2023: //
2024:
2025: NdisReleaseSpinLock(&Adapter->Lock);
2026:
2027: //
2028: // We can start the chip. We may not
2029: // have any bindings to indicateto but this
2030: // is unimportant.
2031: //
2032:
2033: LanceStartChip(Adapter);
2034:
2035:
2036: return NDIS_STATUS_SUCCESS;
2037:
2038:
2039: } else {
2040:
2041: NdisReleaseSpinLock(&Adapter->Lock);
2042:
2043: return NDIS_STATUS_FAILURE;
2044:
2045: }
2046:
2047: }
2048:
2049: STATIC
2050: VOID
2051: LanceStartChip(
2052: IN PLANCE_ADAPTER Adapter
2053: )
2054:
2055: /*++
2056:
2057: Routine Description:
2058:
2059: This routine is used to start an already initialized lance.
2060:
2061: Arguments:
2062:
2063: Adapter - The adapter for the LANCE to start.
2064:
2065: Return Value:
2066:
2067: None.
2068:
2069: --*/
2070:
2071: {
2072:
2073: if (Adapter->ResetInProgress) {
2074:
2075: return;
2076:
2077: }
2078:
2079: //
2080: // Set the RAP to csr0.
2081: //
2082:
2083: LANCE_WRITE_RAP(
2084: Adapter,
2085: LANCE_SELECT_CSR0
2086: );
2087:
2088: //
2089: // Set the RDP to a start chip.
2090: //
2091:
2092: LANCE_WRITE_RDP(
2093: Adapter,
2094: LANCE_CSR0_START | LANCE_CSR0_INTERRUPT_ENABLE
2095: );
2096:
2097: }
2098:
2099: STATIC
2100: BOOLEAN
2101: LanceInterruptSynch(
2102: IN PVOID Context
2103: )
2104:
2105: /*++
2106:
2107: Routine Description:
2108:
2109: This routine is used by the normal interrupt processing routine
2110: to synchronize with interrupts from the card. It will or
2111: the value of the stored csr 0 into the other passed address
2112: in the context and clear the stored csr 0 value.
2113: block and clear the stored csr0.
2114:
2115: Arguments:
2116:
2117: Context - This is really a pointer to a record type peculiar
2118: to this routine. The record contains a pointer to the adapter
2119: and a pointer to an address in which to place the contents
2120: of csr 0.
2121:
2122: Return Value:
2123:
2124: Always returns true.
2125:
2126: --*/
2127:
2128: {
2129:
2130: PLANCE_SYNCH_CONTEXT C = Context;
2131:
2132: *(C->LocalRead) = *(C->LocalRead) | C->Adapter->CSR0Value;
2133:
2134: C->Adapter->CSR0Value = 0;
2135:
2136: return TRUE;
2137:
2138: }
2139:
2140: extern
2141: BOOLEAN
2142: LanceISR(
2143: IN PVOID Context
2144: )
2145:
2146: /*++
2147:
2148: Routine Description:
2149:
2150: Interrupt service routine for the lance. It's main job is
2151: to get the value of CSR0 and record the changes in the
2152: adapters own list of interrupt reasons.
2153:
2154: Arguments:
2155:
2156: Context - Really a pointer to the adapter.
2157:
2158: Return Value:
2159:
2160: Returns true if the INTR bit of CSR0 of the lance is enabled.
2161:
2162: --*/
2163:
2164: {
2165:
2166: //
2167: // Will hold the value from the csr.
2168: //
2169: USHORT LocalCSR0Value;
2170:
2171: //
2172: // Holds the pointer to the adapter.
2173: //
2174: PLANCE_ADAPTER Adapter = Context;
2175:
2176: BOOLEAN StoppedInterrupts=FALSE;
2177:
2178: LOG(IN_ISR);
2179:
2180: if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) {
2181:
2182: //
2183: // If not currently pended, pend interrupts...
2184: //
2185:
2186: if (!(Adapter->InterruptsStopped)){
2187:
2188: //
2189: // Pend interrupts
2190: //
2191:
2192: StoppedInterrupts = TRUE;
2193:
2194: Adapter->InterruptsStopped = TRUE;
2195:
2196: LOG(PEND);
2197:
2198: LANCE_ISR_WRITE_NICSR(Adapter,
2199: LANCE_NICSR_IMASK | LANCE_NICSR_LED_ON | LANCE_NICSR_INT_ON);
2200:
2201: }
2202:
2203: }
2204:
2205: //
2206: // We don't need to select csr0, as the only way we could get
2207: // an interrupt is to have already selected 0.
2208: //
2209:
2210: LANCE_ISR_READ_RDP(Adapter, &LocalCSR0Value);
2211:
2212: if (LocalCSR0Value & LANCE_CSR0_INTERRUPT_FLAG) {
2213:
2214: //
2215: // It's our interrupt. Clear only those bits that we got
2216: // in this read of csr0. We do it this way incase any new
2217: // reasons for interrupts occur between the time that we
2218: // read csr0 and the time that we clear the bits.
2219: //
2220:
2221: LANCE_ISR_WRITE_RDP(
2222: Adapter,
2223: (USHORT)((LANCE_CSR0_CLEAR_INTERRUPT_BITS & LocalCSR0Value) |
2224: LANCE_CSR0_INTERRUPT_ENABLE)
2225: );
2226:
2227:
2228: if (Adapter->FirstInitialization &&
2229: (LocalCSR0Value & LANCE_CSR0_INITIALIZATION_DONE)) {
2230:
2231: Adapter->FirstInitialization = FALSE;
2232:
2233: if ((Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) &&
2234: StoppedInterrupts) {
2235:
2236: //
2237: // Allow interrupts
2238: //
2239:
2240: Adapter->InterruptsStopped = FALSE;
2241:
2242: LOG(UNPEND);
2243:
2244: LANCE_ISR_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
2245:
2246: }
2247:
2248: LOG(OUT_ISR);
2249:
2250: return FALSE;
2251:
2252: } else {
2253:
2254: //
2255: // Or the csr value into the adapter version of csr 0.
2256: //
2257:
2258: Adapter->CSR0Value |= LocalCSR0Value;
2259:
2260: LOG(OUT_ISR);
2261:
2262: return TRUE;
2263:
2264: }
2265:
2266: } else {
2267:
2268: if ((Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) &&
2269: StoppedInterrupts) {
2270:
2271: //
2272: // Allow interrupts
2273: //
2274:
2275: Adapter->InterruptsStopped = FALSE;
2276:
2277: LOG(UNPEND);
2278:
2279: LANCE_ISR_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
2280:
2281: }
2282:
2283: LOG(OUT_ISR);
2284:
2285: return FALSE;
2286:
2287: }
2288:
2289: }
2290:
2291: STATIC
2292: VOID
2293: LanceStandardInterruptDPC(
2294: IN PVOID SystemSpecific,
2295: IN PVOID Context,
2296: IN PVOID SystemArgument1,
2297: IN PVOID SystemArgument2
2298: )
2299:
2300: /*++
2301:
2302: Routine Description:
2303:
2304: This DPC routine is queued by the interrupt service routine
2305: and other routines within the driver that notice that
2306: some deferred processing needs to be done. It's main
2307: job is to call the interrupt processing code.
2308:
2309: Arguments:
2310:
2311: SystemSpecific - not used.
2312:
2313: Context - Really a pointer to the adapter.
2314:
2315:
2316: SystemArgument1 - Flag if we should turn interrupts on when done
2317: processing.
2318:
2319: SystemArgument2 - Not used.
2320:
2321: Return Value:
2322:
2323: None.
2324:
2325: --*/
2326:
2327: {
2328: //
2329: // Holds the pointer to the adapter.
2330: //
2331: PLANCE_ADAPTER Adapter = Context;
2332:
2333: USHORT InterruptsStopped;
2334:
2335: UNREFERENCED_PARAMETER(SystemSpecific);
2336: UNREFERENCED_PARAMETER(SystemArgument1);
2337: UNREFERENCED_PARAMETER(SystemArgument2);
2338:
2339: LOG(IN_DPC);
2340:
2341: NdisDprAcquireSpinLock(&Adapter->Lock);
2342:
2343: if (Adapter->ProcessInterruptRunning) {
2344:
2345: LOG(OUT_DPC);
2346:
2347: NdisDprReleaseSpinLock(&Adapter->Lock);
2348:
2349: return;
2350:
2351: }
2352:
2353: Adapter->ProcessInterruptRunning = TRUE;
2354:
2355: ProcessInterrupt(Adapter);
2356:
2357: InterruptsStopped = Adapter->InterruptsStopped;
2358:
2359: if ((Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) &&
2360: InterruptsStopped) {
2361:
2362: //
2363: // Allow interrupts
2364: //
2365:
2366: LOG(UNPEND);
2367:
2368: LOG(OUT_DPC);
2369:
2370:
2371: //
2372: // Safe to write here since the ISR will not fire with interrupts stopped.
2373: //
2374:
2375: Adapter->InterruptsStopped = FALSE;
2376:
2377: LANCE_WRITE_NICSR(Adapter, LANCE_NICSR_INT_ON);
2378:
2379: } else {
2380:
2381: LOG(OUT_DPC);
2382:
2383: }
2384:
2385: NdisDprReleaseSpinLock(&Adapter->Lock);
2386:
2387: }
2388:
2389: STATIC
2390: BOOLEAN
2391: AllocateAdapterMemory(
2392: IN PLANCE_ADAPTER Adapter
2393: )
2394:
2395: /*++
2396:
2397: Routine Description:
2398:
2399: This routine allocates memory for:
2400:
2401: - Transmit ring entries
2402:
2403: - Receive ring entries
2404:
2405: - Receive buffers
2406:
2407: - Adapter buffers for use if user transmit buffers don't meet hardware
2408: contraints
2409:
2410: - Structures to map transmit ring entries back to the packets.
2411:
2412: Arguments:
2413:
2414: Adapter - The adapter to allocate memory for.
2415:
2416: Return Value:
2417:
2418: Returns FALSE if some memory needed for the adapter could not
2419: be allocated.
2420:
2421: --*/
2422:
2423: {
2424:
2425: //
2426: // Pointer to a transmit ring entry. Used while initializing
2427: // the ring.
2428: //
2429: PLANCE_TRANSMIT_ENTRY CurrentTransmitEntry;
2430:
2431: //
2432: // Pointer to a receive ring entry. Used while initializing
2433: // the ring.
2434: //
2435: PLANCE_RECEIVE_ENTRY CurrentReceiveEntry;
2436:
2437: //
2438: // Simple iteration variable.
2439: //
2440: UINT i;
2441:
2442: //
2443: // These variables exist to reduce the amount of checking below.
2444: //
2445:
2446: ULONG NumberOfSmallBuffers;
2447: ULONG NumberOfMediumBuffers;
2448: ULONG NumberOfLargeBuffers;
2449:
2450:
2451: NumberOfSmallBuffers = Adapter->NumberOfSmallBuffers;
2452: NumberOfMediumBuffers = Adapter->NumberOfMediumBuffers;
2453: NumberOfLargeBuffers = Adapter->NumberOfLargeBuffers;
2454:
2455:
2456:
2457: //
2458: // Allocate memory for the initialization block. Note that
2459: // this memory can not cross a page boundary.
2460: //
2461:
2462: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2463: Adapter,
2464: sizeof(LANCE_INITIALIZATION_BLOCK),
2465: &Adapter->InitBlock
2466: );
2467:
2468: if (Adapter->InitBlock == NULL) {
2469: DeleteAdapterMemory(Adapter);
2470: return FALSE;
2471: }
2472:
2473: //
2474: // Allocate the transmit ring descriptors.
2475: //
2476:
2477: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2478: Adapter,
2479: sizeof(LANCE_TRANSMIT_ENTRY)*Adapter->NumberOfTransmitRings,
2480: &Adapter->TransmitRing
2481: )
2482:
2483: if (Adapter->TransmitRing == NULL) {
2484: DeleteAdapterMemory(Adapter);
2485: return FALSE;
2486: }
2487:
2488: //
2489: // We have the transmit ring descriptors. Make sure each is
2490: // in a clean state.
2491: //
2492:
2493: for (
2494: i = 0, CurrentTransmitEntry = Adapter->TransmitRing;
2495: i < Adapter->NumberOfTransmitRings;
2496: i++,CurrentTransmitEntry++
2497: ) {
2498:
2499: LANCE_ZERO_MEMORY_FOR_HARDWARE(
2500: CurrentTransmitEntry,
2501: sizeof(LANCE_TRANSMIT_ENTRY)
2502: );
2503:
2504: }
2505:
2506:
2507: //
2508: // Allocate all of the receive ring entries
2509: //
2510:
2511: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2512: Adapter,
2513: sizeof(LANCE_RECEIVE_ENTRY)*Adapter->NumberOfReceiveRings,
2514: &Adapter->ReceiveRing
2515: )
2516:
2517: if (Adapter->ReceiveRing == NULL) {
2518: DeleteAdapterMemory(Adapter);
2519: return FALSE;
2520: }
2521:
2522: //
2523: // We have the receive ring descriptors. Allocate an
2524: // array to hold the virtual addresses of each receive
2525: // buffer.
2526: //
2527:
2528: LANCE_ALLOC_PHYS(
2529: &(Adapter->ReceiveVAs),
2530: sizeof(PVOID) * Adapter->NumberOfReceiveRings
2531: );
2532:
2533: if (Adapter->ReceiveVAs == NULL) {
2534: DeleteAdapterMemory(Adapter);
2535: return FALSE;
2536: }
2537:
2538: //
2539: // Clean the above memory
2540: //
2541:
2542: LANCE_ZERO_MEMORY(
2543: Adapter->ReceiveVAs,
2544: (sizeof(PVOID)*Adapter->NumberOfReceiveRings)
2545: );
2546:
2547:
2548: //
2549: // We have the receive ring descriptors. Allocate a buffer
2550: // for each descriptor and make sure descriptor is in a clean state.
2551: //
2552: // While we're at it, relinquish ownership of the ring discriptors to
2553: // the lance.
2554: //
2555:
2556: for (
2557: i = 0, CurrentReceiveEntry = Adapter->ReceiveRing;
2558: i < Adapter->NumberOfReceiveRings;
2559: i++,CurrentReceiveEntry++
2560: ) {
2561:
2562: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2563: Adapter,
2564: Adapter->SizeOfReceiveBuffer,
2565: &Adapter->ReceiveVAs[i]
2566: );
2567:
2568: if (Adapter->ReceiveVAs[i] == NULL) {
2569: DeleteAdapterMemory(Adapter);
2570: return FALSE;
2571: }
2572:
2573:
2574: LANCE_SET_RECEIVE_BUFFER_ADDRESS(
2575: Adapter,
2576: CurrentReceiveEntry,
2577: Adapter->ReceiveVAs[i]
2578: );
2579:
2580:
2581: LANCE_SET_RECEIVE_BUFFER_LENGTH(
2582: CurrentReceiveEntry,
2583: Adapter->SizeOfReceiveBuffer
2584: );
2585:
2586: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
2587: CurrentReceiveEntry->ReceiveSummaryBits,
2588: LANCE_RECEIVE_OWNED_BY_CHIP
2589: );
2590:
2591:
2592: }
2593:
2594: //
2595: // Allocate the ring to packet structure.
2596: //
2597:
2598: LANCE_ALLOC_PHYS(
2599: &(Adapter->RingToPacket),
2600: sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
2601: );
2602:
2603: if (Adapter->RingToPacket == NULL) {
2604: DeleteAdapterMemory(Adapter);
2605: return FALSE;
2606: }
2607:
2608: LANCE_ZERO_MEMORY(
2609: Adapter->RingToPacket,
2610: sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
2611: );
2612:
2613: //
2614: // Allocate the array of buffer descriptors.
2615: //
2616:
2617: LANCE_ALLOC_PHYS(
2618: &(Adapter->LanceBuffers),
2619: sizeof(LANCE_BUFFER_DESCRIPTOR) *
2620: (NumberOfSmallBuffers +
2621: NumberOfMediumBuffers +
2622: NumberOfLargeBuffers)
2623: );
2624:
2625: if (Adapter->LanceBuffers == NULL) {
2626: DeleteAdapterMemory(Adapter);
2627: return FALSE;
2628: }
2629:
2630: //
2631: // Zero the memory of all the descriptors so that we can
2632: // know which buffers wern't allocated incase we can't allocate
2633: // them all.
2634: //
2635: LANCE_ZERO_MEMORY(
2636: Adapter->LanceBuffers,
2637: sizeof(LANCE_BUFFER_DESCRIPTOR)*
2638: (NumberOfSmallBuffers +
2639: NumberOfMediumBuffers +
2640: NumberOfLargeBuffers)
2641: );
2642:
2643: //
2644: // Allocate each of the small lance buffers and fill in the
2645: // buffer descriptor.
2646: //
2647:
2648: Adapter->LanceBufferListHeads[0] = -1;
2649: Adapter->LanceBufferListHeads[1] = 0;
2650:
2651: for (
2652: i = 0;
2653: i < NumberOfSmallBuffers;
2654: i++
2655: ) {
2656:
2657: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2658: Adapter,
2659: LANCE_SMALL_BUFFER_SIZE,
2660: &Adapter->LanceBuffers[i].VirtualLanceBuffer
2661: );
2662:
2663: if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
2664: DeleteAdapterMemory(Adapter);
2665: return FALSE;
2666: }
2667:
2668: Adapter->LanceBuffers[i].Next = i+1;
2669: Adapter->LanceBuffers[i].BufferSize = LANCE_SMALL_BUFFER_SIZE;
2670:
2671: }
2672:
2673: //
2674: // Make sure that the last buffer correctly terminates the free list.
2675: //
2676:
2677: Adapter->LanceBuffers[i-1].Next = -1;
2678:
2679: //
2680: // Do the medium buffers now.
2681: //
2682:
2683: Adapter->LanceBufferListHeads[2] = i;
2684:
2685: for (
2686: ;
2687: i < NumberOfSmallBuffers + NumberOfMediumBuffers;
2688: i++
2689: ) {
2690:
2691: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2692: Adapter,
2693: LANCE_MEDIUM_BUFFER_SIZE,
2694: &Adapter->LanceBuffers[i].VirtualLanceBuffer
2695: );
2696:
2697: if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
2698: DeleteAdapterMemory(Adapter);
2699: return FALSE;
2700: }
2701:
2702:
2703: Adapter->LanceBuffers[i].Next = i+1;
2704: Adapter->LanceBuffers[i].BufferSize = LANCE_MEDIUM_BUFFER_SIZE;
2705:
2706: }
2707:
2708: //
2709: // Make sure that the last buffer correctly terminates the free list.
2710: //
2711:
2712: Adapter->LanceBuffers[i-1].Next = -1;
2713:
2714:
2715: Adapter->LanceBufferListHeads[3] = i;
2716:
2717: for (
2718: ;
2719: i < NumberOfSmallBuffers + NumberOfMediumBuffers + NumberOfLargeBuffers;
2720: i++
2721: ) {
2722:
2723:
2724: LANCE_ALLOCATE_MEMORY_FOR_HARDWARE(
2725: Adapter,
2726: LANCE_LARGE_BUFFER_SIZE,
2727: &Adapter->LanceBuffers[i].VirtualLanceBuffer
2728: );
2729:
2730: if (Adapter->LanceBuffers[i].VirtualLanceBuffer == NULL) {
2731: DeleteAdapterMemory(Adapter);
2732: return FALSE;
2733: }
2734:
2735:
2736: Adapter->LanceBuffers[i].Next = i+1;
2737: Adapter->LanceBuffers[i].BufferSize = LANCE_LARGE_BUFFER_SIZE;
2738:
2739: }
2740:
2741: //
2742: // Make sure that the last buffer correctly terminates the free list.
2743: //
2744:
2745: Adapter->LanceBuffers[i-1].Next = -1;
2746:
2747: return TRUE;
2748:
2749: }
2750:
2751: STATIC
2752: VOID
2753: DeleteAdapterMemory(
2754: IN PLANCE_ADAPTER Adapter
2755: )
2756:
2757: /*++
2758:
2759: Routine Description:
2760:
2761: This routine deallocates memory for:
2762:
2763: - Transmit ring entries
2764:
2765: - Receive ring entries
2766:
2767: - Receive buffers
2768:
2769: - Adapter buffers for use if user transmit buffers don't meet hardware
2770: contraints
2771:
2772: - Structures to map transmit ring entries back to the packets.
2773:
2774: Arguments:
2775:
2776: Adapter - The adapter to deallocate memory for.
2777:
2778: Return Value:
2779:
2780: None.
2781:
2782: --*/
2783:
2784: {
2785:
2786: //
2787: // These variables exist to reduce the amount of checking below.
2788: //
2789:
2790: ULONG NumberOfSmallBuffers;
2791: ULONG NumberOfMediumBuffers;
2792: ULONG NumberOfLargeBuffers;
2793:
2794: NumberOfSmallBuffers = Adapter->NumberOfSmallBuffers;
2795: NumberOfMediumBuffers = Adapter->NumberOfMediumBuffers;
2796: NumberOfLargeBuffers = Adapter->NumberOfLargeBuffers;
2797:
2798:
2799: if (Adapter->InitBlock) {
2800:
2801: LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
2802: Adapter,
2803: Adapter->InitBlock
2804: );
2805:
2806: }
2807:
2808: if (Adapter->TransmitRing) {
2809:
2810: LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
2811: Adapter,
2812: Adapter->TransmitRing
2813: );
2814:
2815: }
2816:
2817: if (Adapter->ReceiveRing) {
2818:
2819: LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
2820: Adapter,
2821: Adapter->ReceiveRing
2822: );
2823:
2824: }
2825:
2826: if (Adapter->ReceiveVAs) {
2827:
2828: UINT i;
2829:
2830: for (
2831: i = 0;
2832: i < Adapter->NumberOfReceiveRings;
2833: i++
2834: ) {
2835:
2836: if (Adapter->ReceiveVAs[i]) {
2837:
2838: LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
2839: Adapter,
2840: Adapter->ReceiveVAs[i]
2841: );
2842:
2843: } else {
2844:
2845: break;
2846:
2847: }
2848:
2849: }
2850:
2851: LANCE_FREE_PHYS(
2852: Adapter->ReceiveVAs,
2853: sizeof(PVOID) * Adapter->NumberOfReceiveRings
2854: );
2855:
2856: }
2857:
2858: if (Adapter->RingToPacket) {
2859:
2860: LANCE_FREE_PHYS(
2861: Adapter->RingToPacket,
2862: sizeof(LANCE_RING_TO_PACKET) * Adapter->NumberOfTransmitRings
2863: );
2864:
2865: }
2866:
2867: if (Adapter->LanceBuffers) {
2868:
2869: UINT i;
2870:
2871: for (
2872: i = 0;
2873: i < NumberOfSmallBuffers + NumberOfMediumBuffers + NumberOfLargeBuffers;
2874: i++) {
2875:
2876: if (Adapter->LanceBuffers[i].VirtualLanceBuffer) {
2877:
2878: LANCE_DEALLOCATE_MEMORY_FOR_HARDWARE(
2879: Adapter,
2880: Adapter->LanceBuffers[i].VirtualLanceBuffer
2881: );
2882:
2883: } else {
2884:
2885: break;
2886:
2887: }
2888:
2889: }
2890:
2891: LANCE_FREE_PHYS(
2892: Adapter->LanceBuffers,
2893: sizeof(LANCE_BUFFER_DESCRIPTOR) *
2894: (NumberOfSmallBuffers +
2895: NumberOfMediumBuffers +
2896: NumberOfLargeBuffers)
2897: );
2898:
2899: }
2900:
2901: }
2902:
2903: STATIC
2904: NDIS_STATUS
2905: LanceOpenAdapter(
2906: OUT PNDIS_STATUS OpenErrorStatus,
2907: OUT NDIS_HANDLE *MacBindingHandle,
2908: OUT PUINT SelectedMediumIndex,
2909: IN PNDIS_MEDIUM MediumArray,
2910: IN UINT MediumArraySize,
2911: IN NDIS_HANDLE NdisBindingContext,
2912: IN NDIS_HANDLE MacAdapterContext,
2913: IN UINT OpenOptions,
2914: IN PSTRING AddressingInformation OPTIONAL
2915: )
2916:
2917: /*++
2918:
2919: Routine Description:
2920:
2921: This routine is used to create an open instance of an adapter, in effect
2922: creating a binding between an upper-level module and the MAC module over
2923: the adapter.
2924:
2925: Arguments:
2926:
2927: MacBindingHandle - A pointer to a location in which the MAC stores
2928: a context value that it uses to represent this binding.
2929:
2930: SelectedMediumIndex - Index of MediumArray which this adapter supports.
2931:
2932: MediumArray - Array of Medium types which the protocol is requesting.
2933:
2934: MediumArraySize - Number of entries in MediumArray.
2935:
2936: NdisBindingContext - A value to be recorded by the MAC and passed as
2937: context whenever an indication is delivered by the MAC for this binding.
2938:
2939: MacAdapterContext - The value associated with the adapter that is being
2940: opened when the MAC registered the adapter with NdisRegisterAdapter.
2941:
2942: OpenOptions - A bit mask of flags. Not used.
2943:
2944: AddressingInformation - An optional pointer to a variable length string
2945: containing hardware-specific information that can be used to program the
2946: device. (This is not used by this MAC.)
2947:
2948: Return Value:
2949:
2950: The function value is the status of the operation. If the MAC does not
2951: complete this request synchronously, the value would be
2952: NDIS_STATUS_PENDING.
2953:
2954:
2955: --*/
2956:
2957: {
2958:
2959: //
2960: // The LANCE_ADAPTER that this open binding should belong too.
2961: //
2962: PLANCE_ADAPTER Adapter;
2963:
2964: //
2965: // Holds the status that should be returned to the caller.
2966: //
2967: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
2968:
2969: PLANCE_OPEN NewOpen;
2970:
2971:
2972: UNREFERENCED_PARAMETER(OpenOptions);
2973: UNREFERENCED_PARAMETER(OpenErrorStatus);
2974: UNREFERENCED_PARAMETER(AddressingInformation);
2975:
2976:
2977: //
2978: // Search for correct medium.
2979: //
2980:
2981: for (; MediumArraySize > 0; MediumArraySize--){
2982:
2983: if (MediumArray[MediumArraySize - 1] == NdisMedium802_3){
2984:
2985: MediumArraySize--;
2986:
2987: break;
2988:
2989: }
2990:
2991: }
2992:
2993: if (MediumArray[MediumArraySize] != NdisMedium802_3){
2994:
2995: return(NDIS_STATUS_UNSUPPORTED_MEDIA);
2996:
2997: }
2998:
2999: *SelectedMediumIndex = MediumArraySize;
3000:
3001:
3002: Adapter = PLANCE_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
3003:
3004: NdisInterlockedAddUlong(&Adapter->References, 1, &Adapter->Lock);
3005:
3006: //
3007: // Allocate the space for the open binding. Fill in the fields.
3008: //
3009:
3010: LANCE_ALLOC_PHYS(&NewOpen,sizeof(LANCE_OPEN));
3011:
3012: if (NewOpen != NULL){
3013:
3014: *MacBindingHandle = BINDING_HANDLE_FROM_PLANCE_OPEN(NewOpen);
3015:
3016: InitializeListHead(&NewOpen->OpenList);
3017:
3018: NewOpen->NdisBindingContext = NdisBindingContext;
3019: NewOpen->References = 0;
3020: NewOpen->BindingShuttingDown = FALSE;
3021: NewOpen->OwningLance = Adapter;
3022:
3023: NewOpen->LookAhead = LANCE_MAX_LOOKAHEAD;
3024:
3025: NdisAcquireSpinLock(&Adapter->Lock);
3026:
3027: Adapter->MaxLookAhead = LANCE_MAX_LOOKAHEAD;
3028:
3029: if (!EthNoteFilterOpenAdapter(
3030: NewOpen->OwningLance->FilterDB,
3031: NewOpen,
3032: NdisBindingContext,
3033: &NewOpen->NdisFilterHandle
3034: )) {
3035:
3036: NdisReleaseSpinLock(&Adapter->Lock);
3037:
3038: LANCE_FREE_PHYS(NewOpen, sizeof(LANCE_OPEN));
3039:
3040: StatusToReturn = NDIS_STATUS_FAILURE;
3041:
3042: NdisAcquireSpinLock(&Adapter->Lock);
3043:
3044: } else {
3045:
3046: //
3047: // Everything has been filled in. Synchronize access to the
3048: // adapter block and link the new open adapter in and increment
3049: // the opens reference count to account for the fact that the
3050: // filter routines have a "reference" to the open.
3051: //
3052:
3053: InsertTailList(&Adapter->OpenBindings,&NewOpen->OpenList);
3054: NewOpen->References++;
3055:
3056: }
3057:
3058: } else {
3059:
3060: NdisWriteErrorLogEntry(
3061: Adapter->NdisAdapterHandle,
3062: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
3063: 1,
3064: (ULONG)openAdapter
3065: );
3066:
3067:
3068: StatusToReturn = NDIS_STATUS_RESOURCES;
3069:
3070: NdisAcquireSpinLock(&Adapter->Lock);
3071:
3072: }
3073:
3074: LANCE_DO_DEFERRED(Adapter);
3075:
3076: return StatusToReturn;
3077: }
3078:
3079: VOID
3080: LanceAdjustMaxLookAhead(
3081: IN PLANCE_ADAPTER Adapter
3082: )
3083: /*++
3084:
3085: Routine Description:
3086:
3087: This routine finds the open with the maximum lookahead value and
3088: stores that in the adapter block.
3089:
3090: Arguments:
3091:
3092: Adapter - A pointer to the adapter block.
3093:
3094: Returns:
3095:
3096: None.
3097:
3098: --*/
3099: {
3100: ULONG CurrentMax = 0;
3101: PLIST_ENTRY Link = &(Adapter->OpenBindings);
3102:
3103: while (Link->Flink != &(Adapter->OpenBindings)) {
3104:
3105: if (((PLANCE_OPEN)(Link->Flink))->LookAhead > CurrentMax) {
3106:
3107: CurrentMax = ((PLANCE_OPEN)(Link->Flink))->LookAhead;
3108:
3109: }
3110:
3111: Link = Link->Flink;
3112:
3113: }
3114:
3115: if (CurrentMax == 0) {
3116:
3117: CurrentMax = LANCE_MAX_LOOKAHEAD;
3118:
3119: }
3120:
3121: Adapter->MaxLookAhead = CurrentMax;
3122:
3123: }
3124:
3125:
3126: STATIC
3127: NDIS_STATUS
3128: LanceCloseAdapter(
3129: IN NDIS_HANDLE MacBindingHandle
3130: )
3131:
3132: /*++
3133:
3134: Routine Description:
3135:
3136: This routine causes the MAC to close an open handle (binding).
3137:
3138: Arguments:
3139:
3140: MacBindingHandle - The context value returned by the MAC when the
3141: adapter was opened. In reality it is a PLANCE_OPEN.
3142:
3143: Return Value:
3144:
3145: The function value is the status of the operation.
3146:
3147:
3148: --*/
3149:
3150: {
3151:
3152: PLANCE_ADAPTER Adapter;
3153:
3154: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
3155:
3156: PLANCE_OPEN Open;
3157:
3158: Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
3159:
3160: //
3161: // Hold the lock while we update the reference counts for the
3162: // adapter and the open.
3163: //
3164:
3165: Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
3166:
3167: NdisAcquireSpinLock(&Adapter->Lock);
3168:
3169: Adapter->References++;
3170:
3171: if (!Open->BindingShuttingDown) {
3172:
3173: Open->References++;
3174:
3175: StatusToReturn = EthDeleteFilterOpenAdapter(
3176: Adapter->FilterDB,
3177: Open->NdisFilterHandle,
3178: NULL
3179: );
3180:
3181: //
3182: // If the status is successful that merely implies that
3183: // we were able to delete the reference to the open binding
3184: // from the filtering code. If we have a successful status
3185: // at this point we still need to check whether the reference
3186: // count to determine whether we can close.
3187: //
3188: //
3189: // The delete filter routine can return a "special" status
3190: // that indicates that there is a current NdisIndicateReceive
3191: // on this binding. See below.
3192: //
3193:
3194: if (StatusToReturn == NDIS_STATUS_SUCCESS) {
3195:
3196: //
3197: // Check whether the reference count is two. If
3198: // it is then we can get rid of the memory for
3199: // this open.
3200: //
3201: // A count of two indicates one for this routine
3202: // and one for the filter which we *know* we can
3203: // get rid of.
3204: //
3205:
3206: if (Open->References == 2) {
3207:
3208: //
3209: // We are the only reference to the open. Remove
3210: // it from the open list and delete the memory.
3211: //
3212:
3213: RemoveEntryList(&Open->OpenList);
3214:
3215: if (Adapter->MaxLookAhead == Open->LookAhead) {
3216:
3217: LanceAdjustMaxLookAhead(Adapter);
3218:
3219: }
3220:
3221: LANCE_FREE_PHYS(Open, sizeof(LANCE_OPEN));
3222:
3223: } else {
3224:
3225: Open->BindingShuttingDown = TRUE;
3226:
3227: //
3228: // Remove the open from the open list and put it on
3229: // the closing list.
3230: //
3231:
3232: RemoveEntryList(&Open->OpenList);
3233: InsertTailList(&Adapter->CloseList,&Open->OpenList);
3234:
3235: //
3236: // Account for this routines reference to the open
3237: // as well as reference because of the filtering.
3238: //
3239:
3240: Open->References -= 2;
3241:
3242: //
3243: // Change the status to indicate that we will
3244: // be closing this later.
3245: //
3246:
3247: StatusToReturn = NDIS_STATUS_PENDING;
3248:
3249: }
3250:
3251: } else if (StatusToReturn == NDIS_STATUS_PENDING) {
3252:
3253: Open->BindingShuttingDown = TRUE;
3254:
3255: //
3256: // Remove the open from the open list and put it on
3257: // the closing list.
3258: //
3259:
3260: RemoveEntryList(&Open->OpenList);
3261: InsertTailList(&Adapter->CloseList,&Open->OpenList);
3262:
3263: //
3264: // Account for this routines reference to the open
3265: // as well as original open reference.
3266: //
3267:
3268: Open->References -= 2;
3269:
3270: } else if (StatusToReturn == NDIS_STATUS_CLOSING_INDICATING) {
3271:
3272: //
3273: // When we have this status it indicates that the filtering
3274: // code was currently doing an NdisIndicateReceive. It
3275: // would not be wise to delete the memory for the open at
3276: // this point. The filtering code will call our close action
3277: // routine upon return from NdisIndicateReceive and that
3278: // action routine will decrement the reference count for
3279: // the open.
3280: //
3281:
3282: Open->BindingShuttingDown = TRUE;
3283:
3284: //
3285: // This status is private to the filtering routine. Just
3286: // tell the caller the the close is pending.
3287: //
3288:
3289: StatusToReturn = NDIS_STATUS_PENDING;
3290:
3291: //
3292: // Remove the open from the open list and put it on
3293: // the closing list.
3294: //
3295:
3296: RemoveEntryList(&Open->OpenList);
3297: InsertTailList(&Adapter->CloseList,&Open->OpenList);
3298:
3299: //
3300: // Account for this routines reference to the open. CloseAction
3301: // will remove the second reference.
3302: //
3303:
3304: Open->References--;
3305:
3306: } else {
3307:
3308: //
3309: // Account for this routines reference to the open.
3310: //
3311:
3312: Open->References--;
3313:
3314: }
3315:
3316: } else {
3317:
3318: StatusToReturn = NDIS_STATUS_CLOSING;
3319:
3320: }
3321:
3322:
3323: LANCE_DO_DEFERRED(Adapter);
3324:
3325: return StatusToReturn;
3326:
3327: }
3328:
3329: NDIS_STATUS
3330: LanceRequest(
3331: IN NDIS_HANDLE MacBindingHandle,
3332: IN PNDIS_REQUEST NdisRequest
3333: )
3334:
3335: /*++
3336:
3337: Routine Description:
3338:
3339: This routine allows a protocol to query and set information
3340: about the MAC.
3341:
3342: Arguments:
3343:
3344: MacBindingHandle - The context value returned by the MAC when the
3345: adapter was opened. In reality, it is a pointer to PLANCE_OPEN.
3346:
3347: NdisRequest - A structure which contains the request type (Set or
3348: Query), an array of operations to perform, and an array for holding
3349: the results of the operations.
3350:
3351: Return Value:
3352:
3353: The function value is the status of the operation.
3354:
3355: --*/
3356:
3357: {
3358: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
3359:
3360: PLANCE_OPEN Open = (PLANCE_OPEN)(MacBindingHandle);
3361: PLANCE_ADAPTER Adapter = (Open->OwningLance);
3362:
3363: if (Adapter->HardwareFailure) {
3364:
3365: return(NDIS_STATUS_FAILURE);
3366:
3367: }
3368:
3369:
3370: //
3371: // Ensure that the open does not close while in this function.
3372: //
3373:
3374: NdisAcquireSpinLock(&Adapter->Lock);
3375:
3376: Adapter->References++;
3377:
3378: #if LANCE_TRACE
3379: DbgPrint("In LanceRequest\n");
3380: #endif
3381:
3382: //
3383: // Process request
3384: //
3385:
3386: if (NdisRequest->RequestType == NdisRequestQueryInformation) {
3387:
3388: StatusToReturn = LanceQueryInformation(Adapter, Open, NdisRequest);
3389:
3390: } else {
3391:
3392: if (NdisRequest->RequestType == NdisRequestSetInformation) {
3393:
3394: StatusToReturn = LanceSetInformation(Adapter,Open,NdisRequest);
3395:
3396: } else {
3397:
3398: StatusToReturn = NDIS_STATUS_NOT_RECOGNIZED;
3399:
3400: }
3401:
3402: }
3403:
3404: LANCE_DO_DEFERRED(Adapter);
3405:
3406: #if LANCE_TRACE
3407: DbgPrint("Out LanceRequest %x\n",StatusToReturn);
3408: #endif
3409:
3410: return(StatusToReturn);
3411:
3412: }
3413:
3414: NDIS_STATUS
3415: LanceQueryProtocolInformation(
3416: IN PLANCE_ADAPTER Adapter,
3417: IN PLANCE_OPEN Open,
3418: IN NDIS_OID Oid,
3419: IN BOOLEAN GlobalMode,
3420: IN PVOID InfoBuffer,
3421: IN UINT BytesLeft,
3422: OUT PUINT BytesNeeded,
3423: OUT PUINT BytesWritten
3424: )
3425:
3426: /*++
3427:
3428: Routine Description:
3429:
3430: The LanceQueryProtocolInformation process a Query request for
3431: NDIS_OIDs that are specific to a binding about the MAC. Note that
3432: some of the OIDs that are specific to bindings are also queryable
3433: on a global basis. Rather than recreate this code to handle the
3434: global queries, I use a flag to indicate if this is a query for the
3435: global data or the binding specific data.
3436:
3437: Arguments:
3438:
3439: Adapter - a pointer to the adapter.
3440:
3441: Open - a pointer to the open instance.
3442:
3443: Oid - the NDIS_OID to process.
3444:
3445: GlobalMode - Some of the binding specific information is also used
3446: when querying global statistics. This is a flag to specify whether
3447: to return the global value, or the binding specific value.
3448:
3449: PlaceInInfoBuffer - a pointer into the NdisRequest->InformationBuffer
3450: into which store the result of the query.
3451:
3452: BytesLeft - the number of bytes left in the InformationBuffer.
3453:
3454: BytesNeeded - If there is not enough room in the information buffer
3455: then this will contain the number of bytes needed to complete the
3456: request.
3457:
3458: BytesWritten - a pointer to the number of bytes written into the
3459: InformationBuffer.
3460:
3461: Return Value:
3462:
3463: The function value is the status of the operation.
3464:
3465: --*/
3466:
3467: {
3468: NDIS_MEDIUM Medium = NdisMedium802_3;
3469: ULONG GenericULong;
3470: USHORT GenericUShort;
3471: UCHAR GenericArray[6];
3472:
3473: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
3474:
3475: //
3476: // Common variables for pointing to result of query
3477: //
3478:
3479: PVOID MoveSource;
3480: ULONG MoveBytes;
3481:
3482: NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
3483:
3484: //
3485: // General Algorithm:
3486: //
3487: // Switch(Request)
3488: // Get requested information
3489: // Store results in a common variable.
3490: // Copy result in common variable to result buffer.
3491: //
3492:
3493: //
3494: // Make sure that ulong is 4 bytes. Else GenericULong must change
3495: // to something of size 4.
3496: //
3497: ASSERT(sizeof(ULONG) == 4);
3498:
3499:
3500: #if LANCE_TRACE
3501: DbgPrint("In LanceQueryProtocolInfo\n");
3502: #endif
3503:
3504: //
3505: // Set default values
3506: //
3507:
3508: MoveSource = (PVOID)(&GenericULong);
3509: MoveBytes = sizeof(GenericULong);
3510:
3511: //
3512: // Switch on request type
3513: //
3514:
3515: switch (Oid) {
3516:
3517: case OID_GEN_MAC_OPTIONS:
3518:
3519: GenericULong = (ULONG)(NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
3520: NDIS_MAC_OPTION_RECEIVE_SERIALIZED
3521: );
3522:
3523: break;
3524:
3525: case OID_GEN_SUPPORTED_LIST:
3526:
3527: if (!GlobalMode){
3528:
3529: MoveSource = (PVOID)(LanceProtocolSupportedOids);
3530: MoveBytes = sizeof(LanceProtocolSupportedOids);
3531:
3532: } else {
3533:
3534: MoveSource = (PVOID)(LanceGlobalSupportedOids);
3535: MoveBytes = sizeof(LanceGlobalSupportedOids);
3536:
3537: }
3538: break;
3539:
3540: case OID_GEN_HARDWARE_STATUS:
3541:
3542:
3543: if (Adapter->ResetInProgress){
3544:
3545: HardwareStatus = NdisHardwareStatusReset;
3546:
3547: } else {
3548:
3549: HardwareStatus = NdisHardwareStatusReady;
3550:
3551: }
3552:
3553:
3554: MoveSource = (PVOID)(&HardwareStatus);
3555: MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
3556:
3557: break;
3558:
3559: case OID_GEN_MEDIA_SUPPORTED:
3560: case OID_GEN_MEDIA_IN_USE:
3561:
3562: MoveSource = (PVOID) (&Medium);
3563: MoveBytes = sizeof(NDIS_MEDIUM);
3564: break;
3565:
3566: case OID_GEN_MAXIMUM_LOOKAHEAD:
3567:
3568: GenericULong = LANCE_MAX_LOOKAHEAD;
3569:
3570: break;
3571:
3572:
3573: case OID_GEN_MAXIMUM_FRAME_SIZE:
3574:
3575: GenericULong = (ULONG)(LANCE_LARGE_BUFFER_SIZE - LANCE_HEADER_SIZE);
3576:
3577: break;
3578:
3579:
3580: case OID_GEN_MAXIMUM_TOTAL_SIZE:
3581:
3582: GenericULong = (ULONG)(LANCE_LARGE_BUFFER_SIZE);
3583:
3584: break;
3585:
3586:
3587: case OID_GEN_LINK_SPEED:
3588:
3589: GenericULong = (ULONG)(100000);
3590:
3591: break;
3592:
3593:
3594: case OID_GEN_TRANSMIT_BUFFER_SPACE:
3595:
3596: GenericULong = (ULONG)((LANCE_SMALL_BUFFER_SIZE * Adapter->NumberOfSmallBuffers) +
3597: (LANCE_MEDIUM_BUFFER_SIZE * Adapter->NumberOfMediumBuffers) +
3598: (LANCE_LARGE_BUFFER_SIZE * Adapter->NumberOfLargeBuffers));
3599:
3600:
3601: break;
3602:
3603: case OID_GEN_RECEIVE_BUFFER_SPACE:
3604:
3605: GenericULong = (ULONG)(Adapter->NumberOfReceiveRings *
3606: Adapter->SizeOfReceiveBuffer);
3607:
3608: break;
3609:
3610: case OID_GEN_TRANSMIT_BLOCK_SIZE:
3611:
3612: GenericULong = (ULONG)(LANCE_SMALL_BUFFER_SIZE);
3613:
3614: break;
3615:
3616: case OID_GEN_RECEIVE_BLOCK_SIZE:
3617:
3618: GenericULong = (ULONG)(Adapter->SizeOfReceiveBuffer);
3619:
3620: break;
3621:
3622: case OID_GEN_VENDOR_ID:
3623:
3624: NdisMoveMemory(
3625: (PVOID)&GenericULong,
3626: Adapter->NetworkAddress,
3627: 3
3628: );
3629:
3630: GenericULong &= 0xFFFFFF00;
3631:
3632: if (Adapter->LanceCard == LANCE_DE201) {
3633:
3634: GenericULong |= 0x01;
3635:
3636: } else if (Adapter->LanceCard == LANCE_DE100) {
3637:
3638: GenericULong |= 0x02;
3639:
3640: } else if (Adapter->LanceCard == LANCE_DE422) {
3641:
3642: GenericULong |= 0x03;
3643:
3644: } else {
3645:
3646: GenericULong |= 0x04;
3647:
3648: }
3649:
3650: MoveSource = (PVOID)(&GenericULong);
3651: MoveBytes = sizeof(GenericULong);
3652: break;
3653:
3654: case OID_GEN_VENDOR_DESCRIPTION:
3655:
3656: if (Adapter->LanceCard == LANCE_DE201) {
3657:
3658: MoveSource = (PVOID)"DEC Etherworks Turbo Adapter";
3659: MoveBytes = 29;
3660:
3661: } else if (Adapter->LanceCard == LANCE_DE100) {
3662:
3663: MoveSource = (PVOID)"DEC Etherworks Adapter";
3664: MoveBytes = 23;
3665:
3666: } else if (Adapter->LanceCard == LANCE_DE422) {
3667:
3668: MoveSource = (PVOID)"DEC Etherworks Turbo EISA Adapter";
3669: MoveBytes = 34;
3670:
3671: } else {
3672:
3673: MoveSource = (PVOID)"Lance Adapter";
3674: MoveBytes = 15;
3675:
3676: }
3677:
3678: break;
3679:
3680: case OID_GEN_DRIVER_VERSION:
3681:
3682: GenericUShort = (USHORT)0x0301;
3683:
3684: MoveSource = (PVOID)(&GenericUShort);
3685: MoveBytes = sizeof(GenericUShort);
3686: break;
3687:
3688:
3689: case OID_GEN_CURRENT_PACKET_FILTER:
3690:
3691: if (GlobalMode ) {
3692:
3693: GenericULong = ETH_QUERY_FILTER_CLASSES(
3694: Adapter->FilterDB
3695: );
3696:
3697: } else {
3698:
3699: GenericULong = ETH_QUERY_PACKET_FILTER(
3700: Adapter->FilterDB,
3701: Open->NdisFilterHandle
3702: );
3703:
3704: }
3705:
3706: break;
3707:
3708: case OID_GEN_CURRENT_LOOKAHEAD:
3709:
3710: if ( GlobalMode ) {
3711:
3712: GenericULong = Adapter->MaxLookAhead;
3713:
3714: } else {
3715:
3716: GenericULong = Open->LookAhead;
3717:
3718: }
3719:
3720: break;
3721:
3722: case OID_802_3_PERMANENT_ADDRESS:
3723:
3724: LANCE_MOVE_MEMORY((PCHAR)GenericArray,
3725: Adapter->NetworkAddress,
3726: ETH_LENGTH_OF_ADDRESS
3727: );
3728:
3729: MoveSource = (PVOID)(GenericArray);
3730: MoveBytes = sizeof(Adapter->NetworkAddress);
3731: break;
3732:
3733: case OID_802_3_CURRENT_ADDRESS:
3734:
3735:
3736: LANCE_MOVE_MEMORY((PCHAR)GenericArray,
3737: Adapter->CurrentNetworkAddress,
3738: ETH_LENGTH_OF_ADDRESS
3739: );
3740:
3741: MoveSource = (PVOID)(GenericArray);
3742: MoveBytes = sizeof(Adapter->CurrentNetworkAddress);
3743: break;
3744:
3745: case OID_802_3_MULTICAST_LIST:
3746:
3747:
3748: {
3749: UINT NumAddresses;
3750:
3751: if (GlobalMode) {
3752:
3753: NumAddresses = ETH_NUMBER_OF_GLOBAL_FILTER_ADDRESSES(Adapter->FilterDB);
3754:
3755: if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
3756:
3757: *BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
3758:
3759: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
3760:
3761: break;
3762:
3763: }
3764:
3765: EthQueryGlobalFilterAddresses(
3766: &StatusToReturn,
3767: Adapter->FilterDB,
3768: BytesLeft,
3769: &NumAddresses,
3770: InfoBuffer
3771: );
3772:
3773: *BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
3774:
3775: //
3776: // Should not be an error since we held the spinlock
3777: // nothing should have changed.
3778: //
3779:
3780: ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
3781:
3782: } else {
3783:
3784: NumAddresses = EthNumberOfOpenFilterAddresses(
3785: Adapter->FilterDB,
3786: Open->NdisFilterHandle
3787: );
3788:
3789: if ((NumAddresses * ETH_LENGTH_OF_ADDRESS) > BytesLeft) {
3790:
3791: *BytesNeeded = (NumAddresses * ETH_LENGTH_OF_ADDRESS);
3792:
3793: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
3794:
3795: break;
3796:
3797: }
3798:
3799: EthQueryOpenFilterAddresses(
3800: &StatusToReturn,
3801: Adapter->FilterDB,
3802: Open->NdisFilterHandle,
3803: BytesLeft,
3804: &NumAddresses,
3805: InfoBuffer
3806: );
3807:
3808: //
3809: // Should not be an error since we held the spinlock
3810: // nothing should have changed.
3811: //
3812:
3813: ASSERT(StatusToReturn == NDIS_STATUS_SUCCESS);
3814:
3815: *BytesWritten = NumAddresses * ETH_LENGTH_OF_ADDRESS;
3816:
3817: }
3818:
3819: }
3820:
3821: MoveSource = (PVOID)NULL;
3822: MoveBytes = 0;
3823:
3824: break;
3825:
3826: case OID_802_3_MAXIMUM_LIST_SIZE:
3827:
3828: GenericULong = Adapter->MaxMulticastList;
3829:
3830: break;
3831:
3832:
3833:
3834: default:
3835:
3836: StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
3837: break;
3838: }
3839:
3840: if (StatusToReturn == NDIS_STATUS_SUCCESS){
3841:
3842: if (MoveBytes > BytesLeft){
3843:
3844: //
3845: // Not enough room in InformationBuffer. Punt
3846: //
3847:
3848: *BytesNeeded = MoveBytes;
3849:
3850: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
3851:
3852: } else {
3853:
3854: //
3855: // Store result.
3856: //
3857:
3858: LANCE_MOVE_MEMORY(InfoBuffer, MoveSource, MoveBytes);
3859:
3860: (*BytesWritten) += MoveBytes;
3861:
3862: }
3863: }
3864:
3865: #if LANCE_TRACE
3866: DbgPrint("Out LanceQueryProtocolInfo\n");
3867: #endif
3868:
3869: return(StatusToReturn);
3870: }
3871:
3872: NDIS_STATUS
3873: LanceQueryInformation(
3874: IN PLANCE_ADAPTER Adapter,
3875: IN PLANCE_OPEN Open,
3876: IN PNDIS_REQUEST NdisRequest
3877: )
3878: /*++
3879:
3880: Routine Description:
3881:
3882: The LanceQueryInformation is used by LanceRequest to query information
3883: about the MAC.
3884:
3885: Arguments:
3886:
3887: Adapter - A pointer to the adapter.
3888:
3889: Open - A pointer to a particular open instance.
3890:
3891: NdisRequest - A structure which contains the request type (Query),
3892: an array of operations to perform, and an array for holding
3893: the results of the operations.
3894:
3895: Return Value:
3896:
3897: The function value is the status of the operation.
3898:
3899: --*/
3900:
3901: {
3902:
3903: UINT BytesWritten = 0;
3904: UINT BytesNeeded = 0;
3905: UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
3906: PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
3907:
3908: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
3909:
3910:
3911: #if LANCE_TRACE
3912: DbgPrint("In LanceQueryInfo\n");
3913: #endif
3914:
3915:
3916: StatusToReturn = LanceQueryProtocolInformation(
3917: Adapter,
3918: Open,
3919: NdisRequest->DATA.QUERY_INFORMATION.Oid,
3920: FALSE,
3921: InfoBuffer,
3922: BytesLeft,
3923: &BytesNeeded,
3924: &BytesWritten
3925: );
3926:
3927:
3928: NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
3929:
3930: NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
3931:
3932: #if LANCE_TRACE
3933: DbgPrint("Out LanceQueryInfo\n");
3934: #endif
3935:
3936: return(StatusToReturn);
3937: }
3938:
3939: NDIS_STATUS
3940: LanceSetInformation(
3941: IN PLANCE_ADAPTER Adapter,
3942: IN PLANCE_OPEN Open,
3943: IN PNDIS_REQUEST NdisRequest
3944: )
3945: /*++
3946:
3947: Routine Description:
3948:
3949: The LanceSetInformation is used by LanceRequest to set information
3950: about the MAC.
3951:
3952: Note: Assumes it is called with the lock held.
3953:
3954: Arguments:
3955:
3956: Adapter - A pointer to the adapter.
3957:
3958: Open - A pointer to an open instance.
3959:
3960: NdisRequest - A structure which contains the request type (Set),
3961: an array of operations to perform, and an array for holding
3962: the results of the operations.
3963:
3964: Return Value:
3965:
3966: The function value is the status of the operation.
3967:
3968: --*/
3969:
3970: {
3971:
3972: //
3973: // General Algorithm:
3974: //
3975: // For each request
3976: // Verify length
3977: // Switch(Request)
3978: // Process Request
3979: //
3980:
3981: UINT BytesRead = 0;
3982: UINT BytesNeeded = 0;
3983: UINT BytesLeft = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
3984: PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.SET_INFORMATION.InformationBuffer);
3985:
3986: //
3987: // Variables for a particular request
3988: //
3989:
3990: NDIS_OID Oid;
3991: UINT OidLength;
3992:
3993: //
3994: // Variables for holding the new values to be used.
3995: //
3996:
3997: ULONG LookAhead;
3998: ULONG Filter;
3999:
4000: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
4001:
4002:
4003: #if LANCE_TRACE
4004: DbgPrint("In LanceSetInfo\n");
4005: #endif
4006:
4007:
4008: //
4009: // Get Oid and Length of next request
4010: //
4011:
4012: Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
4013:
4014: OidLength = BytesLeft;
4015:
4016: switch (Oid) {
4017:
4018:
4019: case OID_802_3_MULTICAST_LIST:
4020:
4021: //
4022: // Verify length
4023: //
4024:
4025: if ((OidLength % ETH_LENGTH_OF_ADDRESS) != 0){
4026:
4027: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
4028:
4029: NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
4030: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4031:
4032: return(StatusToReturn);
4033:
4034: }
4035:
4036: //
4037: // Call into filter package.
4038: //
4039:
4040: if (!Open->BindingShuttingDown) {
4041:
4042: //
4043: // Increment the open while it is going through the filtering
4044: // routines.
4045: //
4046:
4047: Open->References++;
4048:
4049: StatusToReturn = EthChangeFilterAddresses(
4050: Adapter->FilterDB,
4051: Open->NdisFilterHandle,
4052: NdisRequest,
4053: OidLength / ETH_LENGTH_OF_ADDRESS,
4054: (CHAR **)InfoBuffer,
4055: TRUE
4056: );
4057:
4058: Open->References--;
4059:
4060: } else {
4061:
4062: StatusToReturn = NDIS_STATUS_CLOSING;
4063:
4064: }
4065:
4066: break;
4067:
4068:
4069: case OID_GEN_CURRENT_PACKET_FILTER:
4070:
4071: //
4072: // Verify length
4073: //
4074:
4075: if (OidLength != 4) {
4076:
4077: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
4078:
4079: NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
4080: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4081:
4082: break;
4083:
4084: }
4085:
4086:
4087: LANCE_MOVE_MEMORY(&Filter, InfoBuffer, 4);
4088:
4089: //
4090: // Verify bits
4091: //
4092:
4093: if (Filter & (NDIS_PACKET_TYPE_SOURCE_ROUTING |
4094: NDIS_PACKET_TYPE_SMT |
4095: NDIS_PACKET_TYPE_MAC_FRAME |
4096: NDIS_PACKET_TYPE_FUNCTIONAL |
4097: NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
4098: NDIS_PACKET_TYPE_GROUP
4099: )) {
4100:
4101: StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
4102:
4103: NdisRequest->DATA.SET_INFORMATION.BytesRead = 4;
4104: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4105:
4106: break;
4107:
4108: }
4109:
4110: StatusToReturn = LanceSetPacketFilter(Adapter,
4111: Open,
4112: NdisRequest,
4113: Filter);
4114:
4115: break;
4116:
4117: case OID_GEN_CURRENT_LOOKAHEAD:
4118:
4119: //
4120: // Verify length
4121: //
4122:
4123: if (OidLength != 4) {
4124:
4125: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
4126:
4127: NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
4128: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4129:
4130: break;
4131:
4132: }
4133:
4134: LANCE_MOVE_MEMORY(&LookAhead, InfoBuffer, 4);
4135:
4136: if (LookAhead <= (LANCE_MAX_LOOKAHEAD)) {
4137:
4138: if (Open->LookAhead > Adapter->MaxLookAhead) {
4139:
4140: Open->LookAhead = LookAhead;
4141:
4142: Adapter->MaxLookAhead = LookAhead;
4143:
4144: } else {
4145:
4146: if ((Open->LookAhead == Adapter->MaxLookAhead) &&
4147: (LookAhead < Adapter->MaxLookAhead)) {
4148:
4149: Open->LookAhead = LookAhead;
4150:
4151: LanceAdjustMaxLookAhead(Adapter);
4152:
4153: } else {
4154:
4155: Open->LookAhead = LookAhead;
4156:
4157: }
4158:
4159: }
4160:
4161: } else {
4162:
4163: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
4164:
4165: }
4166:
4167: break;
4168:
4169: case OID_GEN_PROTOCOL_OPTIONS:
4170:
4171: StatusToReturn = NDIS_STATUS_SUCCESS;
4172: break;
4173:
4174: default:
4175:
4176: StatusToReturn = NDIS_STATUS_INVALID_OID;
4177:
4178: NdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
4179: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4180:
4181: break;
4182: }
4183:
4184: if (StatusToReturn == NDIS_STATUS_SUCCESS){
4185:
4186: NdisRequest->DATA.SET_INFORMATION.BytesRead = OidLength;
4187: NdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
4188:
4189: }
4190:
4191: #if LANCE_TRACE
4192: DbgPrint("Out LanceSetInfo\n");
4193: #endif
4194:
4195: return(StatusToReturn);
4196: }
4197:
4198: STATIC
4199: NDIS_STATUS
4200: LanceSetPacketFilter(
4201: IN PLANCE_ADAPTER Adapter,
4202: IN PLANCE_OPEN Open,
4203: IN PNDIS_REQUEST NdisRequest,
4204: IN UINT PacketFilter
4205: )
4206:
4207: /*++
4208:
4209: Routine Description:
4210:
4211: The LanceSetPacketFilter request allows a protocol to control the types
4212: of packets that it receives from the MAC.
4213:
4214: Note : Assumes that the lock is currently held.
4215:
4216: Arguments:
4217:
4218: Adapter - Pointer to the LANCE_ADAPTER.
4219:
4220: Open - Pointer to the instance of LANCE_OPEN for Ndis.
4221:
4222: NdisRequest - Pointer to the NDIS_REQUEST which submitted the set
4223: packet filter command.
4224:
4225: PacketFilter - A bit mask that contains flags that correspond to specific
4226: classes of received packets. If a particular bit is set in the mask,
4227: then packet reception for that class of packet is enabled. If the
4228: bit is clear, then packets that fall into that class are not received
4229: by the client. A single exception to this rule is that if the promiscuous
4230: bit is set, then the client receives all packets on the network, regardless
4231: of the state of the other flags.
4232:
4233: Return Value:
4234:
4235: The function value is the status of the operation.
4236:
4237: --*/
4238:
4239: {
4240:
4241: //
4242: // Keeps track of the *MAC's* status. The status will only be
4243: // reset if the filter change action routine is called.
4244: //
4245: NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
4246:
4247:
4248: #if LANCE_TRACE
4249: DbgPrint("In LanceSetPacketFilter\n");
4250: #endif
4251:
4252: Adapter->References++;
4253:
4254: if (!Open->BindingShuttingDown) {
4255:
4256: //
4257: // Increment the open while it is going through the filtering
4258: // routines.
4259: //
4260:
4261: Open->References++;
4262:
4263: StatusOfFilterChange = EthFilterAdjust(
4264: Adapter->FilterDB,
4265: Open->NdisFilterHandle,
4266: NdisRequest,
4267: PacketFilter,
4268: TRUE
4269: );
4270:
4271: Open->References--;
4272:
4273: } else {
4274:
4275: StatusOfFilterChange = NDIS_STATUS_CLOSING;
4276:
4277: }
4278:
4279: Adapter->References--;
4280:
4281: #if LANCE_TRACE
4282: DbgPrint("Out LanceSetPacketFilter\n");
4283: #endif
4284:
4285: return StatusOfFilterChange;
4286: }
4287:
4288:
4289: NDIS_STATUS
4290: LanceFillInGlobalData(
4291: IN PLANCE_ADAPTER Adapter,
4292: IN PNDIS_REQUEST NdisRequest
4293: )
4294:
4295: /*++
4296:
4297: Routine Description:
4298:
4299: This routine completes a GlobalStatistics request. It is critical that
4300: if information is needed from the Adapter->* fields, they have been
4301: updated before this routine is called.
4302:
4303: Arguments:
4304:
4305: Adapter - A pointer to the Adapter.
4306:
4307: NdisRequest - A structure which contains the request type (Global
4308: Query), an array of operations to perform, and an array for holding
4309: the results of the operations.
4310:
4311: Return Value:
4312:
4313: The function value is the status of the operation.
4314:
4315: --*/
4316: {
4317: //
4318: // General Algorithm:
4319: //
4320: // Switch(Request)
4321: // Get requested information
4322: // Store results in a common variable.
4323: // default:
4324: // Try protocol query information
4325: // If that fails, fail query.
4326: //
4327: // Copy result in common variable to result buffer.
4328: // Finish processing
4329:
4330: UINT BytesWritten = 0;
4331: UINT BytesNeeded = 0;
4332: UINT BytesLeft = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
4333: PUCHAR InfoBuffer = (PUCHAR)(NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer);
4334:
4335: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
4336:
4337: //
4338: // This variable holds result of query
4339: //
4340:
4341: ULONG GenericULong;
4342: ULONG MoveBytes = sizeof(ULONG) * 2 + sizeof(NDIS_OID);
4343:
4344: //
4345: // Make sure that int is 4 bytes. Else GenericULong must change
4346: // to something of size 4.
4347: //
4348: ASSERT(sizeof(ULONG) == 4);
4349:
4350:
4351: StatusToReturn = LanceQueryProtocolInformation(
4352: Adapter,
4353: NULL,
4354: NdisRequest->DATA.QUERY_INFORMATION.Oid,
4355: TRUE,
4356: InfoBuffer,
4357: BytesLeft,
4358: &BytesNeeded,
4359: &BytesWritten
4360: );
4361:
4362:
4363: if (StatusToReturn == NDIS_STATUS_NOT_SUPPORTED){
4364:
4365: StatusToReturn = NDIS_STATUS_SUCCESS;
4366:
4367: NdisAcquireSpinLock(&Adapter->Lock);
4368:
4369: //
4370: // Switch on request type
4371: //
4372:
4373: switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
4374:
4375: case OID_GEN_XMIT_OK:
4376:
4377: GenericULong = (ULONG)(Adapter->Transmit +
4378: Adapter->LateCollision);
4379:
4380: break;
4381:
4382: case OID_GEN_RCV_OK:
4383:
4384: GenericULong = (ULONG)(Adapter->Receive);
4385:
4386: break;
4387:
4388: case OID_GEN_XMIT_ERROR:
4389:
4390: GenericULong = (ULONG)(Adapter->LostCarrier);
4391:
4392: break;
4393:
4394: case OID_GEN_RCV_ERROR:
4395:
4396: GenericULong = (ULONG)(Adapter->CRCError);
4397:
4398: break;
4399:
4400: case OID_GEN_RCV_NO_BUFFER:
4401:
4402: GenericULong = (ULONG)(Adapter->OutOfReceiveBuffers);
4403:
4404: break;
4405:
4406: case OID_802_3_RCV_ERROR_ALIGNMENT:
4407:
4408: GenericULong = (ULONG)(Adapter->FramingError);
4409:
4410: break;
4411:
4412: case OID_802_3_XMIT_ONE_COLLISION:
4413:
4414: GenericULong = (ULONG)(Adapter->OneRetry);
4415:
4416: break;
4417:
4418: case OID_802_3_XMIT_MORE_COLLISIONS:
4419:
4420: GenericULong = (ULONG)(Adapter->MoreThanOneRetry);
4421:
4422: break;
4423:
4424:
4425: default:
4426:
4427: StatusToReturn = NDIS_STATUS_INVALID_OID;
4428:
4429: break;
4430:
4431: }
4432:
4433: NdisReleaseSpinLock(&Adapter->Lock);
4434:
4435: if (StatusToReturn == NDIS_STATUS_SUCCESS){
4436:
4437: //
4438: // Check to make sure there is enough room in the
4439: // buffer to store the result.
4440: //
4441:
4442: if (BytesLeft >= sizeof(ULONG)){
4443:
4444: //
4445: // Store the result.
4446: //
4447:
4448: LANCE_MOVE_MEMORY(
4449: (PVOID)InfoBuffer,
4450: (PVOID)(&GenericULong),
4451: sizeof(UINT)
4452: );
4453:
4454: BytesWritten += sizeof(ULONG);
4455:
4456: } else {
4457:
4458: StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
4459:
4460: }
4461:
4462: }
4463:
4464: }
4465:
4466: NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
4467:
4468: NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
4469:
4470: return(StatusToReturn);
4471: }
4472:
4473: NDIS_STATUS
4474: LanceQueryGlobalStatistics(
4475: IN NDIS_HANDLE MacAdapterContext,
4476: IN PNDIS_REQUEST NdisRequest
4477: )
4478:
4479: /*++
4480:
4481: Routine Description:
4482:
4483: The LanceQueryGlobalStatistics is used by the protocol to query
4484: global information about the MAC.
4485:
4486: Arguments:
4487:
4488: MacAdapterContext - The value associated with the adapter that is being
4489: opened when the MAC registered the adapter with NdisRegisterAdapter.
4490:
4491: NdisRequest - A structure which contains the request type (Query),
4492: an array of operations to perform, and an array for holding
4493: the results of the operations.
4494:
4495: Return Value:
4496:
4497: The function value is the status of the operation.
4498:
4499: --*/
4500:
4501: {
4502:
4503: //
4504: // General Algorithm:
4505: //
4506: //
4507: // Check if a request is going to pend...
4508: // If so, pend the entire operation.
4509: //
4510: // Else
4511: // Fill in the request block.
4512: //
4513: //
4514:
4515: PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)(MacAdapterContext);
4516:
4517: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
4518:
4519: //
4520: // Check if a request is valid and going to pend...
4521: // If so, pend the entire operation.
4522: //
4523:
4524:
4525: //
4526: // Switch on request type
4527: //
4528:
4529: switch (NdisRequest->DATA.QUERY_INFORMATION.Oid) {
4530: case OID_GEN_SUPPORTED_LIST:
4531: case OID_GEN_HARDWARE_STATUS:
4532: case OID_GEN_MEDIA_SUPPORTED:
4533: case OID_GEN_MEDIA_IN_USE:
4534: case OID_GEN_MAXIMUM_LOOKAHEAD:
4535: case OID_GEN_MAXIMUM_FRAME_SIZE:
4536: case OID_GEN_MAXIMUM_TOTAL_SIZE:
4537: case OID_GEN_MAC_OPTIONS:
4538: case OID_GEN_LINK_SPEED:
4539: case OID_GEN_TRANSMIT_BUFFER_SPACE:
4540: case OID_GEN_RECEIVE_BUFFER_SPACE:
4541: case OID_GEN_TRANSMIT_BLOCK_SIZE:
4542: case OID_GEN_RECEIVE_BLOCK_SIZE:
4543: case OID_GEN_VENDOR_ID:
4544: case OID_GEN_VENDOR_DESCRIPTION:
4545: case OID_GEN_DRIVER_VERSION:
4546: case OID_GEN_CURRENT_PACKET_FILTER:
4547: case OID_GEN_CURRENT_LOOKAHEAD:
4548: case OID_802_3_PERMANENT_ADDRESS:
4549: case OID_802_3_CURRENT_ADDRESS:
4550: case OID_802_5_CURRENT_FUNCTIONAL:
4551: case OID_GEN_XMIT_OK:
4552: case OID_GEN_RCV_OK:
4553: case OID_GEN_XMIT_ERROR:
4554: case OID_GEN_RCV_ERROR:
4555: case OID_GEN_RCV_NO_BUFFER:
4556: case OID_802_3_MULTICAST_LIST:
4557: case OID_802_3_MAXIMUM_LIST_SIZE:
4558: case OID_802_3_RCV_ERROR_ALIGNMENT:
4559: case OID_802_3_XMIT_ONE_COLLISION:
4560: case OID_802_3_XMIT_MORE_COLLISIONS:
4561:
4562: break;
4563:
4564: default:
4565:
4566: StatusToReturn = NDIS_STATUS_INVALID_OID;
4567:
4568: break;
4569:
4570: }
4571:
4572: if (StatusToReturn == NDIS_STATUS_SUCCESS){
4573:
4574: StatusToReturn = LanceFillInGlobalData(Adapter, NdisRequest);
4575:
4576: }
4577:
4578: return(StatusToReturn);
4579: }
4580:
4581:
4582:
4583: STATIC
4584: NDIS_STATUS
4585: LanceReset(
4586: IN NDIS_HANDLE MacBindingHandle
4587: )
4588:
4589: /*++
4590:
4591: Routine Description:
4592:
4593: The LanceReset request instructs the MAC to issue a hardware reset
4594: to the network adapter. The MAC also resets its software state. See
4595: the description of NdisReset for a detailed description of this request.
4596:
4597: Arguments:
4598:
4599: MacBindingHandle - The context value returned by the MAC when the
4600: adapter was opened. In reality, it is a pointer to LANCE_OPEN.
4601:
4602: Return Value:
4603:
4604: The function value is the status of the operation.
4605:
4606:
4607: --*/
4608:
4609: {
4610:
4611: //
4612: // Holds the status that should be returned to the caller.
4613: //
4614: NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
4615:
4616: PLANCE_ADAPTER Adapter =
4617: PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
4618:
4619: //
4620: // Hold the locks while we update the reference counts on the
4621: // adapter and the open.
4622: //
4623:
4624: NdisAcquireSpinLock(&Adapter->Lock);
4625:
4626: Adapter->References++;
4627:
4628: if (!Adapter->ResetInProgress) {
4629:
4630: PLANCE_OPEN Open;
4631:
4632: Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
4633:
4634: if (!Open->BindingShuttingDown) {
4635:
4636: //
4637: // Is was a reset request
4638: //
4639:
4640: PLIST_ENTRY CurrentLink;
4641:
4642: Open->References++;
4643:
4644: CurrentLink = Adapter->OpenBindings.Flink;
4645:
4646: while (CurrentLink != &Adapter->OpenBindings) {
4647:
4648: Open = CONTAINING_RECORD(
4649: CurrentLink,
4650: LANCE_OPEN,
4651: OpenList
4652: );
4653:
4654: Open->References++;
4655:
4656: NdisReleaseSpinLock(&Adapter->Lock);
4657:
4658: NdisIndicateStatus(
4659: Open->NdisBindingContext,
4660: NDIS_STATUS_RESET_START,
4661: NULL,
4662: 0
4663: );
4664:
4665: NdisAcquireSpinLock(&Adapter->Lock);
4666:
4667: Open->References--;
4668:
4669: CurrentLink = CurrentLink->Flink;
4670:
4671: }
4672:
4673: Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
4674:
4675: #if LANCE_TRACE
4676: DbgPrint("Starting reset for 0x%x\n", Open);
4677: #endif
4678:
4679: SetupForReset(
4680: Adapter,
4681: Open,
4682: NULL,
4683: NdisRequestGeneric1 // Means Reset
4684: );
4685:
4686: Open->References--;
4687:
4688: } else {
4689:
4690: StatusToReturn = NDIS_STATUS_CLOSING;
4691:
4692: }
4693:
4694: } else {
4695:
4696: StatusToReturn = NDIS_STATUS_SUCCESS;
4697:
4698: }
4699:
4700: LANCE_DO_DEFERRED(Adapter);
4701:
4702: return StatusToReturn;
4703:
4704: }
4705:
4706: STATIC
4707: VOID
4708: LanceSetInitializationBlock(
4709: IN PLANCE_ADAPTER Adapter
4710: )
4711:
4712: /*++
4713:
4714: Routine Description:
4715:
4716: This routine simply fills the initialization block
4717: with the information necessary for initialization.
4718:
4719: NOTE: This routine assumes that it is called with the lock
4720: acquired OR that only a single thread of execution is accessing
4721: the particular adapter.
4722:
4723: Arguments:
4724:
4725: Adapter - The adapter which holds the initialization block
4726: to initialize.
4727:
4728: Return Value:
4729:
4730: None.
4731:
4732:
4733: --*/
4734:
4735: {
4736:
4737: PHYSICAL_ADDRESS PhysAdr;
4738:
4739: UINT PacketFilters;
4740:
4741: PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing;
4742: USHORT Mode;
4743: UCHAR RingNumber;
4744: UCHAR i;
4745:
4746: #if LANCE_TRACE
4747: DbgPrint("in SetInitBlock\n");
4748: #endif
4749:
4750: LANCE_ZERO_MEMORY_FOR_HARDWARE(
4751: Adapter->InitBlock,
4752: sizeof(LANCE_INITIALIZATION_BLOCK)
4753: );
4754:
4755: for (i=0; i < ETH_LENGTH_OF_ADDRESS; i++) {
4756:
4757: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4758: Adapter->InitBlock->PhysicalAddress[i],
4759: Adapter->CurrentNetworkAddress[i]
4760: );
4761:
4762: }
4763:
4764: PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(Adapter, Adapter->TransmitRing);
4765:
4766:
4767: LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(
4768: Adapter->InitBlock->LowTransmitRingAddress,
4769: LANCE_GET_LOW_PART_ADDRESS(PhysAdr.LowPart)
4770: );
4771: LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(
4772: Adapter->InitBlock->HighTransmitRingAddress,
4773: LANCE_GET_HIGH_PART_ADDRESS(PhysAdr.LowPart)
4774: );
4775:
4776: PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(Adapter, Adapter->ReceiveRing);
4777:
4778: //
4779: // Set that the chip owns each entry in the ring
4780: //
4781:
4782: for (CurrentEntry = Adapter->ReceiveRing, RingNumber = 0;
4783: RingNumber < Adapter->NumberOfReceiveRings ;
4784: RingNumber++, CurrentEntry++) {
4785:
4786: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4787: CurrentEntry->ReceiveSummaryBits,
4788: LANCE_RECEIVE_OWNED_BY_CHIP
4789: );
4790:
4791: }
4792:
4793:
4794: LANCE_WRITE_HARDWARE_LOW_PART_ADDRESS(
4795: Adapter->InitBlock->LowReceiveRingAddress,
4796: LANCE_GET_LOW_PART_ADDRESS(PhysAdr.LowPart)
4797: );
4798: LANCE_WRITE_HARDWARE_HIGH_PART_ADDRESS(
4799: Adapter->InitBlock->HighReceiveRingAddress,
4800: LANCE_GET_HIGH_PART_ADDRESS(PhysAdr.LowPart)
4801: );
4802:
4803: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4804: Adapter->InitBlock->TransmitLengthLow5BitsReserved,
4805: (UCHAR)(Adapter->LogNumberTransmitRings << 5)
4806: );
4807:
4808: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4809: Adapter->InitBlock->ReceiveLengthLow5BitsReserved,
4810: (UCHAR)(Adapter->LogNumberReceiveRings << 5)
4811: );
4812:
4813: //
4814: // Set up the address filtering.
4815: //
4816: // First get hold of the combined packet filter.
4817: //
4818:
4819: PacketFilters = ETH_QUERY_FILTER_CLASSES(Adapter->FilterDB);
4820:
4821: #if LANCE_TRACE
4822: DbgPrint("Filters 0x%x\n", PacketFilters);
4823: #endif
4824:
4825: if (PacketFilters & NDIS_PACKET_TYPE_PROMISCUOUS) {
4826:
4827: //
4828: // If one binding is promiscuous there is no point in
4829: // setting up any other filtering. Every packet is
4830: // going to be accepted by the hardware.
4831: //
4832:
4833: LANCE_READ_HARDWARE_MEMORY_USHORT(
4834: Adapter->InitBlock->ModeRegister,
4835: &Mode
4836: );
4837:
4838: LANCE_WRITE_HARDWARE_MEMORY_USHORT(
4839: Adapter->InitBlock->ModeRegister,
4840: Mode | LANCE_MODE_PROMISCUOUS
4841: );
4842:
4843: } else if (PacketFilters & NDIS_PACKET_TYPE_ALL_MULTICAST) {
4844:
4845: //
4846: // We turn on all the bits in the filter since one binding
4847: // wants every multicast address.
4848: //
4849:
4850: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4851: Adapter->InitBlock->LogicalAddressFilter[0],
4852: 0xff
4853: );
4854: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4855: Adapter->InitBlock->LogicalAddressFilter[1],
4856: 0xff
4857: );
4858: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4859: Adapter->InitBlock->LogicalAddressFilter[2],
4860: 0xff
4861: );
4862: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4863: Adapter->InitBlock->LogicalAddressFilter[3],
4864: 0xff
4865: );
4866: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4867: Adapter->InitBlock->LogicalAddressFilter[4],
4868: 0xff
4869: );
4870: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4871: Adapter->InitBlock->LogicalAddressFilter[5],
4872: 0xff
4873: );
4874: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4875: Adapter->InitBlock->LogicalAddressFilter[6],
4876: 0xff
4877: );
4878: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4879: Adapter->InitBlock->LogicalAddressFilter[7],
4880: 0xff
4881: );
4882:
4883: } else if (PacketFilters & NDIS_PACKET_TYPE_MULTICAST) {
4884:
4885: //
4886: // At least one open binding wants multicast addresses.
4887: //
4888: // We get the multicast addresses from the filter and
4889: // put each one through a CRC. We then take the high
4890: // order 6 bits from the 32 bit CRC and set that bit
4891: // in the logical address filter.
4892: //
4893:
4894: UINT NumberOfAddresses;
4895:
4896: NDIS_STATUS Status;
4897:
4898: EthQueryGlobalFilterAddresses(
4899: &Status,
4900: Adapter->FilterDB,
4901: MAX_MULTICAST_ADDRESS * ETH_LENGTH_OF_ADDRESS,
4902: &NumberOfAddresses,
4903: MulticastAddresses
4904: );
4905:
4906:
4907: ASSERT(Status == NDIS_STATUS_SUCCESS);
4908:
4909: ASSERT(sizeof(ULONG) == 4);
4910:
4911: for (
4912: ;
4913: NumberOfAddresses;
4914: NumberOfAddresses--
4915: ) {
4916:
4917: UINT CRCValue;
4918:
4919: UINT HashValue = 0;
4920:
4921: CRCValue = CalculateCRC(
4922: 6,
4923: MulticastAddresses[NumberOfAddresses-1]
4924: );
4925:
4926: HashValue |= ((CRCValue & 0x00000001)?(0x00000020):(0x00000000));
4927: HashValue |= ((CRCValue & 0x00000002)?(0x00000010):(0x00000000));
4928: HashValue |= ((CRCValue & 0x00000004)?(0x00000008):(0x00000000));
4929: HashValue |= ((CRCValue & 0x00000008)?(0x00000004):(0x00000000));
4930: HashValue |= ((CRCValue & 0x00000010)?(0x00000002):(0x00000000));
4931: HashValue |= ((CRCValue & 0x00000020)?(0x00000001):(0x00000000));
4932:
4933: LANCE_READ_HARDWARE_MEMORY_UCHAR(
4934: Adapter->InitBlock->LogicalAddressFilter[HashValue >> 3],
4935: &RingNumber
4936: );
4937:
4938: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
4939: Adapter->InitBlock->LogicalAddressFilter[HashValue >> 3],
4940: RingNumber | (1 << (HashValue & 0x00000007))
4941: );
4942:
4943: }
4944:
4945: }
4946:
4947: #if LANCE_TRACE
4948: DbgPrint("out SetInitBlock\n");
4949: #endif
4950: }
4951:
4952: STATIC
4953: UINT
4954: CalculateCRC(
4955: IN UINT NumberOfBytes,
4956: IN PCHAR Input
4957: )
4958:
4959: /*++
4960:
4961: Routine Description:
4962:
4963: Calculates a 32 bit crc value over the input number of bytes.
4964:
4965: Arguments:
4966:
4967: NumberOfBytes - The number of bytes in the input.
4968:
4969: Input - An input "string" to calculate a CRC over.
4970:
4971: Return Value:
4972:
4973: A 32 bit crc value.
4974:
4975:
4976: --*/
4977:
4978: {
4979:
4980: const UINT POLY = 0x04c11db6;
4981: UINT CRCValue = 0xffffffff;
4982:
4983: ASSERT(sizeof(UINT) == 4);
4984:
4985: for (
4986: ;
4987: NumberOfBytes;
4988: NumberOfBytes--
4989: ) {
4990:
4991: UINT CurrentBit;
4992: UCHAR CurrentByte = *Input;
4993: Input++;
4994:
4995: for (
4996: CurrentBit = 8;
4997: CurrentBit;
4998: CurrentBit--
4999: ) {
5000:
5001: UINT CurrentCRCHigh = CRCValue >> 31;
5002:
5003: CRCValue <<= 1;
5004:
5005: if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
5006:
5007: CRCValue ^= POLY;
5008: CRCValue |= 0x00000001;
5009:
5010: }
5011:
5012: CurrentByte >>= 1;
5013:
5014: }
5015:
5016: }
5017:
5018: return CRCValue;
5019:
5020: }
5021:
5022: STATIC
5023: NDIS_STATUS
5024: LanceChangeMulticastAddresses(
5025: IN UINT OldFilterCount,
5026: IN CHAR OldAddresses[][ETH_LENGTH_OF_ADDRESS],
5027: IN UINT NewFilterCount,
5028: IN CHAR NewAddresses[][ETH_LENGTH_OF_ADDRESS],
5029: IN NDIS_HANDLE MacBindingHandle,
5030: IN PNDIS_REQUEST NdisRequest,
5031: IN BOOLEAN Set
5032: )
5033:
5034: /*++
5035:
5036: Routine Description:
5037:
5038: Action routine that will get called when a particular filter
5039: class is first used or last cleared.
5040:
5041: NOTE: This routine assumes that it is called with the lock
5042: acquired.
5043:
5044: Arguments:
5045:
5046:
5047: OldFilterCount - Number of Addresses in the old list of multicast
5048: addresses.
5049:
5050: OldAddresses - An array of all the multicast addresses that used
5051: to be on the adapter.
5052:
5053: NewFilterCount - Number of Addresses that should be put on the adapter.
5054:
5055: NewAddresses - An array of all the multicast addresses that should
5056: now be used.
5057:
5058: MacBindingHandle - The context value returned by the MAC when the
5059: adapter was opened. In reality, it is a pointer to LANCE_OPEN.
5060:
5061: NdisRequest - The request which submitted the filter change.
5062: Must use when completing this request with the NdisCompleteRequest
5063: service, if the MAC completes this request asynchronously.
5064:
5065: Set - If true the change resulted from a set, otherwise the
5066: change resulted from a open closing.
5067:
5068: Return Value:
5069:
5070: None.
5071:
5072:
5073: --*/
5074:
5075: {
5076:
5077:
5078: PLANCE_ADAPTER Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
5079:
5080: UNREFERENCED_PARAMETER(OldFilterCount);
5081: UNREFERENCED_PARAMETER(OldAddresses);
5082: UNREFERENCED_PARAMETER(NewFilterCount);
5083: UNREFERENCED_PARAMETER(NewAddresses);
5084:
5085: #if LANCE_TRACE
5086: DbgPrint("In LanceChangeMultiAdresses\n");
5087: #endif
5088:
5089: if (Adapter->HardwareFailure) {
5090:
5091: return(NDIS_STATUS_SUCCESS);
5092:
5093: }
5094:
5095: if (NdisRequest == NULL) {
5096:
5097: //
5098: // It's a close request.
5099: //
5100:
5101: NdisRequest = (PNDIS_REQUEST)
5102: &(PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->CloseMulticastRequest);
5103:
5104: }
5105:
5106: //
5107: // Check to see if the device is already resetting. If it is
5108: // then pend this add.
5109: //
5110:
5111: if (Adapter->ResetInProgress) {
5112:
5113: if (Adapter->PendQueue == NULL) {
5114:
5115: Adapter->PendQueue = Adapter->PendQueueTail = NdisRequest;
5116:
5117: } else {
5118:
5119: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(Adapter->PendQueueTail)->Next =
5120: NdisRequest;
5121:
5122: }
5123:
5124: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Next = NULL;
5125:
5126: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Open =
5127: PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
5128:
5129: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->RequestType =
5130: Set ? NdisRequestGeneric2 : NdisRequestClose;
5131:
5132: return(NDIS_STATUS_PENDING);
5133:
5134: } else {
5135:
5136: //
5137: // We need to add this to the hardware multicast filtering.
5138: //
5139:
5140: SetupForReset(
5141: Adapter,
5142: PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
5143: NdisRequest,
5144: Set ? NdisRequestGeneric2 : // Means SetMulticastAddress
5145: NdisRequestClose
5146: );
5147:
5148: }
5149:
5150: #if LANCE_TRACE
5151: DbgPrint("Out LanceChangeMultiAdresses\n");
5152: #endif
5153:
5154: return NDIS_STATUS_PENDING;
5155:
5156: }
5157:
5158: STATIC
5159: NDIS_STATUS
5160: LanceChangeFilterClasses(
5161: IN UINT OldFilterClasses,
5162: IN UINT NewFilterClasses,
5163: IN NDIS_HANDLE MacBindingHandle,
5164: IN PNDIS_REQUEST NdisRequest,
5165: IN BOOLEAN Set
5166: )
5167:
5168: /*++
5169:
5170: Routine Description:
5171:
5172: Action routine that will get called when an address is added to
5173: the filter that wasn't referenced by any other open binding.
5174:
5175: NOTE: This routine assumes that it is called with the lock
5176: acquired.
5177:
5178: Arguments:
5179:
5180: OldFilterClasses - The filter mask that used to be on the adapter.
5181:
5182: NewFilterClasses - The new filter mask to be put on the adapter.
5183:
5184: MacBindingHandle - The context value returned by the MAC when the
5185: adapter was opened. In reality, it is a pointer to LANCE_OPEN.
5186:
5187: NdisRequest - The request which submitted the filter change.
5188: Must use when completing this request with the NdisCompleteRequest
5189: service, if the MAC completes this request asynchronously.
5190:
5191: Set - If true the change resulted from a set, otherwise the
5192: change resulted from a open closing.
5193:
5194: --*/
5195:
5196: {
5197:
5198: PLANCE_ADAPTER Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
5199:
5200: UNREFERENCED_PARAMETER(OldFilterClasses);
5201: UNREFERENCED_PARAMETER(NewFilterClasses);
5202:
5203: #if LANCE_TRACE
5204: DbgPrint("In LanceChangeFilterClasses\n");
5205: #endif
5206:
5207:
5208: if (Adapter->HardwareFailure) {
5209:
5210: return(NDIS_STATUS_SUCCESS);
5211:
5212: }
5213:
5214:
5215: if (NdisRequest == NULL) {
5216:
5217: //
5218: // It's a close request.
5219: //
5220:
5221: NdisRequest = (PNDIS_REQUEST)
5222: &(PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->CloseFilterRequest);
5223:
5224: }
5225:
5226: //
5227: // Check to see if the device is already resetting. If it is
5228: // then pend this add.
5229: //
5230:
5231:
5232: if (Adapter->ResetInProgress) {
5233:
5234: if (Adapter->PendQueue == NULL) {
5235:
5236: Adapter->PendQueue = Adapter->PendQueueTail = NdisRequest;
5237:
5238: } else {
5239:
5240: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(Adapter->PendQueueTail)->Next =
5241: NdisRequest;
5242:
5243: }
5244:
5245: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Next = NULL;
5246:
5247: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Open =
5248: PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
5249:
5250: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->RequestType =
5251: Set ? NdisRequestGeneric2 : NdisRequestClose;
5252:
5253: return(NDIS_STATUS_PENDING);
5254:
5255: } else {
5256:
5257: //
5258: // We need to add this to the hardware multicast filtering.
5259: //
5260:
5261: SetupForReset(
5262: Adapter,
5263: PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
5264: NdisRequest,
5265: Set ? NdisRequestGeneric3 : // Means SetPacketFilter
5266: NdisRequestClose
5267: );
5268:
5269: }
5270:
5271: #if LANCE_TRACE
5272: DbgPrint("Out LanceChangeFilterClasses\n");
5273: #endif
5274:
5275: return NDIS_STATUS_PENDING;
5276:
5277: }
5278:
5279: STATIC
5280: VOID
5281: LanceCloseAction(
5282: IN NDIS_HANDLE MacBindingHandle
5283: )
5284:
5285: /*++
5286:
5287: Routine Description:
5288:
5289: Action routine that will get called when a particular binding
5290: was closed while it was indicating through NdisIndicateReceive
5291:
5292: All this routine needs to do is to decrement the reference count
5293: of the binding.
5294:
5295: NOTE: This routine assumes that it is called with the lock acquired.
5296:
5297: Arguments:
5298:
5299: MacBindingHandle - The context value returned by the MAC when the
5300: adapter was opened. In reality, it is a pointer to LANCE_OPEN.
5301:
5302: Return Value:
5303:
5304: None.
5305:
5306:
5307: --*/
5308:
5309: {
5310:
5311: PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->References--;
5312:
5313: }
5314:
5315: STATIC
5316: VOID
5317: ProcessInterrupt(
5318: IN PLANCE_ADAPTER Adapter
5319: )
5320:
5321: /*++
5322:
5323: Routine Description:
5324:
5325: Main routine for processing interrupts.
5326:
5327: NOTE: MUST BE CALLED WITH LOCK HELD!
5328:
5329: Arguments:
5330:
5331: Adapter - The Adapter to process interrupts for.
5332:
5333: Return Value:
5334:
5335: None.
5336:
5337: --*/
5338:
5339: {
5340:
5341: //
5342: // Holds a value of csr0.
5343: //
5344: USHORT Csr = 0;
5345:
5346: //
5347: // Loop until there are no more processing sources.
5348: //
5349:
5350: while (TRUE) {
5351:
5352: Adapter->WakeUpTimeout = FALSE;
5353:
5354: GET_CSR0_SINCE_LAST_PROCESSED(
5355: Adapter,
5356: &Csr
5357: );
5358:
5359: //
5360: // Check the interrupt source and other reasons
5361: // for processing. If there are no reasons to
5362: // process then exit this loop.
5363: //
5364: // Note that when we check the for processing sources
5365: // that we "carefully" check to see if we are already
5366: // processing one of the stage queues. We do this
5367: // by checking the "AlreadyProcessingStageX" variables
5368: // in the adapter. If any of these are true then
5369: // we let whoever set that boolean take care of pushing
5370: // the packet through the stage queues.
5371: //
5372: // By checking the "AlreadyProcessingStageX" variables
5373: // we can prevent a possible priority inversion where
5374: // we get "stuck" behind something that is processing
5375: // at a lower priority level.
5376: //
5377:
5378: if (((!Adapter->ResetInitStarted) &&
5379: ((Csr & (LANCE_CSR0_MEMORY_ERROR |
5380: LANCE_CSR0_MISSED_PACKET |
5381: LANCE_CSR0_BABBLE |
5382: LANCE_CSR0_RECEIVER_INTERRUPT |
5383: LANCE_CSR0_TRANSMITTER_INTERRUPT)) ||
5384: (Adapter->FirstLoopBack) ||
5385: (Adapter->ResetInProgress && (!Adapter->References)) ||
5386: ((!Adapter->AlreadyProcessingStage) &&
5387: (Adapter->StageOpen && Adapter->FirstStage1Packet)))) ||
5388: (Csr & LANCE_CSR0_INITIALIZATION_DONE)) {
5389:
5390: Adapter->References++;
5391:
5392: } else {
5393:
5394: break;
5395:
5396: }
5397:
5398: //
5399: // Check for initialization.
5400: //
5401: // Note that we come out of the synchronization above holding
5402: // the spinlock.
5403: //
5404:
5405: if (Csr & LANCE_CSR0_INITIALIZATION_DONE) {
5406:
5407: //
5408: // This will point (possibly null) to the open that
5409: // initiated the reset.
5410: //
5411: PLANCE_OPEN ResettingOpen;
5412:
5413: //
5414: // Possibly undefined reason why the reset was requested.
5415: //
5416: // It is undefined if the adapter initiated the reset
5417: // request on its own. It could do that if there
5418: // were some sort of error not associated with any particular
5419: // open.
5420: //
5421: NDIS_REQUEST_TYPE ResetRequestType;
5422:
5423: //
5424: // Possibly undefined request for the reset request.
5425: //
5426: PNDIS_REQUEST ResetNdisRequest;
5427:
5428: LOG(RESET_STEP_3);
5429:
5430: ASSERT(!Adapter->FirstInitialization);
5431:
5432: Csr &= ~LANCE_CSR0_INITIALIZATION_DONE;
5433:
5434: Adapter->ResetInProgress = FALSE;
5435: Adapter->ResetInitStarted = FALSE;
5436:
5437: //
5438: // We save off the open that caused this reset incase
5439: // we get *another* reset while we're indicating the
5440: // last reset is done.
5441: //
5442:
5443: ResettingOpen = Adapter->ResettingOpen;
5444: ResetRequestType = Adapter->ResetRequestType;
5445: ResetNdisRequest = Adapter->ResetNdisRequest;
5446:
5447: //
5448: // We need to signal every open binding that the
5449: // reset is complete. We increment the reference
5450: // count on the open binding while we're doing indications
5451: // so that the open can't be deleted out from under
5452: // us while we're indicating (recall that we can't own
5453: // the lock during the indication).
5454: //
5455:
5456: {
5457:
5458: PLANCE_OPEN Open;
5459:
5460: //
5461: // Look to see which open initiated the reset.
5462: //
5463: // If the reset was initiated by an open because it
5464: // was closing we will let the closing binding loop
5465: // further on in this routine indicate that the
5466: // request was complete.
5467: //
5468: // If the reset was initiated for some obscure hardware
5469: // reason that can't be associated with a particular
5470: // open (e.g. memory error on receiving a packet) then
5471: // we won't have an initiating request so we can't
5472: // indicate. (The ResettingOpen pointer will be
5473: // NULL in this case.)
5474: //
5475:
5476: #if LANCE_TRACE
5477: DbgPrint("0x%x 0x%x 0x%x %d %d\n",
5478: Adapter,
5479: ResettingOpen,
5480: ResetNdisRequest,
5481: ResetRequestType,
5482: NdisRequestClose
5483: );
5484: #endif
5485:
5486: if ((ResettingOpen != NULL) &&
5487: (ResetRequestType != NdisRequestClose)) {
5488:
5489: if (ResetNdisRequest != NULL) {
5490:
5491: //
5492: // It was a request submitted by a protocol.
5493: //
5494:
5495: FinishPendOp(Adapter, TRUE);
5496:
5497: } else {
5498:
5499: //
5500: // It was a request submitted by the MAC or
5501: // a reset command.
5502: //
5503:
5504: if (ResetRequestType == NdisRequestGeneric1) {
5505:
5506: //
5507: // Is was a reset request
5508: //
5509:
5510: PLIST_ENTRY CurrentLink;
5511:
5512: CurrentLink = Adapter->OpenBindings.Flink;
5513:
5514: while (CurrentLink != &Adapter->OpenBindings) {
5515:
5516: Open = CONTAINING_RECORD(
5517: CurrentLink,
5518: LANCE_OPEN,
5519: OpenList
5520: );
5521:
5522: Open->References++;
5523: NdisDprReleaseSpinLock(&Adapter->Lock);
5524:
5525: NdisIndicateStatus(
5526: Open->NdisBindingContext,
5527: NDIS_STATUS_RESET_END,
5528: NULL,
5529: 0
5530: );
5531:
5532: NdisIndicateStatusComplete(
5533: Open->NdisBindingContext
5534: );
5535:
5536: NdisDprAcquireSpinLock(&Adapter->Lock);
5537:
5538: Open->References--;
5539:
5540: CurrentLink = CurrentLink->Flink;
5541:
5542: }
5543:
5544: #if DBG
5545: Adapter->ResettingOpen = NULL;
5546: Adapter->ResetNdisRequest = NULL;
5547: Adapter->ResetRequestType = (NDIS_REQUEST_TYPE)0;
5548: #endif
5549:
5550: #if LANCE_TRACE
5551: DbgPrint("Completing reset\n");
5552: #endif
5553:
5554: NdisDprReleaseSpinLock(&Adapter->Lock);
5555:
5556: NdisCompleteReset(
5557: ResettingOpen->NdisBindingContext,
5558: NDIS_STATUS_SUCCESS
5559: );
5560:
5561:
5562: NdisDprAcquireSpinLock(&Adapter->Lock);
5563:
5564: ResettingOpen->References--;
5565:
5566: }
5567:
5568:
5569: }
5570:
5571: //
5572: // Restart the chip.
5573: //
5574:
5575: LanceStartChip(Adapter);
5576:
5577: } else {
5578:
5579: //
5580: // It was a close that pended (if there is
5581: // a ResettingOpen). Subtract 2, one for the
5582: // reset and one for the pended operation.
5583: //
5584:
5585: if (ResettingOpen) {
5586:
5587: ResettingOpen->References--;
5588:
5589: #if DBG
5590: Adapter->ResettingOpen = NULL;
5591: Adapter->ResetNdisRequest = NULL;
5592: Adapter->ResetRequestType = (NDIS_REQUEST_TYPE)0;
5593: #endif
5594:
5595: }
5596:
5597: if (!Adapter->ResetInProgress) {
5598:
5599: LanceStartChip(Adapter);
5600:
5601: }
5602:
5603: }
5604:
5605: }
5606:
5607: //
5608: // Fire off any pending operations...
5609: //
5610:
5611: if (Adapter->PendQueue != NULL) {
5612:
5613: PNDIS_REQUEST NdisRequest;
5614:
5615: NdisRequest = Adapter->PendQueue;
5616:
5617: Adapter->PendQueue =
5618: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Next;
5619:
5620: if (NdisRequest == Adapter->PendQueueTail) {
5621:
5622: Adapter->PendQueueTail = NULL;
5623:
5624: }
5625:
5626: if (PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->RequestType ==
5627: NdisRequestClose) {
5628:
5629: SetupForReset(
5630: Adapter,
5631: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Open,
5632: NULL,
5633: NdisRequestClose
5634: );
5635:
5636: } else {
5637:
5638: SetupForReset(
5639: Adapter,
5640: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->Open,
5641: NdisRequest,
5642: PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(NdisRequest)->RequestType
5643: );
5644:
5645: }
5646:
5647: }
5648:
5649: goto LoopBottom;
5650:
5651: }
5652:
5653: //
5654: // Note that the following code depends on the fact that
5655: // code above left the spinlock held.
5656: //
5657:
5658: //
5659: // If we have a reset in progress and the adapters reference
5660: // count is 1 (meaning no routine is in the interface and
5661: // we are the only "active" interrupt processing routine) then
5662: // it is safe to start the reset.
5663: //
5664:
5665: if (Adapter->ResetInProgress &&
5666: !Adapter->ResetInitStarted &&
5667: (Adapter->References == 1)) {
5668:
5669: #if LANCE_TRACE
5670: DbgPrint("Starting Initialization.\n");
5671: #endif
5672:
5673: StartAdapterReset(Adapter);
5674:
5675: Adapter->ResetInitStarted = TRUE;
5676: goto LoopBottom;
5677:
5678: }
5679:
5680: //
5681: // Check for non-packet related errors.
5682: //
5683:
5684: if (Csr & (LANCE_CSR0_MEMORY_ERROR |
5685: LANCE_CSR0_MISSED_PACKET |
5686: LANCE_CSR0_BABBLE)) {
5687:
5688: if (Csr & LANCE_CSR0_MISSED_PACKET) {
5689:
5690: Adapter->MissedPacket++;
5691:
5692: } else if (Csr & LANCE_CSR0_BABBLE) {
5693:
5694: //
5695: // A babble error implies that we've sent a
5696: // packet that is greater than the ethernet length.
5697: // This implies that the driver is broken.
5698: //
5699:
5700: Adapter->Babble++;
5701:
5702: NdisWriteErrorLogEntry(
5703: Adapter->NdisAdapterHandle,
5704: NDIS_ERROR_CODE_DRIVER_FAILURE,
5705: 2,
5706: (ULONG)processInterrupt,
5707: (ULONG)0x1
5708: );
5709:
5710:
5711: } else {
5712:
5713: //
5714: // Could only be a memory error. This shuts down
5715: // the receiver and the transmitter. We have to
5716: // reset to get the device started again.
5717: //
5718:
5719: Adapter->MemoryError++;
5720:
5721: SetupForReset(
5722: Adapter,
5723: NULL,
5724: NULL,
5725: NdisRequestGeneric4 // Means MAC issued
5726: );
5727:
5728: }
5729:
5730: Csr &= ~LANCE_CSR0_ERROR_BITS;
5731:
5732: }
5733:
5734: //
5735: // Check the interrupt vector and see if there are any
5736: // more receives to process. After we process any
5737: // other interrupt source we always come back to the top
5738: // of the loop to check if any more receive packets have
5739: // come in. This is to lessen the probability that we
5740: // drop a receive.
5741: //
5742:
5743:
5744: if (Csr & LANCE_CSR0_RECEIVER_INTERRUPT) {
5745:
5746: if (ProcessReceiveInterrupts(Adapter)) {
5747:
5748: Csr &= ~LANCE_CSR0_RECEIVER_INTERRUPT;
5749:
5750: }
5751:
5752: }
5753:
5754: //
5755: // Process the transmit interrupts if there are any.
5756: //
5757:
5758: if (Csr & LANCE_CSR0_TRANSMITTER_INTERRUPT) {
5759:
5760: //
5761: // We need to check if the transmitter has
5762: // stopped as a result of an error. If it
5763: // has then we really need to reset the adapter.
5764: //
5765:
5766: if (!(Csr & LANCE_CSR0_TRANSMITTER_ON)) {
5767:
5768: //
5769: // Might as well turn off the transmitter interrupt
5770: // source since we won't ever be processing them
5771: // and we don't want to come back here again.
5772: //
5773:
5774: Csr &= ~LANCE_CSR0_TRANSMITTER_INTERRUPT;
5775:
5776: //
5777: // Before we setup for the reset make sure that
5778: // we aren't already resetting.
5779: //
5780:
5781: if (!Adapter->ResetInProgress) {
5782:
5783: SetupForReset(
5784: Adapter,
5785: NULL,
5786: 0,
5787: NdisRequestGeneric4 // means MAC issued
5788: );
5789:
5790: }
5791:
5792: goto LoopBottom;
5793:
5794: } else {
5795:
5796: if (!ProcessTransmitInterrupts(Adapter)) {
5797:
5798: //
5799: // Process interrupts returns false if it
5800: // finds no more work to do. If this so we
5801: // turn off the transmitter interrupt source.
5802: //
5803:
5804: Csr &= ~LANCE_CSR0_TRANSMITTER_INTERRUPT;
5805:
5806: }
5807:
5808: }
5809:
5810: }
5811:
5812:
5813: //
5814: // Only try to push a packet through the stage queues
5815: // if somebody else isn't already doing it and
5816: // there is some hope of moving some packets
5817: // ahead.
5818: //
5819:
5820: if ((!Adapter->AlreadyProcessingStage) &&
5821: (Adapter->StageOpen && Adapter->FirstStage1Packet)) {
5822:
5823: LanceStagedAllocation(Adapter);
5824:
5825: }
5826:
5827: //
5828: // Process the loopback queue.
5829: //
5830: //
5831:
5832: if (Adapter->FirstLoopBack != NULL) {
5833:
5834: LanceProcessLoopback(Adapter);
5835:
5836: }
5837:
5838: //
5839: // If there are any opens on the closing list and their
5840: // reference counts are zero then complete the close and
5841: // delete them from the list.
5842: //
5843: //
5844:
5845: LoopBottom:;
5846:
5847: //
5848: // NOTE: This code assumes that the above code left
5849: // the spinlock acquired.
5850: //
5851: // Bottom of the interrupt processing loop. Another dpc
5852: // could be coming in at this point to process interrupts.
5853: // We clear the flag that says we're processing interrupts
5854: // so that some invocation of the DPC can grab it and process
5855: // any further interrupts.
5856: //
5857:
5858: if (!IsListEmpty(&Adapter->CloseList)) {
5859:
5860: PLANCE_OPEN Open;
5861: PLIST_ENTRY Link = &(Adapter->CloseList);
5862:
5863:
5864: while (Link->Flink != &(Adapter->CloseList)) {
5865:
5866: Open = CONTAINING_RECORD(
5867: Link->Flink,
5868: LANCE_OPEN,
5869: OpenList
5870: );
5871:
5872:
5873: if (!Open->References) {
5874:
5875: NdisDprReleaseSpinLock(&Adapter->Lock);
5876:
5877: NdisCompleteCloseAdapter(
5878: Open->NdisBindingContext,
5879: NDIS_STATUS_SUCCESS
5880: );
5881:
5882: NdisDprAcquireSpinLock(&Adapter->Lock);
5883:
5884: RemoveEntryList(&Open->OpenList);
5885:
5886: if (Adapter->MaxLookAhead == Open->LookAhead) {
5887:
5888: LanceAdjustMaxLookAhead(Adapter);
5889:
5890: }
5891:
5892: LANCE_FREE_PHYS(Open, sizeof(LANCE_OPEN));
5893:
5894: }
5895:
5896: Link = Link->Flink;
5897:
5898: }
5899:
5900:
5901: }
5902:
5903: Adapter->References--;
5904:
5905: }
5906:
5907: Adapter->ProcessInterruptRunning = FALSE;
5908:
5909: //
5910: // Check if we indicated any packets.
5911: //
5912: // Note: The only way to get out of the loop (via the break above) is
5913: // while we're still holding the spin lock.
5914: //
5915:
5916: if (Adapter->IndicatedAPacket) {
5917:
5918: Adapter->IndicatedAPacket = FALSE;
5919:
5920: NdisDprReleaseSpinLock(&Adapter->Lock);
5921:
5922: EthFilterIndicateReceiveComplete(Adapter->FilterDB);
5923:
5924: NdisDprAcquireSpinLock(&Adapter->Lock);
5925:
5926: }
5927:
5928: }
5929:
5930: STATIC
5931: BOOLEAN
5932: ProcessReceiveInterrupts(
5933: IN PLANCE_ADAPTER Adapter
5934: )
5935:
5936: /*++
5937:
5938: Routine Description:
5939:
5940: Process the packets that have finished receiving.
5941:
5942: NOTE: This routine assumes that no other thread of execution
5943: is processing receives! THE LOCK MUST BE HELD
5944:
5945: Arguments:
5946:
5947: Adapter - The adapter to indicate to.
5948:
5949: Return Value:
5950:
5951: Whether to clear the interrupt or not.
5952:
5953: --*/
5954:
5955: {
5956:
5957:
5958: //
5959: // We don't get here unless there was a receive. Loop through
5960: // the receive descriptors starting at the last known descriptor
5961: // owned by the hardware that begins a packet.
5962: //
5963: // Examine each receive ring descriptor for errors.
5964: //
5965: // We keep an array whose elements are indexed by the ring
5966: // index of the receive descriptors. The arrays elements are
5967: // the virtual addresses of the buffers pointed to by
5968: // each ring descriptor.
5969: //
5970: // When we have the entire packet (and error processing doesn't
5971: // prevent us from indicating it), we give the routine that
5972: // processes the packet through the filter, the buffers virtual
5973: // address (which is always the lookahead size) and as the
5974: // MAC context the index to the first and last ring descriptors
5975: // comprising the packet.
5976: //
5977:
5978: //
5979: // Index of the ring descriptor in the ring.
5980: //
5981: UINT CurrentIndex = Adapter->CurrentReceiveIndex;
5982:
5983: //
5984: // Pointer to the ring descriptor being examined.
5985: //
5986: PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing + CurrentIndex;
5987:
5988: //
5989: // Hold in a local the top receive ring index so that we don't
5990: // need to get it from the adapter all the time.
5991: //
5992: const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
5993:
5994: //
5995: // Boolean to record the fact that we've finished processing
5996: // one packet and we're about to start a new one.
5997: //
5998: BOOLEAN NewPacket = FALSE;
5999:
6000: //
6001: // Count of the number of buffers in the current packet.
6002: //
6003: UINT NumberOfBuffers = 1;
6004:
6005: //
6006: // Pointer to host addressable space for the lookahead buffer
6007: //
6008: PUCHAR LookaheadBuffer;
6009:
6010: ULONG ReceivePacketCount = 0;
6011:
6012: while (TRUE) {
6013:
6014: UCHAR ReceiveSummaryBits;
6015:
6016:
6017: //
6018: // Check to see whether we own the packet. If
6019: // we don't then simply return to the caller.
6020: //
6021:
6022: LANCE_READ_HARDWARE_MEMORY_UCHAR(
6023: CurrentEntry->ReceiveSummaryBits,
6024: &ReceiveSummaryBits
6025: );
6026:
6027: if (ReceiveSummaryBits & LANCE_RECEIVE_OWNED_BY_CHIP) {
6028:
6029: LOG(RECEIVE);
6030:
6031: return TRUE;
6032:
6033: } else if (ReceivePacketCount > 10) {
6034:
6035: LOG(RECEIVE)
6036:
6037: return FALSE;
6038:
6039: } else if (ReceiveSummaryBits & LANCE_RECEIVE_ERROR_SUMMARY) {
6040:
6041:
6042: //
6043: // We have an error in the packet. Record
6044: // the details of the error.
6045: //
6046:
6047: //
6048: // Synch with the set/query information routines.
6049: //
6050:
6051: if (ReceiveSummaryBits & LANCE_RECEIVE_BUFFER_ERROR) {
6052:
6053: //
6054: // Probably ran out of descriptors.
6055: //
6056:
6057: Adapter->OutOfReceiveBuffers++;
6058:
6059: } else if (ReceiveSummaryBits & LANCE_RECEIVE_CRC_ERROR) {
6060:
6061: Adapter->CRCError++;
6062:
6063: } else if (ReceiveSummaryBits & LANCE_RECEIVE_OVERFLOW_ERROR) {
6064:
6065: Adapter->OutOfReceiveBuffers++;
6066:
6067: } else if (ReceiveSummaryBits & LANCE_RECEIVE_FRAMING_ERROR) {
6068:
6069: Adapter->FramingError++;
6070:
6071: }
6072:
6073: ReceivePacketCount++;
6074:
6075: //
6076: // Give the packet back to the hardware.
6077: //
6078:
6079: RelinquishReceivePacket(
6080: Adapter,
6081: Adapter->CurrentReceiveIndex,
6082: NumberOfBuffers
6083: );
6084:
6085: NewPacket = TRUE;
6086:
6087: } else if (ReceiveSummaryBits & LANCE_RECEIVE_END_OF_PACKET) {
6088:
6089: //
6090: // We've reached the end of the packet. Prepare
6091: // the parameters for indication, then indicate.
6092: //
6093:
6094: UINT PacketSize;
6095: UINT LookAheadSize;
6096:
6097: LANCE_RECEIVE_CONTEXT Context;
6098:
6099: ASSERT(sizeof(LANCE_RECEIVE_CONTEXT) == sizeof(NDIS_HANDLE));
6100:
6101: //
6102: // Check just before we do indications that we aren't
6103: // resetting.
6104: //
6105:
6106: if (Adapter->ResetInProgress) {
6107:
6108: return TRUE;
6109: }
6110:
6111: Context.INFO.IsContext = TRUE;
6112: Context.INFO.FirstBuffer = Adapter->CurrentReceiveIndex;
6113: Context.INFO.LastBuffer = CurrentIndex;
6114:
6115: LANCE_GET_MESSAGE_SIZE(CurrentEntry, PacketSize);
6116:
6117: LookAheadSize = PacketSize;
6118:
6119: //
6120: // Find amount to indicate.
6121: //
6122:
6123: LookAheadSize = ((LookAheadSize < Adapter->SizeOfReceiveBuffer) ?
6124: LookAheadSize :
6125: Adapter->SizeOfReceiveBuffer);
6126:
6127: LookAheadSize -= LANCE_HEADER_SIZE;
6128:
6129: //
6130: // Increment the number of packets succesfully received.
6131: //
6132:
6133: Adapter->Receive++;
6134:
6135: LOG(INDICATE);
6136:
6137: Adapter->IndicatingMacReceiveContext = Context;
6138:
6139: Adapter->IndicatedAPacket = TRUE;
6140:
6141: NdisDprReleaseSpinLock(&Adapter->Lock);
6142:
6143: NdisCreateLookaheadBufferFromSharedMemory(
6144: (PVOID)(Adapter->ReceiveVAs[Adapter->CurrentReceiveIndex]),
6145: LookAheadSize + LANCE_HEADER_SIZE,
6146: &LookaheadBuffer
6147: );
6148:
6149: if (LookaheadBuffer != NULL) {
6150:
6151: if (PacketSize < LANCE_HEADER_SIZE) {
6152:
6153: if (PacketSize >= ETH_LENGTH_OF_ADDRESS) {
6154:
6155: //
6156: // Runt packet
6157: //
6158:
6159: EthFilterIndicateReceive(
6160: Adapter->FilterDB,
6161: (NDIS_HANDLE)Context.WholeThing,
6162: LookaheadBuffer,
6163: LookaheadBuffer,
6164: PacketSize,
6165: NULL,
6166: 0,
6167: 0
6168: );
6169:
6170: }
6171:
6172: } else {
6173:
6174: EthFilterIndicateReceive(
6175: Adapter->FilterDB,
6176: (NDIS_HANDLE)Context.WholeThing,
6177: LookaheadBuffer,
6178: LookaheadBuffer,
6179: LANCE_HEADER_SIZE,
6180: LookaheadBuffer + LANCE_HEADER_SIZE,
6181: LookAheadSize,
6182: PacketSize - LANCE_HEADER_SIZE
6183: );
6184:
6185: }
6186:
6187: NdisDestroyLookaheadBufferFromSharedMemory(
6188: LookaheadBuffer
6189: );
6190:
6191: }
6192:
6193: NdisDprAcquireSpinLock(&Adapter->Lock);
6194:
6195: ReceivePacketCount++;
6196:
6197: //
6198: // Give the packet back to the hardware.
6199: //
6200:
6201: RelinquishReceivePacket(
6202: Adapter,
6203: Adapter->CurrentReceiveIndex,
6204: NumberOfBuffers
6205: );
6206:
6207: NewPacket = TRUE;
6208:
6209: }
6210:
6211: //
6212: // We're at some indermediate packet. Advance to
6213: // the next one.
6214: //
6215:
6216: if (CurrentIndex == TopReceiveIndex) {
6217:
6218: CurrentIndex = 0;
6219: CurrentEntry = Adapter->ReceiveRing;
6220:
6221: } else {
6222:
6223: CurrentIndex++;
6224: CurrentEntry++;
6225:
6226: }
6227:
6228: if (NewPacket) {
6229:
6230: Adapter->CurrentReceiveIndex = CurrentIndex;
6231: NewPacket = FALSE;
6232: NumberOfBuffers = 0;
6233:
6234: }
6235:
6236: NumberOfBuffers++;
6237:
6238: if (NumberOfBuffers > (TopReceiveIndex + 1)) {
6239:
6240: //
6241: // Error! For some reason we wrapped without ever seeing
6242: // the end of packet. The card is hosed. Stop the
6243: // whole process.
6244: //
6245:
6246: //
6247: // There are opens to notify
6248: //
6249:
6250: PLIST_ENTRY CurrentLink;
6251: PLANCE_OPEN Open;
6252: BOOLEAN Cancel;
6253:
6254: Adapter->HardwareFailure = TRUE;
6255:
6256: CurrentLink = Adapter->OpenBindings.Flink;
6257:
6258: while (CurrentLink != &Adapter->OpenBindings) {
6259:
6260: Open = CONTAINING_RECORD(
6261: CurrentLink,
6262: LANCE_OPEN,
6263: OpenList
6264: );
6265:
6266: Open->References++;
6267:
6268: NdisDprReleaseSpinLock(&Adapter->Lock);
6269:
6270: NdisIndicateStatus(
6271: Open->NdisBindingContext,
6272: NDIS_STATUS_CLOSING,
6273: NULL,
6274: 0
6275: );
6276:
6277: NdisIndicateStatusComplete(
6278: Open->NdisBindingContext
6279: );
6280:
6281: NdisDprAcquireSpinLock(&Adapter->Lock);
6282:
6283: Open->References--;
6284:
6285: CurrentLink = CurrentLink->Flink;
6286:
6287: }
6288:
6289: #if LANCELOG
6290:
6291: if (LogTimerRunning) {
6292:
6293: NdisCancelTimer(&LogTimer, &Cancel);
6294: NdisStallExecution(500000);
6295: LogTimerRunning = FALSE;
6296:
6297: }
6298:
6299: #endif
6300:
6301:
6302: NdisRemoveInterrupt(&(Adapter->Interrupt));
6303:
6304: NdisWriteErrorLogEntry(
6305: Adapter->NdisAdapterHandle,
6306: NDIS_ERROR_CODE_HARDWARE_FAILURE,
6307: 0
6308: );
6309:
6310: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
6311:
6312: return TRUE;
6313:
6314: }
6315:
6316: }
6317:
6318: }
6319:
6320: STATIC
6321: VOID
6322: RelinquishReceivePacket(
6323: IN PLANCE_ADAPTER Adapter,
6324: IN UINT StartingIndex,
6325: IN UINT NumberOfBuffers
6326: )
6327:
6328: /*++
6329:
6330: Routine Description:
6331:
6332: Gives a range of receive descriptors back to the hardware.
6333:
6334: NOTE: MUST BE CALLED WITH THE LOCK HELD!!
6335:
6336: Arguments:
6337:
6338: Adapter - The adapter that the ring works with.
6339:
6340: StartingIndex - The first ring to return. Note that since
6341: we are dealing with a ring, this value could be greater than
6342: the EndingIndex.
6343:
6344: NumberOfBuffers - The number of buffers (or ring descriptors) in
6345: the current packet.
6346:
6347: Return Value:
6348:
6349: None.
6350:
6351: --*/
6352:
6353: {
6354:
6355: //
6356: // Index of the ring descriptor in the ring.
6357: //
6358: UINT CurrentIndex = StartingIndex;
6359:
6360: //
6361: // Pointer to the ring descriptor being returned.
6362: //
6363: PLANCE_RECEIVE_ENTRY CurrentEntry = Adapter->ReceiveRing + CurrentIndex;
6364:
6365: //
6366: // Hold in a local so that we don't need to access via the adapter.
6367: //
6368: const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
6369:
6370: UCHAR Tmp;
6371:
6372: LANCE_READ_HARDWARE_MEMORY_UCHAR(
6373: CurrentEntry->ReceiveSummaryBits,
6374: &Tmp
6375: );
6376:
6377: ASSERT(!(Tmp & LANCE_RECEIVE_OWNED_BY_CHIP));
6378: ASSERT(Tmp & LANCE_RECEIVE_START_OF_PACKET);
6379:
6380: for (
6381: ;
6382: NumberOfBuffers;
6383: NumberOfBuffers--
6384: ) {
6385:
6386: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
6387: CurrentEntry->ReceiveSummaryBits,
6388: LANCE_RECEIVE_OWNED_BY_CHIP
6389: );
6390:
6391: if (CurrentIndex == TopReceiveIndex) {
6392:
6393: CurrentEntry = Adapter->ReceiveRing;
6394: CurrentIndex = 0;
6395:
6396: } else {
6397:
6398: CurrentEntry++;
6399: CurrentIndex++;
6400:
6401: }
6402:
6403: }
6404:
6405: }
6406:
6407: STATIC
6408: BOOLEAN
6409: ProcessTransmitInterrupts(
6410: IN PLANCE_ADAPTER Adapter
6411: )
6412:
6413: /*++
6414:
6415: Routine Description:
6416:
6417: Process the packets that have finished transmitting.
6418:
6419: NOTE: This routine assumes that it is being executed in a
6420: single thread of execution. CALLED WITH LOCK HELD!!!
6421:
6422: Arguments:
6423:
6424: Adapter - The adapter that was sent from.
6425:
6426: Return Value:
6427:
6428: This function will return TRUE if it finished up the
6429: send on a packet. It will return FALSE if for some
6430: reason there was no packet to process.
6431:
6432: --*/
6433:
6434: {
6435: //
6436: // Index into the ring to packet structure. This index points
6437: // to the first ring entry for the first buffer used for transmitting
6438: // the packet.
6439: //
6440: UINT FirstIndex;
6441:
6442: //
6443: // Pointer to the last ring entry for the packet to be transmitted.
6444: // This pointer might actually point to a ring entry before the first
6445: // ring entry for the packet since the ring structure is, simply, a ring.
6446: //
6447: PLANCE_TRANSMIT_ENTRY LastRingEntry;
6448:
6449: //
6450: // Pointer to the packet that started this transmission.
6451: //
6452: PNDIS_PACKET OwningPacket;
6453:
6454: //
6455: // First Buffer
6456: //
6457: PNDIS_BUFFER FirstBuffer;
6458:
6459: //
6460: // Virtual address of first buffer
6461: //
6462: PVOID BufferVA;
6463:
6464: //
6465: // Length of the first buffer
6466: //
6467: UINT Length;
6468:
6469: //
6470: // Points to the reserved part of the OwningPacket.
6471: //
6472: PLANCE_RESERVED Reserved;
6473:
6474: UCHAR TransmitSummaryBits;
6475: USHORT ErrorSummaryInfo;
6476:
6477: //
6478: // Used to hold the ring to packet mapping information so that
6479: // we can release the ring entries as quickly as possible.
6480: //
6481: LANCE_RING_TO_PACKET SavedRingMapping;
6482:
6483:
6484: //
6485: // Get hold of the first transmitted packet.
6486: //
6487:
6488: //
6489: // First we check that this is a packet that was transmitted
6490: // but not already processed. Recall that this routine
6491: // will be called repeatedly until this tests false, Or we
6492: // hit a packet that we don't completely own.
6493: //
6494:
6495: //
6496: // NOTE: I found a problem where FirstUncommitedRing wraps around
6497: // and becomes equal to TransmittingRing. This only happens when
6498: // NumberOfAvailableRings is 0 (JohnsonA)
6499: //
6500:
6501: if ((Adapter->TransmittingRing == Adapter->FirstUncommittedRing) &&
6502: (Adapter->NumberOfAvailableRings > 0)) {
6503:
6504: return FALSE;
6505:
6506: } else {
6507:
6508: FirstIndex = Adapter->TransmittingRing - Adapter->TransmitRing;
6509:
6510: }
6511:
6512:
6513: //
6514: // We put the mapping into a local variable so that we
6515: // can return the mapping as soon as possible.
6516: //
6517:
6518: SavedRingMapping = Adapter->RingToPacket[FirstIndex];
6519:
6520: //
6521: // Get a pointer to the last ring entry for this packet.
6522: //
6523:
6524: LastRingEntry = Adapter->TransmitRing +
6525: SavedRingMapping.RingIndex;
6526:
6527: //
6528: // Get a pointer to the owning packet and the reserved part of
6529: // the packet.
6530: //
6531:
6532: OwningPacket = SavedRingMapping.OwningPacket;
6533:
6534: SavedRingMapping.OwningPacket = NULL;
6535:
6536: if (OwningPacket == NULL) {
6537:
6538: //
6539: // We seem to be in a messed up state. Ignore this interrupt and
6540: // the wake up dpc will reset the card if necessary.
6541: //
6542:
6543: ASSERT(OwningPacket != NULL);
6544: return(FALSE);
6545:
6546: }
6547:
6548: if (Adapter->FirstFinishTransmit == NULL) {
6549:
6550: //
6551: // We seem to be in a messed up state. Ignore this interrupt and
6552: // the wake up dpc will reset the card if necessary.
6553: //
6554:
6555: ASSERT(Adapter->FirstFinishTransmit != NULL);
6556: return(FALSE);
6557:
6558: }
6559:
6560: Reserved = PLANCE_RESERVED_FROM_PACKET(OwningPacket);
6561:
6562: //
6563: // Check that the host does indeed own this entire packet.
6564: //
6565:
6566: LANCE_READ_HARDWARE_MEMORY_UCHAR(
6567: LastRingEntry->TransmitSummaryBits,
6568: &TransmitSummaryBits
6569: );
6570:
6571: if (TransmitSummaryBits & LANCE_TRANSMIT_OWNED_BY_CHIP) {
6572:
6573: //
6574: // We don't own this last packet. We return FALSE to indicate
6575: // that we don't have any more packets to work on.
6576: //
6577:
6578: return FALSE;
6579:
6580: } else {
6581:
6582: //
6583: // Pointer to the current ring descriptor being examine for errors
6584: // and the statistics accumulated during its transmission.
6585: //
6586: PLANCE_TRANSMIT_ENTRY CurrentRingEntry;
6587:
6588: //
6589: // The binding that is submitting this packet.
6590: //
6591: PLANCE_OPEN Open;
6592:
6593: //
6594: // Holds whether the packet successfully transmitted or not.
6595: //
6596: BOOLEAN Successful = TRUE;
6597:
6598: LOG(TRANSMIT_COMPLETE);
6599:
6600: CurrentRingEntry = Adapter->TransmitRing + FirstIndex;
6601:
6602: //
6603: // now return these buffers to the adapter.
6604: //
6605:
6606: ReturnAdapterResources(
6607: Adapter,
6608: SavedRingMapping.LanceBuffersIndex
6609: );
6610:
6611: //
6612: // Since the host owns the entire packet check the ring
6613: // entries from first to last for any errors in transmission.
6614: // Any errors found or multiple tries should be recorded in
6615: // the information structure for the adapter.
6616: //
6617: // We treat Late Collisions as success since the packet was
6618: // fully transmitted and may have been received.
6619: //
6620:
6621: while (TRUE) {
6622:
6623: LANCE_READ_HARDWARE_MEMORY_UCHAR(
6624: CurrentRingEntry->TransmitSummaryBits,
6625: &TransmitSummaryBits
6626: );
6627:
6628: LANCE_READ_HARDWARE_MEMORY_USHORT(
6629: CurrentRingEntry->ErrorSummaryInfo,
6630: &ErrorSummaryInfo
6631: );
6632:
6633: if ((TransmitSummaryBits & LANCE_TRANSMIT_ANY_ERRORS) &&
6634: !(ErrorSummaryInfo & LANCE_TRANSMIT_LATE_COLLISION)) {
6635:
6636: if (ErrorSummaryInfo & LANCE_TRANSMIT_RETRY) {
6637:
6638: Adapter->RetryFailure++;
6639:
6640: } else if (ErrorSummaryInfo & LANCE_TRANSMIT_LOST_CARRIER) {
6641:
6642: Adapter->LostCarrier++;
6643:
6644: } else if (ErrorSummaryInfo & LANCE_TRANSMIT_UNDERFLOW) {
6645:
6646: Adapter->UnderFlow++;
6647:
6648: }
6649:
6650: #if DBG
6651: LanceSendFails[LanceSendFailPlace] =
6652: (UCHAR)(ErrorSummaryInfo);
6653: LanceSendFailPlace++;
6654:
6655:
6656: #endif
6657:
6658: #if LANCE_TRACE
6659: DbgPrint("Unsuccessful Transmit 0x%x\n",
6660: ErrorSummaryInfo);
6661: #endif
6662:
6663: Successful = FALSE;
6664:
6665: //
6666: // Move the pointer to transmitting but unprocessed
6667: // ring entries to after this packet, and recover
6668: // the remaining now available ring entries.
6669: //
6670:
6671: Adapter->NumberOfAvailableRings +=
6672: (CurrentRingEntry <= LastRingEntry)?
6673: ((LastRingEntry - CurrentRingEntry)+1):
6674: ((Adapter->LastTransmitRingEntry - CurrentRingEntry) +
6675: (LastRingEntry-Adapter->TransmitRing) + 2);
6676:
6677: if (LastRingEntry == Adapter->LastTransmitRingEntry) {
6678:
6679: Adapter->TransmittingRing = Adapter->TransmitRing;
6680:
6681: } else {
6682:
6683: Adapter->TransmittingRing = LastRingEntry + 1;
6684:
6685: }
6686:
6687: break;
6688:
6689: } else {
6690:
6691: //
6692: // Logical variable that records whether this
6693: // is the last packet.
6694: //
6695: BOOLEAN DoneWithPacket =
6696: TransmitSummaryBits &
6697: LANCE_TRANSMIT_END_OF_PACKET;
6698:
6699: if (ErrorSummaryInfo &
6700: LANCE_TRANSMIT_LATE_COLLISION) {
6701:
6702: Adapter->LateCollision++;
6703:
6704: }
6705:
6706: if (TransmitSummaryBits &
6707: LANCE_TRANSMIT_START_OF_PACKET) {
6708:
6709: //
6710: // Collect some statistics on how many tries were needed.
6711: //
6712:
6713: if (TransmitSummaryBits & LANCE_TRANSMIT_DEFERRED) {
6714:
6715: Adapter->Deferred++;
6716:
6717: } else if (TransmitSummaryBits & LANCE_TRANSMIT_ONE_RETRY) {
6718:
6719: Adapter->OneRetry++;
6720:
6721: } else if (TransmitSummaryBits & LANCE_TRANSMIT_MORE_THAN_ONE_RETRY) {
6722:
6723: Adapter->MoreThanOneRetry++;
6724:
6725:
6726: }
6727:
6728: }
6729:
6730: if (CurrentRingEntry == Adapter->LastTransmitRingEntry) {
6731:
6732: CurrentRingEntry = Adapter->TransmitRing;
6733:
6734: } else {
6735:
6736: CurrentRingEntry++;
6737:
6738: }
6739:
6740: Adapter->TransmittingRing = CurrentRingEntry;
6741: Adapter->NumberOfAvailableRings++;
6742:
6743: if (DoneWithPacket) {
6744:
6745: break;
6746:
6747: }
6748:
6749: }
6750:
6751: }
6752:
6753: //
6754: // Store result
6755: //
6756:
6757: if (Successful) {
6758:
6759: //
6760: // Increment number of packets successfully sent.
6761: //
6762:
6763: Adapter->Transmit++;
6764:
6765: }
6766:
6767: //
6768: // Remove packet from sending queue
6769: //
6770:
6771: Adapter->FirstFinishTransmit = Reserved->Next;
6772:
6773: if (Adapter->FirstFinishTransmit == NULL) {
6774:
6775: Adapter->LastFinishTransmit = NULL;
6776:
6777: }
6778:
6779: //
6780: // Do a quick check to see if the packet has a high likelyhood
6781: // of needing to loopback. (NOTE: This means that if the packet
6782: // must be loopbacked then this function will return true. If
6783: // the packet doesn't need to be loopbacked then the function
6784: // will probably return false.)
6785: //
6786:
6787: //
6788: // Get first buffer
6789: //
6790:
6791: NdisQueryPacket(
6792: OwningPacket,
6793: NULL,
6794: NULL,
6795: &FirstBuffer,
6796: NULL
6797: );
6798:
6799: //
6800: // Get VA of first buffer
6801: //
6802:
6803: NdisQueryBuffer(
6804: FirstBuffer,
6805: &BufferVA,
6806: &Length
6807: );
6808:
6809: if (EthShouldAddressLoopBack(
6810: Adapter->FilterDB,
6811: BufferVA
6812: )) {
6813:
6814: Reserved->SuccessfulTransmit = Successful;
6815:
6816: if (!Adapter->FirstLoopBack) {
6817:
6818: Adapter->FirstLoopBack = OwningPacket;
6819:
6820: } else {
6821:
6822: PLANCE_RESERVED_FROM_PACKET(Adapter->LastLoopBack)->Next = OwningPacket;
6823:
6824: }
6825:
6826: Reserved->Next = NULL;
6827: Adapter->LastLoopBack = OwningPacket;
6828:
6829: } else {
6830:
6831:
6832: Open = PLANCE_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
6833:
6834: //
6835: // Along with at least one reference because of the coming
6836: // indication there should be a reference because of the
6837: // packet to indicate.
6838: //
6839:
6840: ASSERT(Open->References > 0);
6841:
6842: NdisDprReleaseSpinLock(&Adapter->Lock);
6843:
6844: NdisCompleteSend(
6845: Open->NdisBindingContext,
6846: OwningPacket,
6847: ((Successful)?(NDIS_STATUS_SUCCESS):(NDIS_STATUS_FAILURE))
6848: );
6849:
6850: NdisDprAcquireSpinLock(&Adapter->Lock);
6851:
6852: //
6853: // Remove reference for packet
6854: //
6855:
6856: Open->References--;
6857:
6858: }
6859:
6860: //
6861: // Since we've given back some ring entries we should
6862: // open of the stage if it was closed and we are not resetting.
6863: //
6864:
6865: if ((!Adapter->StageOpen) && (!Adapter->ResetInProgress)) {
6866:
6867: Adapter->StageOpen = TRUE;
6868:
6869: }
6870:
6871: return TRUE;
6872: }
6873:
6874: }
6875:
6876: STATIC
6877: VOID
6878: ReturnAdapterResources(
6879: IN PLANCE_ADAPTER Adapter,
6880: IN UINT BufferIndex
6881: )
6882:
6883: /*++
6884:
6885: Routine Description:
6886:
6887: Given that a packet has used adapter resources (which the routine
6888: asserts), return those resources to the adapter.
6889:
6890: NOTE: CALLED WITH LOCK HELD!!!
6891:
6892: Arguments:
6893:
6894: Adapter - The adapter that the packet came through.
6895:
6896: BufferIndex - The adapter buffer descriptor index to put back on the
6897: free list.
6898:
6899:
6900: Return Value:
6901:
6902: None.
6903:
6904: --*/
6905: {
6906:
6907: //
6908: // The adapter buffer descriptor that was allocated to this packet.
6909: //
6910: PLANCE_BUFFER_DESCRIPTOR BufferDescriptor = Adapter->LanceBuffers +
6911: BufferIndex;
6912:
6913: //
6914: // Index of the listhead that heads the list that the adapter
6915: // buffer descriptor belongs too.
6916: //
6917: INT ListHeadIndex = BufferDescriptor->Next;
6918:
6919: //
6920: // Put the adapter buffer back on the free list.
6921: //
6922:
6923: BufferDescriptor->Next = Adapter->LanceBufferListHeads[ListHeadIndex];
6924: Adapter->LanceBufferListHeads[ListHeadIndex] = BufferIndex;
6925:
6926: //
6927: // If the stage was closed and we aren't resetting then open
6928: // it back up.
6929: //
6930:
6931: if ((!Adapter->StageOpen) && (!Adapter->ResetInProgress)) {
6932:
6933: Adapter->StageOpen = TRUE;
6934:
6935: }
6936:
6937: }
6938:
6939: STATIC
6940: VOID
6941: StartAdapterReset(
6942: IN PLANCE_ADAPTER Adapter
6943: )
6944:
6945: /*++
6946:
6947: Routine Description:
6948:
6949: This is the first phase of resetting the adapter hardware.
6950:
6951: It makes the following assumptions:
6952:
6953: 1) That the hardware has been stopped.
6954:
6955: 2) That it can not be preempted.
6956:
6957: 3) That no other adapter activity can occur.
6958:
6959: When this routine is finished all of the adapter information
6960: will be as if the driver was just initialized.
6961:
6962: Arguments:
6963:
6964: Adapter - The adapter whose hardware is to be reset.
6965:
6966: Return Value:
6967:
6968: None.
6969:
6970: --*/
6971:
6972: {
6973: UINT i;
6974: PNDIS_PACKET Packet;
6975: PLANCE_RESERVED Reserved;
6976: PLANCE_OPEN Open;
6977: PNDIS_PACKET Next;
6978:
6979:
6980: #if LANCE_TRACE
6981: DbgPrint("In StartAdapterReset\n");
6982: #endif
6983:
6984: LOG(RESET_STEP_2);
6985:
6986: //
6987: // Go through the various transmit lists and....
6988: //
6989:
6990:
6991: for (
6992: i = 3;
6993: i > 0;
6994: i--
6995: ) {
6996:
6997: switch (i) {
6998:
6999: case 1:
7000: Next = Adapter->FirstFinishTransmit;
7001: break;
7002: case 2:
7003: Next = Adapter->FirstStage1Packet;
7004: break;
7005: case 3:
7006: Next = Adapter->FirstLoopBack;
7007: break;
7008:
7009: }
7010:
7011:
7012: while (Next) {
7013:
7014: Packet = Next;
7015: Reserved = PLANCE_RESERVED_FROM_PACKET(Packet);
7016: Next = Reserved->Next;
7017: Open =
7018: PLANCE_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
7019:
7020:
7021: if (Adapter->ResetRequestType == NdisRequestGeneric1) {
7022:
7023: //
7024: // Abort the packet
7025: //
7026: // The completion of the packet is one less reason
7027: // to keep the open around.
7028: //
7029:
7030: ASSERT(Open->References);
7031:
7032: Open->References--;
7033:
7034: NdisReleaseSpinLock(&Adapter->Lock);
7035:
7036: NdisCompleteSend(
7037: Open->NdisBindingContext,
7038: Packet,
7039: NDIS_STATUS_REQUEST_ABORTED
7040: );
7041:
7042: NdisAcquireSpinLock(&Adapter->Lock);
7043:
7044: } else if ((i == 1) || (i ==3)) {
7045:
7046: //
7047: // Complete these sends
7048: //
7049: // The completion of the packet is one less reason
7050: // to keep the open around.
7051: //
7052:
7053: ASSERT(Open->References);
7054:
7055: Adapter->Transmit++;
7056:
7057: LOG(RESET_COMPLETE_PACKET);
7058:
7059: NdisReleaseSpinLock(&Adapter->Lock);
7060:
7061: NdisCompleteSend(
7062: Open->NdisBindingContext,
7063: Packet,
7064: NDIS_STATUS_SUCCESS
7065: );
7066:
7067: NdisAcquireSpinLock(&Adapter->Lock);
7068:
7069: Open->References--;
7070:
7071: }
7072:
7073: }
7074:
7075: }
7076:
7077:
7078:
7079: Adapter->CSR0Value = 0;
7080: Adapter->NumberOfAvailableRings = Adapter->NumberOfTransmitRings;
7081: Adapter->AllocateableRing = Adapter->TransmitRing;
7082: Adapter->TransmittingRing = Adapter->TransmitRing;
7083: Adapter->FirstUncommittedRing = Adapter->TransmitRing;
7084:
7085:
7086: Adapter->StageOpen = TRUE;
7087:
7088: Adapter->AlreadyProcessingStage = FALSE;
7089:
7090: Adapter->CurrentReceiveIndex = 0;
7091:
7092: //
7093: // Clean all of the receive ring entries.
7094: //
7095:
7096: {
7097:
7098: PLANCE_RECEIVE_ENTRY CurrentReceive = Adapter->ReceiveRing;
7099: const PLANCE_RECEIVE_ENTRY After = Adapter->ReceiveRing+
7100: Adapter->NumberOfReceiveRings;
7101:
7102: do {
7103:
7104: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
7105: CurrentReceive->ReceiveSummaryBits,
7106: LANCE_RECEIVE_OWNED_BY_CHIP
7107: );
7108: CurrentReceive++;
7109:
7110:
7111: } while (CurrentReceive != After);
7112:
7113: }
7114:
7115:
7116: //
7117: // Clean all of the transmit ring entries.
7118: //
7119:
7120: {
7121:
7122: PLANCE_TRANSMIT_ENTRY CurrentTransmit = Adapter->TransmitRing;
7123: const PLANCE_TRANSMIT_ENTRY After = Adapter->TransmitRing+
7124: Adapter->NumberOfTransmitRings;
7125:
7126: do {
7127:
7128: LANCE_WRITE_HARDWARE_MEMORY_UCHAR(
7129: CurrentTransmit->TransmitSummaryBits,
7130: 0x00
7131: );
7132: CurrentTransmit++;
7133:
7134:
7135: } while (CurrentTransmit != After);
7136:
7137: }
7138:
7139: //
7140: // Recover all of the adapter buffers.
7141: //
7142:
7143: for (
7144: i = 0;
7145: i < (Adapter->NumberOfSmallBuffers +
7146: Adapter->NumberOfMediumBuffers +
7147: Adapter->NumberOfLargeBuffers);
7148: i++
7149: ) {
7150:
7151: Adapter->LanceBuffers[i].Next = i+1;
7152:
7153: }
7154:
7155: Adapter->LanceBufferListHeads[0] = -1;
7156: Adapter->LanceBufferListHeads[1] = 0;
7157: Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers)-1].Next = -1;
7158: Adapter->LanceBufferListHeads[2] = Adapter->NumberOfSmallBuffers;
7159: Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers +
7160: Adapter->NumberOfMediumBuffers)-1].Next = -1;
7161: Adapter->LanceBufferListHeads[3] = Adapter->NumberOfSmallBuffers +
7162: Adapter->NumberOfMediumBuffers;
7163: Adapter->LanceBuffers[(Adapter->NumberOfSmallBuffers+
7164: Adapter->NumberOfMediumBuffers+
7165: Adapter->NumberOfLargeBuffers)-1].Next = -1;
7166:
7167: //
7168: // If it was a Reset from LanceReset(), clear out all queues.
7169: //
7170:
7171: if (Adapter->ResetRequestType == NdisRequestGeneric1) {
7172:
7173: Adapter->FirstLoopBack = NULL;
7174: Adapter->LastLoopBack = NULL;
7175: Adapter->FirstFinishTransmit = NULL;
7176: Adapter->LastFinishTransmit = NULL;
7177: Adapter->FirstStage1Packet = NULL;
7178: Adapter->LastStage1Packet = NULL;
7179:
7180: } else {
7181:
7182: //
7183: // It was a reset from a SetInfo,
7184: // Clear out only the intermediate queues - the
7185: // packets were moved out and back to stage1. (sigh)
7186: //
7187:
7188: Adapter->FirstFinishTransmit = NULL;
7189: Adapter->LastFinishTransmit = NULL;
7190:
7191: //
7192: // Re-allocate all the stage 1 packets.
7193: //
7194:
7195: Next = Adapter->FirstStage1Packet;
7196:
7197: Adapter->FirstStage1Packet = NULL;
7198: Adapter->LastStage1Packet = NULL;
7199:
7200: while (Next != NULL) {
7201:
7202: LOG(RESET_RECOVER_PACKET);
7203:
7204: Packet = Next,
7205: Reserved = PLANCE_RESERVED_FROM_PACKET(Packet);
7206: Next = Reserved->Next;
7207:
7208: SetupAllocate(Adapter, Reserved->MacBindingHandle, Packet);
7209:
7210: }
7211:
7212: }
7213:
7214:
7215: SetInitBlockAndInit(Adapter);
7216:
7217: #if LANCE_TRACE
7218: DbgPrint("Out StartAdapterReset\n");
7219: #endif
7220:
7221: }
7222:
7223: STATIC
7224: VOID
7225: SetInitBlockAndInit(
7226: IN PLANCE_ADAPTER Adapter
7227: )
7228:
7229: /*++
7230:
7231: Routine Description:
7232:
7233: It is this routines responsibility to make sure that the
7234: initialization block is filled and the chip is initialized
7235: *but not* started.
7236:
7237: NOTE: This routine assumes that it is called with the lock
7238: acquired OR that only a single thread of execution is working
7239: with this particular adapter.
7240:
7241: Arguments:
7242:
7243: Adapter - The adapter whose hardware is to be initialized.
7244:
7245: Return Value:
7246:
7247: None.
7248:
7249: --*/
7250: {
7251:
7252: PHYSICAL_ADDRESS PhysAdr;
7253:
7254: //
7255: // Fill in the adapters initialization block.
7256: //
7257:
7258: LanceSetInitializationBlock(Adapter);
7259:
7260: PhysAdr = LANCE_GET_HARDWARE_PHYSICAL_ADDRESS(Adapter,Adapter->InitBlock);
7261:
7262: //
7263: // Make sure that it does have even byte alignment.
7264: //
7265:
7266: ASSERT(!(PhysAdr.LowPart & 0x01));
7267:
7268: //
7269: // Write the address of the initialization block to csr1 and csr2.
7270: //
7271:
7272: LANCE_WRITE_RAP(
7273: Adapter,
7274: LANCE_SELECT_CSR1
7275: );
7276:
7277: LANCE_WRITE_RDP(
7278: Adapter,
7279: LANCE_GET_LOW_PART_ADDRESS(PhysAdr.LowPart)
7280: );
7281:
7282: LANCE_WRITE_RAP(
7283: Adapter,
7284: LANCE_SELECT_CSR2
7285: );
7286:
7287: LANCE_WRITE_RDP(
7288: Adapter,
7289: LANCE_GET_HIGH_PART_ADDRESS(PhysAdr.LowPart)
7290: );
7291:
7292: //
7293: // Write to csr0 to initialize the chip.
7294: //
7295:
7296: LANCE_WRITE_RAP(
7297: Adapter,
7298: LANCE_SELECT_CSR0
7299: );
7300:
7301: LANCE_WRITE_RDP(
7302: Adapter,
7303: LANCE_CSR0_INIT_CHIP
7304: );
7305:
7306: }
7307:
7308: STATIC
7309: VOID
7310: SetupForReset(
7311: IN PLANCE_ADAPTER Adapter,
7312: IN PLANCE_OPEN Open,
7313: IN PNDIS_REQUEST NdisRequest,
7314: IN NDIS_REQUEST_TYPE RequestType
7315: )
7316:
7317: /*++
7318:
7319: Routine Description:
7320:
7321: This routine is used to fill in the who and why a reset is
7322: being set up as well as setting the appropriate fields in the
7323: adapter.
7324:
7325: NOTE: This routine must be called with the lock acquired.
7326:
7327: Arguments:
7328:
7329: Adapter - The adapter whose hardware is to be initialized.
7330:
7331: Open - A (possibly NULL) pointer to an lance open structure.
7332: The reason it could be null is if the adapter is initiating the
7333: reset on its own.
7334:
7335: NdisRequest - A pointer to the NDIS_REQUEST which requested the reset.
7336:
7337: RequestType - If the open is not null then the request type that
7338: is causing the reset.
7339:
7340: Return Value:
7341:
7342: None.
7343:
7344: --*/
7345: {
7346:
7347: #if LANCE_TRACE
7348: DbgPrint("In SetupForReset\n");
7349: #endif
7350:
7351: LOG(RESET_STEP_1);
7352:
7353: //
7354: // Shut down the chip. We won't be doing any more work until
7355: // the reset is complete.
7356: //
7357:
7358: NdisSynchronizeWithInterrupt(
7359: &Adapter->Interrupt,
7360: LanceSyncStopChip,
7361: (PVOID)Adapter
7362: );
7363:
7364: //
7365: // Once the chip is stopped we can't get any more interrupts.
7366: // Any interrupts that are "queued" for processing could
7367: // only possibly service this reset. It is therefore safe for
7368: // us to clear the adapter global csr value.
7369: //
7370:
7371: Adapter->CSR0Value = 0;
7372:
7373: Adapter->ResetInProgress = TRUE;
7374: Adapter->ResetInitStarted = FALSE;
7375:
7376: //
7377: // Shut down all of the transmit queues so that the
7378: // transmit portion of the chip will eventually calm down.
7379: //
7380:
7381: Adapter->StageOpen = FALSE;
7382:
7383: Adapter->ResetNdisRequest = NdisRequest;
7384: Adapter->ResettingOpen = Open;
7385: Adapter->ResetRequestType = RequestType;
7386:
7387: //
7388: // If there is a valid open we should up the reference count
7389: // so that the open can't be deleted before we indicate that
7390: // their request is finished.
7391: //
7392:
7393: if (Open) {
7394:
7395: Open->References++;
7396:
7397: }
7398:
7399: #if LANCE_TRACE
7400: DbgPrint("Out SetupForReset\n");
7401: #endif
7402:
7403: }
7404:
7405:
7406: STATIC
7407: VOID
7408: FinishPendOp(
7409: IN PLANCE_ADAPTER Adapter,
7410: IN BOOLEAN Successful
7411: )
7412:
7413: /*++
7414:
7415: Routine Description:
7416:
7417: This routine is called when a pended operation completes.
7418: It calles CompleteRequest if needed and does any other
7419: cleanup required.
7420:
7421: NOTE: This routine is called with the lock held and
7422: returns with it held.
7423:
7424: NOTE: This routine assumes that the pended operation to
7425: be completed was specifically requested by the protocol.
7426:
7427:
7428: Arguments:
7429:
7430: Adapter - The adapter.
7431:
7432: Successful - Was the pended operation completed successfully.
7433:
7434: Return Value:
7435:
7436: None.
7437:
7438: --*/
7439:
7440: {
7441: ASSERT(Adapter->ResetNdisRequest != NULL);
7442:
7443:
7444: //
7445: // It was a request for filter change or multicastlist change.
7446: //
7447:
7448: if (Successful) {
7449:
7450: //
7451: // complete the operation.
7452: //
7453:
7454:
7455: NdisReleaseSpinLock(&(Adapter->Lock));
7456:
7457: NdisCompleteRequest(
7458: Adapter->ResettingOpen->NdisBindingContext,
7459: Adapter->ResetNdisRequest,
7460: NDIS_STATUS_SUCCESS
7461: );
7462:
7463: NdisAcquireSpinLock(&(Adapter->Lock));
7464:
7465: Adapter->ResetNdisRequest = NULL;
7466:
7467: Adapter->ResettingOpen->References--;
7468:
7469: } else {
7470:
7471:
7472: //
7473: // complete the operation.
7474: //
7475:
7476:
7477: NdisReleaseSpinLock(&(Adapter->Lock));
7478:
7479: NdisCompleteRequest(
7480: Adapter->ResettingOpen->NdisBindingContext,
7481: Adapter->ResetNdisRequest,
7482: NDIS_STATUS_FAILURE
7483: );
7484:
7485: NdisAcquireSpinLock(&(Adapter->Lock));
7486:
7487: Adapter->ResetNdisRequest = NULL;
7488:
7489: Adapter->ResettingOpen->References--;
7490:
7491: }
7492:
7493: return;
7494:
7495: }
7496:
7497:
7498:
7499: STATIC
7500: BOOLEAN
7501: LanceSyncWriteRAP(
7502: IN PVOID Context
7503: )
7504: /*++
7505:
7506: Routine Description:
7507:
7508: This routine is used by the normal interrupt processing routine
7509: to synchronize with interrupts from the card. It will write
7510: to the RAP
7511:
7512:
7513: Arguments:
7514:
7515: Context - This is really a pointer to a record type peculiar
7516: to this routine. The record contains a pointer to the adapter
7517: and a pointer to the value to write.
7518:
7519:
7520: Return Value:
7521:
7522: Always returns true.
7523:
7524: --*/
7525:
7526: {
7527:
7528:
7529: PLANCE_SYNCH_CONTEXT C = Context;
7530:
7531: LANCE_ISR_WRITE_RAP(C->Adapter, C->LocalWrite);
7532:
7533: return FALSE;
7534:
7535: }
7536:
7537: BOOLEAN
7538: LanceSyncWriteRDP(
7539: IN PVOID Context
7540: )
7541: /*++
7542:
7543: Routine Description:
7544:
7545: This routine is used by the normal interrupt processing routine
7546: to synchronize with interrupts from the card. It will write
7547: into the RDP register
7548:
7549:
7550: Arguments:
7551:
7552: Context - This is really a pointer to a record type peculiar
7553: to this routine. The record contains a pointer to the adapter
7554: and a pointer to the value to write.
7555:
7556: Return Value:
7557:
7558: Always returns true.
7559:
7560: --*/
7561:
7562: {
7563:
7564:
7565: PLANCE_SYNCH_CONTEXT C = Context;
7566:
7567: LANCE_ISR_WRITE_RDP(C->Adapter, C->LocalWrite);
7568:
7569: return FALSE;
7570:
7571:
7572: }
7573:
7574: STATIC
7575: BOOLEAN
7576: LanceSyncReadRDP(
7577: IN PVOID Context
7578: )
7579: /*++
7580:
7581: Routine Description:
7582:
7583: This routine is used by the normal interrupt processing routine
7584: to synchronize with interrupts from the card. It will read
7585: from the RDP.
7586:
7587: Arguments:
7588:
7589: Context - This is really a pointer to a record type peculiar
7590: to this routine. The record contains a pointer to the adapter
7591: and a pointer to a USHORT to store the value into.
7592:
7593: Return Value:
7594:
7595: Always returns true.
7596:
7597: --*/
7598:
7599: {
7600:
7601:
7602: PLANCE_SYNCH_CONTEXT C = Context;
7603:
7604: LANCE_ISR_READ_RDP(C->Adapter, C->LocalRead);
7605:
7606: return FALSE;
7607:
7608: }
7609:
7610: STATIC
7611: BOOLEAN
7612: LanceSyncWriteNicsr(
7613: IN PVOID Context
7614: )
7615: /*++
7616:
7617: Routine Description:
7618:
7619: This routine is used by the normal interrupt processing routine
7620: to synchronize with interrupts from the card. It will
7621: Write to the NIC Status Register.
7622:
7623: Arguments:
7624:
7625: Context - This is really a pointer to a record type peculiar
7626: to this routine. The record contains a pointer to the adapter
7627: and a pointer to an address which holds the value to write.
7628:
7629: Return Value:
7630:
7631: Always returns false.
7632:
7633: --*/
7634:
7635: {
7636:
7637: PLANCE_SYNCH_CONTEXT C = Context;
7638:
7639: LANCE_ISR_WRITE_NICSR(C->Adapter, C->LocalWrite);
7640:
7641: return FALSE;
7642:
7643: }
7644:
7645: STATIC
7646: BOOLEAN
7647: LanceSyncStopChip(
7648: IN PVOID Context
7649: )
7650:
7651: /*++
7652:
7653: Routine Description:
7654:
7655: This routine is used to stop a lance.
7656:
7657:
7658:
7659: Arguments:
7660:
7661: Adapter - The adapter for the LANCE to stop.
7662:
7663: Return Value:
7664:
7665: FALSE
7666:
7667: --*/
7668:
7669: {
7670:
7671: PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)Context;
7672:
7673: //
7674: // Set the RAP to csr0.
7675: //
7676:
7677: LANCE_ISR_WRITE_RAP(
7678: Adapter,
7679: LANCE_SELECT_CSR0
7680: );
7681:
7682: //
7683: // Set the RDP to stop chip.
7684: //
7685:
7686: LANCE_ISR_WRITE_RDP(
7687: Adapter,
7688: LANCE_CSR0_STOP
7689: );
7690:
7691: if (Adapter->LanceCard & (LANCE_DE201 | LANCE_DE100 | LANCE_DE422)) {
7692:
7693: //
7694: // Always reset the ACON bit after a stop.
7695: //
7696:
7697: LANCE_ISR_WRITE_RAP(
7698: Adapter,
7699: LANCE_SELECT_CSR3
7700: );
7701:
7702: LANCE_ISR_WRITE_RDP(
7703: Adapter,
7704: LANCE_CSR3_ACON
7705: );
7706:
7707: }
7708:
7709: //
7710: // Select CSR0 again.
7711: //
7712:
7713: LANCE_ISR_WRITE_RAP(
7714: Adapter,
7715: LANCE_SELECT_CSR0
7716: );
7717:
7718: return(FALSE);
7719: }
7720:
7721:
7722: VOID
7723: LanceWakeUpDpc(
7724: IN PVOID SystemSpecific1,
7725: IN PVOID Context,
7726: IN PVOID SystemSpecific2,
7727: IN PVOID SystemSpecific3
7728: )
7729:
7730: /*++
7731:
7732: Routine Description:
7733:
7734: This DPC routine is queued every 5 seconds to check on the
7735: queues. If an interrupt was not received
7736: in the last 5 seconds and there should have been one,
7737: then we abort all operations.
7738:
7739: Arguments:
7740:
7741: Context - Really a pointer to the adapter.
7742:
7743: Return Value:
7744:
7745: None.
7746:
7747: --*/
7748: {
7749: PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)Context;
7750: PLANCE_OPEN TmpOpen;
7751: PNDIS_PACKET TransmitPacket;
7752: PLANCE_PEND_DATA PendOp;
7753: PNDIS_REQUEST Request;
7754: PLANCE_RESERVED Reserved;
7755:
7756: UNREFERENCED_PARAMETER(SystemSpecific1);
7757: UNREFERENCED_PARAMETER(SystemSpecific2);
7758: UNREFERENCED_PARAMETER(SystemSpecific3);
7759:
7760: NdisDprAcquireSpinLock(&Adapter->Lock);
7761:
7762: if ((Adapter->WakeUpTimeout) &&
7763: ((Adapter->FirstFinishTransmit != NULL) ||
7764: (Adapter->FirstStage1Packet != NULL) ||
7765: (Adapter->PendQueue != NULL) ||
7766: (Adapter->ResetNdisRequest != NULL))) {
7767:
7768: //
7769: // We had a pending operation the last time we ran,
7770: // and it has not been completed...we need to complete
7771: // it now.
7772:
7773: Adapter->WakeUpTimeout = FALSE;
7774:
7775: Adapter->TimeoutCount++;
7776:
7777: if (Adapter->TimeoutCount < 10) {
7778:
7779: //
7780: // Limit the number of error log entries
7781: //
7782:
7783: NdisWriteErrorLogEntry(
7784: Adapter->NdisAdapterHandle,
7785: NDIS_ERROR_CODE_HARDWARE_FAILURE,
7786: 0
7787: );
7788:
7789:
7790: }
7791:
7792: if ((Adapter->ResettingOpen != NULL) &&
7793: (Adapter->ResetRequestType != NdisRequestClose)) {
7794:
7795: if (Adapter->ResetNdisRequest != NULL) {
7796:
7797: //
7798: // It was a request submitted by a protocol.
7799: //
7800:
7801: TmpOpen = Adapter->ResettingOpen;
7802:
7803: NdisDprReleaseSpinLock(&(Adapter->Lock));
7804:
7805: NdisCompleteRequest(
7806: Adapter->ResettingOpen->NdisBindingContext,
7807: Adapter->ResetNdisRequest,
7808: NDIS_STATUS_SUCCESS
7809: );
7810:
7811: NdisDprAcquireSpinLock(&(Adapter->Lock));
7812:
7813: TmpOpen->References--;
7814:
7815: }
7816:
7817: }
7818:
7819: while (Adapter->PendQueue) {
7820:
7821: Request = Adapter->PendQueue;
7822: PendOp = PLANCE_PEND_DATA_FROM_PNDIS_REQUEST(Request);
7823:
7824: Adapter->PendQueue = PendOp->Next;
7825:
7826: if (Adapter->PendQueue == NULL){
7827:
7828: //
7829: // We have just emptied the list.
7830: //
7831:
7832: Adapter->PendQueueTail = NULL;
7833:
7834: }
7835:
7836:
7837: if ((PendOp->Open != NULL) &&
7838: (PendOp->RequestType != NdisRequestClose)) {
7839:
7840: //
7841: // It was a request submitted by a protocol.
7842: //
7843:
7844: TmpOpen = PendOp->Open;
7845:
7846: NdisDprReleaseSpinLock(&(Adapter->Lock));
7847:
7848: NdisCompleteRequest(
7849: PendOp->Open->NdisBindingContext,
7850: Request,
7851: NDIS_STATUS_SUCCESS
7852: );
7853:
7854: NdisDprAcquireSpinLock(&(Adapter->Lock));
7855:
7856: TmpOpen->References--;
7857:
7858: }
7859:
7860: }
7861:
7862: while (Adapter->FirstFinishTransmit != NULL) {
7863:
7864: TransmitPacket = Adapter->FirstFinishTransmit;
7865:
7866: Reserved = PLANCE_RESERVED_FROM_PACKET(TransmitPacket);
7867:
7868: Adapter->FirstFinishTransmit = Reserved->Next;
7869:
7870: if (Adapter->FirstFinishTransmit == NULL) {
7871:
7872: Adapter->LastFinishTransmit = NULL;
7873:
7874: }
7875:
7876: TmpOpen = PLANCE_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
7877:
7878: NdisDprReleaseSpinLock(&Adapter->Lock);
7879:
7880: NdisCompleteSend(
7881: TmpOpen->NdisBindingContext,
7882: TransmitPacket,
7883: NDIS_STATUS_SUCCESS
7884: );
7885:
7886: NdisDprAcquireSpinLock(&Adapter->Lock);
7887:
7888: TmpOpen->References--;
7889:
7890: }
7891:
7892: while (Adapter->FirstStage1Packet != NULL) {
7893:
7894: TransmitPacket = Adapter->FirstStage1Packet;
7895:
7896: Reserved = PLANCE_RESERVED_FROM_PACKET(TransmitPacket);
7897:
7898: //
7899: // Remove the packet from the queue.
7900: //
7901:
7902: Adapter->FirstStage1Packet = Reserved->Next;
7903:
7904: if (Adapter->FirstStage1Packet == NULL) {
7905:
7906: Adapter->LastStage1Packet = NULL;
7907:
7908: }
7909:
7910: TmpOpen = PLANCE_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
7911:
7912: NdisDprReleaseSpinLock(&Adapter->Lock);
7913:
7914: NdisCompleteSend(
7915: TmpOpen->NdisBindingContext,
7916: TransmitPacket,
7917: NDIS_STATUS_SUCCESS
7918: );
7919:
7920: NdisDprAcquireSpinLock(&Adapter->Lock);
7921:
7922: TmpOpen->References--;
7923:
7924: }
7925:
7926: Adapter->WakeUpTimeout = FALSE;
7927:
7928: SetupForReset(
7929: Adapter,
7930: NULL,
7931: NULL,
7932: NdisRequestGeneric4 // Means MAC issued
7933: );
7934:
7935: NdisSetTimer(&Adapter->DeferredTimer, 0);
7936:
7937: NdisDprReleaseSpinLock(&Adapter->Lock);
7938:
7939: } else {
7940:
7941: if ((Adapter->FirstFinishTransmit != NULL) ||
7942: (Adapter->FirstStage1Packet != NULL) ||
7943: (Adapter->PendQueue != NULL) ||
7944: (Adapter->ResetNdisRequest != NULL)) {
7945:
7946: Adapter->WakeUpTimeout = TRUE;
7947:
7948: }
7949:
7950: NdisDprReleaseSpinLock(&Adapter->Lock);
7951:
7952:
7953: }
7954:
7955: //
7956: // Fire off another Dpc to execute after 5 seconds
7957: //
7958:
7959: NdisSetTimer(
7960: &Adapter->WakeUpTimer,
7961: 5000
7962: );
7963:
7964: }
7965:
7966:
7967:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.