Annotation of ntddk/src/network/sonic/interrup.c, revision 1.1.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.