Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2165 lines
49 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. interrup.c
  5. Abstract:
  6. This is a part of the driver for the National Semiconductor Novell 2000
  7. Ethernet controller. It contains the interrupt-handling routines.
  8. This driver conforms to the NDIS 3.0 interface.
  9. The overall structure and much of the code is taken from
  10. the Lance NDIS driver by Tony Ercolano.
  11. Author:
  12. Sean Selitrennikoff (seanse) Dec-1991
  13. Environment:
  14. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  15. Revision History:
  16. Bob Noradki - Apr 93 - added piggyback interrupt code.
  17. Jameel Hyder- Dec 94 - Fixed initialization - part of the fixes from JimMcn
  18. --*/
  19. #include "precomp.h"
  20. //
  21. // On debug builds tell the compiler to keep the symbols for
  22. // internal functions, otw throw them out.
  23. //
  24. #if DBG
  25. #define STATIC
  26. #else
  27. #define STATIC static
  28. #endif
  29. INDICATE_STATUS
  30. Ne2000IndicatePacket(
  31. IN PNE2000_ADAPTER Adapter
  32. );
  33. VOID
  34. Ne2000DoNextSend(
  35. PNE2000_ADAPTER Adapter
  36. );
  37. //
  38. // This is used to pad short packets.
  39. //
  40. static UCHAR BlankBuffer[60] = " ";
  41. VOID
  42. Ne2000EnableInterrupt(
  43. IN NDIS_HANDLE MiniportAdapterContext
  44. )
  45. /*++
  46. Routine Description:
  47. This routine is used to turn on the interrupt mask.
  48. Arguments:
  49. Context - The adapter for the NE2000 to start.
  50. Return Value:
  51. None.
  52. --*/
  53. {
  54. PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);
  55. IF_LOG( Ne2000Log('P'); )
  56. CardUnblockInterrupts(Adapter);
  57. Adapter->InterruptsEnabled = TRUE;
  58. }
  59. VOID
  60. Ne2000DisableInterrupt(
  61. IN NDIS_HANDLE MiniportAdapterContext
  62. )
  63. /*++
  64. Routine Description:
  65. This routine is used to turn off the interrupt mask.
  66. Arguments:
  67. Context - The adapter for the NE2000 to start.
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);
  73. IF_LOG( Ne2000Log('p'); )
  74. CardBlockInterrupts(Adapter);
  75. Adapter->InterruptsEnabled = FALSE;
  76. }
  77. VOID
  78. Ne2000Isr(
  79. OUT PBOOLEAN InterruptRecognized,
  80. OUT PBOOLEAN QueueDpc,
  81. IN PVOID Context
  82. )
  83. /*++
  84. Routine Description:
  85. This is the interrupt handler which is registered with the operating
  86. system. If several are pending (i.e. transmit complete and receive),
  87. handle them all. Block new interrupts until all pending interrupts
  88. are handled.
  89. Arguments:
  90. InterruptRecognized - Boolean value which returns TRUE if the
  91. ISR recognizes the interrupt as coming from this adapter.
  92. QueueDpc - TRUE if a DPC should be queued.
  93. Context - pointer to the adapter object
  94. Return Value:
  95. None.
  96. --*/
  97. {
  98. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)Context);
  99. UCHAR InterruptStatus;
  100. UCHAR InterruptMask;
  101. IF_LOUD( DbgPrint("In Ne2000ISR\n");)
  102. IF_LOG( Ne2000Log('i'); )
  103. IF_VERY_LOUD( DbgPrint( "Ne2000InterruptHandler entered\n" );)
  104. if (!Adapter->InterruptsEnabled) {
  105. *InterruptRecognized = FALSE;
  106. *QueueDpc = FALSE;
  107. return;
  108. }
  109. //
  110. // Look to see if an interrupt has been asserted
  111. //
  112. CardGetInterruptStatus(Adapter, &InterruptStatus);
  113. if (InterruptStatus == 0) {
  114. *InterruptRecognized = FALSE;
  115. *QueueDpc = FALSE;
  116. return;
  117. }
  118. //
  119. // It appears to be our interrupt.
  120. // Force the INT signal from the chip low. When all
  121. // interrupts are acknowledged interrupts will be unblocked,
  122. //
  123. CardBlockInterrupts(Adapter);
  124. *InterruptRecognized = TRUE;
  125. *QueueDpc = TRUE;
  126. IF_LOG( Ne2000Log('I'); )
  127. return;
  128. }
  129. VOID
  130. Ne2000HandleInterrupt(
  131. IN NDIS_HANDLE MiniportAdapterContext
  132. )
  133. /*++
  134. Routine Description:
  135. This is the defered processing routine for interrupts. It
  136. reads from the Interrupt Status Register any outstanding
  137. interrupts and handles them.
  138. Arguments:
  139. MiniportAdapterContext - a handle to the adapter block.
  140. Return Value:
  141. NONE.
  142. --*/
  143. {
  144. //
  145. // The adapter to process
  146. //
  147. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)MiniportAdapterContext);
  148. //
  149. // The most recent port value read.
  150. //
  151. UCHAR InterruptStatus;
  152. //
  153. // The interrupt type currently being processed.
  154. //
  155. INTERRUPT_TYPE InterruptType;
  156. ULONG CardTestCount = 0;
  157. IF_LOUD( DbgPrint("==>IntDpc\n");)
  158. IF_LOG( Ne2000Log('d'); )
  159. //
  160. // Get the interrupt bits and save them.
  161. //
  162. CardGetInterruptStatus(Adapter, &InterruptStatus);
  163. Adapter->InterruptStatus |= InterruptStatus;
  164. if (InterruptStatus != ISR_EMPTY) {
  165. //
  166. // Acknowledge the interrupts
  167. //
  168. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS,
  169. InterruptStatus
  170. );
  171. }
  172. //
  173. // Return the type of the most important interrupt waiting on the card.
  174. // Order of importance is COUNTER, OVERFLOW, TRANSMIT,and RECEIVE.
  175. //
  176. InterruptType = CARD_GET_INTERRUPT_TYPE(Adapter, Adapter->InterruptStatus);
  177. //
  178. // InterruptType is used to dispatch to correct DPC and are then cleared
  179. //
  180. while (InterruptType != UNKNOWN) {
  181. //
  182. // Handle the interrupts
  183. //
  184. switch (InterruptType) {
  185. case COUNTER:
  186. //
  187. // One of the counters' MSB has been set, read in all
  188. // the values just to be sure (and then exit below).
  189. //
  190. IF_LOUD( DbgPrint("DPC got COUNTER\n");)
  191. SyncCardUpdateCounters((PVOID)Adapter);
  192. //
  193. // Clear the COUNTER interrupt bit
  194. //
  195. Adapter->InterruptStatus &= ~ISR_COUNTER;
  196. break;
  197. case OVERFLOW:
  198. //
  199. // Overflow interrupts are handled as part of a receive interrupt,
  200. // so set a flag and then pretend to be a receive, in case there
  201. // is no receive already being handled.
  202. //
  203. Adapter->BufferOverflow = TRUE;
  204. IF_LOUD( DbgPrint("Overflow Int\n"); )
  205. IF_VERY_LOUD( DbgPrint(" overflow interrupt\n"); )
  206. //
  207. // Clear the OVERFLOW interrupt bit
  208. //
  209. Adapter->InterruptStatus &= ~ISR_OVERFLOW;
  210. case RECEIVE:
  211. IF_LOG( Ne2000Log('R'); )
  212. IF_LOUD( DbgPrint("DPC got RCV\n"); )
  213. //
  214. // For receives, call this to handle the receive
  215. //
  216. if (Ne2000RcvDpc(Adapter)) {
  217. //
  218. // Clear the RECEIVE interrupt bits
  219. //
  220. Adapter->InterruptStatus &= ~(ISR_RCV | ISR_RCV_ERR);
  221. }
  222. IF_LOG( Ne2000Log('r'); )
  223. if (!(Adapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR)))
  224. break;
  225. case TRANSMIT:
  226. IF_LOG( Ne2000Log('X'); )
  227. ASSERT(!Adapter->OverflowRestartXmitDpc);
  228. //
  229. // Get the status of the transmit
  230. //
  231. SyncCardGetXmitStatus((PVOID)Adapter);
  232. //
  233. // We are no longer expecting an interrupts, as
  234. // we just got it.
  235. //
  236. Adapter->TransmitInterruptPending = FALSE;
  237. IF_LOUD( DbgPrint( "DPC got XMIT\n"); )
  238. //
  239. // Handle transmit errors
  240. //
  241. if (Adapter->InterruptStatus & ISR_XMIT_ERR) {
  242. OctogmetusceratorRevisited(Adapter);
  243. }
  244. //
  245. // Handle the transmit
  246. //
  247. if (Adapter->InterruptStatus & ISR_XMIT) {
  248. Ne2000XmitDpc(Adapter);
  249. }
  250. //
  251. // Clear the TRANSMIT interrupt bits
  252. //
  253. Adapter->InterruptStatus &= ~(ISR_XMIT | ISR_XMIT_ERR);
  254. break;
  255. default:
  256. IF_LOUD( DbgPrint("unhandled interrupt type: %x\n", InterruptType); )
  257. break;
  258. }
  259. //
  260. // Get any new interrupts
  261. //
  262. CardGetInterruptStatus(Adapter, &InterruptStatus);
  263. if ((InterruptStatus == 0xff) && (++CardTestCount > 10)) {
  264. //
  265. // this card appears dead
  266. //
  267. break;
  268. }
  269. if (InterruptStatus != ISR_EMPTY) {
  270. //
  271. // Acknowledge the interrupt
  272. //
  273. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS,
  274. InterruptStatus
  275. );
  276. }
  277. //
  278. // Save the interrupt reasons
  279. //
  280. Adapter->InterruptStatus |= InterruptStatus;
  281. //
  282. // Get next interrupt to process
  283. //
  284. InterruptType = CARD_GET_INTERRUPT_TYPE(Adapter, Adapter->InterruptStatus);
  285. }
  286. if (Adapter->InterruptMode == NdisInterruptLevelSensitive) {
  287. //
  288. // Re-enable the interrupt (disabled in Isr)
  289. //
  290. NdisMSynchronizeWithInterrupt(&Adapter->Interrupt,
  291. Ne2000EnableInterrupt,
  292. Adapter);
  293. }
  294. IF_LOG( Ne2000Log('D'); )
  295. IF_LOUD( DbgPrint("<==IntDpc\n"); )
  296. }
  297. BOOLEAN
  298. Ne2000RcvDpc(
  299. IN PNE2000_ADAPTER Adapter
  300. )
  301. /*++
  302. Routine Description:
  303. This is the real interrupt handler for receive/overflow interrupt.
  304. Called when a receive interrupt is received. It first indicates
  305. all packets on the card and finally indicates ReceiveComplete().
  306. Arguments:
  307. Adapter - Pointer to the adapter block.
  308. Return Value:
  309. TRUE if done with all receives, else FALSE.
  310. --*/
  311. {
  312. //
  313. // Use to restart a transmit if a buffer overflow occured
  314. // during a transmission
  315. //
  316. BOOLEAN TransmitInterruptWasPending = FALSE;
  317. //
  318. // Status of a received packet.
  319. //
  320. INDICATE_STATUS IndicateStatus = INDICATE_OK;
  321. //
  322. // Flag to tell when the receive process is complete
  323. //
  324. BOOLEAN Done = TRUE;
  325. IF_LOUD( DbgPrint( "Ne2000RcvDpc entered\n" );)
  326. //
  327. // Default to not indicating NdisMEthIndicateReceiveComplete
  328. //
  329. Adapter->IndicateReceiveDone = FALSE;
  330. //
  331. // At this point, receive interrupts are disabled.
  332. //
  333. SyncCardGetCurrent((PVOID)Adapter);
  334. //
  335. // Handle a buffer overflow
  336. //
  337. if (Adapter->BufferOverflow) {
  338. SyncCardHandleOverflow(Adapter);
  339. #if DBG
  340. if (Adapter->OverflowRestartXmitDpc) {
  341. IF_LOG( Ne2000Log('O');)
  342. IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:RcvDpc\n"); )
  343. }
  344. #endif // DBG
  345. }
  346. //
  347. // Loop
  348. //
  349. while (TRUE)
  350. {
  351. if ((Adapter->InterruptStatus & ISR_RCV_ERR) &&
  352. !Adapter->BufferOverflow
  353. )
  354. {
  355. IF_LOUD( DbgPrint ("RCV_ERR, IR=%x\n",Adapter->InterruptStatus); )
  356. //
  357. // Skip this packet
  358. //
  359. SyncCardGetCurrent((PVOID)Adapter);
  360. Adapter->NicNextPacket = Adapter->Current;
  361. CardSetBoundary(Adapter);
  362. break;
  363. }
  364. if (Adapter->Current == Adapter->NicNextPacket) {
  365. //
  366. // Acknowledge previous packet before the check for new ones,
  367. // then read in the Current register.
  368. // The card register Current used to point to
  369. // the end of the packet just received; read
  370. // the new value off the card and see if it
  371. // still does.
  372. //
  373. // This will store the value in Adapter->Current and acknowledge
  374. // the receive interrupt.
  375. //
  376. //
  377. SyncCardGetCurrent((PVOID)Adapter);
  378. if (Adapter->Current == Adapter->NicNextPacket) {
  379. //
  380. // End of Loop -- no more packets
  381. //
  382. break;
  383. }
  384. }
  385. //
  386. // A packet was found on the card, indicate it.
  387. //
  388. Adapter->ReceivePacketCount++;
  389. //
  390. // Verify packet is not corrupt
  391. //
  392. if (Ne2000PacketOK(Adapter)) {
  393. ULONG PacketLen;
  394. PacketLen = (Adapter->PacketHeader[2]) + ((Adapter->PacketHeader[3])*256) - 4;
  395. PacketLen = (PacketLen < Adapter->MaxLookAhead)?
  396. PacketLen :
  397. Adapter->MaxLookAhead;
  398. //
  399. // Copy up the lookahead data
  400. //
  401. if (!CardCopyUp(Adapter,
  402. Adapter->Lookahead,
  403. Adapter->PacketHeaderLoc,
  404. PacketLen + NE2000_HEADER_SIZE
  405. )) {
  406. //
  407. // Failed! Skip this packet
  408. //
  409. IndicateStatus = SKIPPED;
  410. } else {
  411. //
  412. // Indicate the packet to the wrapper
  413. //
  414. IndicateStatus = Ne2000IndicatePacket(Adapter);
  415. if (IndicateStatus != CARD_BAD) {
  416. Adapter->FramesRcvGood++;
  417. }
  418. }
  419. } else {
  420. //
  421. // Packet is corrupt, skip it.
  422. //
  423. IF_LOUD( DbgPrint("Packet did not pass OK check\n"); )
  424. IndicateStatus = SKIPPED;
  425. }
  426. //
  427. // Handle when the card is unable to indicate good packets
  428. //
  429. if (IndicateStatus == CARD_BAD) {
  430. #if DBG
  431. IF_NE2000DEBUG( NE2000_DEBUG_CARD_BAD ) {
  432. DbgPrint("R: <%x %x %x %x> C %x N %x\n",
  433. Adapter->PacketHeader[0],
  434. Adapter->PacketHeader[1],
  435. Adapter->PacketHeader[2],
  436. Adapter->PacketHeader[3],
  437. Adapter->Current,
  438. Adapter->NicNextPacket);
  439. }
  440. #endif
  441. IF_LOG( Ne2000Log('W');)
  442. //
  443. // Start off with receive interrupts disabled.
  444. //
  445. Adapter->NicInterruptMask = IMR_XMIT | IMR_XMIT_ERR | IMR_OVERFLOW;
  446. //
  447. // Reset the adapter
  448. //
  449. CardReset(Adapter);
  450. //
  451. // Since the adapter was just reset, stop indicating packets.
  452. //
  453. break;
  454. }
  455. //
  456. // (IndicateStatus == SKIPPED) is OK, just move to next packet.
  457. //
  458. if (IndicateStatus == SKIPPED) {
  459. SyncCardGetCurrent((PVOID)Adapter);
  460. Adapter->NicNextPacket = Adapter->Current;
  461. } else {
  462. //
  463. // Free the space used by packet on card.
  464. //
  465. Adapter->NicNextPacket = Adapter->PacketHeader[1];
  466. }
  467. //
  468. // This will set BOUNDARY to one behind NicNextPacket.
  469. //
  470. CardSetBoundary(Adapter);
  471. if (Adapter->ReceivePacketCount > 10) {
  472. //
  473. // Give transmit interrupts a chance
  474. //
  475. Done = FALSE;
  476. Adapter->ReceivePacketCount = 0;
  477. break;
  478. }
  479. }
  480. //
  481. // See if a buffer overflow occured previously.
  482. //
  483. if (Adapter->BufferOverflow) {
  484. //
  485. // ... and set a flag to restart the card after receiving
  486. // a packet.
  487. //
  488. Adapter->BufferOverflow = FALSE;
  489. SyncCardAcknowledgeOverflow(Adapter);
  490. //
  491. // Undo loopback mode
  492. //
  493. CardStart(Adapter);
  494. IF_LOG( Ne2000Log('f'); )
  495. //
  496. // Check if transmission needs to be queued or not
  497. //
  498. if (Adapter->OverflowRestartXmitDpc && Adapter->CurBufXmitting != -1) {
  499. IF_LOUD( DbgPrint("queueing xmit in RcvDpc\n"); )
  500. Adapter->OverflowRestartXmitDpc = FALSE;
  501. Adapter->TransmitInterruptPending = TRUE;
  502. IF_LOG( Ne2000Log('5'); )
  503. CardStartXmit(Adapter);
  504. }
  505. }
  506. //
  507. // Finally, indicate ReceiveComplete to all protocols which received packets
  508. //
  509. if (Adapter->IndicateReceiveDone) {
  510. NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
  511. Adapter->IndicateReceiveDone = FALSE;
  512. }
  513. IF_LOUD( DbgPrint( "Ne2000RcvDpc exiting\n" );)
  514. return (Done);
  515. }
  516. VOID
  517. Ne2000XmitDpc(
  518. IN PNE2000_ADAPTER Adapter
  519. )
  520. /*++
  521. Routine Description:
  522. This is the real interrupt handler for a transmit complete interrupt.
  523. Ne2000Dpc queues a call to it.
  524. Called after a transmit complete interrupt. It checks the
  525. status of the transmission, completes the send if needed,
  526. and sees if any more packets are ready to be sent.
  527. Arguments:
  528. Adapter - Pointer to the adapter block.
  529. Return Value:
  530. None.
  531. --*/
  532. {
  533. //
  534. // Packet that was transmitted
  535. //
  536. PNDIS_PACKET Packet;
  537. //
  538. // Status of the send
  539. //
  540. NDIS_STATUS Status;
  541. //
  542. // Length of the packet sent
  543. //
  544. ULONG Len;
  545. //
  546. // Temporary loopnig variable
  547. //
  548. UINT i;
  549. IF_VERY_LOUD( DbgPrint( "Ne2000XmitDpc entered\n" );)
  550. //
  551. // Verify that we are transmitting a packet
  552. //
  553. if ( Adapter->CurBufXmitting == -1 ) {
  554. #if DBG
  555. DbgPrint( "Ne2000HandleXmitComplete called with nothing transmitting!\n" );
  556. #endif
  557. NdisWriteErrorLogEntry(
  558. Adapter->MiniportAdapterHandle,
  559. NDIS_ERROR_CODE_DRIVER_FAILURE,
  560. 1,
  561. NE2000_ERRMSG_HANDLE_XMIT_COMPLETE
  562. );
  563. return;
  564. }
  565. IF_LOG( Ne2000Log('C');)
  566. //
  567. // Get the status of the transmit
  568. //
  569. SyncCardGetXmitStatus((PVOID)Adapter);
  570. //
  571. // Statistics
  572. //
  573. if (Adapter->XmitStatus & TSR_XMIT_OK) {
  574. Adapter->FramesXmitGood++;
  575. Status = NDIS_STATUS_SUCCESS;
  576. } else {
  577. Adapter->FramesXmitBad++;
  578. Status = NDIS_STATUS_FAILURE;
  579. }
  580. //
  581. // Mark the current transmit as done.
  582. //
  583. Len = (Adapter->PacketLens[Adapter->CurBufXmitting] + 255) >> 8;
  584. ASSERT (Len != 0);
  585. //
  586. // Free the transmit buffers
  587. //
  588. for (i = Adapter->CurBufXmitting; i < Adapter->CurBufXmitting + Len; i++) {
  589. Adapter->BufferStatus[i] = EMPTY;
  590. }
  591. //
  592. // Set the next buffer to start transmitting.
  593. //
  594. Adapter->NextBufToXmit += Len;
  595. if (Adapter->NextBufToXmit == MAX_XMIT_BUFS) {
  596. Adapter->NextBufToXmit = 0;
  597. }
  598. if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY &&
  599. Adapter->NextBufToFill != Adapter->NextBufToXmit) {
  600. Adapter->NextBufToXmit = 0;
  601. }
  602. //
  603. // Remove the packet from the outstanding packet list.
  604. //
  605. Packet = Adapter->Packets[Adapter->CurBufXmitting];
  606. Adapter->Packets[Adapter->CurBufXmitting] = (PNDIS_PACKET)NULL;
  607. //
  608. // See what to do next.
  609. //
  610. switch (Adapter->BufferStatus[Adapter->NextBufToXmit]) {
  611. case FULL:
  612. //
  613. // The next packet is ready to go -- only happens with
  614. // more than one transmit buffer.
  615. //
  616. IF_LOUD( DbgPrint( " next packet ready to go\n" );)
  617. //
  618. // Start the transmission and check for more.
  619. //
  620. Adapter->CurBufXmitting = Adapter->NextBufToXmit;
  621. IF_LOG( Ne2000Log('2');)
  622. //
  623. // This is used to check if stopping the chip prevented
  624. // a transmit complete interrupt from coming through (it
  625. // is cleared in the ISR if a transmit DPC is queued).
  626. //
  627. Adapter->TransmitInterruptPending = TRUE;
  628. IF_LOG( Ne2000Log('6'); )
  629. CardStartXmit(Adapter);
  630. break;
  631. case EMPTY:
  632. //
  633. // No packet is ready to transmit.
  634. //
  635. IF_LOUD( DbgPrint( " next packet empty\n" );)
  636. Adapter->CurBufXmitting = (XMIT_BUF)-1;
  637. break;
  638. }
  639. //
  640. // Start next send
  641. //
  642. Ne2000DoNextSend(Adapter);
  643. IF_VERY_LOUD( DbgPrint( "Ne2000XmitDpc exiting\n" );)
  644. }
  645. BOOLEAN
  646. Ne2000PacketOK(
  647. IN PNE2000_ADAPTER Adapter
  648. )
  649. /*++
  650. Routine Description:
  651. Reads a packet off the card -- checking if the CRC is good. This is
  652. a workaround for a bug where bytes in the data portion of the packet
  653. are shifted either left or right by two in some weird 8390 cases.
  654. This routine is a combination of Ne2000TransferData (to copy up data
  655. from the card), CardCalculateCrc and CardCalculatePacketCrc.
  656. Arguments:
  657. Adapter - pointer to the adapter block.
  658. Return Value:
  659. TRUE if the packet seems ok, else false.
  660. --*/
  661. {
  662. //
  663. // Length of the packet
  664. //
  665. UINT PacketLen;
  666. //
  667. // Guess at where the packet is located
  668. //
  669. PUCHAR PacketLoc;
  670. //
  671. // Header Validation Variables
  672. //
  673. BOOLEAN FrameAlign;
  674. PUCHAR PacketRcvStatus;
  675. PUCHAR NextPacket;
  676. PUCHAR PacketLenLo;
  677. PUCHAR PacketLenHi;
  678. PUCHAR ReceiveDestAddrLo;
  679. UINT FrameAlignCount;
  680. UCHAR OldPacketLenHi;
  681. UCHAR TempPacketHeader[6];
  682. PUCHAR BeginPacketHeader;
  683. //
  684. // First copy up the four-byte header the card attaches
  685. // plus first two bytes of the data packet (which contain
  686. // the destination address of the packet). We use the extra
  687. // two bytes in case the packet was shifted right 1 or 2 bytes
  688. //
  689. PacketLoc = Adapter->PageStart +
  690. 256*(Adapter->NicNextPacket-Adapter->NicPageStart);
  691. if (!CardCopyUp(Adapter, TempPacketHeader, PacketLoc, 6)) {
  692. return FALSE;
  693. }
  694. PacketLoc += 4;
  695. //
  696. // Validate the header
  697. //
  698. FrameAlignCount = 0;
  699. BeginPacketHeader = TempPacketHeader;
  700. //
  701. // Sometimes the Ne2000 will misplace a packet and shift the
  702. // entire packet and header by a byte, either up by 1 or 2 bytes.
  703. // This loop will look for the packet in the expected place,
  704. // and then shift up in an effort to find the packet.
  705. //
  706. do {
  707. //
  708. // Set where we think the packet is
  709. //
  710. PacketRcvStatus = BeginPacketHeader;
  711. NextPacket = BeginPacketHeader + 1;
  712. PacketLenLo = BeginPacketHeader + 2;
  713. PacketLenHi = BeginPacketHeader + 3;
  714. OldPacketLenHi = *PacketLenHi;
  715. ReceiveDestAddrLo = BeginPacketHeader + 4;
  716. FrameAlign = FALSE;
  717. //
  718. // Check if the status makes sense as is.
  719. //
  720. if (*PacketRcvStatus & 0x05E){
  721. FrameAlign = TRUE;
  722. } else if ((*PacketRcvStatus & RSR_MULTICAST) // If a multicast packet
  723. && (!FrameAlignCount) // and hasn't been aligned
  724. && !(*ReceiveDestAddrLo & 1) // and lsb is set on dest addr
  725. ){
  726. FrameAlign = TRUE;
  727. } else {
  728. //
  729. // Compare high and low address bytes. If the same, the low
  730. // byte may have been copied into the high byte.
  731. //
  732. if (*PacketLenLo == *PacketLenHi){
  733. //
  734. // Save the old packetlenhi
  735. //
  736. OldPacketLenHi = *PacketLenHi;
  737. //
  738. // Compute new packet length
  739. //
  740. *PacketLenHi = *NextPacket - Adapter->NicNextPacket - 1;
  741. if (*PacketLenHi < 0) {
  742. *PacketLenHi = (Adapter->NicPageStop - Adapter->NicNextPacket) +
  743. (*NextPacket - Adapter->NicPageStart) - 1;
  744. }
  745. if (*PacketLenLo > 0xFC) {
  746. *PacketLenHi++;
  747. }
  748. }
  749. PacketLen = (*PacketLenLo) + ((*PacketLenHi)*256) - 4;
  750. //
  751. // Does it make sense?
  752. //
  753. if ((PacketLen > 1514) || (PacketLen < 60)){
  754. //
  755. // Bad length. Restore the old packetlenhi
  756. //
  757. *PacketLenHi = OldPacketLenHi;
  758. FrameAlign = TRUE;
  759. }
  760. //
  761. // Did we recover the frame?
  762. //
  763. if (!FrameAlign && ((*NextPacket < Adapter->NicPageStart) ||
  764. (*NextPacket > Adapter->NicPageStop))) {
  765. IF_LOUD( DbgPrint ("Packet address invalid in HeaderValidation\n"); )
  766. FrameAlign = TRUE;
  767. }
  768. }
  769. //
  770. // FrameAlignment - if first time through, shift packetheader right 1 or 2 bytes.
  771. // If second time through, shift it back to where it was and let it through.
  772. // This compensates for a known bug in the 8390D chip.
  773. //
  774. if (FrameAlign){
  775. switch (FrameAlignCount){
  776. case 0:
  777. BeginPacketHeader++;
  778. PacketLoc++;
  779. if (!Adapter->EightBitSlot){
  780. BeginPacketHeader++;
  781. PacketLoc++;
  782. }
  783. break;
  784. case 1:
  785. BeginPacketHeader--;
  786. PacketLoc--;
  787. if (!Adapter->EightBitSlot){
  788. BeginPacketHeader--;
  789. PacketLoc--;
  790. }
  791. break;
  792. }
  793. FrameAlignCount++;
  794. }
  795. } while ( (FrameAlignCount < 2) && FrameAlign );
  796. //
  797. // Now grab the packet header information
  798. //
  799. Adapter->PacketHeader[0] = *BeginPacketHeader;
  800. BeginPacketHeader++;
  801. Adapter->PacketHeader[1] = *BeginPacketHeader;
  802. BeginPacketHeader++;
  803. Adapter->PacketHeader[2] = *BeginPacketHeader;
  804. BeginPacketHeader++;
  805. Adapter->PacketHeader[3] = *BeginPacketHeader;
  806. //
  807. // Packet length is in bytes 3 and 4 of the header.
  808. //
  809. Adapter->PacketHeaderLoc = PacketLoc;
  810. PacketLen = (Adapter->PacketHeader[2]) + ((Adapter->PacketHeader[3])*256) - 4;
  811. //
  812. // Sanity check the packet
  813. //
  814. if ((PacketLen > 1514) || (PacketLen < 60)){
  815. if ((Adapter->PacketHeader[1] < Adapter->NicPageStart) ||
  816. (Adapter->PacketHeader[1] > Adapter->NicPageStop)) {
  817. //
  818. // Return TRUE here since IndicatePacket will notice the error
  819. // and handle it correctly.
  820. //
  821. return(TRUE);
  822. }
  823. return(FALSE);
  824. }
  825. return(TRUE);
  826. }
  827. INDICATE_STATUS
  828. Ne2000IndicatePacket(
  829. IN PNE2000_ADAPTER Adapter
  830. )
  831. /*++
  832. Routine Description:
  833. Indicates the first packet on the card to the protocols.
  834. NOTE: For MP, non-x86 architectures, this assumes that the packet has been
  835. read from the card and into Adapter->PacketHeader and Adapter->Lookahead.
  836. NOTE: For UP x86 systems this assumes that the packet header has been
  837. read into Adapter->PacketHeader and the minimal lookahead stored in
  838. Adapter->Lookahead
  839. Arguments:
  840. Adapter - pointer to the adapter block.
  841. Return Value:
  842. CARD_BAD if the card should be reset;
  843. INDICATE_OK otherwise.
  844. --*/
  845. {
  846. //
  847. // Length of the packet
  848. //
  849. UINT PacketLen;
  850. //
  851. // Length of the lookahead buffer
  852. //
  853. UINT IndicateLen;
  854. //
  855. // Variables for checking if the packet header looks valid
  856. //
  857. UCHAR PossibleNextPacket1, PossibleNextPacket2;
  858. //
  859. // Check if the next packet byte agress with the length, as
  860. // described on p. A-3 of the Etherlink II Technical Reference.
  861. // The start of the packet plus the MSB of the length must
  862. // be equal to the start of the next packet minus one or two.
  863. // Otherwise the header is considered corrupted, and the
  864. // card must be reset.
  865. //
  866. PossibleNextPacket1 =
  867. Adapter->NicNextPacket + Adapter->PacketHeader[3] + (UCHAR)1;
  868. if (PossibleNextPacket1 >= Adapter->NicPageStop) {
  869. PossibleNextPacket1 -= (Adapter->NicPageStop - Adapter->NicPageStart);
  870. }
  871. if (PossibleNextPacket1 != Adapter->PacketHeader[1]) {
  872. PossibleNextPacket2 = PossibleNextPacket1+(UCHAR)1;
  873. if (PossibleNextPacket2 == Adapter->NicPageStop) {
  874. PossibleNextPacket2 = Adapter->NicPageStart;
  875. }
  876. if (PossibleNextPacket2 != Adapter->PacketHeader[1]) {
  877. IF_LOUD( DbgPrint("First CARD_BAD check failed\n"); )
  878. return SKIPPED;
  879. }
  880. }
  881. //
  882. // Check that the Next is valid
  883. //
  884. if ((Adapter->PacketHeader[1] < Adapter->NicPageStart) ||
  885. (Adapter->PacketHeader[1] > Adapter->NicPageStop)) {
  886. IF_LOUD( DbgPrint("Second CARD_BAD check failed\n"); )
  887. return(SKIPPED);
  888. }
  889. //
  890. // Sanity check the length
  891. //
  892. PacketLen = Adapter->PacketHeader[2] + Adapter->PacketHeader[3]*256 - 4;
  893. if (PacketLen > 1514) {
  894. IF_LOUD( DbgPrint("Third CARD_BAD check failed\n"); )
  895. return(SKIPPED);
  896. }
  897. #if DBG
  898. IF_NE2000DEBUG( NE2000_DEBUG_WORKAROUND1 ) {
  899. //
  900. // Now check for the high order 2 bits being set, as described
  901. // on page A-2 of the Etherlink II Technical Reference. If either
  902. // of the two high order bits is set in the receive status byte
  903. // in the packet header, the packet should be skipped (but
  904. // the adapter does not need to be reset).
  905. //
  906. if (Adapter->PacketHeader[0] & (RSR_DISABLED|RSR_DEFERRING)) {
  907. IF_LOUD (DbgPrint("H");)
  908. return SKIPPED;
  909. }
  910. }
  911. #endif
  912. //
  913. // Lookahead amount to indicate
  914. //
  915. IndicateLen = (PacketLen > (Adapter->MaxLookAhead + NE2000_HEADER_SIZE)) ?
  916. (Adapter->MaxLookAhead + NE2000_HEADER_SIZE) :
  917. PacketLen;
  918. //
  919. // Indicate packet
  920. //
  921. Adapter->PacketLen = PacketLen;
  922. if (IndicateLen < NE2000_HEADER_SIZE) {
  923. //
  924. // Runt Packet
  925. //
  926. NdisMEthIndicateReceive(
  927. Adapter->MiniportAdapterHandle,
  928. (NDIS_HANDLE)Adapter,
  929. (PCHAR)(Adapter->Lookahead),
  930. IndicateLen,
  931. NULL,
  932. 0,
  933. 0
  934. );
  935. } else {
  936. NdisMEthIndicateReceive(
  937. Adapter->MiniportAdapterHandle,
  938. (NDIS_HANDLE)Adapter,
  939. (PCHAR)(Adapter->Lookahead),
  940. NE2000_HEADER_SIZE,
  941. (PCHAR)(Adapter->Lookahead) + NE2000_HEADER_SIZE,
  942. IndicateLen - NE2000_HEADER_SIZE,
  943. PacketLen - NE2000_HEADER_SIZE
  944. );
  945. }
  946. Adapter->IndicateReceiveDone = TRUE;
  947. return INDICATE_OK;
  948. }
  949. NDIS_STATUS
  950. Ne2000TransferData(
  951. OUT PNDIS_PACKET Packet,
  952. OUT PUINT BytesTransferred,
  953. IN NDIS_HANDLE MiniportAdapterContext,
  954. IN NDIS_HANDLE MiniportReceiveContext,
  955. IN UINT ByteOffset,
  956. IN UINT BytesToTransfer
  957. )
  958. /*++
  959. Routine Description:
  960. A protocol calls the Ne2000TransferData request (indirectly via
  961. NdisTransferData) from within its Receive event handler
  962. to instruct the driver to copy the contents of the received packet
  963. a specified packet buffer.
  964. Arguments:
  965. MiniportAdapterContext - Context registered with the wrapper, really
  966. a pointer to the adapter.
  967. MiniportReceiveContext - The context value passed by the driver on its call
  968. to NdisMEthIndicateReceive. The driver can use this value to determine
  969. which packet, on which adapter, is being received.
  970. ByteOffset - An unsigned integer specifying the offset within the
  971. received packet at which the copy is to begin. If the entire packet
  972. is to be copied, ByteOffset must be zero.
  973. BytesToTransfer - An unsigned integer specifying the number of bytes
  974. to copy. It is legal to transfer zero bytes; this has no effect. If
  975. the sum of ByteOffset and BytesToTransfer is greater than the size
  976. of the received packet, then the remainder of the packet (starting from
  977. ByteOffset) is transferred, and the trailing portion of the receive
  978. buffer is not modified.
  979. Packet - A pointer to a descriptor for the packet storage into which
  980. the MAC is to copy the received packet.
  981. BytesTransfered - A pointer to an unsigned integer. The MAC writes
  982. the actual number of bytes transferred into this location. This value
  983. is not valid if the return status is STATUS_PENDING.
  984. Notes:
  985. - The MacReceiveContext will be a pointer to the open block for
  986. the packet.
  987. --*/
  988. {
  989. //
  990. // Variables for the number of bytes to copy, how much can be
  991. // copied at this moment, and the total number of bytes to copy.
  992. //
  993. UINT BytesLeft, BytesNow, BytesWanted;
  994. //
  995. // Current NDIS_BUFFER to copy into
  996. //
  997. PNDIS_BUFFER CurBuffer;
  998. //
  999. // Virtual address of the buffer.
  1000. //
  1001. XMIT_BUF NextBufToXmit;
  1002. PUCHAR BufStart;
  1003. //
  1004. // Length and offset into the buffer.
  1005. //
  1006. UINT BufLen, BufOff;
  1007. //
  1008. // The adapter to transfer from.
  1009. //
  1010. PNE2000_ADAPTER Adapter = ((PNE2000_ADAPTER)MiniportReceiveContext);
  1011. IF_LOG( Ne2000Log('t');)
  1012. //
  1013. // Add the packet header onto the offset.
  1014. //
  1015. ByteOffset += NE2000_HEADER_SIZE;
  1016. //
  1017. // See how much data there is to transfer.
  1018. //
  1019. if (ByteOffset+BytesToTransfer > Adapter->PacketLen) {
  1020. if (Adapter->PacketLen < ByteOffset) {
  1021. *BytesTransferred = 0;
  1022. IF_LOG( Ne2000Log('T');)
  1023. return(NDIS_STATUS_FAILURE);
  1024. }
  1025. BytesWanted = Adapter->PacketLen - ByteOffset;
  1026. } else {
  1027. BytesWanted = BytesToTransfer;
  1028. }
  1029. //
  1030. // Set the number of bytes left to transfer
  1031. //
  1032. BytesLeft = BytesWanted;
  1033. {
  1034. //
  1035. // Address on the adapter to copy from
  1036. //
  1037. PUCHAR CurCardLoc;
  1038. //
  1039. // Copy data from the card -- it is not completely stored in the
  1040. // adapter structure.
  1041. //
  1042. // Determine where the copying should start.
  1043. //
  1044. CurCardLoc = Adapter->PacketHeaderLoc + ByteOffset;
  1045. if (CurCardLoc > Adapter->PageStop) {
  1046. CurCardLoc = CurCardLoc - (Adapter->PageStop - Adapter->PageStart);
  1047. }
  1048. //
  1049. // Get location to copy into
  1050. //
  1051. NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
  1052. NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen);
  1053. BufOff = 0;
  1054. //
  1055. // Loop, filling each buffer in the packet until there
  1056. // are no more buffers or the data has all been copied.
  1057. //
  1058. while (BytesLeft > 0) {
  1059. //
  1060. // See how much data to read into this buffer.
  1061. //
  1062. if ((BufLen-BufOff) > BytesLeft) {
  1063. BytesNow = BytesLeft;
  1064. } else {
  1065. BytesNow = (BufLen - BufOff);
  1066. }
  1067. //
  1068. // See if the data for this buffer wraps around the end
  1069. // of the receive buffers (if so filling this buffer
  1070. // will use two iterations of the loop).
  1071. //
  1072. if (CurCardLoc + BytesNow > Adapter->PageStop) {
  1073. BytesNow = (UINT)(Adapter->PageStop - CurCardLoc);
  1074. }
  1075. //
  1076. // Copy up the data.
  1077. //
  1078. if (!CardCopyUp(Adapter, BufStart+BufOff, CurCardLoc, BytesNow)) {
  1079. *BytesTransferred = BytesWanted - BytesLeft;
  1080. NdisWriteErrorLogEntry(
  1081. Adapter->MiniportAdapterHandle,
  1082. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1083. 1,
  1084. 0x2
  1085. );
  1086. return(NDIS_STATUS_FAILURE);
  1087. }
  1088. //
  1089. // Update offsets and counts
  1090. //
  1091. CurCardLoc += BytesNow;
  1092. BytesLeft -= BytesNow;
  1093. //
  1094. // Is the transfer done now?
  1095. //
  1096. if (BytesLeft == 0) {
  1097. break;
  1098. }
  1099. //
  1100. // Wrap around the end of the receive buffers?
  1101. //
  1102. if (CurCardLoc == Adapter->PageStop) {
  1103. CurCardLoc = Adapter->PageStart;
  1104. }
  1105. //
  1106. // Was the end of this packet buffer reached?
  1107. //
  1108. BufOff += BytesNow;
  1109. if (BufOff == BufLen) {
  1110. NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1111. if (CurBuffer == (PNDIS_BUFFER)NULL) {
  1112. break;
  1113. }
  1114. NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen);
  1115. BufOff = 0;
  1116. }
  1117. }
  1118. *BytesTransferred = BytesWanted - BytesLeft;
  1119. //
  1120. // Did a transmit complete while we were doing what we were doing?
  1121. //
  1122. if (!Adapter->BufferOverflow && Adapter->CurBufXmitting != -1) {
  1123. ULONG Len;
  1124. UINT i;
  1125. UCHAR Status;
  1126. PNDIS_PACKET Packet;
  1127. NDIS_STATUS NdisStatus;
  1128. //
  1129. // Check if it completed
  1130. //
  1131. CardGetInterruptStatus(Adapter, &Status);
  1132. if (Status & ISR_XMIT_ERR) {
  1133. OctogmetusceratorRevisited(Adapter);
  1134. Adapter->InterruptStatus &= ~ISR_XMIT_ERR;
  1135. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, (ISR_XMIT_ERR));
  1136. Status &= ~ISR_XMIT_ERR;
  1137. }
  1138. if (Status & (ISR_XMIT)) {
  1139. IF_LOG( Ne2000Log('*'); )
  1140. //
  1141. // Update NextBufToXmit
  1142. //
  1143. Len = (Adapter->PacketLens[Adapter->CurBufXmitting] + 255) >> 8;
  1144. NextBufToXmit = Adapter->NextBufToXmit + Len;
  1145. // Adapter->NextBufToXmit += Len;
  1146. if (NextBufToXmit == MAX_XMIT_BUFS) {
  1147. NextBufToXmit = 0;
  1148. }
  1149. if (Adapter->BufferStatus[NextBufToXmit] == EMPTY &&
  1150. Adapter->NextBufToFill != NextBufToXmit) {
  1151. NextBufToXmit = 0;
  1152. }
  1153. //
  1154. // If the next packet is ready to go, start it.
  1155. //
  1156. if (Adapter->BufferStatus[NextBufToXmit] == FULL) {
  1157. //
  1158. // Ack the transmit
  1159. //
  1160. //
  1161. // Remove the packet from the packet list.
  1162. //
  1163. Adapter->NextBufToXmit = NextBufToXmit;
  1164. Packet = Adapter->Packets[Adapter->CurBufXmitting];
  1165. Adapter->Packets[Adapter->CurBufXmitting] = (PNDIS_PACKET)NULL;
  1166. SyncCardGetXmitStatus((PVOID)Adapter);
  1167. //
  1168. // Statistics
  1169. //
  1170. if (Adapter->XmitStatus & TSR_XMIT_OK) {
  1171. Adapter->FramesXmitGood++;
  1172. NdisStatus = NDIS_STATUS_SUCCESS;
  1173. } else {
  1174. Adapter->FramesXmitBad++;
  1175. NdisStatus = NDIS_STATUS_FAILURE;
  1176. }
  1177. for (i = Adapter->CurBufXmitting; i < Adapter->CurBufXmitting + Len; i++) {
  1178. Adapter->BufferStatus[i] = EMPTY;
  1179. }
  1180. Adapter->TransmitInterruptPending = FALSE;
  1181. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, (ISR_XMIT));
  1182. Adapter->CurBufXmitting = Adapter->NextBufToXmit;
  1183. Adapter->TransmitInterruptPending = TRUE;
  1184. IF_LOG( Ne2000Log('8'); )
  1185. Adapter->InterruptStatus &= ~(ISR_XMIT);
  1186. CardStartXmit(Adapter);
  1187. } else {
  1188. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, (ISR_XMIT));
  1189. Adapter->InterruptStatus |= (Status);
  1190. }
  1191. }
  1192. }
  1193. return(NDIS_STATUS_SUCCESS);
  1194. }
  1195. }
  1196. NDIS_STATUS
  1197. Ne2000Send(
  1198. IN NDIS_HANDLE MiniportAdapterContext,
  1199. IN PNDIS_PACKET Packet,
  1200. IN UINT Flags
  1201. )
  1202. /*++
  1203. Routine Description:
  1204. The Ne2000Send request instructs a driver to transmit a packet through
  1205. the adapter onto the medium.
  1206. Arguments:
  1207. MiniportAdapterContext - Context registered with the wrapper, really
  1208. a pointer to the adapter.
  1209. Packet - A pointer to a descriptor for the packet that is to be
  1210. transmitted.
  1211. SendFlags - Optional send flags
  1212. Notes:
  1213. This miniport driver will always accept a send. This is because
  1214. the Ne2000 has limited send resources and the driver needs packets
  1215. to copy to the adapter immediately after a transmit completes in
  1216. order to keep the adapter as busy as possible.
  1217. This is not required for other adapters, as they have enough
  1218. resources to keep the transmitter busy until the wrapper submits
  1219. the next packet.
  1220. --*/
  1221. {
  1222. PNE2000_ADAPTER Adapter = (PNE2000_ADAPTER)(MiniportAdapterContext);
  1223. //
  1224. // Put the packet on the send queue.
  1225. //
  1226. if (Adapter->FirstPacket == NULL) {
  1227. Adapter->FirstPacket = Packet;
  1228. } else {
  1229. RESERVED(Adapter->LastPacket)->Next = Packet;
  1230. }
  1231. RESERVED(Packet)->Next = NULL;
  1232. Adapter->LastPacket = Packet;
  1233. //
  1234. // Process the next send
  1235. //
  1236. Ne2000DoNextSend(Adapter);
  1237. return(NDIS_STATUS_PENDING);
  1238. }
  1239. VOID
  1240. Ne2000DoNextSend(
  1241. PNE2000_ADAPTER Adapter
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. This routine examines if the packet at the head of the packet
  1246. list can be copied to the adapter, and does so.
  1247. Arguments:
  1248. Adapter - Pointer to the adapter block.
  1249. Return Value:
  1250. None
  1251. --*/
  1252. {
  1253. //
  1254. // The packet to process.
  1255. //
  1256. PNDIS_PACKET Packet;
  1257. //
  1258. // The current destination transmit buffer.
  1259. //
  1260. XMIT_BUF TmpBuf1;
  1261. //
  1262. // Length of the packet
  1263. //
  1264. ULONG Len;
  1265. //
  1266. // Temporary looping variable
  1267. //
  1268. ULONG i;
  1269. IF_LOG( Ne2000Log('s'); )
  1270. //
  1271. // Check if we have enough resources and a packet to process
  1272. //
  1273. while((Adapter->FirstPacket != NULL) &&
  1274. (Adapter->BufferStatus[Adapter->NextBufToFill] == EMPTY)) {
  1275. //
  1276. // Get the length of the packet.
  1277. //
  1278. NdisQueryPacket(
  1279. Adapter->FirstPacket,
  1280. NULL,
  1281. NULL,
  1282. NULL,
  1283. &Len
  1284. );
  1285. //
  1286. // Convert length to the number of transmit buffers needed.
  1287. //
  1288. Len = (Len + 255) >> 8;
  1289. //
  1290. // If not transmitting
  1291. //
  1292. if (Adapter->CurBufXmitting == -1) {
  1293. //
  1294. // Then check from the next free buffer if the packet will
  1295. // fit.
  1296. //
  1297. if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY) {
  1298. //
  1299. // It won't fit at the end, so put it at the first buffer
  1300. //
  1301. if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
  1302. Adapter->NextBufToFill = 0;
  1303. }
  1304. } else {
  1305. //
  1306. // Check if this packet will fit before the packet on the
  1307. // adapter.
  1308. //
  1309. if (Adapter->NextBufToXmit > Adapter->NextBufToFill) {
  1310. if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit) {
  1311. IF_LOG( Ne2000Log('^'); )
  1312. IF_LOG( Ne2000Log('S'); )
  1313. break;
  1314. }
  1315. } else {
  1316. //
  1317. // Check if it will fit after the packet already on the
  1318. // adapter.
  1319. //
  1320. if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
  1321. Adapter->NextBufToFill = 0;
  1322. if (Adapter->NextBufToFill + Len > Adapter->NextBufToXmit){
  1323. IF_LOG( Ne2000Log('%'); )
  1324. IF_LOG( Ne2000Log('S'); )
  1325. break;
  1326. }
  1327. }
  1328. }
  1329. }
  1330. } else {
  1331. //
  1332. // Check if the packet will fit before the packet currently
  1333. // transmitting
  1334. //
  1335. if (Adapter->CurBufXmitting > Adapter->NextBufToFill) {
  1336. if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting) {
  1337. IF_LOG( Ne2000Log('$'); )
  1338. IF_LOG( Ne2000Log('S'); )
  1339. break;
  1340. }
  1341. } else {
  1342. //
  1343. // Check if it will fit after the packet currently transmitting
  1344. //
  1345. if (Adapter->NextBufToFill + Len > MAX_XMIT_BUFS) {
  1346. Adapter->NextBufToFill = 0;
  1347. if (Adapter->NextBufToFill + Len > Adapter->CurBufXmitting){
  1348. IF_LOG( Ne2000Log('!'); )
  1349. IF_LOG( Ne2000Log('S'); )
  1350. break;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. //
  1356. // Set starting location
  1357. //
  1358. TmpBuf1 = Adapter->NextBufToFill;
  1359. //
  1360. // Remove the packet from the queue.
  1361. //
  1362. Packet = Adapter->FirstPacket;
  1363. Adapter->FirstPacket = RESERVED(Packet)->Next;
  1364. if (Packet == Adapter->LastPacket) {
  1365. Adapter->LastPacket = NULL;
  1366. }
  1367. //
  1368. // Store the packet in the list
  1369. //
  1370. Adapter->Packets[TmpBuf1] = Packet;
  1371. //
  1372. // Copy down the packet.
  1373. //
  1374. if (CardCopyDownPacket(Adapter, Packet,
  1375. &Adapter->PacketLens[TmpBuf1]) == FALSE) {
  1376. for (i = TmpBuf1; i < TmpBuf1 + Len; i++) {
  1377. Adapter->BufferStatus[i] = EMPTY;
  1378. }
  1379. Adapter->Packets[TmpBuf1] = NULL;
  1380. IF_LOG( Ne2000Log('F'); )
  1381. IF_LOG( Ne2000Log('S'); )
  1382. NdisMSendComplete(
  1383. Adapter->MiniportAdapterHandle,
  1384. Packet,
  1385. NDIS_STATUS_FAILURE
  1386. );
  1387. continue;
  1388. }
  1389. //
  1390. // Pad short packets with blanks.
  1391. //
  1392. if (Adapter->PacketLens[TmpBuf1] < 60) {
  1393. (VOID)CardCopyDown(
  1394. Adapter,
  1395. ((PUCHAR)Adapter->XmitStart +
  1396. TmpBuf1*TX_BUF_SIZE +
  1397. Adapter->PacketLens[TmpBuf1]),
  1398. BlankBuffer,
  1399. 60-Adapter->PacketLens[TmpBuf1]
  1400. );
  1401. }
  1402. //
  1403. // Set the buffer status
  1404. //
  1405. for (i = TmpBuf1; i < (TmpBuf1 + Len); i++) {
  1406. Adapter->BufferStatus[i] = FULL;
  1407. }
  1408. //
  1409. // Update next free buffer
  1410. //
  1411. Adapter->NextBufToFill += Len;
  1412. if (Adapter->NextBufToFill == MAX_XMIT_BUFS) {
  1413. Adapter->NextBufToFill = 0;
  1414. }
  1415. //
  1416. // See whether to start the transmission.
  1417. //
  1418. if (Adapter->CurBufXmitting == -1) {
  1419. //
  1420. // OK to start transmission.
  1421. //
  1422. if (Adapter->BufferStatus[Adapter->NextBufToXmit] == EMPTY &&
  1423. Adapter->NextBufToFill != Adapter->NextBufToXmit) {
  1424. Adapter->NextBufToXmit = 0;
  1425. }
  1426. Adapter->CurBufXmitting = Adapter->NextBufToXmit;
  1427. IF_LOG( Ne2000Log('4');)
  1428. //
  1429. // If we are currently handling an overflow, then we need to let
  1430. // the overflow handler send this packet...
  1431. //
  1432. if (Adapter->BufferOverflow) {
  1433. Adapter->OverflowRestartXmitDpc = TRUE;
  1434. IF_LOG( Ne2000Log('O');)
  1435. IF_LOUD( DbgPrint ("Adapter->OverflowRestartXmitDpc set:copy and send");)
  1436. } else {
  1437. //
  1438. // This is used to check if stopping the chip prevented
  1439. // a transmit complete interrupt from coming through (it
  1440. // is cleared in the ISR if a transmit DPC is queued).
  1441. //
  1442. Adapter->TransmitInterruptPending = TRUE;
  1443. IF_LOG( Ne2000Log('9'); )
  1444. CardStartXmit(Adapter);
  1445. }
  1446. }
  1447. //
  1448. // Ack the send immediately. If for some reason it
  1449. // should fail, the protocol should be able to handle
  1450. // the retransmit.
  1451. //
  1452. IF_LOG( Ne2000Log('S'); )
  1453. NdisMSendComplete(
  1454. Adapter->MiniportAdapterHandle,
  1455. Packet,
  1456. NDIS_STATUS_SUCCESS
  1457. );
  1458. }
  1459. }
  1460. VOID
  1461. OctogmetusceratorRevisited(
  1462. IN PNE2000_ADAPTER Adapter
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Recovers the card from a transmit error.
  1467. Arguments:
  1468. Adapter - pointer to the adapter block
  1469. Return Value:
  1470. None.
  1471. --*/
  1472. {
  1473. IF_LOUD( DbgPrint("Octogmetuscerator called!"); )
  1474. IF_LOG( Ne2000Log('y'); )
  1475. //
  1476. // Ack the interrupt, if needed
  1477. //
  1478. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, ISR_XMIT_ERR);
  1479. //
  1480. // Stop the card
  1481. //
  1482. SyncCardStop(Adapter);
  1483. //
  1484. // Wait up to 1.6 milliseconds for any receives to finish
  1485. //
  1486. NdisStallExecution(2000);
  1487. //
  1488. // Place the card in Loopback
  1489. //
  1490. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  1491. //
  1492. // Start the card in Loopback
  1493. //
  1494. NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
  1495. //
  1496. // Get out of loopback and start the card
  1497. //
  1498. CardStart(Adapter);
  1499. //
  1500. // If there was a packet waiting to get sent, send it.
  1501. //
  1502. if (Adapter->CurBufXmitting != -1) {
  1503. Adapter->TransmitInterruptPending = TRUE;
  1504. CardStartXmit(Adapter);
  1505. }
  1506. IF_LOG( Ne2000Log('Y'); )
  1507. }