Annotation of ntddk/src/network/sonic/interrup.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.