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