|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990-1992 Microsoft Corporation
4:
5: Module Name:
6:
7: interrup.c
8:
9: Abstract:
10:
11: This is a part of the driver for the National Semiconductor SONIC
12: Ethernet controller. It contains the interrupt-handling routines.
13: This driver conforms to the NDIS 3.0 interface.
14:
15: The overall structure and much of the code is taken from
16: the Lance NDIS driver by Tony Ercolano.
17:
18: Author:
19:
20: Adam Barr (adamba) 16-Jan-1991
21:
22: Environment:
23:
24: Kernel Mode - Or whatever is the equivalent.
25:
26: Revision History:
27:
28:
29: --*/
30:
31: #include <ndis.h>
32:
33:
34: #include <efilter.h>
35: #include <sonichrd.h>
36: #include <sonicsft.h>
37:
38: #undef DPR_INTERRUPTS
39:
40: //
41: // We use the #define DPR_INTERRUPTS to determine how we handle
42: // disabling interrupts during the ISR and DPR
43: //
44: // If DPR_INTERRUPTS is not defined, then we mask off all interrupts
45: // in the ISR and reenable them when the DPR has run. If it is
46: // defined, then we keep interrupts enabled during the DPR.
47: //
48: // With DPR_INTERRUPTS undefined, there will only be one DPR running
49: // at one time time, and in addition the ISR and DPR will never be
50: // running at the same time. This saves us interrupts and calls to
51: // NdisSynchronizeWithInterrupt, but prevents parallelism on MP. It
52: // is also good programming practice for drivers that can cause the
53: // interrupt line to drop during the DPR, to prevent the "short interrupt"
54: // problem on some steppings of the 486 (the sonic driver as structured
55: // does not have this problem).
56: //
57:
58:
59: #ifdef DPR_INTERRUPTS
60:
61: //
62: // We need this structures to call NdisSynchronizeWithInterrupt
63: // because it only takes one parameter.
64: //
65:
66: typedef struct _SONIC_SYNCH_CONTEXT {
67:
68: //
69: // Pointer to the sonic adapter for which interrupts are
70: // being synchronized.
71: //
72: PSONIC_ADAPTER Adapter;
73:
74: //
75: // Pointer used differently depending on the call;
76: //
77: // For GET_ISR_SINCE_LAST_PROCESSED, it points
78: // to a local variable that will receive the value
79: // of the adapter's IsrValue.
80: // For REMOVE_EOL_AND_ACK, it points to the Link
81: // field to remove the EOL bit from.
82: // For WRITE_RWP_AND_ACK, it holds the value
83: // to be written to the Current Write Pointer register.
84: //
85: PVOID Local;
86:
87: //
88: // Pointer used by GET_ISR_SINCE_LAST_PROCESSED, it
89: // determines which bits in the ISR we care about.
90: //
91: USHORT Parameter;
92:
93: } SONIC_SYNCH_CONTEXT,*PSONIC_SYNCH_CONTEXT;
94:
95: //
96: // NOTE: This macro is to synchronize execution with interrupts. It
97: // gets the stored value of the ISR and clears the old value,
98: // only dealing with the bits specified by M.
99: //
100: #define GET_ISR_SINCE_LAST_PROCESSED(A,V,M) \
101: { \
102: PSONIC_ADAPTER _A = A; \
103: SONIC_SYNCH_CONTEXT _C; \
104: _C.Adapter = _A; \
105: _C.Local = (PVOID)(V); \
106: _C.Parameter = (M); \
107: NdisSynchronizeWithInterrupt( \
108: &_A->Interrupt, \
109: SonicSynchGetIsr, \
110: &_C \
111: ); \
112: }
113:
114:
115: //
116: // NOTE: This macro is to synchronize execution with interrupts.
117: // It clears the EOL bit in the Link field and acknowledges
118: // the ReceiveDescriptorsExhausted interrupt.
119: //
120: #define REMOVE_EOL_AND_ACK(A,L) \
121: { \
122: PSONIC_ADAPTER _A = A; \
123: SONIC_SYNCH_CONTEXT _C; \
124: _C.Adapter = _A; \
125: _C.Local = (PVOID)(L); \
126: NdisSynchronizeWithInterrupt( \
127: &_A->Interrupt, \
128: SonicSynchRemoveEol, \
129: &_C \
130: ); \
131: }
132:
133:
134: //
135: // NOTE: This macro is to synchronize execution with interrupts.
136: // It writes the specified value to the RWP register and
137: // acknowledges the ReceiveBuffersExhausted interrupt.
138: //
139: #define WRITE_RWP_AND_ACK(A,RWP) \
140: { \
141: PSONIC_ADAPTER _A = A; \
142: SONIC_SYNCH_CONTEXT _C; \
143: _C.Adapter = _A; \
144: _C.Local = (PVOID)(RWP); \
145: NdisSynchronizeWithInterrupt( \
146: &_A->Interrupt, \
147: SonicSynchWriteRwp, \
148: &_C \
149: ); \
150: }
151:
152: #else // DPR_INTERRUPTS
153:
154: //
155: // Define the macros to do what the functions do directly,
156: // since the ISR and DPR won't be running concurrently. We
157: // also don't write to the interrupt mask register since it
158: // will be set to 0 when these calls are made (from the DPR).
159: //
160:
161: #define GET_ISR_SINCE_LAST_PROCESSED(A,V,M) \
162: { \
163: PSONIC_ADAPTER _A = A; \
164: *(V) |= ((_A)->IsrValue & (M)); \
165: (_A)->IsrValue &= (USHORT)~(M); \
166: }
167:
168: #define REMOVE_EOL_AND_ACK(A,L) \
169: { \
170: PSONIC_ADAPTER _A = A; \
171: SONIC_REMOVE_END_OF_LIST(L); \
172: if ((_A)->ReceiveDescriptorsExhausted) { \
173: SONIC_WRITE_PORT((_A), SONIC_INTERRUPT_STATUS, \
174: SONIC_INT_RECEIVE_DESCRIPTORS \
175: ); \
176: (_A)->InterruptMaskRegister |= SONIC_INT_RECEIVE_DESCRIPTORS; \
177: (_A)->ReceiveDescriptorsExhausted = FALSE; \
178: } \
179: }
180:
181: #define WRITE_RWP_AND_ACK(A,RWP) \
182: { \
183: PSONIC_ADAPTER _A = A; \
184: SONIC_WRITE_PORT((_A), SONIC_RESOURCE_WRITE, (RWP)); \
185: if ((_A)->ReceiveBuffersExhausted) { \
186: SONIC_WRITE_PORT((_A), SONIC_INTERRUPT_STATUS, \
187: SONIC_INT_RECEIVE_BUFFERS \
188: ); \
189: (_A)->InterruptMaskRegister |= SONIC_INT_RECEIVE_BUFFERS; \
190: (_A)->ReceiveBuffersExhausted = FALSE; \
191: } \
192: }
193:
194: #endif // DPR_INTERRUPTS
195:
196:
197:
198: STATIC
199: BOOLEAN
200: ProcessReceiveInterrupts(
201: IN PSONIC_ADAPTER Adapter
202: );
203:
204: STATIC
205: BOOLEAN
206: ProcessTransmitInterrupts(
207: IN PSONIC_ADAPTER Adapter
208: );
209:
210: #ifdef DPR_INTERRUPTS
211:
212: STATIC
213: BOOLEAN
214: SonicSynchGetIsr(
215: IN PVOID Context
216: );
217:
218: STATIC
219: BOOLEAN
220: SonicSynchRemoveEol(
221: IN PVOID Context
222: );
223:
224: STATIC
225: BOOLEAN
226: SonicSynchWriteRwp(
227: IN PVOID Context
228: );
229:
230: #endif // DPR_INTERRUPTS
231:
232: STATIC
233: VOID
234: ProcessInterrupt(
235: IN PSONIC_ADAPTER Adapter
236: );
237:
238:
239: #ifdef DPR_INTERRUPTS
240:
241: //
242: // These functions are for use with NdisSynchronizeWithInterrupt.
243: //
244:
245:
246: STATIC
247: BOOLEAN
248: SonicSynchGetIsr(
249: IN PVOID Context
250: )
251:
252: /*++
253:
254: Routine Description:
255:
256: This routine is used by the normal interrupt processing routine
257: to synchronize with interrupts from the card. It will or
258: the value of the stored ISR into the other passed address
259: in the context and clear the stored ISR value. It only
260: returns and clears the bits specified in the parameter
261: field of the context.
262:
263: Arguments:
264:
265: Context - This is really a pointer to a record type peculiar
266: to this routine. The record contains a pointer to the adapter
267: and a pointer to an address in which to place the contents
268: of the ISR.
269:
270: Return Value:
271:
272: Always returns true.
273:
274: --*/
275:
276: {
277:
278: PSONIC_SYNCH_CONTEXT C = Context;
279: USHORT Mask = C->Parameter;
280:
281: *((PUSHORT)C->Local) = *((PUSHORT)C->Local) |
282: (C->Adapter->IsrValue & Mask);
283:
284: C->Adapter->IsrValue &= (USHORT)~Mask;
285:
286: return TRUE;
287:
288: }
289:
290: STATIC
291: BOOLEAN
292: SonicSynchRemoveEol(
293: IN PVOID Context
294: )
295:
296: /*++
297:
298: Routine Description:
299:
300: This routine is used by the normal interrupt processing routine
301: to synchronize with interrupts from the card. It will clear
302: the EOL bit from the specified link field in the receive
303: descriptor, acknowledge the RDE interrupt, and reenable the
304: interrupt.
305:
306: Arguments:
307:
308: Context - This is really a pointer to a record type peculiar
309: to this routine. The record contains a pointer to the adapter
310: and a pointer to the address of the link field.
311:
312: Return Value:
313:
314: Always returns true.
315:
316: --*/
317:
318: {
319:
320: PSONIC_SYNCH_CONTEXT C = Context;
321:
322: SONIC_REMOVE_END_OF_LIST(
323: (PSONIC_PHYSICAL_ADDRESS)C->Local
324: );
325:
326: if (C->Adapter->ReceiveDescriptorsExhausted) {
327:
328: SONIC_WRITE_PORT(C->Adapter, SONIC_INTERRUPT_STATUS,
329: SONIC_INT_RECEIVE_DESCRIPTORS
330: );
331:
332: C->Adapter->InterruptMaskRegister |= SONIC_INT_RECEIVE_DESCRIPTORS;
333: SONIC_WRITE_PORT(C->Adapter, SONIC_INTERRUPT_MASK,
334: C->Adapter->InterruptMaskRegister
335: );
336:
337: C->Adapter->ReceiveDescriptorsExhausted = FALSE;
338:
339: }
340:
341: return TRUE;
342:
343: }
344:
345: STATIC
346: BOOLEAN
347: SonicSynchWriteRwp(
348: IN PVOID Context
349: )
350:
351: /*++
352:
353: Routine Description:
354:
355: This routine is used by the normal interrupt processing routine
356: to synchronize with interrupts from the card. It will write
357: the specified value to the Current Write Pointer register
358: (effectively adding a receive buffer), acknowledge the RBE
359: interrupt, and reenable that interrupt.
360:
361: Arguments:
362:
363: Context - This is really a pointer to a record type peculiar
364: to this routine. The record contains a pointer to the adapter
365: and the new value of the RWP register.
366:
367: Return Value:
368:
369: Always returns true.
370:
371: --*/
372:
373: {
374:
375: PSONIC_SYNCH_CONTEXT C = Context;
376:
377: SONIC_WRITE_PORT(C->Adapter, SONIC_RESOURCE_WRITE,
378: (USHORT)C->Local
379: );
380:
381: if (C->Adapter->ReceiveBuffersExhausted) {
382:
383: SONIC_WRITE_PORT(C->Adapter, SONIC_INTERRUPT_STATUS,
384: SONIC_INT_RECEIVE_BUFFERS
385: );
386:
387: C->Adapter->InterruptMaskRegister |= SONIC_INT_RECEIVE_BUFFERS;
388: SONIC_WRITE_PORT(C->Adapter, SONIC_INTERRUPT_MASK,
389: C->Adapter->InterruptMaskRegister
390: );
391:
392: C->Adapter->ReceiveBuffersExhausted = FALSE;
393:
394: }
395:
396: return TRUE;
397:
398: }
399: #endif // DPR_INTERRUPTS
400:
401: extern
402: BOOLEAN
403: SonicInterruptService(
404: IN PVOID Context
405: )
406:
407: /*++
408:
409: Routine Description:
410:
411: Interrupt service routine for the sonic. It's main job is
412: to get the value of ISR and record the changes in the
413: adapters own list of interrupt reasons.
414:
415: Arguments:
416:
417: Context - Really a pointer to the adapter.
418:
419: Return Value:
420:
421: Returns true if the card ISR is non-zero.
422:
423: --*/
424:
425: {
426:
427: //
428: // Will hold the value from the ISR.
429: //
430: USHORT LocalIsrValue;
431:
432: //
433: // Holds the pointer to the adapter.
434: //
435: PSONIC_ADAPTER Adapter = Context;
436:
437:
438: SONIC_READ_PORT(Adapter, SONIC_INTERRUPT_STATUS, &LocalIsrValue);
439:
440: if (LocalIsrValue != 0x0000) {
441:
442: #if DBG
443: if (SonicDbg) {
444: if (LocalIsrValue & (
445: SONIC_INT_BUS_RETRY |
446: SONIC_INT_LOAD_CAM_DONE |
447: SONIC_INT_PROG_INTERRUPT |
448: SONIC_INT_TRANSMIT_ERROR |
449: SONIC_INT_RECEIVE_DESCRIPTORS |
450: SONIC_INT_RECEIVE_BUFFERS |
451: SONIC_INT_RECEIVE_OVERFLOW |
452: SONIC_INT_CRC_TALLY_ROLLOVER |
453: SONIC_INT_FAE_TALLY_ROLLOVER |
454: SONIC_INT_MP_TALLY_ROLLOVER
455: )) {
456: DbgPrint("ISR %x\n", LocalIsrValue);
457: }
458: }
459: #endif
460: //
461: // It's our interrupt. Clear only those bits that we got
462: // in this read of ISR. We do it this way in case any new
463: // reasons for interrupts occur between the time that we
464: // read ISR and the time that we clear the bits.
465: //
466: // Also, we don't clear the RDE or RBE bits, but set
467: // the flags for later acknowledgement.
468: //
469:
470: #ifndef DPR_INTERRUPTS
471: //
472: // If desired, mask off all interrupts here. Do this
473: // before acking them in the status register to remove
474: // the possibility of another interrupt being generated.
475: //
476:
477: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK, 0);
478: #endif
479:
480: SONIC_WRITE_PORT(
481: Adapter,
482: SONIC_INTERRUPT_STATUS,
483: (USHORT)(LocalIsrValue & SONIC_INT_IMMEDIATE_ACK)
484: );
485:
486:
487: //
488: // See if we have a new RDE or RBE interrupt, if so
489: // set the flag and mask that interrupt (otherwise,
490: // since we don't ack it, we would get reinterrupted
491: // right away).
492: //
493:
494: if (LocalIsrValue & SONIC_INT_RECEIVE_DESCRIPTORS) {
495:
496: if (!Adapter->ReceiveDescriptorsExhausted) {
497:
498: Adapter->ReceiveDescriptorsExhausted = TRUE;
499:
500: Adapter->InterruptMaskRegister &=
501: ~SONIC_INT_RECEIVE_DESCRIPTORS;
502: #ifdef DPR_INTERRUPTS
503: //
504: // Update the interrupt mask register unless we
505: // have it masked off completely.
506: //
507: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
508: Adapter->InterruptMaskRegister
509: );
510: #endif
511:
512: }
513:
514: }
515:
516: if (LocalIsrValue & SONIC_INT_RECEIVE_BUFFERS) {
517:
518: if (!Adapter->ReceiveBuffersExhausted) {
519:
520: Adapter->ReceiveBuffersExhausted = TRUE;
521:
522: Adapter->InterruptMaskRegister &=
523: ~SONIC_INT_RECEIVE_BUFFERS;
524: #ifdef DPR_INTERRUPTS
525: //
526: // Update the interrupt mask register unless we
527: // have it masked off completely.
528: //
529: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
530: Adapter->InterruptMaskRegister
531: );
532: #endif
533:
534: }
535:
536: }
537:
538:
539: //
540: // If we got a LOAD_CAM_DONE interrupt, it may be
541: // because our first initialization is complete.
542: // We check this here because on some systems the
543: // DeferredProcessing call might not interrupt
544: // the initialization process.
545: //
546:
547: if (LocalIsrValue & SONIC_INT_LOAD_CAM_DONE) {
548:
549: if (Adapter->FirstInitialization) {
550:
551: Adapter->FirstInitialization = FALSE;
552:
553: #if DBG
554: {
555: USHORT PortValue;
556:
557: SONIC_READ_PORT(Adapter, SONIC_SILICON_REVISION, &PortValue);
558: if (SonicDbg) {
559: DbgPrint("SONIC Initialized: Revision %d\n", PortValue);
560: }
561: }
562: #endif
563:
564: #ifndef DPR_INTERRUPTS
565: //
566: // Re-enable the interrupts we just disabled.
567: //
568:
569: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
570: Adapter->InterruptMaskRegister
571: );
572: #endif
573: //
574: // No deferred processing is needed.
575: //
576:
577: return FALSE;
578:
579: }
580: }
581:
582:
583: //
584: // Or the ISR value into the adapter version of the ISR.
585: //
586:
587: Adapter->IsrValue |= LocalIsrValue;
588:
589:
590: #ifdef DPR_INTERRUPTS
591: //
592: // For latched interrupts, we want to force an edge
593: // in the case where interrupts appeared between when we
594: // read the ISR and when we wrote it back out. We mask
595: // the IMR off here, then reenable it during the
596: // deferred processing routine.
597: //
598:
599: if (Adapter->InterruptLatched) {
600: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK, 0);
601: }
602: #endif
603:
604: return TRUE;
605:
606: } else {
607:
608: return FALSE;
609:
610: }
611:
612: }
613:
614: extern
615: VOID
616: SonicDeferredProcessing(
617: IN PVOID SystemSpecific1,
618: IN PVOID Context,
619: IN PVOID SystemSpecific2,
620: IN PVOID SystemSpecific3
621: )
622:
623: /*++
624:
625: Routine Description:
626:
627: This DPR routine is queued by the interrupt service routine
628: and other routines within the driver that notice that
629: some deferred processing needs to be done. It's main
630: job is to call the interrupt processing code.
631:
632: Arguments:
633:
634: Context - Really a pointer to the adapter.
635:
636: SystemSpecific123 - None of these arguments is used.
637:
638: Return Value:
639:
640: None.
641:
642: --*/
643:
644: {
645:
646: //
647: // A pointer to the adapter object.
648: //
649: PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)Context;
650:
651: //
652: // Holds a value of the Interrupt Status register.
653: //
654: USHORT Isr = 0;
655:
656: //
657: // TRUE if the main loop did something.
658: //
659: BOOLEAN DidSomething = TRUE;
660:
661: //
662: // TRUE if ReceiveComplete needs to be indicated.
663: //
664: BOOLEAN IndicateReceiveComplete = FALSE;
665:
666: UNREFERENCED_PARAMETER(SystemSpecific1);
667: UNREFERENCED_PARAMETER(SystemSpecific2);
668: UNREFERENCED_PARAMETER(SystemSpecific3);
669:
670:
671: #ifdef DPR_INTERRUPTS
672: //
673: // For latched interrupts, unmask the IMR to force
674: // an edge.
675: //
676:
677: if (Adapter->InterruptLatched) {
678: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
679: Adapter->InterruptMaskRegister
680: );
681: }
682: #endif
683:
684:
685: //
686: // Loop until there are no more processing sources.
687: //
688:
689: NdisDprAcquireSpinLock(&Adapter->Lock);
690:
691: #if DBG
692: if (SonicDbg) {
693:
694: DbgPrint("In Dpr\n");
695: }
696: #endif
697:
698: while (DidSomething) {
699:
700: //
701: // Set this FALSE now, so if nothing happens we
702: // will exit.
703: //
704:
705: DidSomething = FALSE;
706:
707: //
708: // Check for receive interrupts.
709: //
710:
711: if (Adapter->ProcessingReceiveInterrupt) {
712:
713: goto DoneProcessingReceives;
714:
715: } else {
716:
717: GET_ISR_SINCE_LAST_PROCESSED(
718: Adapter,
719: &Isr,
720: SONIC_INT_PACKET_RECEIVED
721: );
722:
723: if (Isr & SONIC_INT_PACKET_RECEIVED) {
724:
725: Adapter->References++;
726: Adapter->ProcessingReceiveInterrupt = TRUE;
727: DidSomething = TRUE;
728:
729: } else {
730:
731: goto DoneProcessingReceives;
732:
733: }
734:
735: }
736:
737: NdisDprReleaseSpinLock(&Adapter->Lock);
738:
739: //
740: // After we process any
741: // other interrupt source we always come back to the top
742: // of the loop to check if any more receive packets have
743: // come in. This is to lessen the probability that we
744: // drop a receive.
745: //
746: // ProcessReceiveInterrupts may exit early if it has
747: // processed too many receives in a row. In this case
748: // it returns FALSE, we don't clear the PACKET_RECEIVED
749: // bit, and we will loop through here again.
750: //
751:
752: if (ProcessReceiveInterrupts(Adapter)) {
753: Isr &= ~SONIC_INT_PACKET_RECEIVED;
754: }
755:
756: IndicateReceiveComplete = TRUE;
757:
758: //
759: // We set ProcessingReceiveInterrupt to FALSE here so
760: // that we can issue new receive indications while
761: // the rest of the loop is proceeding.
762: //
763:
764: NdisDprAcquireSpinLock(&Adapter->Lock);
765:
766: Adapter->ProcessingReceiveInterrupt = FALSE;
767: Adapter->References--;
768:
769: DoneProcessingReceives:;
770:
771: //
772: // NOTE: We have the spinlock here.
773: //
774:
775: if (Adapter->ProcessingGeneralInterrupt) {
776:
777: goto DoneProcessingGeneral;
778:
779: } else {
780:
781: GET_ISR_SINCE_LAST_PROCESSED(
782: Adapter,
783: &Isr,
784: (USHORT)~SONIC_INT_PACKET_RECEIVED
785: );
786:
787: //
788: // Check the interrupt source and other reasons
789: // for processing. If there are no reasons to
790: // process then exit this loop.
791: //
792:
793: if ((Isr & (SONIC_INT_LOAD_CAM_DONE |
794: SONIC_INT_PROG_INTERRUPT |
795: SONIC_INT_PACKET_TRANSMITTED |
796: SONIC_INT_TRANSMIT_ERROR |
797: SONIC_INT_CRC_TALLY_ROLLOVER |
798: SONIC_INT_FAE_TALLY_ROLLOVER |
799: SONIC_INT_MP_TALLY_ROLLOVER))) {
800:
801: Adapter->References++;
802: Adapter->ProcessingGeneralInterrupt = TRUE;
803: DidSomething = TRUE;
804:
805: } else {
806:
807: goto DoneProcessingGeneral;
808:
809: }
810:
811: }
812:
813:
814: //
815: // Check for a Load CAM completing.
816: //
817: // This can happen due to a change in the CAM, due to
818: // initialization (in which case we won't save the bit
819: // and will not come through this code), or a reset
820: // (in which case ResetInProgress will be TRUE).
821: //
822: // Note that we come out of the synchronization above holding
823: // the spinlock.
824: //
825:
826:
827: //
828: // Check for non-packet related happenings.
829: //
830:
831: if (Isr & SONIC_INT_LOAD_CAM_DONE) {
832:
833: Isr &= ~SONIC_INT_LOAD_CAM_DONE;
834:
835: if (Adapter->ResetInProgress) {
836:
837: PSONIC_OPEN Open;
838: PLIST_ENTRY CurrentLink;
839:
840: //
841: // This initialization is from a reset.
842: //
843:
844: //
845: // This will point to the open that
846: // initiated the reset.
847: //
848: PSONIC_OPEN ResettingOpen;
849:
850: Adapter->ResetInProgress = FALSE;
851: Adapter->IndicatingResetEnd = TRUE;
852:
853: //
854: // Restart the chip.
855: //
856:
857: SonicStartChip(Adapter);
858:
859: //
860: // We save off the open that caused this reset incase
861: // we get *another* reset while we're indicating the
862: // last reset is done; that would overwrite
863: // Adapter->ResettingOpen.
864: //
865:
866: ResettingOpen = Adapter->ResettingOpen;
867:
868: //
869: // If anything queued up while we were resetting
870: // (in practice that could only be close requests)
871: // then restart them now.
872: //
873:
874: if (Adapter->FirstRequest) {
875: SonicProcessRequestQueue(Adapter);
876: }
877:
878: //
879: // We need to signal every open binding that the
880: // reset is complete. We increment the reference
881: // count on the open binding while we're doing indications
882: // so that the open can't be deleted out from under
883: // us while we're indicating (recall that we can't own
884: // the lock during the indication).
885: //
886:
887: CurrentLink = Adapter->OpenBindings.Flink;
888:
889: while (CurrentLink != &Adapter->OpenBindings) {
890:
891: Open = CONTAINING_RECORD(
892: CurrentLink,
893: SONIC_OPEN,
894: OpenList
895: );
896:
897: Open->References++;
898: NdisDprReleaseSpinLock(&Adapter->Lock);
899:
900: NdisIndicateStatus(
901: Open->NdisBindingContext,
902: NDIS_STATUS_RESET_END,
903: NULL,
904: 0
905: );
906:
907: NdisIndicateStatusComplete(Open->NdisBindingContext);
908:
909: NdisDprAcquireSpinLock(&Adapter->Lock);
910: Open->References--;
911:
912: CurrentLink = CurrentLink->Flink;
913:
914: }
915:
916: //
917: // Look to see which open initiated the reset.
918: //
919:
920: NdisDprReleaseSpinLock(&Adapter->Lock);
921:
922: NdisCompleteReset(
923: ResettingOpen->NdisBindingContext,
924: NDIS_STATUS_SUCCESS
925: );
926: NdisDprAcquireSpinLock(&Adapter->Lock);
927:
928: ResettingOpen->References--;
929: Adapter->IndicatingResetEnd = FALSE;
930:
931: if (Adapter->IndicatingResetStart) {
932:
933: //
934: // Somebody has started a reset while we were
935: // indicating the reset end.
936: //
937:
938: //
939: // Indicate Reset Start
940: //
941:
942: CurrentLink = Adapter->OpenBindings.Flink;
943:
944: while (CurrentLink != &Adapter->OpenBindings) {
945:
946: Open = CONTAINING_RECORD(
947: CurrentLink,
948: SONIC_OPEN,
949: OpenList
950: );
951:
952: Open->References++;
953: NdisDprReleaseSpinLock(&Adapter->Lock);
954:
955: NdisIndicateStatus(
956: Open->NdisBindingContext,
957: NDIS_STATUS_RESET_START,
958: NULL,
959: 0
960: );
961:
962: NdisIndicateStatusComplete(Open->NdisBindingContext);
963:
964: NdisDprAcquireSpinLock(&Adapter->Lock);
965:
966: Open->References--;
967:
968: CurrentLink = CurrentLink->Flink;
969:
970: }
971:
972: Adapter->IndicatingResetStart = FALSE;
973:
974: SetupForReset(
975: Adapter,
976: Adapter->ResettingOpen
977: );
978:
979: }
980:
981: } else { // ResetInProgress FALSE
982:
983: PNDIS_REQUEST Request;
984: PSONIC_REQUEST_RESERVED Reserved;
985: PSONIC_OPEN Open;
986:
987: Request = Adapter->FirstRequest;
988: Reserved = PSONIC_RESERVED_FROM_REQUEST(Request);
989:
990: switch (Request->RequestType) {
991:
992: case NdisRequestQueryInformation:
993: case NdisRequestSetInformation:
994:
995: Adapter->FirstRequest = Reserved->Next;
996: Open = Reserved->OpenBlock;
997:
998: NdisDprReleaseSpinLock(&Adapter->Lock);
999:
1000: NdisCompleteRequest(
1001: Open->NdisBindingContext,
1002: Request,
1003: NDIS_STATUS_SUCCESS);
1004:
1005: NdisDprAcquireSpinLock(&Adapter->Lock);
1006:
1007: --Open->References;
1008:
1009: break;
1010:
1011: case NdisRequestQueryStatistics:
1012:
1013: Adapter->FirstRequest = Reserved->Next;
1014:
1015: NdisDprReleaseSpinLock(&Adapter->Lock);
1016:
1017: NdisCompleteQueryStatistics(
1018: Adapter->NdisAdapterHandle,
1019: Request,
1020: NDIS_STATUS_SUCCESS);
1021:
1022: NdisDprAcquireSpinLock(&Adapter->Lock);
1023:
1024: break;
1025:
1026: case NdisRequestClose:
1027:
1028: Adapter->FirstRequest = Reserved->Next;
1029: Open = Reserved->OpenBlock;
1030:
1031: //
1032: // The close will get completed when the
1033: // reference count goes to 0.
1034: //
1035:
1036: --Open->References;
1037:
1038: }
1039:
1040: //
1041: // Now continue processing requests if needed
1042: // (this is called with the lock held).
1043: //
1044:
1045: SonicProcessRequestQueue(Adapter);
1046:
1047: }
1048:
1049: }
1050:
1051: //
1052: // We hold the spinlock here.
1053: //
1054:
1055: if (Isr & (SONIC_INT_CRC_TALLY_ROLLOVER |
1056: SONIC_INT_FAE_TALLY_ROLLOVER |
1057: SONIC_INT_MP_TALLY_ROLLOVER)) {
1058:
1059: //
1060: // If any of the counters overflowed, then we update
1061: // the counter by adding one to the high sixteen bits
1062: // and reading the register for the low sixteen bits.
1063: //
1064:
1065: if (Isr & SONIC_INT_CRC_TALLY_ROLLOVER) {
1066:
1067: USHORT CrcError;
1068: SONIC_READ_PORT(Adapter, SONIC_CRC_ERROR, &CrcError);
1069:
1070: Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] =
1071: (Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START] & 0xffff0000) +
1072: 0x10000 +
1073: CrcError;
1074:
1075: }
1076:
1077: if (Isr & SONIC_INT_FAE_TALLY_ROLLOVER) {
1078:
1079: USHORT FaError;
1080: SONIC_READ_PORT(Adapter, SONIC_FRAME_ALIGNMENT_ERROR, &FaError);
1081:
1082: Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] =
1083: (Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT] & 0xffff0000) +
1084: 0x10000 +
1085: FaError;
1086:
1087: }
1088:
1089: if (Isr & SONIC_INT_MP_TALLY_ROLLOVER) {
1090:
1091: USHORT MissedPacket;
1092: SONIC_READ_PORT(Adapter, SONIC_MISSED_PACKET, &MissedPacket);
1093:
1094: Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] =
1095: (Adapter->GeneralMandatory[GM_RECEIVE_NO_BUFFER] & 0xffff0000) +
1096: 0x10000 +
1097: MissedPacket;
1098:
1099: }
1100:
1101: Isr &= ~(SONIC_INT_CRC_TALLY_ROLLOVER |
1102: SONIC_INT_FAE_TALLY_ROLLOVER |
1103: SONIC_INT_MP_TALLY_ROLLOVER);
1104:
1105: }
1106:
1107: //
1108: // Process the transmit interrupts if there are any.
1109: //
1110:
1111: if (Isr & (SONIC_INT_PROG_INTERRUPT |
1112: SONIC_INT_PACKET_TRANSMITTED |
1113: SONIC_INT_TRANSMIT_ERROR)) {
1114:
1115: {
1116:
1117: if (!ProcessTransmitInterrupts(Adapter)) {
1118:
1119: //
1120: // Process interrupts returns false if it
1121: // finds no more work to do. If this so we
1122: // turn off the transmitter interrupt source.
1123: //
1124:
1125: Isr &= ~ (SONIC_INT_PROG_INTERRUPT |
1126: SONIC_INT_PACKET_TRANSMITTED |
1127: SONIC_INT_TRANSMIT_ERROR);
1128:
1129: }
1130:
1131: }
1132:
1133: }
1134:
1135:
1136: Adapter->ProcessingGeneralInterrupt = FALSE;
1137: Adapter->References--;
1138:
1139:
1140: DoneProcessingGeneral:;
1141:
1142: //
1143: // Note that when we check the for processing sources
1144: // that we "carefully" check to see if we are already
1145: // processing the stage queue. We do this
1146: // by checking the "AlreadyProcessingSendStage" variable
1147: // in the adapter. If this is true then
1148: // we let whoever set that boolean take care of pushing
1149: // the packet through the stage queue.
1150: //
1151:
1152: if ((!Adapter->AlreadyProcessingSendStage) &&
1153: Adapter->FirstSendStagePacket &&
1154: Adapter->SendStageOpen) {
1155:
1156: Adapter->References++;
1157: DidSomething = TRUE;
1158:
1159: } else {
1160:
1161: goto DoneProcessingSend;
1162:
1163: }
1164:
1165: //
1166: // This routine is called with and returns with the
1167: // spinlock held, but may release it internally.
1168: //
1169:
1170: SonicStagedAllocation(Adapter);
1171:
1172: Adapter->References--;
1173:
1174:
1175: DoneProcessingSend:;
1176:
1177: //
1178: // NOTE: We have the spinlock here.
1179: //
1180:
1181:
1182: if ((!Adapter->ProcessingDeferredOperations) &&
1183: (Adapter->FirstLoopBack ||
1184: (Adapter->ResetInProgress && (Adapter->References == 1)) ||
1185: (!IsListEmpty(&Adapter->CloseList)))) {
1186:
1187: Adapter->ProcessingDeferredOperations = TRUE;
1188: Adapter->References++;
1189:
1190: NdisSetTimer(
1191: &Adapter->DeferredTimer,
1192: 0);
1193:
1194: DidSomething = TRUE;
1195:
1196: }
1197:
1198:
1199: //
1200: // NOTE: This code assumes that the above code left
1201: // the spinlock held, since the while loop assumes
1202: // it is held at the beginning.
1203: //
1204:
1205: #ifndef DPR_INTERRUPTS
1206:
1207: //
1208: // If we have interrups disabled, then we won't get another
1209: // InterruptServiceRoutine, so we check here for any new
1210: // bits that are on. We don't worry about receive buffers
1211: // or descriptors being exhausted, we'll catch that case
1212: // with another interrupt.
1213: //
1214:
1215: {
1216: USHORT LocalIsrValue;
1217:
1218: SONIC_READ_PORT(Adapter, SONIC_INTERRUPT_STATUS, &LocalIsrValue);
1219: LocalIsrValue &= SONIC_INT_IMMEDIATE_ACK;
1220:
1221: if (LocalIsrValue != 0x0000) {
1222:
1223: //
1224: // Ack the bits and set DidSomething so we force
1225: // a loop back to the top.
1226: //
1227:
1228: SONIC_WRITE_PORT(
1229: Adapter,
1230: SONIC_INTERRUPT_STATUS,
1231: LocalIsrValue
1232: );
1233:
1234: Adapter->IsrValue |= LocalIsrValue;
1235: DidSomething = TRUE;
1236: }
1237: }
1238:
1239: #endif
1240:
1241: }
1242:
1243: #ifndef DPR_INTERRUPTS
1244: //
1245: // If we have had interrupts disabled this whole time,
1246: // then reenable them here to permit future interrupts.
1247: //
1248: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
1249: Adapter->InterruptMaskRegister
1250: );
1251: #endif
1252:
1253: NdisDprReleaseSpinLock(&Adapter->Lock);
1254:
1255: if (IndicateReceiveComplete) {
1256:
1257: //
1258: // We have indicated at least one packet, we now
1259: // need to signal every open binding that the
1260: // receives are complete.
1261: //
1262:
1263: EthFilterIndicateReceiveComplete(Adapter->FilterDB);
1264:
1265: }
1266:
1267: }
1268:
1269: extern
1270: VOID
1271: SonicTimerProcess(
1272: IN PVOID SystemSpecific1,
1273: IN PVOID Context,
1274: IN PVOID SystemSpecific2,
1275: IN PVOID SystemSpecific3
1276: )
1277:
1278: /*++
1279:
1280: Routine Description:
1281:
1282: Process the operations that are deferred by SonicDeferredProcessing.
1283:
1284: Arguments:
1285:
1286: Context - A pointer to the adapter.
1287:
1288: Return Value:
1289:
1290: None.
1291:
1292: --*/
1293:
1294: {
1295:
1296: PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)Context;
1297:
1298: UNREFERENCED_PARAMETER(SystemSpecific1);
1299: UNREFERENCED_PARAMETER(SystemSpecific2);
1300: UNREFERENCED_PARAMETER(SystemSpecific3);
1301:
1302: NdisDprAcquireSpinLock(&Adapter->Lock);
1303:
1304: while ((Adapter->FirstLoopBack ||
1305: (Adapter->ResetInProgress && (Adapter->References == 2)) ||
1306: (!IsListEmpty(&Adapter->CloseList)))) {
1307:
1308: //
1309: // Note that the following code depends on the fact that
1310: // code above left the spinlock held.
1311: //
1312:
1313: //
1314: // If we have a reset in progress and the adapters reference
1315: // count is 1 (meaning no routine is in the interface and
1316: // we are the only "active" interrupt processing routine) then
1317: // it is safe to start the reset.
1318: //
1319:
1320: if (Adapter->ResetInProgress && (Adapter->References == 2)) {
1321:
1322: Adapter->ProcessingDeferredOperations = FALSE;
1323: Adapter->References--;
1324: NdisDprReleaseSpinLock(&Adapter->Lock);
1325:
1326: StartAdapterReset(Adapter);
1327: return;
1328:
1329: }
1330:
1331: //
1332: // Process the loopback queue.
1333: //
1334: // NOTE: Incase anyone ever figures out how to make this
1335: // loop more reentriant, special care needs to be taken that
1336: // loopback packets and regular receive packets are NOT being
1337: // indicated at the same time. While the filter indication
1338: // routines can handle this, I doubt that the transport can.
1339: //
1340:
1341: if (Adapter->FirstLoopBack != NULL ) {
1342:
1343: SonicProcessLoopback(Adapter);
1344:
1345: }
1346:
1347: //
1348: // If there are any opens on the closing list and their
1349: // reference counts are zero then complete the close and
1350: // delete them from the list.
1351: //
1352:
1353: if (!IsListEmpty(&Adapter->CloseList)) {
1354:
1355: PSONIC_OPEN Open;
1356:
1357: Open = CONTAINING_RECORD(
1358: Adapter->CloseList.Flink,
1359: SONIC_OPEN,
1360: OpenList
1361: );
1362:
1363: if (!Open->References) {
1364:
1365: NDIS_HANDLE OpenBindingContext = Open->NdisBindingContext;
1366:
1367: RemoveEntryList(&Open->OpenList);
1368: SONIC_FREE_MEMORY(Open, sizeof(SONIC_OPEN));
1369:
1370: --Adapter->OpenCount;
1371:
1372: NdisDprReleaseSpinLock(&Adapter->Lock);
1373:
1374: NdisCompleteCloseAdapter(
1375: OpenBindingContext,
1376: NDIS_STATUS_SUCCESS
1377: );
1378:
1379: NdisDprAcquireSpinLock(&Adapter->Lock);
1380:
1381: }
1382:
1383: }
1384:
1385: //
1386: // NOTE: We hold the spinlock here.
1387: //
1388:
1389: }
1390:
1391: Adapter->ProcessingDeferredOperations = FALSE;
1392: Adapter->References--;
1393: NdisDprReleaseSpinLock(&Adapter->Lock);
1394:
1395: }
1396:
1397: #define SONIC_RECEIVE_LIMIT 10
1398:
1399:
1400: STATIC
1401: BOOLEAN
1402: ProcessReceiveInterrupts(
1403: IN PSONIC_ADAPTER Adapter
1404: )
1405:
1406: /*++
1407:
1408: Routine Description:
1409:
1410: Process the packets that have finished receiving.
1411:
1412: NOTE: This routine assumes that no other thread of execution
1413: is processing receives!
1414:
1415: Arguments:
1416:
1417: Adapter - The adapter to indicate to.
1418:
1419: Return Value:
1420:
1421: FALSE if we exit because we have indicated SONIC_RECEIVE_LIMIT
1422: packets, TRUE if there are no more packets.
1423:
1424: --*/
1425:
1426: {
1427:
1428: //
1429: // We don't get here unless there was a receive. Loop through
1430: // the receive descriptors starting at the last known descriptor
1431: // owned by the hardware that begins a packet.
1432: //
1433: // Examine each receive ring descriptor for errors.
1434: //
1435: // We keep an array whose elements are indexed by the ring
1436: // index of the receive descriptors. The arrays elements are
1437: // the virtual addresses of the buffers pointed to by
1438: // each ring descriptor.
1439: //
1440: // When we have the entire packet (and error processing doesn't
1441: // prevent us from indicating it), we give the routine that
1442: // processes the packet through the filter, the buffers virtual
1443: // address (which is always the lookahead size) and as the
1444: // MAC context the index to the first and last ring descriptors
1445: // comprising the packet.
1446: //
1447:
1448:
1449: //
1450: // Pointer to the receive descriptor being examined.
1451: //
1452: PSONIC_RECEIVE_DESCRIPTOR CurrentDescriptor =
1453: &Adapter->ReceiveDescriptorArea[
1454: Adapter->CurrentReceiveDescriptorIndex];
1455:
1456: //
1457: // Index of the RBA that the next packet should
1458: // come out of.
1459: //
1460: UINT CurrentRbaIndex = Adapter->CurrentReceiveBufferIndex;
1461:
1462: //
1463: // Virtual address of the start of that RBA.
1464: //
1465: PVOID CurrentRbaVa = Adapter->ReceiveBufferArea[CurrentRbaIndex];
1466:
1467: //
1468: // Physical address of the start of that RBA.
1469: //
1470: SONIC_PHYSICAL_ADDRESS CurrentRbaPhysical =
1471: SONIC_GET_RECEIVE_RESOURCE_ADDRESS(&Adapter->ReceiveResourceArea[CurrentRbaIndex]);
1472:
1473: //
1474: // The size of the packet.
1475: //
1476: UINT PacketSize;
1477:
1478: //
1479: // The amount of data received in the RBA (will be PacketSize +
1480: // 4 for the CRC).
1481:
1482: USHORT ByteCount;
1483:
1484: //
1485: // The amount of lookahead data to indicate.
1486: //
1487: UINT LookAheadSize;
1488:
1489: //
1490: // The offset of the start of the packet in its receive buffer.
1491: //
1492: UINT PacketOffsetInRba;
1493:
1494: //
1495: // The Physical address of the packet.
1496: //
1497: SONIC_PHYSICAL_ADDRESS PacketPhysical;
1498:
1499: //
1500: // A pointer to the link field at the end of the receive
1501: // descriptor before the one we are processing.
1502: //
1503: PSONIC_PHYSICAL_ADDRESS PrevLinkFieldAddr;
1504:
1505: //
1506: // The virtual address of the packet.
1507: //
1508: PVOID PacketVa;
1509:
1510: //
1511: // The status of the packet.
1512: //
1513: USHORT ReceiveStatus;
1514:
1515: //
1516: // Is the descriptor in use by the sonic.
1517: //
1518: ULONG InUse;
1519:
1520: //
1521: // Used tempoerarily to determine PacketPhysical.
1522: //
1523: USHORT PacketAddress;
1524:
1525: //
1526: // How many packets we have indicated this time.
1527: //
1528: UINT PacketsIndicated = 0;
1529:
1530: #if DBG
1531: //
1532: // For debugging, save the previous receive descriptor.
1533: //
1534: static SONIC_RECEIVE_DESCRIPTOR PreviousDescriptor;
1535: #endif
1536:
1537:
1538: do {
1539:
1540: //
1541: // Ensure that the system memory copy of the
1542: // receive descriptor is up-to-date.
1543: //
1544:
1545: NdisUpdateSharedMemory(
1546: Adapter->NdisAdapterHandle,
1547: sizeof(SONIC_RECEIVE_DESCRIPTOR) *
1548: Adapter->NumberOfReceiveDescriptors,
1549: Adapter->ReceiveDescriptorArea,
1550: Adapter->ReceiveDescriptorAreaPhysical
1551: );
1552:
1553:
1554: //
1555: // Check to see whether we own the packet. If
1556: // we don't then simply return to the caller.
1557: //
1558:
1559: NdisReadRegisterUlong(&CurrentDescriptor->InUse, &InUse);
1560:
1561: if (InUse != SONIC_OWNED_BY_SYSTEM) {
1562:
1563: return TRUE;
1564:
1565: }
1566:
1567:
1568: //
1569: // Figure out the virtual address of the packet.
1570: //
1571:
1572: NdisReadRegisterUshort(&CurrentDescriptor->LowPacketAddress, &PacketAddress);
1573: PacketPhysical = PacketAddress;
1574: NdisReadRegisterUshort(&CurrentDescriptor->HighPacketAddress, &PacketAddress);
1575: PacketPhysical += PacketAddress << 16;
1576:
1577: if ((PacketPhysical < CurrentRbaPhysical) ||
1578: (PacketPhysical >
1579: (CurrentRbaPhysical + SONIC_SIZE_OF_RECEIVE_BUFFERS))) {
1580:
1581: //
1582: // Something is wrong, the packet is not in the
1583: // receive buffer that we expect it in.
1584: //
1585:
1586: SONIC_PHYSICAL_ADDRESS ResourcePhysical;
1587: PSONIC_RECEIVE_RESOURCE CurrentReceiveResource;
1588: UINT i;
1589:
1590: if (Adapter->WrongRbaErrorLogCount++ < 5) {
1591:
1592: //
1593: // Log an error the first five times this happens.
1594: //
1595:
1596: NdisWriteErrorLogEntry(
1597: Adapter->NdisAdapterHandle,
1598: NDIS_ERROR_CODE_HARDWARE_FAILURE,
1599: 6,
1600: processReceiveInterrupts,
1601: SONIC_ERRMSG_WRONG_RBA,
1602: (ULONG)CurrentRbaPhysical,
1603: (ULONG)PacketPhysical,
1604: (ULONG)CurrentDescriptor,
1605: (ULONG)Adapter->ReceiveDescriptorArea
1606: );
1607:
1608: #if DBG
1609: DbgPrint("SONIC: RBA at %lx [%lx], Packet at %lx\n", CurrentRbaPhysical, CurrentRbaVa, PacketPhysical);
1610: DbgPrint("descriptor %lx, start %lx, prev %lx\n",
1611: (ULONG)CurrentDescriptor,
1612: (ULONG)Adapter->ReceiveDescriptorArea,
1613: &PreviousDescriptor);
1614: #endif
1615: }
1616:
1617: //
1618: // Attempt to recover by advancing the relevant pointers
1619: // to where the SONIC thinks the packet is. First we need
1620: // to find the receive buffer that matches the indicated
1621: // physical address.
1622: //
1623:
1624: for (
1625: i = 0, CurrentReceiveResource = Adapter->ReceiveResourceArea;
1626: i < Adapter->NumberOfReceiveBuffers;
1627: i++,CurrentReceiveResource++
1628: ) {
1629:
1630: ResourcePhysical = SONIC_GET_RECEIVE_RESOURCE_ADDRESS(CurrentReceiveResource);
1631: if ((PacketPhysical >= ResourcePhysical) &&
1632: (PacketPhysical <
1633: (ResourcePhysical + SONIC_SIZE_OF_RECEIVE_BUFFERS))) {
1634:
1635: //
1636: // We found the receive resource.
1637: //
1638: break;
1639:
1640: }
1641:
1642: }
1643:
1644: #ifdef NDIS_NT
1645: if (i == Adapter->NumberOfReceiveBuffers) {
1646: KeBugCheck(NDIS_INTERNAL_ERROR);
1647: }
1648: #endif
1649:
1650: //
1651: // Update our pointers.
1652: //
1653:
1654: Adapter->CurrentReceiveBufferIndex = i;
1655: CurrentRbaIndex = i;
1656:
1657: CurrentRbaVa = Adapter->ReceiveBufferArea[i];
1658: CurrentRbaPhysical =
1659: SONIC_GET_RECEIVE_RESOURCE_ADDRESS(&Adapter->ReceiveResourceArea[i]);
1660:
1661: //
1662: // Ensure that we release buffers before this one
1663: // back to the sonic.
1664: //
1665:
1666: WRITE_RWP_AND_ACK(
1667: Adapter,
1668: (USHORT)(CurrentRbaPhysical & 0xffff)
1669: );
1670:
1671: }
1672:
1673:
1674: PacketOffsetInRba = PacketPhysical - CurrentRbaPhysical;
1675:
1676:
1677: //
1678: // Check that the packet was received correctly...note that
1679: // we always compute PacketOffsetInRba and ByteCount,
1680: // which are needed to skip the packet even if we do not
1681: // indicate it.
1682: //
1683:
1684: NdisReadRegisterUshort(&CurrentDescriptor->ReceiveStatus, &ReceiveStatus);
1685:
1686: NdisReadRegisterUshort(&CurrentDescriptor->ByteCount, &ByteCount);
1687:
1688: if (!(ReceiveStatus & SONIC_RCR_PACKET_RECEIVED_OK)) {
1689:
1690: #if DBG
1691: if (SonicDbg) {
1692: DbgPrint("SONIC: Skipping %lx\n", ReceiveStatus);
1693: }
1694: #endif
1695:
1696: goto SkipIndication;
1697:
1698: }
1699:
1700: //
1701: // Prepare to indicate the packet.
1702: //
1703:
1704: PacketSize = ByteCount - 4;
1705:
1706: if (PacketSize > 1514) {
1707: #if DBG
1708: DbgPrint("SONIC: Skipping packet, length %d\n", PacketSize);
1709: #endif
1710: goto SkipIndication;
1711: }
1712:
1713:
1714: if (PacketSize < SONIC_INDICATE_MAXIMUM) {
1715:
1716: LookAheadSize = PacketSize;
1717:
1718: } else {
1719:
1720: LookAheadSize = SONIC_INDICATE_MAXIMUM;
1721:
1722: }
1723:
1724: PacketVa = (PUCHAR)CurrentRbaVa + PacketOffsetInRba;
1725:
1726:
1727: //
1728: // Check just before we do indications that we aren't
1729: // resetting.
1730: //
1731:
1732: if (Adapter->ResetInProgress) {
1733: return TRUE;
1734: }
1735:
1736: //
1737: // Ensure that the system memory version of this RBA is
1738: // up-to-date.
1739: //
1740:
1741: {
1742: NDIS_PHYSICAL_ADDRESS TempAddress;
1743:
1744: NdisSetPhysicalAddressLow (TempAddress,
1745: SONIC_GET_RECEIVE_RESOURCE_ADDRESS(&Adapter->ReceiveResourceArea[CurrentRbaIndex]));
1746: NdisSetPhysicalAddressHigh (TempAddress, 0);
1747:
1748: NdisUpdateSharedMemory(
1749: Adapter->NdisAdapterHandle,
1750: SONIC_SIZE_OF_RECEIVE_BUFFERS,
1751: Adapter->ReceiveBufferArea[CurrentRbaIndex],
1752: TempAddress
1753: );
1754:
1755: }
1756:
1757: if (PacketSize < 14) {
1758:
1759: //
1760: // Must have at least the destination address
1761: //
1762:
1763: if (PacketSize >= ETH_LENGTH_OF_ADDRESS) {
1764:
1765: //
1766: // Runt packet
1767: //
1768:
1769: EthFilterIndicateReceive(
1770: Adapter->FilterDB,
1771: (NDIS_HANDLE)((PUCHAR)PacketVa + 14), // context
1772: PacketVa, // destination address
1773: PacketVa, // header buffer
1774: PacketSize, // header buffer size
1775: NULL, // lookahead buffer
1776: 0, // lookahead buffer size
1777: 0 // packet size
1778: );
1779:
1780: }
1781:
1782: } else {
1783:
1784: EthFilterIndicateReceive(
1785: Adapter->FilterDB,
1786: (NDIS_HANDLE)((PUCHAR)PacketVa + 14), // context
1787: PacketVa, // destination address
1788: PacketVa, // header buffer
1789: 14, // header buffer size
1790: (PUCHAR)PacketVa + 14, // lookahead buffer
1791: LookAheadSize - 14, // lookahead buffer size
1792: PacketSize - 14 // packet size
1793: );
1794:
1795: }
1796:
1797: SkipIndication:;
1798:
1799: #if DBG
1800: SONIC_MOVE_MEMORY (&PreviousDescriptor, CurrentDescriptor, sizeof(SONIC_RECEIVE_DESCRIPTOR));
1801: #endif
1802:
1803: //
1804: // Give the packet back to the hardware.
1805: //
1806:
1807: NdisWriteRegisterUlong(&CurrentDescriptor->InUse, SONIC_OWNED_BY_SONIC);
1808:
1809: //
1810: // And re-set the EOL fields correctly.
1811: //
1812:
1813: SONIC_SET_END_OF_LIST(
1814: &(CurrentDescriptor->Link)
1815: );
1816:
1817:
1818:
1819: if (CurrentDescriptor == Adapter->ReceiveDescriptorArea) {
1820:
1821: //
1822: // we are at the first one
1823: //
1824:
1825: PrevLinkFieldAddr = &(Adapter->LastReceiveDescriptor->Link);
1826:
1827: } else {
1828:
1829: PrevLinkFieldAddr = &((CurrentDescriptor-1)->Link);
1830:
1831: }
1832:
1833:
1834: REMOVE_EOL_AND_ACK(
1835: Adapter,
1836: PrevLinkFieldAddr
1837: );
1838:
1839:
1840:
1841: //
1842: // Now figure out if the RBA is done with.
1843: //
1844:
1845: if (ReceiveStatus & SONIC_RCR_LAST_PACKET_IN_RBA) {
1846:
1847: //
1848: // Advance which RBA we are looking at.
1849: //
1850:
1851: ++CurrentRbaIndex;
1852:
1853: if (CurrentRbaIndex == Adapter->NumberOfReceiveBuffers) {
1854:
1855: CurrentRbaIndex = 0;
1856:
1857: }
1858:
1859: Adapter->CurrentReceiveBufferIndex = CurrentRbaIndex;
1860:
1861: CurrentRbaVa = Adapter->ReceiveBufferArea[CurrentRbaIndex];
1862: CurrentRbaPhysical =
1863: SONIC_GET_RECEIVE_RESOURCE_ADDRESS(&Adapter->ReceiveResourceArea[CurrentRbaIndex]);
1864:
1865:
1866: WRITE_RWP_AND_ACK(
1867: Adapter,
1868: (USHORT)(CurrentRbaPhysical & 0xffff)
1869: );
1870:
1871: }
1872:
1873: //
1874: // Update statistics now based on the receive status.
1875: //
1876:
1877: if (ReceiveStatus & SONIC_RCR_PACKET_RECEIVED_OK) {
1878:
1879: ++Adapter->GeneralMandatory[GM_RECEIVE_GOOD];
1880:
1881: if (ReceiveStatus & SONIC_RCR_BROADCAST_RECEIVED) {
1882:
1883: ++Adapter->GeneralOptionalFrameCount[GO_BROADCAST_RECEIVES];
1884: SonicAddUlongToLargeInteger(
1885: &Adapter->GeneralOptionalByteCount[GO_BROADCAST_RECEIVES],
1886: PacketSize);
1887:
1888: } else if (ReceiveStatus & SONIC_RCR_MULTICAST_RECEIVED) {
1889:
1890: ++Adapter->GeneralOptionalFrameCount[GO_MULTICAST_RECEIVES];
1891: SonicAddUlongToLargeInteger(
1892: &Adapter->GeneralOptionalByteCount[GO_MULTICAST_RECEIVES],
1893: PacketSize);
1894:
1895: } else {
1896:
1897: ++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_RECEIVES];
1898: SonicAddUlongToLargeInteger(
1899: &Adapter->GeneralOptionalByteCount[GO_DIRECTED_RECEIVES],
1900: PacketSize);
1901:
1902: }
1903:
1904: } else {
1905:
1906: ++Adapter->GeneralMandatory[GM_RECEIVE_BAD];
1907:
1908: if (ReceiveStatus & SONIC_RCR_CRC_ERROR) {
1909: ++Adapter->GeneralOptional[GO_RECEIVE_CRC - GO_ARRAY_START];
1910: } else if (ReceiveStatus & SONIC_RCR_FRAME_ALIGNMENT) {
1911: ++Adapter->MediaMandatory[MM_RECEIVE_ERROR_ALIGNMENT];
1912: }
1913:
1914: }
1915:
1916: //
1917: // Advance our pointers to the next packet.
1918:
1919: if (CurrentDescriptor == Adapter->LastReceiveDescriptor) {
1920:
1921: Adapter->CurrentReceiveDescriptorIndex = 0;
1922:
1923: } else {
1924:
1925: ++(Adapter->CurrentReceiveDescriptorIndex);
1926:
1927: }
1928:
1929: CurrentDescriptor = &Adapter->ReceiveDescriptorArea[
1930: Adapter->CurrentReceiveDescriptorIndex];
1931:
1932: ++PacketsIndicated;
1933:
1934: } while (PacketsIndicated < SONIC_RECEIVE_LIMIT);
1935:
1936: //
1937: // Indicate that we returned because we indicated SONIC_RECEIVE_
1938: // LIMIT packets, not because we ran out of packets to indicate.
1939: //
1940:
1941: return FALSE;
1942:
1943: }
1944:
1945: STATIC
1946: BOOLEAN
1947: ProcessTransmitInterrupts(
1948: IN PSONIC_ADAPTER Adapter
1949: )
1950:
1951: /*++
1952:
1953: Routine Description:
1954:
1955: Process the packets that have finished transmitting.
1956:
1957: NOTE: Called with the lock held!
1958:
1959: Arguments:
1960:
1961: Adapter - The adapter that was sent from.
1962:
1963: Return Value:
1964:
1965: This function will return TRUE if it finished up the
1966: send on a packet. It will return FALSE if for some
1967: reason there was no packet to process.
1968:
1969: --*/
1970:
1971: {
1972: //
1973: // Index into the ring to packet structure. This index points
1974: // to the first ring entry for the first buffer used for transmitting
1975: // the packet.
1976: //
1977: UINT DescriptorIndex;
1978:
1979: //
1980: // The transmit desctiptor for the packet at Transmitting Descriptor
1981: //
1982: PSONIC_TRANSMIT_DESCRIPTOR TransmitDescriptor;
1983:
1984: //
1985: // Temporarily holds the transmit descriptor after TransmitDescriptor
1986: //
1987: PSONIC_TRANSMIT_DESCRIPTOR NextTransmitDescriptor;
1988:
1989: //
1990: // Pointer to the packet that started this transmission.
1991: //
1992: PNDIS_PACKET OwningPacket;
1993:
1994: //
1995: // Points to the reserved part of the OwningPacket.
1996: //
1997: PSONIC_PACKET_RESERVED Reserved;
1998:
1999: //
2000: // Used to hold the ring to packet mapping information so that
2001: // we can release the ring entries as quickly as possible.
2002: //
2003: SONIC_DESCRIPTOR_TO_PACKET SavedDescriptorMapping;
2004:
2005: //
2006: // The status of the transmit.
2007: //
2008: USHORT TransmitStatus;
2009:
2010: //
2011: // Hold the first Ndis buffer;
2012: //
2013: PNDIS_BUFFER FirstBuffer;
2014:
2015: //
2016: // Holds the address of the data in the first buffer
2017: //
2018: PVOID BufferVirtualAddress;
2019:
2020: //
2021: // Number of bytes in the first buffer.
2022: //
2023: UINT BufferLength;
2024:
2025:
2026: //
2027: // Get hold of the first transmitted packet.
2028: //
2029:
2030: //
2031: // First we check that this is a packet that was transmitted
2032: // but not already processed. Recall that this routine
2033: // will be called repeatedly until this tests false, Or we
2034: // hit a packet that we don't completely own.
2035: //
2036:
2037: if (Adapter->TransmittingDescriptor !=
2038: Adapter->FirstUncommittedDescriptor) {
2039:
2040: DescriptorIndex =
2041: Adapter->TransmittingDescriptor - Adapter->TransmitDescriptorArea;
2042:
2043: } else {
2044:
2045: return FALSE;
2046:
2047: }
2048:
2049: //
2050: // We put the mapping into a local variable so that we
2051: // can return the mapping as soon as possible.
2052: //
2053:
2054: SavedDescriptorMapping = Adapter->DescriptorToPacket[DescriptorIndex];
2055:
2056: //
2057: // Get a pointer to the transmit descriptor for this packet.
2058: //
2059:
2060: TransmitDescriptor = Adapter->TransmitDescriptorArea + DescriptorIndex;
2061:
2062: //
2063: // Get a pointer to the owning packet and the reserved part of
2064: // the packet.
2065: //
2066:
2067: OwningPacket = SavedDescriptorMapping.OwningPacket;
2068:
2069: Reserved = PSONIC_RESERVED_FROM_PACKET(OwningPacket);
2070:
2071:
2072: //
2073: // Check that status bits were written into the transmit
2074: // descriptor.
2075: //
2076:
2077: NdisReadRegisterUshort(&TransmitDescriptor->TransmitStatus, &TransmitStatus);
2078:
2079: if (!(TransmitStatus & SONIC_TCR_STATUS_MASK)) {
2080:
2081: //
2082: // The transmit has not completed.
2083: //
2084:
2085: return FALSE;
2086:
2087: } else {
2088:
2089: //
2090: // Holds whether the packet successfully transmitted or not.
2091: //
2092: BOOLEAN Successful = TRUE;
2093:
2094: Adapter->WakeUpTimeout = FALSE;
2095:
2096: if (SavedDescriptorMapping.UsedSonicBuffer) {
2097:
2098: //
2099: // This packet used adapter buffers. We can
2100: // now return these buffers to the adapter.
2101: //
2102:
2103: //
2104: // The adapter buffer descriptor that was allocated to this packet.
2105: //
2106: PSONIC_BUFFER_DESCRIPTOR BufferDescriptor = Adapter->SonicBuffers +
2107: SavedDescriptorMapping.SonicBuffersIndex;
2108:
2109: //
2110: // Index of the listhead that heads the list that the adapter
2111: // buffer descriptor belongs too.
2112: //
2113: INT ListHeadIndex = BufferDescriptor->Next;
2114:
2115:
2116: //
2117: // Put the adapter buffer back on the free list.
2118: //
2119:
2120: BufferDescriptor->Next = Adapter->SonicBufferListHeads[ListHeadIndex];
2121: Adapter->SonicBufferListHeads[ListHeadIndex] = SavedDescriptorMapping.SonicBuffersIndex;
2122:
2123: } else {
2124:
2125: //
2126: // Points to the current ndis buffer being walked.
2127: //
2128: PNDIS_BUFFER CurrentBuffer;
2129:
2130: //
2131: // Which map register we use for this buffer.
2132: //
2133: UINT CurMapRegister;
2134:
2135: //
2136: // The transmit is finished, so we can release
2137: // the physical mapping used for it.
2138: //
2139:
2140: NdisQueryPacket(
2141: OwningPacket,
2142: NULL,
2143: NULL,
2144: &CurrentBuffer,
2145: NULL
2146: );
2147:
2148: CurMapRegister = DescriptorIndex * SONIC_MAX_FRAGMENTS;
2149:
2150: while (CurrentBuffer) {
2151:
2152: NdisCompleteBufferPhysicalMapping(
2153: Adapter->NdisAdapterHandle,
2154: CurrentBuffer,
2155: CurMapRegister
2156: );
2157:
2158: ++CurMapRegister;
2159:
2160: NdisGetNextBuffer(
2161: CurrentBuffer,
2162: &CurrentBuffer
2163: );
2164:
2165: }
2166:
2167: }
2168:
2169:
2170: //
2171: // Now release the transmit descriptor, since we have
2172: // gotten all the information we need from it.
2173: //
2174:
2175: if (TransmitDescriptor == Adapter->LastTransmitDescriptor) {
2176:
2177: NextTransmitDescriptor = Adapter->TransmitDescriptorArea;
2178:
2179: } else {
2180:
2181: NextTransmitDescriptor = Adapter->TransmittingDescriptor + 1;
2182:
2183: }
2184:
2185: if (TransmitStatus &
2186: (SONIC_TCR_EXCESSIVE_DEFERRAL |
2187: SONIC_TCR_EXCESSIVE_COLLISIONS |
2188: SONIC_TCR_FIFO_UNDERRUN |
2189: SONIC_TCR_BYTE_COUNT_MISMATCH)) {
2190:
2191: //
2192: // If the packet completed with an abort state, then we
2193: // need to restart the transmitter unless we are the
2194: // last transmit queued up. We set CTDA to point after
2195: // this descriptor in any case.
2196: //
2197:
2198: #if DBG
2199: if (SonicDbg) {
2200: DbgPrint ("SONIC: Advancing CTDA after abort\n");
2201: }
2202: #endif
2203:
2204: SONIC_WRITE_PORT(Adapter, SONIC_CURR_TRANSMIT_DESCRIPTOR,
2205: SONIC_GET_LOW_PART_ADDRESS(
2206: NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical) +
2207: ((PUCHAR)NextTransmitDescriptor -
2208: (PUCHAR)Adapter->TransmitDescriptorArea))
2209: );
2210:
2211: if (Adapter->FirstUncommittedDescriptor != NextTransmitDescriptor) {
2212: #if DBG
2213: if (SonicDbg) {
2214: DbgPrint ("SONIC: Restarting transmit after abort\n");
2215: }
2216: #endif
2217: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND, SONIC_CR_TRANSMIT_PACKETS);
2218: }
2219:
2220: }
2221:
2222: Adapter->TransmittingDescriptor = NextTransmitDescriptor;
2223: Adapter->NumberOfAvailableDescriptors++;
2224:
2225: //
2226: // Check if the packet completed OK, and update statistics.
2227: //
2228:
2229: if (!(TransmitStatus & SONIC_TCR_PACKET_TRANSMITTED_OK)) {
2230:
2231: #if DBG
2232: if (SonicDbg) {
2233: DbgPrint("SONIC: Transmit failed: %lx\n", TransmitStatus);
2234: }
2235: #endif
2236: Successful = FALSE;
2237:
2238: ++Adapter->GeneralMandatory[GM_TRANSMIT_BAD];
2239:
2240: if (TransmitStatus & SONIC_TCR_EXCESSIVE_COLLISIONS) {
2241: ++Adapter->MediaOptional[MO_TRANSMIT_MAX_COLLISIONS];
2242: }
2243:
2244: if (TransmitStatus & SONIC_TCR_FIFO_UNDERRUN) {
2245: ++Adapter->MediaOptional[MO_TRANSMIT_UNDERRUN];
2246: }
2247:
2248: } else {
2249:
2250: INT Collisions = (TransmitStatus & SONIC_TCR_COLLISIONS_MASK) >> SONIC_TCR_COLLISIONS_SHIFT;
2251:
2252: Successful = TRUE;
2253:
2254: ++Adapter->GeneralMandatory[GM_TRANSMIT_GOOD];
2255:
2256: if (Collisions > 0) {
2257: if (Collisions == 1) {
2258: ++Adapter->MediaMandatory[MM_TRANSMIT_ONE_COLLISION];
2259: } else {
2260: ++Adapter->MediaMandatory[MM_TRANSMIT_MORE_COLLISIONS];
2261: }
2262: }
2263:
2264: if (TransmitStatus &
2265: (SONIC_TCR_DEFERRED_TRANSMISSION |
2266: SONIC_TCR_NO_CARRIER_SENSE |
2267: SONIC_TCR_CARRIER_LOST |
2268: SONIC_TCR_OUT_OF_WINDOW)) {
2269:
2270: if (TransmitStatus & SONIC_TCR_DEFERRED_TRANSMISSION) {
2271: ++Adapter->MediaOptional[MO_TRANSMIT_DEFERRED];
2272: }
2273: if (TransmitStatus & SONIC_TCR_NO_CARRIER_SENSE) {
2274: ++Adapter->MediaOptional[MO_TRANSMIT_HEARTBEAT_FAILURE];
2275: }
2276: if (TransmitStatus & SONIC_TCR_CARRIER_LOST) {
2277: ++Adapter->MediaOptional[MO_TRANSMIT_TIMES_CRS_LOST];
2278: }
2279: if (TransmitStatus & SONIC_TCR_OUT_OF_WINDOW) {
2280: ++Adapter->MediaOptional[MO_TRANSMIT_LATE_COLLISIONS];
2281: }
2282: }
2283:
2284: switch (Reserved->PacketType) {
2285:
2286: case SONIC_DIRECTED:
2287:
2288: ++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_TRANSMITS];
2289: SonicAddUlongToLargeInteger(
2290: &Adapter->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS],
2291: Reserved->PacketLength);
2292: break;
2293:
2294: case SONIC_MULTICAST:
2295:
2296: ++Adapter->GeneralOptionalFrameCount[GO_MULTICAST_TRANSMITS];
2297: SonicAddUlongToLargeInteger(
2298: &Adapter->GeneralOptionalByteCount[GO_MULTICAST_TRANSMITS],
2299: Reserved->PacketLength);
2300: break;
2301:
2302: case SONIC_BROADCAST:
2303:
2304: ++Adapter->GeneralOptionalFrameCount[GO_BROADCAST_TRANSMITS];
2305: SonicAddUlongToLargeInteger(
2306: &Adapter->GeneralOptionalByteCount[GO_BROADCAST_TRANSMITS],
2307: Reserved->PacketLength);
2308: break;
2309:
2310: }
2311:
2312: }
2313:
2314: //
2315: // Remove packet from queue.
2316: //
2317:
2318: if (Adapter->LastFinishTransmit == OwningPacket) {
2319:
2320: Adapter->FirstFinishTransmit = NULL;
2321: Adapter->LastFinishTransmit = NULL;
2322:
2323: } else {
2324:
2325: Adapter->FirstFinishTransmit = Reserved->Next;
2326: }
2327:
2328: #ifdef CHECK_DUP_SENDS
2329: {
2330: VOID SonicRemovePacketFromList(PSONIC_ADAPTER, PNDIS_PACKET);
2331: SonicRemovePacketFromList(Adapter, OwningPacket);
2332: }
2333: #endif
2334:
2335: //
2336: // Now check if the packet needs to be loopbacked as well. If not,
2337: // then we complete the send, else after it is loopbacked it will
2338: // get completed there.
2339: //
2340:
2341: NdisQueryPacket(
2342: OwningPacket,
2343: NULL,
2344: NULL,
2345: &FirstBuffer,
2346: NULL
2347: );
2348:
2349: //
2350: // Get VA of first buffer
2351: //
2352:
2353: NdisQueryBuffer(
2354: FirstBuffer,
2355: &BufferVirtualAddress,
2356: &BufferLength
2357: );
2358:
2359: if (!EthShouldAddressLoopBack(
2360: Adapter->FilterDB,
2361: BufferVirtualAddress
2362: )) {
2363:
2364: //
2365: // The binding that is submitting this packet.
2366: //
2367: PSONIC_OPEN Open =
2368: PSONIC_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
2369:
2370: //
2371: // Along with at least one reference because of the coming
2372: // indication there should be a reference because of the
2373: // packet to indicate.
2374: //
2375:
2376: ASSERT(Open->References > 1);
2377:
2378:
2379: NdisDprReleaseSpinLock(&Adapter->Lock);
2380:
2381: NdisCompleteSend(
2382: Open->NdisBindingContext,
2383: OwningPacket,
2384: ((Successful)?(NDIS_STATUS_SUCCESS):(NDIS_STATUS_FAILURE))
2385: );
2386:
2387: NdisDprAcquireSpinLock(&Adapter->Lock);
2388:
2389: //
2390: // We reduce the count by two to account for the fact
2391: // that we aren't indicating to the open and that one
2392: // less packet is owned by this open.
2393: //
2394:
2395: Open->References--;
2396:
2397: } else {
2398:
2399: //
2400: // Put it on the loopback queue.
2401: //
2402:
2403: SonicPutPacketOnLoopBack(
2404: Adapter,
2405: OwningPacket,
2406: Successful
2407: );
2408:
2409: }
2410:
2411: //
2412: // Since we've given back some ring entries we should
2413: // open the send stage if it was closed and we are not resetting.
2414: //
2415:
2416: if ((!Adapter->SendStageOpen) && (!Adapter->ResetInProgress)) {
2417:
2418: Adapter->SendStageOpen = TRUE;
2419:
2420: }
2421:
2422: Adapter->PacketsSinceLastInterrupt = 0;
2423:
2424: return TRUE;
2425: }
2426:
2427: }
2428:
2429: VOID
2430: SonicWakeUpDpc(
2431: IN PVOID SystemSpecific1,
2432: IN PVOID Context,
2433: IN PVOID SystemSpecific2,
2434: IN PVOID SystemSpecific3
2435: )
2436:
2437: /*++
2438:
2439: Routine Description:
2440:
2441: This DPC routine is queued every 5 seconds to check on the
2442: transmit descriptor ring. This is to solve problems where
2443: no status is written into the currently transmitting transmit
2444: descriptor, which hangs our transmit completion processing.
2445: If we detect this state, we simulate a transmit interrupt.
2446:
2447: Arguments:
2448:
2449: Context - Really a pointer to the adapter.
2450:
2451: Return Value:
2452:
2453: None.
2454:
2455: --*/
2456: {
2457: PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)Context;
2458: UINT DescriptorIndex;
2459: PSONIC_TRANSMIT_DESCRIPTOR TransmitDescriptor;
2460: USHORT TransmitStatus;
2461:
2462:
2463: UNREFERENCED_PARAMETER(SystemSpecific1);
2464: UNREFERENCED_PARAMETER(SystemSpecific2);
2465: UNREFERENCED_PARAMETER(SystemSpecific3);
2466:
2467: NdisDprAcquireSpinLock(&Adapter->Lock);
2468:
2469: if (Adapter->WakeUpTimeout) {
2470:
2471: //
2472: // We had a pending send the last time we ran,
2473: // and it has not been completed...we need to fake
2474: // its completion.
2475: //
2476:
2477: ASSERT (Adapter->TransmittingDescriptor !=
2478: Adapter->FirstUncommittedDescriptor);
2479:
2480: DescriptorIndex =
2481: Adapter->TransmittingDescriptor - Adapter->TransmitDescriptorArea;
2482:
2483: TransmitDescriptor = Adapter->TransmitDescriptorArea + DescriptorIndex;
2484: NdisReadRegisterUshort(&TransmitDescriptor->TransmitStatus, &TransmitStatus);
2485:
2486: if (!(TransmitStatus & SONIC_TCR_STATUS_MASK)) {
2487:
2488: NdisWriteRegisterUshort (&TransmitDescriptor->TransmitStatus,
2489: SONIC_TCR_PACKET_TRANSMITTED_OK);
2490:
2491: #if DBG
2492: DbgPrint ("SONIC: Woke up descriptor at %lx\n", TransmitDescriptor);
2493: #endif
2494:
2495: }
2496:
2497: Adapter->IsrValue |= SONIC_INT_PACKET_TRANSMITTED;
2498:
2499: Adapter->WakeUpTimeout = FALSE;
2500:
2501: NdisWriteErrorLogEntry(
2502: Adapter->NdisAdapterHandle,
2503: NDIS_ERROR_CODE_HARDWARE_FAILURE,
2504: 0
2505: );
2506:
2507: } else if (Adapter->TransmittingDescriptor !=
2508: Adapter->FirstUncommittedDescriptor) {
2509:
2510: DescriptorIndex =
2511: Adapter->TransmittingDescriptor - Adapter->TransmitDescriptorArea;
2512:
2513: TransmitDescriptor = Adapter->TransmitDescriptorArea + DescriptorIndex;
2514: NdisReadRegisterUshort(&TransmitDescriptor->TransmitStatus, &TransmitStatus);
2515:
2516: if (!(TransmitStatus & SONIC_TCR_STATUS_MASK)) {
2517:
2518: Adapter->WakeUpTimeout = TRUE;
2519:
2520: }
2521:
2522: }
2523:
2524: NdisDprReleaseSpinLock(&Adapter->Lock);
2525:
2526: //
2527: // Fire off another Dpc to execute after 5 seconds
2528: //
2529:
2530: NdisSetTimer(
2531: &Adapter->WakeUpTimer,
2532: 5000
2533: );
2534:
2535: }
2536:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.