Windows NT 4.0 source code leak
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.

4855 lines
126 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. interrup.c
  5. Abstract:
  6. This is a part of the driver for the IBM IBMTOK
  7. Token-ring 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. Adam Barr (adamba) 16-Jan-1991
  13. Environment:
  14. Kernel Mode - Or whatever is the equivalent.
  15. Revision History:
  16. Sean Selitrennikoff - 10/91
  17. Fixed synchronization bugs.
  18. Sean Selitrennikoff - 10/15/91
  19. Converted to Ndis 3.0
  20. Sean Selitrennikoff - 1/8/92
  21. Added error logging
  22. Brian E. Moore - 9/7/94
  23. Added PCMCIA support
  24. --*/
  25. #pragma optimize("",off)
  26. #include <ndis.h>
  27. #include <tfilter.h>
  28. #include <tokhrd.h>
  29. #include <toksft.h>
  30. #if DEVL
  31. #define STATIC
  32. #else
  33. #define STATIC static
  34. #endif
  35. #if DBG
  36. extern INT IbmtokDbg;
  37. #endif
  38. //
  39. // This section contains all the functions and definitions for
  40. // doing logging of input and output to/from the card.
  41. //
  42. #if LOG
  43. //
  44. // Place in the circular buffer.
  45. //
  46. UCHAR IbmtokLogPlace;
  47. //
  48. // Circular buffer for storing log information.
  49. //
  50. UCHAR IbmtokLog[256];
  51. #endif
  52. VOID
  53. SetResetVariables(
  54. IN PIBMTOK_ADAPTER Adapter
  55. );
  56. STATIC
  57. VOID
  58. IbmtokHandleSrbSsb(
  59. IN PIBMTOK_ADAPTER Adapter
  60. );
  61. STATIC
  62. VOID
  63. IbmtokHandleArbAsb(
  64. IN PIBMTOK_ADAPTER Adapter
  65. );
  66. STATIC
  67. VOID
  68. HandleResetStaging(
  69. IN PIBMTOK_ADAPTER Adapter
  70. );
  71. STATIC
  72. BOOLEAN
  73. IbmtokSynchGetSrbSsbBits(
  74. IN PVOID Context
  75. );
  76. STATIC
  77. BOOLEAN
  78. IbmtokSynchGetArbAsbBits(
  79. IN PVOID Context
  80. );
  81. STATIC
  82. VOID
  83. PutPacketOnWaitingForAsb(
  84. IN PIBMTOK_ADAPTER Adapter,
  85. IN PNDIS_PACKET Packet
  86. );
  87. STATIC
  88. PNDIS_PACKET
  89. RemoveTransmitFromSrb(
  90. IN PIBMTOK_ADAPTER Adapter,
  91. OUT PBOOLEAN PacketRemoved
  92. );
  93. STATIC
  94. VOID
  95. SetupTransmitFrameSrb(
  96. IN PIBMTOK_ADAPTER Adapter,
  97. IN PNDIS_PACKET Packet
  98. );
  99. STATIC
  100. VOID
  101. SetupTransmitStatusAsb(
  102. IN PIBMTOK_ADAPTER Adapter,
  103. IN PNDIS_PACKET Packet
  104. );
  105. STATIC
  106. VOID
  107. GetAdapterStatisticsFromSrb(
  108. PIBMTOK_ADAPTER Adapter
  109. );
  110. STATIC
  111. VOID
  112. GetAdapterErrorsFromSrb(
  113. PIBMTOK_ADAPTER Adapter
  114. );
  115. STATIC
  116. NDIS_STATUS
  117. StartPendQueueOp(
  118. IN PIBMTOK_ADAPTER Adapter
  119. );
  120. STATIC
  121. NDIS_STATUS
  122. FinishSetOperation(
  123. IN PIBMTOK_ADAPTER Adapter,
  124. IN PIBMTOK_PEND_DATA PendOp
  125. );
  126. STATIC
  127. BOOLEAN
  128. FinishPendQueueOp(
  129. IN PIBMTOK_ADAPTER Adapter,
  130. IN BOOLEAN Successful
  131. );
  132. STATIC
  133. NDIS_STATUS
  134. SetAdapterFunctionalAddress(
  135. IN PIBMTOK_ADAPTER Adapter
  136. );
  137. STATIC
  138. VOID
  139. SetupFunctionalSrb(
  140. IN PIBMTOK_ADAPTER Adapter,
  141. IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
  142. );
  143. STATIC
  144. NDIS_STATUS
  145. SetAdapterGroupAddress(
  146. IN PIBMTOK_ADAPTER Adapter
  147. );
  148. STATIC
  149. VOID
  150. SetupGroupSrb(
  151. IN PIBMTOK_ADAPTER Adapter,
  152. IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
  153. );
  154. STATIC
  155. VOID
  156. SetupReceivedDataAsb(
  157. IN PIBMTOK_ADAPTER Adapter,
  158. IN SRAM_PTR ReceiveBuffer
  159. );
  160. //
  161. // These macros are used to set the SRPR correctly.
  162. //
  163. #define SET_SRB_SRPR(Adapter) \
  164. if (Adapter->SharedRamPaging) { \
  165. WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->SrbSrprLow) \
  166. }
  167. #define SET_SSB_SRPR(Adapter) \
  168. if (Adapter->SharedRamPaging) { \
  169. WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->SsbSrprLow) \
  170. }
  171. #define SET_ARB_SRPR(Adapter) \
  172. if (Adapter->SharedRamPaging) { \
  173. WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->ArbSrprLow) \
  174. }
  175. #define SET_ASB_SRPR(Adapter) \
  176. if (Adapter->SharedRamPaging) { \
  177. WRITE_ADAPTER_REGISTER(Adapter, SRPR_LOW, Adapter->AsbSrprLow) \
  178. }
  179. typedef struct _IBMTOK_SYNCH_CONTEXT {
  180. //
  181. // Pointer to the ibmtok adapter for which interrupts are
  182. // being synchronized.
  183. //
  184. PIBMTOK_ADAPTER Adapter;
  185. //
  186. // Points to the variable on to which the relevant
  187. // interrupt bits should be ORed.
  188. //
  189. PVOID Local;
  190. } IBMTOK_SYNCH_CONTEXT, * PIBMTOK_SYNCH_CONTEXT;
  191. //
  192. // This macro is to synchronize execution with interrupts. It
  193. // gets the stored value of the SRB/SSB bits and clears the
  194. // old value.
  195. //
  196. #define GET_SRB_SSB_BITS(A,L) \
  197. { \
  198. PIBMTOK_ADAPTER _A = A; \
  199. IBMTOK_SYNCH_CONTEXT _C; \
  200. _C.Adapter = _A; \
  201. _C.Local = (PVOID)(L); \
  202. NdisSynchronizeWithInterrupt( \
  203. &(_A->Interrupt), \
  204. (PVOID) IbmtokSynchGetSrbSsbBits, \
  205. &_C \
  206. ); \
  207. }
  208. //
  209. // This macro is to synchronize execution with interrupts. It
  210. // gets the stored value of the ARB/ASB bits and clears the
  211. // old value.
  212. //
  213. #define GET_ARB_ASB_BITS(A,L) \
  214. { \
  215. PIBMTOK_ADAPTER _A = A; \
  216. IBMTOK_SYNCH_CONTEXT _C; \
  217. _C.Adapter = _A; \
  218. _C.Local = (PVOID)(L); \
  219. NdisSynchronizeWithInterrupt( \
  220. &(_A->Interrupt), \
  221. (PVOID) IbmtokSynchGetArbAsbBits, \
  222. &_C \
  223. ); \
  224. }
  225. //++
  226. //
  227. // PNDIS_PACKET
  228. // FindPacketGivenCorrelator(
  229. // IN PIBMTOK_ADAPTER Adapter,
  230. // IN UCHAR CommandCorrelator
  231. // )
  232. //
  233. //
  234. // Routine Description:
  235. //
  236. // This looks a packet up on the command correlator array.
  237. //
  238. // This routine should be called with the spinlock held.
  239. //
  240. // Arguments:
  241. //
  242. // Adapter - The adapter that this packet is coming through.
  243. //
  244. // CommandCorrelator - The command correlator to search based on.
  245. //
  246. // Return Value:
  247. //
  248. // The packet if found, NULL otherwise.
  249. //
  250. //--
  251. #define FindPacketGivenCorrelator(_Adapter, _CommandCorrelator) \
  252. ((_Adapter)->CorrelatorArray[_CommandCorrelator])
  253. STATIC
  254. BOOLEAN
  255. IbmtokSynchGetSrbSsbBits(
  256. IN PVOID Context
  257. )
  258. /*++
  259. Routine Description:
  260. This routine is used by the normal interrupt processing routine
  261. to synchronize with interrupts from the card. It will or
  262. the value of the stored SRB/SSB bits into the other passed address
  263. in the context and clear the stored value.
  264. Arguments:
  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 ISRP.
  269. Return Value:
  270. Always returns true.
  271. --*/
  272. {
  273. PIBMTOK_SYNCH_CONTEXT C = (PIBMTOK_SYNCH_CONTEXT)Context;
  274. *((PUCHAR)C->Local) = (C->Adapter->IsrpBits) &
  275. (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
  276. C->Adapter->IsrpBits = (C->Adapter->IsrpBits) &
  277. (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
  278. return TRUE;
  279. }
  280. ULONG PCMCIAStall = 0;
  281. STATIC
  282. BOOLEAN
  283. IbmtokSynchGetArbAsbBits(
  284. IN PVOID Context
  285. )
  286. /*++
  287. Routine Description:
  288. This routine is used by the normal interrupt processing routine
  289. to synchronize with interrupts from the card. It will or
  290. the value of the stored ARB/ASB bits into the other passed address
  291. in the context and clear the stored value.
  292. Arguments:
  293. Context - This is really a pointer to a record type peculiar
  294. to this routine. The record contains a pointer to the adapter
  295. and a pointer to an address in which to place the contents
  296. of the ISRP.
  297. Return Value:
  298. Always returns true.
  299. --*/
  300. {
  301. PIBMTOK_SYNCH_CONTEXT C = (PIBMTOK_SYNCH_CONTEXT)Context;
  302. UCHAR Test,i;
  303. IF_LOG('*');
  304. if (C->Adapter->CardType == IBM_TOKEN_RING_PCMCIA)
  305. {
  306. NdisStallExecution(PCMCIAStall);
  307. }
  308. *((PUCHAR)C->Local) = (C->Adapter->IsrpBits) &
  309. (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
  310. C->Adapter->IsrpBits = (C->Adapter->IsrpBits) &
  311. (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
  312. return TRUE;
  313. }
  314. extern
  315. BOOLEAN
  316. IbmtokSynchSetReset(
  317. IN PVOID Context
  318. )
  319. /*++
  320. Routine Description:
  321. This routine is called by the SET_INTERRUPT_RESET_FLAG macro.
  322. It sets the ResetInterruptAllowed flag to TRUE.
  323. Arguments:
  324. Context - A pointer to the Adapter structure.
  325. Return Value:
  326. Always returns true.
  327. --*/
  328. {
  329. PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
  330. Adapter->ResetInterruptAllowed = TRUE;
  331. return TRUE;
  332. }
  333. extern
  334. BOOLEAN
  335. IbmtokSynchClearIsrpBits(
  336. IN PVOID Context
  337. )
  338. /*++
  339. Routine Description:
  340. This routine is called by the CLEAR_ISRP_BITS macro.
  341. It clears the SRB/SSB and ARB/ASB bits. This is used
  342. when a reset has started to prevent a previously
  343. queued interrupt handler to come in and start
  344. playing with an adapter that is being reset.
  345. Arguments:
  346. Context - A pointer to the Adapter structure.
  347. Return Value:
  348. Always returns true.
  349. --*/
  350. {
  351. PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
  352. Adapter->IsrpBits = 0;
  353. return TRUE;
  354. }
  355. extern
  356. BOOLEAN
  357. IbmtokISR(
  358. IN PVOID Context
  359. )
  360. /*++
  361. Routine Description:
  362. Interrupt service routine for the token-ring card. It's main job is
  363. to get the value of ISR and record the changes in the
  364. adapters own list of interrupt reasons.
  365. Arguments:
  366. Context - Really a pointer to the adapter.
  367. Return Value:
  368. Returns true if the card ISR is non-zero.
  369. --*/
  370. {
  371. //
  372. // Holds the pointer to the adapter.
  373. //
  374. PIBMTOK_ADAPTER Adapter = Context;
  375. //
  376. // Holds the value of the ISRP High
  377. //
  378. UCHAR IsrpHigh;
  379. READ_ADAPTER_REGISTER(Adapter, ISRP_HIGH, &IsrpHigh);
  380. if (!Adapter->BringUp)
  381. {
  382. Adapter->ContinuousIsrs++;
  383. if (Adapter->ContinuousIsrs == 0xFF)
  384. {
  385. //
  386. // We seemed to be confused since the DPCs aren't getting in.
  387. // Shutdown and exit.
  388. //
  389. #if DBG
  390. if (IbmtokDbg)
  391. DbgPrint("IBMTOK: Continuous ISRs received\n");
  392. #endif
  393. WRITE_ADAPTER_PORT(Adapter, RESET_LATCH, 0);
  394. return(FALSE);
  395. }
  396. }
  397. #if DBG
  398. if (IbmtokDbg) DbgPrint("ISRP High: %x\n", IsrpHigh);
  399. #endif
  400. IF_LOG('i');
  401. //
  402. // Acknowledge all the interrupts we got in IsrpHigh.
  403. //
  404. WRITE_ADAPTER_REGISTER(Adapter, ISRP_HIGH_RESET, (UCHAR)(~IsrpHigh));
  405. //
  406. // If the adapter is not accepting requests, ignore everything
  407. // but SRB_RESPONSE interrupts, saving any others until
  408. // NotAcceptingRequests goes to FALSE (note that we have
  409. // already turned off ALL bits in ISRP_HIGH).
  410. //
  411. if (Adapter->NotAcceptingRequests)
  412. {
  413. Adapter->IsrpDeferredBits |= (IsrpHigh & (~ISRP_HIGH_SRB_RESPONSE));
  414. IsrpHigh &= ISRP_HIGH_SRB_RESPONSE;
  415. }
  416. else
  417. {
  418. //
  419. // Put the deferred bits back on (after the first time
  420. // through they will be 0).
  421. //
  422. IsrpHigh |= Adapter->IsrpDeferredBits;
  423. Adapter->IsrpDeferredBits = 0;
  424. }
  425. //
  426. // Now store the bits for the DPC.
  427. //
  428. Adapter->IsrpBits |= IsrpHigh;
  429. //
  430. // If this is the reset interrupt, set the flag.
  431. //
  432. if (Adapter->ResetInterruptAllowed)
  433. {
  434. Adapter->ResetInterruptHasArrived = TRUE;
  435. }
  436. if (Adapter->FirstInitialization)
  437. {
  438. USHORT WrbOffset;
  439. PSRB_BRING_UP_RESULT BringUpSrb;
  440. UCHAR Value1, Value2;
  441. USHORT RegValue;
  442. READ_ADAPTER_REGISTER(Adapter, WRBR_LOW, &Value1);
  443. READ_ADAPTER_REGISTER(Adapter, WRBR_HIGH, &Value2);
  444. WrbOffset = (((USHORT)Value1) << 8) + (USHORT)Value2;
  445. if (WrbOffset & 0x1)
  446. {
  447. //
  448. // Mis-aligned WRB, fail to load
  449. //
  450. if (Adapter->UsingPcIoBus)
  451. {
  452. WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
  453. }
  454. return(FALSE);
  455. }
  456. Adapter->InitialWrbOffset = WrbOffset;
  457. BringUpSrb = (PSRB_BRING_UP_RESULT)(Adapter->SharedRam + WrbOffset);
  458. NdisReadRegisterUshort(&(BringUpSrb->ReturnCode), &RegValue);
  459. if (RegValue == 0x0000)
  460. {
  461. Adapter->BringUp = TRUE;
  462. }
  463. //
  464. // If we are using the PC I/O Bus then we have to re-enable
  465. // interrupts because the card is blocking all other interrupts
  466. //
  467. if (Adapter->UsingPcIoBus)
  468. {
  469. WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
  470. }
  471. IF_LOG('I');
  472. //
  473. // no DPC for the first init.
  474. //
  475. return(FALSE);
  476. }
  477. //
  478. // If we are using the PC I/O Bus then we have to re-enable
  479. // interrupts because the card is blocking all other interrupts
  480. //
  481. if (Adapter->UsingPcIoBus)
  482. {
  483. WRITE_ADAPTER_PORT(Adapter, INTERRUPT_RELEASE_ISA_ONLY, 1);
  484. }
  485. if (IsrpHigh == 0x0)
  486. {
  487. //
  488. // This means that the interrupt was generated from the IsrpLow
  489. // and needs to be cleared.
  490. //
  491. READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &IsrpHigh);
  492. //
  493. // Mask off the bits we need.
  494. //
  495. IsrpHigh &= 0x1C;
  496. Adapter->IsrpLowBits = IsrpHigh;
  497. //
  498. // Acknowledge all the interrupts we got in IsrpLow.
  499. //
  500. WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW_RESET, (UCHAR)(~IsrpHigh));
  501. }
  502. IF_LOG('I');
  503. if (Adapter->IsrpBits != 0)
  504. {
  505. return TRUE;
  506. }
  507. else
  508. {
  509. return FALSE;
  510. }
  511. }
  512. extern
  513. VOID
  514. IbmtokDPC(
  515. IN PVOID SystemSpecific1,
  516. IN PVOID Context,
  517. IN PVOID SystemArgument1,
  518. IN PVOID SystemArgument2
  519. )
  520. /*++
  521. Routine Description:
  522. This DPC routine is queued by Ndis after interrupt service routine
  523. has run. It's main job is to call the interrupt processing code.
  524. Arguments:
  525. SystemSpecific1 - Not used.
  526. Context - Really a pointer to the adapter.
  527. SystemArgument1(2) - Neither of these arguments used.
  528. Return Value:
  529. None.
  530. --*/
  531. {
  532. PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
  533. NdisDprAcquireSpinLock(&Adapter->Lock);
  534. Adapter->ContinuousIsrs = 0;
  535. IF_LOG('d');
  536. if (Adapter->IsrpLowBits)
  537. {
  538. Adapter->IsrpLowBits = 0;
  539. }
  540. if ((Adapter->IsrpBits & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE)) &&
  541. (!Adapter->HandleArbRunning))
  542. {
  543. IbmtokHandleArbAsb(Adapter);
  544. NdisDprAcquireSpinLock(&(Adapter->Lock));
  545. }
  546. if ((Adapter->IsrpBits & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE)) &&
  547. (!Adapter->HandleSrbRunning))
  548. {
  549. IbmtokHandleSrbSsb(Adapter);
  550. }
  551. else
  552. {
  553. NdisDprReleaseSpinLock(&Adapter->Lock);
  554. }
  555. #if DBG
  556. NdisDprAcquireSpinLock(&Adapter->Lock);
  557. IF_LOG('D');
  558. NdisDprReleaseSpinLock(&Adapter->Lock);
  559. #endif
  560. }
  561. extern
  562. VOID
  563. IbmtokHandleSrbSsb(
  564. IN PIBMTOK_ADAPTER Adapter
  565. )
  566. /*++
  567. Routine Description:
  568. This routine is called by the DPC routine
  569. and other routines within the driver that notice that
  570. some deferred processing needs to be done. It's main
  571. job is to call the interrupt processing code.
  572. NOTE: THIS ROUTINE IS CALLED WITH THE LOCK HELD!! AND RETURNS
  573. WITH IT RELEASED!!
  574. Arguments:
  575. Adapter - A pointer to the adapter.
  576. Return Value:
  577. None.
  578. --*/
  579. {
  580. UCHAR IsrpHigh;
  581. UCHAR TmpUchar;
  582. USHORT TmpUshort;
  583. UCHAR Temp;
  584. UINT Nibble3;
  585. IF_LOG('h');
  586. Adapter->References++;
  587. if (Adapter->ResetInProgress)
  588. {
  589. if (Adapter->ResetInterruptHasArrived)
  590. {
  591. //
  592. // This is the interrupt after a reset,
  593. // continue things along.
  594. //
  595. HandleResetStaging(Adapter);
  596. IBMTOK_DO_DEFERRED(Adapter);
  597. return;
  598. }
  599. }
  600. //
  601. // If ResetInProgress is TRUE but this is an old
  602. // interrupt, proceed as usual (once the reset
  603. // actually starts, GET_SRB_SSB_BITS will return
  604. // nothing so no work will get done).
  605. //
  606. Adapter->HandleSrbRunning = TRUE;
  607. if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
  608. {
  609. GET_SRB_SSB_BITS(Adapter, &IsrpHigh);
  610. }
  611. else
  612. {
  613. //
  614. // disable interrupts on the card,
  615. // since we don't trust ndissyncint to work
  616. //
  617. READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
  618. WRITE_ADAPTER_REGISTER(
  619. Adapter,
  620. ISRP_LOW,
  621. Temp & ~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE));
  622. //
  623. // update arb_asb
  624. //
  625. IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
  626. Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
  627. //
  628. // reenable interrupts on the card
  629. //
  630. WRITE_ADAPTER_REGISTER(
  631. Adapter,
  632. ISRP_LOW,
  633. ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
  634. }
  635. while (IsrpHigh & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE))
  636. {
  637. IF_LOG((UCHAR)(Adapter->OpenInProgress));
  638. if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
  639. {
  640. //
  641. // Do, nothing. This is most likely a stale interrupt. We
  642. // wait until we get a ring status interrupt telling us that
  643. // the cable is plugged in.
  644. //
  645. break;
  646. }
  647. if (IsrpHigh & ISRP_HIGH_SRB_RESPONSE)
  648. {
  649. if (Adapter->OpenInProgress)
  650. {
  651. //
  652. // Handle the result of the DIR.OPEN.ADAPTER command.
  653. //
  654. PSRB_OPEN_RESPONSE OpenResponseSrb;
  655. PIBMTOK_OPEN Open;
  656. PLIST_ENTRY CurrentLink;
  657. UCHAR ReturnCode;
  658. OpenResponseSrb = (PSRB_OPEN_RESPONSE)
  659. (Adapter->SharedRam + Adapter->InitialWrbOffset);
  660. NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode), &ReturnCode);
  661. #if DBG
  662. if (IbmtokDbg)
  663. DbgPrint("IBMTOK: OPEN, Return code = %x, at %lx\n",
  664. ReturnCode,
  665. OpenResponseSrb);
  666. #endif
  667. //
  668. if (ReturnCode == 0x0)
  669. {
  670. NdisDprReleaseSpinLock(&(Adapter->Lock));
  671. if (Adapter->SharedRamPaging)
  672. {
  673. NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
  674. TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
  675. Adapter->SrbAddress = SHARED_RAM_ADDRESS(Adapter,
  676. SHARED_RAM_LOW_BITS(TmpUshort));
  677. Adapter->SrbSrprLow = (UCHAR)(TmpUshort >> 14);
  678. NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
  679. TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
  680. Adapter->SsbAddress = SHARED_RAM_ADDRESS(Adapter,
  681. SHARED_RAM_LOW_BITS(TmpUshort));
  682. Adapter->SsbSrprLow = (UCHAR)(TmpUshort >> 14);
  683. NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
  684. TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
  685. Adapter->ArbAddress = SHARED_RAM_ADDRESS(Adapter,
  686. SHARED_RAM_LOW_BITS(TmpUshort));
  687. Adapter->ArbSrprLow = (UCHAR)(TmpUshort >> 14);
  688. NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
  689. TmpUshort = IBMSHORT_TO_USHORT(TmpUshort);
  690. Adapter->AsbAddress = SHARED_RAM_ADDRESS(Adapter,
  691. SHARED_RAM_LOW_BITS(TmpUshort));
  692. Adapter->AsbSrprLow = (UCHAR)(TmpUshort >> 14);
  693. }
  694. else
  695. {
  696. NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
  697. Adapter->SrbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
  698. NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
  699. Adapter->SsbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
  700. NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
  701. Adapter->ArbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
  702. NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
  703. Adapter->AsbAddress = SRAM_PTR_TO_PVOID(Adapter, TmpUshort);
  704. }
  705. if (((ULONG)Adapter->SrbAddress >
  706. (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
  707. ((ULONG)Adapter->SsbAddress >
  708. (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
  709. ((ULONG)Adapter->ArbAddress >
  710. (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)) ||
  711. ((ULONG)Adapter->AsbAddress >
  712. (ULONG)(Adapter->SharedRam + Adapter->MappedSharedRam)))
  713. {
  714. //
  715. // Something is definitely wrong. Fail!
  716. //
  717. goto OpenFailed;
  718. }
  719. #if DBG
  720. if (IbmtokDbg)
  721. {
  722. USHORT TmpUshort1;
  723. USHORT TmpUshort2;
  724. USHORT TmpUshort3;
  725. USHORT TmpUshort4;
  726. NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort1);
  727. NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort2);
  728. NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort3);
  729. NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort4);
  730. DbgPrint("IBMTOK: Offsets: SRB %x SSB %x ARB %x ASB %x\n",
  731. IBMSHORT_TO_USHORT(TmpUshort1),
  732. IBMSHORT_TO_USHORT(TmpUshort2),
  733. IBMSHORT_TO_USHORT(TmpUshort3),
  734. IBMSHORT_TO_USHORT(TmpUshort4));
  735. }
  736. #endif
  737. //
  738. // Now we have to start worrying about synchronization.
  739. //
  740. NdisDprAcquireSpinLock(&(Adapter->Lock));
  741. Adapter->CurrentRingState = NdisRingStateOpened;
  742. Adapter->OpenInProgress = FALSE;
  743. Adapter->OpenErrorCode = 0;
  744. Adapter->AdapterNotOpen = FALSE;
  745. Adapter->NotAcceptingRequests = FALSE;
  746. //
  747. // Complete all opens that pended during this operation.
  748. //
  749. CurrentLink = Adapter->OpenBindings.Flink;
  750. while (CurrentLink != &(Adapter->OpenBindings))
  751. {
  752. Open = CONTAINING_RECORD(CurrentLink, IBMTOK_OPEN, OpenList);
  753. if (Open->OpenPending)
  754. {
  755. Open->OpenPending = FALSE;
  756. NdisDprReleaseSpinLock(&(Adapter->Lock));
  757. NdisCompleteOpenAdapter(
  758. Open->NdisBindingContext,
  759. NDIS_STATUS_SUCCESS,
  760. 0);
  761. NdisDprAcquireSpinLock(&(Adapter->Lock));
  762. }
  763. CurrentLink = CurrentLink->Flink;
  764. }
  765. //
  766. // Get any interrupts that have been deferred
  767. // while NotAcceptingRequests was TRUE.
  768. //
  769. IbmtokForceAdapterInterrupt(Adapter);
  770. }
  771. else
  772. {
  773. //
  774. // Open Failed!
  775. //
  776. // Here is where I check the return code from the Open and see if it
  777. // indicates an incorrect ring speed. If it does, I change the ring speed
  778. // and reissue the OpenAdapter. BEM
  779. //
  780. NdisReadRegisterUshort(
  781. &(OpenResponseSrb->ErrorCode),
  782. &(TmpUshort));
  783. //
  784. // If a catastrophic error and a frequency error and we want ring speed listen
  785. // and the number of retries > 0, bail out. We have already tried a different
  786. // speed
  787. //
  788. if ((ReturnCode == 0x07) && // catastrophic error
  789. (TmpUshort == 0x2400) && // frequency error
  790. Adapter->RingSpeedListen && // we want ring speed listen
  791. (Adapter->RingSpeedRetries == 0)) // have not tried before
  792. {
  793. #if DBG
  794. if (IbmtokDbg)
  795. DbgPrint("IBMTOK: Incorrect Ring Speed, Changing.\n");
  796. #endif
  797. //
  798. //
  799. // Change the ring speed
  800. //
  801. if (Adapter->Running16Mbps == TRUE)
  802. Adapter->Running16Mbps == FALSE;
  803. else
  804. Adapter->Running16Mbps == TRUE;
  805. Nibble3 = NIBBLE_3;
  806. if (Adapter->RingSpeed == 16)
  807. { // swap speeds
  808. Nibble3 |= RING_SPEED_4_MPS;
  809. }
  810. else
  811. {
  812. Nibble3 |= RING_SPEED_16_MPS;
  813. }
  814. switch (Adapter->RamSize)
  815. {
  816. case 0x10000:
  817. Nibble3 |= SHARED_RAM_64K;
  818. break;
  819. case 0x8000:
  820. Nibble3 |= SHARED_RAM_32K;
  821. break;
  822. case 0x4000:
  823. Nibble3 |= SHARED_RAM_16K;
  824. break;
  825. case 0x2000:
  826. Nibble3 |= SHARED_RAM_8K;
  827. break;
  828. }
  829. WRITE_ADAPTER_PORT(Adapter, SWITCH_READ_1, Nibble3);
  830. //
  831. // Now to reissue the Open Adapter SRB with the necessary changes.
  832. //
  833. // Reset these fields in the SRB for the Open Adapter.
  834. //
  835. OpenResponseSrb->ReturnCode = 0xFE;
  836. OpenResponseSrb->ErrorCode = 0x0000;
  837. // DbgBreakPoint();
  838. //
  839. // Tell the adapter to handle the change.
  840. //
  841. WRITE_ADAPTER_REGISTER(
  842. Adapter,
  843. ISRA_HIGH_SET,
  844. ISRA_HIGH_COMMAND_IN_SRB);
  845. Adapter->RingSpeedRetries++; // first retry
  846. // end of check for incorrect ring speed
  847. }
  848. else
  849. {
  850. OpenFailed:
  851. #if DBG
  852. if (IbmtokDbg)
  853. {
  854. DbgPrint("IBMTOK: Open failed!\n");
  855. }
  856. #endif
  857. //
  858. // Now we have to start worrying about synchronization.
  859. //
  860. Adapter->CurrentRingState = NdisRingStateOpenFailure;
  861. Adapter->OpenInProgress = FALSE;
  862. NdisReadRegisterUshort(
  863. &(OpenResponseSrb->ErrorCode),
  864. &(Adapter->OpenErrorCode));
  865. Adapter->OpenErrorCode = IBMSHORT_TO_USHORT(Adapter->OpenErrorCode);
  866. Adapter->AdapterNotOpen = TRUE;
  867. Adapter->NotAcceptingRequests = TRUE;
  868. //
  869. // Fail all opens that pended during this operation.
  870. //
  871. CurrentLink = Adapter->OpenBindings.Flink;
  872. while (CurrentLink != &(Adapter->OpenBindings))
  873. {
  874. Open = CONTAINING_RECORD(
  875. CurrentLink,
  876. IBMTOK_OPEN,
  877. OpenList);
  878. if (Open->OpenPending)
  879. {
  880. Open->OpenPending = FALSE;
  881. NdisDprReleaseSpinLock(&(Adapter->Lock));
  882. NdisCompleteOpenAdapter(
  883. Open->NdisBindingContext,
  884. NDIS_STATUS_OPEN_FAILED,
  885. NDIS_STATUS_TOKEN_RING_OPEN_ERROR |
  886. (NDIS_STATUS)(Adapter->OpenErrorCode));
  887. NdisDprAcquireSpinLock(&(Adapter->Lock));
  888. CurrentLink = CurrentLink->Flink;
  889. RemoveEntryList(&(Open->OpenList));
  890. IBMTOK_FREE_PHYS(Open, sizeof(IBMTOK_OPEN));
  891. Adapter->References--;
  892. }
  893. else
  894. {
  895. //
  896. // Note: All opens are pending, otherwise the
  897. // adapter would have already been open.
  898. //
  899. }
  900. }
  901. }
  902. }
  903. }
  904. else
  905. {
  906. #if DBG
  907. if (IbmtokDbg)
  908. DbgPrint("IBMTOK: SRB Response\n");
  909. #endif
  910. IF_LOG('>');
  911. if (Adapter->TransmittingPacket != (PNDIS_PACKET)NULL)
  912. {
  913. BOOLEAN PacketRemoved;
  914. //
  915. // Happens if the transmit failed.
  916. //
  917. (PVOID)RemoveTransmitFromSrb(Adapter, &PacketRemoved);
  918. //
  919. // If the packet was successfully removed, then
  920. // start the next command.
  921. //
  922. // This will release the spin lock.
  923. //
  924. if (PacketRemoved)
  925. {
  926. //
  927. // SrbAvailable will still be FALSE here,
  928. // as required.
  929. //
  930. SetupSrbCommand(Adapter);
  931. }
  932. }
  933. else if (!Adapter->SrbAvailable)
  934. {
  935. PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
  936. UCHAR ReturnCode;
  937. //
  938. // Another command in progress, complete it unless
  939. // it was an INTERRUPT command.
  940. //
  941. NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
  942. IF_LOG('N');
  943. NdisReadRegisterUchar(&(GenericSrb->Command), &TmpUchar);
  944. if (TmpUchar != SRB_CMD_INTERRUPT)
  945. {
  946. if ((TmpUchar != SRB_CMD_READ_LOG) &&
  947. (TmpUchar != SRB_CMD_SET_FUNCTIONAL_ADDRESS) &&
  948. (TmpUchar != SRB_CMD_SET_GROUP_ADDRESS) &&
  949. (TmpUchar != SRB_CMD_DLC_STATISTICS))
  950. {
  951. //
  952. // We have an invalid response. Log an error an exit.
  953. //
  954. NdisWriteErrorLogEntry(
  955. Adapter->NdisAdapterHandle,
  956. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  957. 3,
  958. handleSrbSsb,
  959. IBMTOK_ERRMSG_INVALID_CMD,
  960. (ULONG)TmpUchar);
  961. }
  962. else
  963. {
  964. //
  965. // This interrupt had to come from a pended op.
  966. //
  967. ASSERT(Adapter->PendData != NULL);
  968. if (Adapter->PendData->RequestType == NdisRequestGeneric1)
  969. {
  970. //
  971. // If no request, it came as a result of the
  972. // card overflowing a counter and then we
  973. // submitted the correcting operation.
  974. //
  975. if (ReturnCode == 0x00)
  976. {
  977. if (Adapter->PendData->COMMAND.MAC.ReadLogPending)
  978. {
  979. //
  980. // We are getting an SRB_CMD_READ_LOG from
  981. // we sent as a result to a RING_STATUS_CHANGE.
  982. //
  983. GetAdapterErrorsFromSrb(Adapter);
  984. }
  985. else
  986. {
  987. //
  988. // We are getting an SRB_CMD_DLC_STATISTICS from
  989. // we sent as a result to a DLC_STATUS.
  990. //
  991. GetAdapterStatisticsFromSrb(Adapter);
  992. }
  993. }
  994. //
  995. // Free up pend operation.
  996. //
  997. IBMTOK_FREE_PHYS(Adapter->PendData, sizeof(IBMTOK_PEND_DATA));
  998. Adapter->PendData = NULL;
  999. //
  1000. // Fire off next command.
  1001. //
  1002. SetupSrbCommand(Adapter);
  1003. }
  1004. else
  1005. {
  1006. //
  1007. // This is the result of a pending op from Ndis.
  1008. //
  1009. if (FinishPendQueueOp(
  1010. Adapter,
  1011. (BOOLEAN)(ReturnCode == 0x00 ? TRUE : FALSE)))
  1012. {
  1013. //
  1014. // Fire off next command.
  1015. //
  1016. SetupSrbCommand(Adapter);
  1017. }
  1018. }
  1019. }
  1020. }
  1021. else
  1022. {
  1023. SetupSrbCommand(Adapter);
  1024. }
  1025. }
  1026. else
  1027. {
  1028. //
  1029. // Nothing to do -- we get here when an SRB_FREE_REQUEST
  1030. // comes through after the ARB to transfer the data has
  1031. // already come through.
  1032. //
  1033. }
  1034. }
  1035. }
  1036. if (IsrpHigh & ISRP_HIGH_SSB_RESPONSE)
  1037. {
  1038. //
  1039. // This has to be a transmit completing since
  1040. // that is the only operation we do that pends.
  1041. //
  1042. PSSB_TRANSMIT_COMPLETE ResponseSsb =
  1043. (PSSB_TRANSMIT_COMPLETE)Adapter->SsbAddress;
  1044. NdisReadRegisterUchar(&(ResponseSsb->Command), &TmpUchar);
  1045. if (TmpUchar == SRB_CMD_TRANSMIT_DIR_FRAME)
  1046. {
  1047. UCHAR CorrelatorInSrb;
  1048. NDIS_STATUS SendStatus;
  1049. UCHAR SrbReturnCode;
  1050. //
  1051. // Initialize this to one less since the loop starts by
  1052. // incrementing it.
  1053. //
  1054. UCHAR CurrentCorrelator = (UCHAR)
  1055. ((Adapter->NextCorrelatorToComplete +
  1056. (MAX_COMMAND_CORRELATOR-1)) %
  1057. MAX_COMMAND_CORRELATOR);
  1058. NdisReadRegisterUchar(&(ResponseSsb->CommandCorrelator), &CorrelatorInSrb);
  1059. //
  1060. // Have to loop to complete since supposedly one
  1061. // of these can indicate multiple completing sends.
  1062. //
  1063. //
  1064. // Figure out what the return code should be.
  1065. //
  1066. NdisReadRegisterUchar(&(ResponseSsb->ReturnCode), &SrbReturnCode);
  1067. if (SrbReturnCode == 0x00)
  1068. {
  1069. SendStatus = NDIS_STATUS_SUCCESS;
  1070. }
  1071. else if (SrbReturnCode == 0x22)
  1072. {
  1073. //
  1074. // Check the frame status.
  1075. //
  1076. UCHAR FrameStatus;
  1077. UCHAR HighAc;
  1078. UCHAR LowAc;
  1079. NdisReadRegisterUchar(&(ResponseSsb->ErrorFrameStatus), &FrameStatus);
  1080. HighAc = GET_FRAME_STATUS_HIGH_AC(FrameStatus);
  1081. LowAc = GET_FRAME_STATUS_LOW_AC(FrameStatus);
  1082. if (HighAc != LowAc ||
  1083. (HighAc != AC_NOT_RECOGNIZED))
  1084. {
  1085. SendStatus = NDIS_STATUS_NOT_RECOGNIZED;
  1086. }
  1087. else
  1088. {
  1089. SendStatus = NDIS_STATUS_SUCCESS;
  1090. }
  1091. #if DBG
  1092. if (IbmtokDbg) DbgPrint("IBMTOK: Send failed, code %x err %x\n",
  1093. SrbReturnCode,
  1094. FrameStatus);
  1095. #endif
  1096. }
  1097. else
  1098. {
  1099. SendStatus = NDIS_STATUS_FAILURE;
  1100. #if DBG
  1101. if (IbmtokDbg) DbgPrint("IBMTOK: Send failed, code %x\n",
  1102. SrbReturnCode);
  1103. #endif
  1104. }
  1105. NdisDprReleaseSpinLock(&(Adapter->Lock));
  1106. do
  1107. {
  1108. PNDIS_PACKET TransmitPacket;
  1109. PIBMTOK_RESERVED Reserved;
  1110. PIBMTOK_OPEN Open;
  1111. CurrentCorrelator = (UCHAR)((CurrentCorrelator + 1) %
  1112. MAX_COMMAND_CORRELATOR);
  1113. //
  1114. // Complete the transmit.
  1115. //
  1116. TransmitPacket =
  1117. FindPacketGivenCorrelator(Adapter, CurrentCorrelator);
  1118. if (TransmitPacket == (PNDIS_PACKET)NULL)
  1119. {
  1120. #if DBG
  1121. if (IbmtokDbg) DbgPrint("IBMTOK: Missing %d to complete, %d to %d\n",
  1122. CurrentCorrelator,
  1123. Adapter->NextCorrelatorToComplete,
  1124. CorrelatorInSrb);
  1125. #endif
  1126. continue;
  1127. }
  1128. RemovePacketFromCorrelatorArray(Adapter, TransmitPacket);
  1129. Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  1130. Open =
  1131. PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  1132. //
  1133. // If doing LOOPBACK, this should really be a check
  1134. // of ReadyToComplete etc.
  1135. //
  1136. #ifdef CHECK_DUP_SENDS
  1137. {
  1138. VOID IbmtokRemovePacketFromList(PIBMTOK_ADAPTER, PNDIS_PACKET);
  1139. IbmtokRemovePacketFromList(Adapter, TransmitPacket);
  1140. }
  1141. #endif
  1142. if (SendStatus == NDIS_STATUS_SUCCESS)
  1143. {
  1144. Adapter->FramesTransmitted++;
  1145. }
  1146. else
  1147. {
  1148. Adapter->FrameTransmitErrors++;
  1149. }
  1150. NdisCompleteSend(
  1151. Open->NdisBindingContext,
  1152. Reserved->Packet,
  1153. SendStatus);
  1154. //
  1155. // Decrement the reference count for the open.
  1156. //
  1157. #if DBG
  1158. NdisDprAcquireSpinLock(&(Adapter->Lock));
  1159. IF_LOG('C');
  1160. NdisDprReleaseSpinLock(&(Adapter->Lock));
  1161. #endif
  1162. NdisInterlockedAddUlong((PULONG)&Open->References, (UINT)-1, &Adapter->Lock);
  1163. } while (CurrentCorrelator != CorrelatorInSrb);
  1164. NdisDprAcquireSpinLock(&(Adapter->Lock));
  1165. Adapter->SendTimeout = FALSE;
  1166. Adapter->NextCorrelatorToComplete =
  1167. (UCHAR)((CurrentCorrelator + 1) % MAX_COMMAND_CORRELATOR);
  1168. //
  1169. // We know that SrbAvailable is FALSE...
  1170. //
  1171. IF_LOG('<');
  1172. SetupSrbCommand(Adapter);
  1173. }
  1174. else
  1175. {
  1176. //
  1177. // Nothing else should pend!!
  1178. //
  1179. NdisWriteErrorLogEntry(
  1180. Adapter->NdisAdapterHandle,
  1181. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  1182. 3,
  1183. handleSrbSsb,
  1184. IBMTOK_ERRMSG_INVALID_CMD,
  1185. (ULONG)TmpUchar);
  1186. #if DBG
  1187. if (IbmtokDbg) DbgPrint("IBMTOK: Error! Got Cmd %x\n",TmpUchar);
  1188. #endif
  1189. }
  1190. WRITE_ADAPTER_REGISTER(
  1191. Adapter,
  1192. ISRA_HIGH_SET,
  1193. ISRA_HIGH_SSB_FREE);
  1194. }
  1195. if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
  1196. {
  1197. GET_SRB_SSB_BITS(Adapter, &IsrpHigh);
  1198. }
  1199. else
  1200. {
  1201. //
  1202. // disable interrupts on the card, since we don't trust ndissyncint to work
  1203. //
  1204. READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
  1205. WRITE_ADAPTER_REGISTER(
  1206. Adapter,
  1207. ISRP_LOW,
  1208. Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
  1209. //
  1210. // update arb_asb
  1211. //
  1212. IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE);
  1213. Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_SRB_RESPONSE | ISRP_HIGH_SSB_RESPONSE));
  1214. //
  1215. // reenable interrupts on the card
  1216. //
  1217. WRITE_ADAPTER_REGISTER(
  1218. Adapter,
  1219. ISRP_LOW,
  1220. ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
  1221. }
  1222. }
  1223. Adapter->HandleSrbRunning = FALSE;
  1224. IF_LOG('H');
  1225. //
  1226. // This macro assumes it is called with the lock held,
  1227. // and releases it.
  1228. //
  1229. IBMTOK_DO_DEFERRED(Adapter);
  1230. }
  1231. extern
  1232. VOID
  1233. IbmtokHandleArbAsb(
  1234. IN PIBMTOK_ADAPTER Adapter
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. This routine is called by the DPC
  1239. and other routines within the driver that notice that
  1240. some deferred processing needs to be done. It's main
  1241. job is to call the interrupt processing code.
  1242. NOTE: THIS ROUTINE IS CALLED WITH THE LOCK HELD!! AND RETURNS WITH
  1243. THE LOCK REALEASED!!
  1244. Arguments:
  1245. Adapter - A pointer to the adapter.
  1246. Return Value:
  1247. None.
  1248. --*/
  1249. {
  1250. UCHAR IsrpHigh;
  1251. PARB_TRANSMIT_DATA_REQUEST TransmitDataArb;
  1252. PARB_RECEIVED_DATA ReceivedDataArb;
  1253. PNDIS_PACKET TransmitPacket;
  1254. SRAM_PTR ReceiveBufferPointer;
  1255. PRECEIVE_BUFFER ReceiveBuffer;
  1256. UINT PacketLength, DummyBytesCopied;
  1257. BOOLEAN FreedSrb;
  1258. PIBMTOK_RESERVED Reserved;
  1259. PUCHAR DhbAddress;
  1260. UINT PacketSize, LookaheadSize;
  1261. PUCHAR FrameData;
  1262. ULONG HeaderLength;
  1263. UCHAR TmpUchar;
  1264. USHORT TmpUshort;
  1265. PUCHAR LookaheadBuffer;
  1266. UCHAR Temp;
  1267. Adapter->References++;
  1268. Adapter->HandleArbRunning = TRUE;
  1269. IF_LOG('j');
  1270. if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
  1271. {
  1272. GET_ARB_ASB_BITS(Adapter, &IsrpHigh);
  1273. }
  1274. else
  1275. {
  1276. //
  1277. // disable interrupts on the card, since we don't trust ndissyncint to work
  1278. //
  1279. READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
  1280. WRITE_ADAPTER_REGISTER(
  1281. Adapter,
  1282. ISRP_LOW,
  1283. Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
  1284. //
  1285. // update arb_asb
  1286. //
  1287. IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
  1288. Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
  1289. //
  1290. // reenable interrupts on the card
  1291. //
  1292. WRITE_ADAPTER_REGISTER(
  1293. Adapter,
  1294. ISRP_LOW,
  1295. ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
  1296. }
  1297. while (IsrpHigh & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE))
  1298. {
  1299. if (IsrpHigh & ISRP_HIGH_ARB_COMMAND)
  1300. {
  1301. NdisReadRegisterUchar(&((PARB_GENERIC)Adapter->ArbAddress)->Command, &TmpUchar);
  1302. switch (TmpUchar)
  1303. {
  1304. case ARB_CMD_DLC_STATUS:
  1305. #if DBG
  1306. if (IbmtokDbg)
  1307. {
  1308. NdisReadRegisterUshort(
  1309. &((PARB_DLC_STATUS)Adapter->ArbAddress)->Status, &TmpUshort);
  1310. DbgPrint("IBMTOK: DLC Status %x\n",
  1311. IBMSHORT_TO_USHORT(TmpUshort));
  1312. }
  1313. #endif
  1314. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1315. ISRA_HIGH_ARB_FREE);
  1316. IF_LOG('#');
  1317. //
  1318. // If it is a counter overflow, we need to queue a
  1319. // DLC.STATISTICS command.
  1320. //
  1321. NdisReadRegisterUshort(
  1322. &((PARB_RING_STATUS_CHANGE)Adapter->ArbAddress)->NetworkStatus,
  1323. &TmpUshort);
  1324. if (IBMSHORT_TO_USHORT(TmpUshort) & 0x0040 )
  1325. {
  1326. //
  1327. // Build a pending operation. It will get run ASAP
  1328. // by ProcessSrbCommand.
  1329. //
  1330. PIBMTOK_PEND_DATA PendOp;
  1331. if (IBMTOK_ALLOC_PHYS(&PendOp,sizeof(IBMTOK_PEND_DATA)) !=
  1332. NDIS_STATUS_SUCCESS)
  1333. {
  1334. NdisWriteErrorLogEntry(
  1335. Adapter->NdisAdapterHandle,
  1336. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1337. 2,
  1338. handleSrbSsb,
  1339. IBMTOK_ERRMSG_ALLOC_MEM);
  1340. break;
  1341. }
  1342. PendOp->Next = NULL;
  1343. PendOp->RequestType = NdisRequestGeneric1;
  1344. PendOp->COMMAND.MAC.ReadLogPending = FALSE;
  1345. if (Adapter->PendQueue == NULL)
  1346. {
  1347. Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
  1348. }
  1349. else
  1350. {
  1351. //
  1352. // Put this operation on the front, so it can
  1353. // correct the error quickly.
  1354. //
  1355. PendOp->Next = Adapter->PendQueue;
  1356. Adapter->PendQueue = PendOp;
  1357. }
  1358. //
  1359. // It is now in the pend
  1360. // queue so we should start that up.
  1361. //
  1362. IbmtokProcessSrbRequests(Adapter);
  1363. }
  1364. break;
  1365. case ARB_CMD_RECEIVED_DATA:
  1366. #if DBG
  1367. if (IbmtokDbg)
  1368. DbgPrint("IBMTOK: Received data\n");
  1369. #endif
  1370. IF_LOG('r');
  1371. if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
  1372. {
  1373. //
  1374. // Do, nothing. This is most likely a stale interrupt. We
  1375. // wait until we get a ring status interrupt telling us that
  1376. // the cable is plugged in.
  1377. //
  1378. break;
  1379. }
  1380. ReceivedDataArb = (PARB_RECEIVED_DATA)Adapter->ArbAddress;
  1381. NdisReadRegisterUshort(&(ReceivedDataArb->ReceiveBuffer), &ReceiveBufferPointer);
  1382. //
  1383. // Prepare for indication.
  1384. //
  1385. Adapter->IndicatedReceiveBuffer = ReceiveBufferPointer;
  1386. ReceiveBuffer = (PRECEIVE_BUFFER)
  1387. ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter, ReceiveBufferPointer) + 2);
  1388. NdisReadRegisterUshort(&(ReceivedDataArb->FrameLength), &PacketSize);
  1389. PacketSize = IBMSHORT_TO_USHORT(PacketSize);
  1390. NdisReadRegisterUshort(&(ReceiveBuffer->BufferLength), &LookaheadSize);
  1391. LookaheadSize = IBMSHORT_TO_USHORT(LookaheadSize);
  1392. WRITE_ADAPTER_REGISTER(
  1393. Adapter,
  1394. ISRA_HIGH_SET,
  1395. ISRA_HIGH_ARB_FREE);
  1396. #if DBG
  1397. if (IbmtokDbg)
  1398. DbgPrint("IBMTOK: indicate len %d, lookahead %d\n", PacketSize, LookaheadSize);
  1399. #endif
  1400. //
  1401. // Calculate how big the header is for this
  1402. // packet.
  1403. //
  1404. FrameData = ReceiveBuffer->FrameData;
  1405. NdisReadRegisterUchar(&FrameData[8], &TmpUchar);
  1406. if (TmpUchar & 0x80)
  1407. {
  1408. //
  1409. // Source routing bit is on in source address.
  1410. //
  1411. NdisReadRegisterUchar(&FrameData[14], &TmpUchar);
  1412. HeaderLength = (TmpUchar & 0x1f) + 14;
  1413. }
  1414. else
  1415. {
  1416. HeaderLength = 14;
  1417. }
  1418. Adapter->IndicatedHeaderLength = (USHORT)HeaderLength;
  1419. Adapter->FramesReceived++;
  1420. NdisDprReleaseSpinLock(&Adapter->Lock);
  1421. //
  1422. // Call into the filter package to do the
  1423. // indication.
  1424. //
  1425. if (LookaheadSize < HeaderLength)
  1426. {
  1427. //
  1428. // Must at least have an address
  1429. //
  1430. if (LookaheadSize >= TR_LENGTH_OF_ADDRESS)
  1431. {
  1432. NdisCreateLookaheadBufferFromSharedMemory(
  1433. (PVOID)FrameData,
  1434. LookaheadSize,
  1435. &LookaheadBuffer);
  1436. if (LookaheadBuffer != NULL)
  1437. {
  1438. //
  1439. // Runt Packet
  1440. //
  1441. TrFilterIndicateReceive(
  1442. Adapter->FilterDB,
  1443. (NDIS_HANDLE)ReceiveBuffer, // context
  1444. LookaheadBuffer, // header
  1445. LookaheadSize, // header length
  1446. NULL, // lookahead
  1447. 0, // lookahead length
  1448. 0);
  1449. NdisDestroyLookaheadBufferFromSharedMemory(LookaheadBuffer);
  1450. }
  1451. }
  1452. }
  1453. else
  1454. {
  1455. NdisCreateLookaheadBufferFromSharedMemory(
  1456. (PVOID)FrameData,
  1457. LookaheadSize,
  1458. &LookaheadBuffer);
  1459. if (LookaheadBuffer != NULL)
  1460. {
  1461. TrFilterIndicateReceive(
  1462. Adapter->FilterDB,
  1463. (NDIS_HANDLE)ReceiveBuffer, // context
  1464. LookaheadBuffer, // header
  1465. HeaderLength, // header length
  1466. LookaheadBuffer + HeaderLength, // lookahead
  1467. LookaheadSize - HeaderLength, // lookahead length
  1468. PacketSize - HeaderLength);
  1469. NdisDestroyLookaheadBufferFromSharedMemory(LookaheadBuffer);
  1470. }
  1471. }
  1472. TrFilterIndicateReceiveComplete( Adapter->FilterDB );
  1473. //
  1474. // Now worry about the ASB.
  1475. //
  1476. NdisDprAcquireSpinLock(&(Adapter->Lock));
  1477. //
  1478. // Set response in ASB, if possible, else queue the response
  1479. //
  1480. if (Adapter->AsbAvailable)
  1481. {
  1482. Adapter->AsbAvailable = FALSE;
  1483. Adapter->UseNextAsbForReceive = FALSE;
  1484. SetupReceivedDataAsb(Adapter, ReceiveBufferPointer);
  1485. WRITE_ADAPTER_REGISTER(
  1486. Adapter,
  1487. ISRA_HIGH_SET,
  1488. ISRA_HIGH_RESPONSE_IN_ASB);
  1489. //
  1490. // LOOPBACK HERE!!
  1491. //
  1492. }
  1493. else
  1494. {
  1495. #if DBG
  1496. if (IbmtokDbg) DbgPrint("W_ASB R\n");
  1497. #endif
  1498. if (Adapter->ReceiveWaitingForAsbEnd == (USHORT)(-1))
  1499. {
  1500. Adapter->ReceiveWaitingForAsbList = ReceiveBufferPointer;
  1501. }
  1502. else
  1503. {
  1504. PVOID PEnd;
  1505. PEnd = SRAM_PTR_TO_PVOID(
  1506. Adapter,
  1507. Adapter->ReceiveWaitingForAsbEnd);
  1508. NdisWriteRegisterUshort(PEnd, ReceiveBufferPointer);
  1509. }
  1510. Adapter->ReceiveWaitingForAsbEnd = ReceiveBufferPointer;
  1511. if (!(Adapter->OutstandingAsbFreeRequest))
  1512. {
  1513. Adapter->OutstandingAsbFreeRequest = TRUE;
  1514. WRITE_ADAPTER_REGISTER(
  1515. Adapter,
  1516. ISRA_HIGH_SET,
  1517. ISRA_HIGH_ASB_FREE_REQUEST);
  1518. IF_LOG('a');
  1519. }
  1520. }
  1521. break;
  1522. case ARB_CMD_RING_STATUS_CHANGE:
  1523. {
  1524. USHORT RingStatus;
  1525. NDIS_STATUS NotifyStatus = 0;
  1526. NdisReadRegisterUshort(
  1527. &((PARB_RING_STATUS_CHANGE)Adapter->ArbAddress)->NetworkStatus,
  1528. &RingStatus);
  1529. RingStatus = IBMSHORT_TO_USHORT(RingStatus);
  1530. #if DBG
  1531. if (IbmtokDbg)
  1532. DbgPrint("IBMTOK: Ring Status %x\n", RingStatus);
  1533. #endif
  1534. WRITE_ADAPTER_REGISTER(
  1535. Adapter,
  1536. ISRA_HIGH_SET,
  1537. ISRA_HIGH_ARB_FREE);
  1538. //
  1539. // If it is a counter overflow, we need to queue a
  1540. // DIR.READ.LOG command.
  1541. //
  1542. if (RingStatus & 0x0080)
  1543. {
  1544. //
  1545. // Build a pending operation. It will get run ASAP
  1546. // by ProcessSrbCommand.
  1547. //
  1548. PIBMTOK_PEND_DATA PendOp;
  1549. if (IBMTOK_ALLOC_PHYS(&PendOp,sizeof(IBMTOK_PEND_DATA)) !=
  1550. NDIS_STATUS_SUCCESS)
  1551. {
  1552. NdisWriteErrorLogEntry(
  1553. Adapter->NdisAdapterHandle,
  1554. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  1555. 2,
  1556. handleSrbSsb,
  1557. IBMTOK_ERRMSG_ALLOC_MEM);
  1558. break;
  1559. }
  1560. PendOp->Next = NULL;
  1561. PendOp->RequestType = NdisRequestGeneric1;
  1562. PendOp->COMMAND.MAC.ReadLogPending = TRUE;
  1563. if (Adapter->PendQueue == NULL)
  1564. {
  1565. Adapter->PendQueue = Adapter->EndOfPendQueue = PendOp;
  1566. }
  1567. else
  1568. {
  1569. //
  1570. // Put this operation on the front, so it can
  1571. // correct the error quickly.
  1572. //
  1573. PendOp->Next = Adapter->PendQueue;
  1574. Adapter->PendQueue = PendOp;
  1575. }
  1576. //
  1577. // It is now in the pend
  1578. // queue so we should start that up.
  1579. // Returns with lock released
  1580. //
  1581. IbmtokProcessSrbRequests(Adapter);
  1582. }
  1583. if (RingStatus & 0x0020)
  1584. {
  1585. //
  1586. // Ring Recovery
  1587. //
  1588. NotifyStatus |= NDIS_RING_RING_RECOVERY;
  1589. }
  1590. if (RingStatus & 0x0040)
  1591. {
  1592. //
  1593. // Single Station
  1594. //
  1595. NotifyStatus |= NDIS_RING_SINGLE_STATION;
  1596. }
  1597. if (RingStatus & 0x0080)
  1598. {
  1599. //
  1600. // Counter Overflow
  1601. //
  1602. NotifyStatus |= NDIS_RING_COUNTER_OVERFLOW;
  1603. }
  1604. if (RingStatus & 0x0100)
  1605. {
  1606. //
  1607. // Remove received
  1608. //
  1609. NotifyStatus |= NDIS_RING_REMOVE_RECEIVED;
  1610. }
  1611. if (RingStatus & 0x0400)
  1612. {
  1613. //
  1614. // Auto-removal
  1615. //
  1616. NotifyStatus |= NDIS_RING_AUTO_REMOVAL_ERROR;
  1617. }
  1618. if (RingStatus & 0x0800)
  1619. {
  1620. //
  1621. // Lobe wire fault
  1622. //
  1623. NotifyStatus |= NDIS_RING_LOBE_WIRE_FAULT;
  1624. }
  1625. if (RingStatus & 0x1000)
  1626. {
  1627. //
  1628. // Transmit Beacon
  1629. //
  1630. NotifyStatus |= NDIS_RING_TRANSMIT_BEACON;
  1631. }
  1632. if (RingStatus & 0x2000)
  1633. {
  1634. //
  1635. // Soft error
  1636. //
  1637. NotifyStatus |= NDIS_RING_SOFT_ERROR;
  1638. }
  1639. if (RingStatus & 0x4000)
  1640. {
  1641. //
  1642. // Hard error
  1643. //
  1644. NotifyStatus |= NDIS_RING_HARD_ERROR;
  1645. }
  1646. if (RingStatus & 0x8000)
  1647. {
  1648. //
  1649. // Signal loss
  1650. //
  1651. NotifyStatus |= NDIS_RING_SIGNAL_LOSS;
  1652. }
  1653. if (NotifyStatus != 0)
  1654. {
  1655. PLIST_ENTRY CurrentLink;
  1656. PIBMTOK_OPEN TempOpen;
  1657. //
  1658. // Indicate Status to all opens
  1659. //
  1660. CurrentLink = Adapter->OpenBindings.Flink;
  1661. while (CurrentLink != &(Adapter->OpenBindings)){
  1662. TempOpen = CONTAINING_RECORD(
  1663. CurrentLink,
  1664. IBMTOK_OPEN,
  1665. OpenList);
  1666. TempOpen->References++;
  1667. NdisDprReleaseSpinLock(&Adapter->Lock);
  1668. NdisIndicateStatus(
  1669. TempOpen->NdisBindingContext,
  1670. NDIS_STATUS_RING_STATUS,
  1671. (PVOID)&NotifyStatus,
  1672. sizeof(NotifyStatus));
  1673. NdisIndicateStatusComplete(TempOpen->NdisBindingContext);
  1674. NdisDprAcquireSpinLock(&Adapter->Lock);
  1675. CurrentLink = CurrentLink->Flink;
  1676. TempOpen->References--;
  1677. }
  1678. Adapter->LastNotifyStatus = NotifyStatus;
  1679. }
  1680. //
  1681. // Handle a cable being unplugged
  1682. //
  1683. if ((RingStatus & 0x5000) == 0x5000)
  1684. {
  1685. // receive and transmit beacon
  1686. //
  1687. // Ok, the cable has been unplugged. We now abort all
  1688. // outstanding sends, etc.
  1689. //
  1690. Adapter->Unplugged = TRUE;
  1691. IbmtokAbortPending(Adapter, NDIS_STATUS_DEVICE_FAILED);
  1692. if ((RingStatus & 0x800) == 0x800)
  1693. {
  1694. Adapter->LobeWireFaultIndicated = TRUE;
  1695. }
  1696. }
  1697. else if ((RingStatus & 0x0020) &&
  1698. !(RingStatus & 0x4000) &&
  1699. (Adapter->Unplugged) &&
  1700. (!Adapter->UnpluggedResetInProgress))
  1701. {
  1702. //
  1703. // Reset the adapter to remove all stale information
  1704. //
  1705. Adapter->UnpluggedResetInProgress = TRUE;
  1706. IbmtokSetupForReset(Adapter, NULL);
  1707. IbmtokHandleDeferred(Adapter);
  1708. }
  1709. }
  1710. break;
  1711. case ARB_CMD_TRANSMIT_DATA_REQUEST:
  1712. #if DBG
  1713. if (IbmtokDbg) DbgPrint("IBMTOK: Transmit data\n");
  1714. #endif
  1715. if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
  1716. {
  1717. //
  1718. // Do, nothing. This is most likely a stale interrupt. We
  1719. // wait until we get a ring status interrupt telling us that
  1720. // the cable is plugged in.
  1721. //
  1722. break;
  1723. }
  1724. TransmitDataArb =
  1725. (PARB_TRANSMIT_DATA_REQUEST)Adapter->ArbAddress;
  1726. //
  1727. // First see if we have to assign the command correlator.
  1728. //
  1729. NdisReadRegisterUchar(&(TransmitDataArb->CommandCorrelator), &TmpUchar);
  1730. TransmitPacket = FindPacketGivenCorrelator(Adapter, TmpUchar);
  1731. if (TransmitPacket == NULL)
  1732. {
  1733. BOOLEAN PacketRemoved;
  1734. //
  1735. // Have to take the correlator out of the SRB
  1736. // ourselves. This means that the SRB must still
  1737. // be occupied by the request for this transmit.
  1738. //
  1739. ASSERT(!Adapter->SrbAvailable);
  1740. FreedSrb = FALSE;
  1741. //
  1742. // This call will remove the packet from the SRB.
  1743. //
  1744. TransmitPacket =
  1745. RemoveTransmitFromSrb(Adapter, &PacketRemoved);
  1746. //
  1747. // This will be NULL if there was an error in
  1748. // the transmit command, but in that case why
  1749. // are we getting this ARB request?? Just exit.
  1750. // The WakeUpDpc will reset the card if it is hosed.
  1751. //
  1752. if ((TransmitPacket == (PNDIS_PACKET)NULL) || !PacketRemoved)
  1753. {
  1754. break;
  1755. }
  1756. }
  1757. else
  1758. {
  1759. FreedSrb = FALSE;
  1760. Reserved =
  1761. PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  1762. }
  1763. NdisDprReleaseSpinLock(&(Adapter->Lock));
  1764. //
  1765. // Fill in the AC and FC bytes.
  1766. //
  1767. NdisReadRegisterUshort(&(TransmitDataArb->DhbPointer), &TmpUshort);
  1768. DhbAddress = (PUCHAR)SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
  1769. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1770. ISRA_HIGH_ARB_FREE);
  1771. //
  1772. // Now copy the data down from TransmitPacket.
  1773. //
  1774. NdisQueryPacket(
  1775. TransmitPacket,
  1776. NULL,
  1777. NULL,
  1778. NULL,
  1779. &PacketLength);
  1780. IbmtokCopyFromPacketToBuffer(
  1781. TransmitPacket,
  1782. 0,
  1783. PacketLength,
  1784. (PCHAR)DhbAddress,
  1785. &DummyBytesCopied);
  1786. //
  1787. // Now worry about the ASB.
  1788. //
  1789. NdisDprAcquireSpinLock(&(Adapter->Lock));
  1790. IF_LOG('c');
  1791. //
  1792. // Set response in ASB, if available, else queue response
  1793. //
  1794. if (Adapter->AsbAvailable)
  1795. {
  1796. Adapter->AsbAvailable = FALSE;
  1797. Adapter->UseNextAsbForReceive = TRUE;
  1798. SetupTransmitStatusAsb(Adapter, TransmitPacket);
  1799. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1800. ISRA_HIGH_RESPONSE_IN_ASB);
  1801. //
  1802. // LOOPBACK HERE!!
  1803. //
  1804. }
  1805. else
  1806. {
  1807. #if DBG
  1808. if (IbmtokDbg) DbgPrint("W_ASB T\n");
  1809. #endif
  1810. PutPacketOnWaitingForAsb(Adapter, TransmitPacket);
  1811. if (!(Adapter->OutstandingAsbFreeRequest))
  1812. {
  1813. Adapter->OutstandingAsbFreeRequest = TRUE;
  1814. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1815. ISRA_HIGH_ASB_FREE_REQUEST);
  1816. IF_LOG('a');
  1817. }
  1818. //
  1819. // FINAL RETURNCODE CHECK HERE!
  1820. //
  1821. }
  1822. //
  1823. // If we freed up the SRB, queue the next command
  1824. // if there is one.
  1825. // Returns with lock released
  1826. //
  1827. if (FreedSrb)
  1828. {
  1829. IbmtokProcessSrbRequests(Adapter);
  1830. }
  1831. break;
  1832. default:
  1833. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1834. ISRA_HIGH_ARB_FREE);
  1835. break;
  1836. }
  1837. }
  1838. if (IsrpHigh & ISRP_HIGH_ASB_FREE)
  1839. {
  1840. BOOLEAN ReceiveNeedsAsb = FALSE;
  1841. BOOLEAN TransmitNeedsAsb = FALSE;
  1842. //
  1843. // Check whether we have stuff to do.
  1844. //
  1845. IF_LOG('A');
  1846. if (Adapter->Unplugged && !Adapter->UnpluggedResetInProgress)
  1847. {
  1848. //
  1849. // Do, nothing. This is most likely a stale interrupt. We
  1850. // wait until we get a ring status interrupt telling us that
  1851. // the cable is plugged in.
  1852. //
  1853. break;
  1854. }
  1855. ASSERT(Adapter->AsbAvailable == FALSE);
  1856. ASSERT(Adapter->OutstandingAsbFreeRequest == TRUE);
  1857. if (Adapter->ReceiveWaitingForAsbList != (USHORT)-1)
  1858. {
  1859. ReceiveNeedsAsb = TRUE;
  1860. }
  1861. if (Adapter->FirstWaitingForAsb != NULL)
  1862. {
  1863. TransmitNeedsAsb = TRUE;
  1864. }
  1865. if (ReceiveNeedsAsb && (!TransmitNeedsAsb || Adapter->UseNextAsbForReceive))
  1866. {
  1867. SRAM_PTR ReceiveBufferPointer;
  1868. PVOID PFront;
  1869. #if DBG
  1870. if (IbmtokDbg) DbgPrint("ASB R\n");
  1871. #endif
  1872. IF_LOG('R');
  1873. //
  1874. // Save ReceiveWaitingForAsb so we can release
  1875. // the spinlock.
  1876. //
  1877. ReceiveBufferPointer = Adapter->ReceiveWaitingForAsbList;
  1878. if (Adapter->ReceiveWaitingForAsbList == Adapter->ReceiveWaitingForAsbEnd)
  1879. {
  1880. Adapter->ReceiveWaitingForAsbList = (USHORT)-1;
  1881. Adapter->ReceiveWaitingForAsbEnd = (USHORT)-1;
  1882. }
  1883. else
  1884. {
  1885. PFront = SRAM_PTR_TO_PVOID(Adapter,ReceiveBufferPointer);
  1886. NdisReadRegisterUshort(
  1887. ((PUSHORT)PFront),
  1888. &(Adapter->ReceiveWaitingForAsbList));
  1889. }
  1890. Adapter->AsbAvailable = FALSE;
  1891. Adapter->UseNextAsbForReceive = FALSE;
  1892. //
  1893. // Fill in the ASB and submit it.
  1894. //
  1895. SetupReceivedDataAsb(Adapter, ReceiveBufferPointer);
  1896. if (TransmitNeedsAsb)
  1897. {
  1898. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1899. ISRA_HIGH_RESPONSE_IN_ASB | ISRA_HIGH_ASB_FREE_REQUEST);
  1900. }
  1901. else
  1902. {
  1903. Adapter->OutstandingAsbFreeRequest = FALSE;
  1904. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1905. ISRA_HIGH_RESPONSE_IN_ASB);
  1906. }
  1907. }
  1908. else if (TransmitNeedsAsb)
  1909. {
  1910. PNDIS_PACKET AsbPacket = Adapter->FirstWaitingForAsb;
  1911. PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(AsbPacket);
  1912. #if DBG
  1913. if (IbmtokDbg) DbgPrint("ASB T\n");
  1914. #endif
  1915. IF_LOG('T');
  1916. //
  1917. // Take the packet off of WaitingForAsb;
  1918. //
  1919. Adapter->FirstWaitingForAsb = Reserved->Next;
  1920. Adapter->AsbAvailable = FALSE;
  1921. Adapter->UseNextAsbForReceive = TRUE;
  1922. //
  1923. // Now fill in the ASB and fire it off.
  1924. //
  1925. SetupTransmitStatusAsb(Adapter, AsbPacket);
  1926. if (ReceiveNeedsAsb || (Adapter->FirstWaitingForAsb != NULL))
  1927. {
  1928. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1929. ISRA_HIGH_RESPONSE_IN_ASB | ISRA_HIGH_ASB_FREE_REQUEST);
  1930. }
  1931. else
  1932. {
  1933. Adapter->OutstandingAsbFreeRequest = FALSE;
  1934. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  1935. ISRA_HIGH_RESPONSE_IN_ASB);
  1936. }
  1937. //
  1938. // LOOPBACK HERE!!
  1939. //
  1940. }
  1941. else
  1942. {
  1943. #if DBG
  1944. if (IbmtokDbg) DbgPrint("ASB -\n");
  1945. #endif
  1946. Adapter->AsbAvailable = TRUE;
  1947. }
  1948. }
  1949. if (Adapter->CardType != IBM_TOKEN_RING_PCMCIA)
  1950. {
  1951. GET_ARB_ASB_BITS(Adapter, &IsrpHigh);
  1952. }
  1953. else
  1954. {
  1955. //
  1956. // disable interrupts on the card, since we don't trust ndissyncint to work
  1957. //
  1958. READ_ADAPTER_REGISTER(Adapter, ISRP_LOW, &Temp);
  1959. WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
  1960. Temp & (~(ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE) ) );
  1961. //
  1962. // update arb_asb
  1963. //
  1964. IsrpHigh = (Adapter->IsrpBits) & (ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE);
  1965. Adapter->IsrpBits = (Adapter->IsrpBits) & (~(ISRP_HIGH_ARB_COMMAND | ISRP_HIGH_ASB_FREE));
  1966. //
  1967. // reenable interrupts on the card
  1968. //
  1969. WRITE_ADAPTER_REGISTER(Adapter, ISRP_LOW,
  1970. ISRP_LOW_NO_CHANNEL_CHECK | ISRP_LOW_INTERRUPT_ENABLE);
  1971. }
  1972. }
  1973. Adapter->HandleArbRunning = FALSE;
  1974. IF_LOG('J');
  1975. //
  1976. // This macro assumes it is called with the lock held,
  1977. // and releases it.
  1978. //
  1979. IBMTOK_DO_DEFERRED(Adapter);
  1980. }
  1981. STATIC
  1982. VOID
  1983. CleanupResetFailure(
  1984. IN PIBMTOK_ADAPTER Adapter,
  1985. PNDIS_STATUS IndicateStatus,
  1986. IN ULONG FailureCode,
  1987. IN ULONG ResetStage
  1988. )
  1989. /*++
  1990. Routine Description:
  1991. Clean up if a reset fails partway through. Called
  1992. from HandleResetStaging.
  1993. Called with the lock held and returns with it held.
  1994. Arguments:
  1995. Adapter - The adapter that the reset is for.
  1996. IndicateStatus - Status to indicate to the protocols, or NULL.
  1997. FailureCode - A code to include in the error log.
  1998. ResetStage - The stage of the reset where the failure occured.
  1999. Return Value:
  2000. None.
  2001. --*/
  2002. {
  2003. PLIST_ENTRY CurrentLink;
  2004. PIBMTOK_OPEN TempOpen;
  2005. if (!Adapter->UnpluggedResetInProgress)
  2006. {
  2007. //
  2008. // signal failure....
  2009. //
  2010. Adapter->CurrentRingState = NdisRingStateRingFailure;
  2011. //
  2012. // Indicate Status to all opens
  2013. //
  2014. CurrentLink = Adapter->OpenBindings.Flink;
  2015. while (CurrentLink != &(Adapter->OpenBindings))
  2016. {
  2017. TempOpen = CONTAINING_RECORD(CurrentLink, IBMTOK_OPEN, OpenList);
  2018. TempOpen->References++;
  2019. NdisReleaseSpinLock(&Adapter->Lock);
  2020. if (IndicateStatus)
  2021. {
  2022. NdisIndicateStatus(TempOpen->NdisBindingContext,
  2023. NDIS_STATUS_CLOSED,
  2024. IndicateStatus,
  2025. sizeof(NDIS_STATUS));
  2026. }
  2027. else
  2028. {
  2029. NdisIndicateStatus(TempOpen->NdisBindingContext,
  2030. NDIS_STATUS_CLOSED,
  2031. NULL,
  2032. 0);
  2033. }
  2034. NdisIndicateStatusComplete(TempOpen->NdisBindingContext);
  2035. NdisAcquireSpinLock(&Adapter->Lock);
  2036. CurrentLink = CurrentLink->Flink;
  2037. TempOpen->References--;
  2038. }
  2039. NdisWriteErrorLogEntry(
  2040. Adapter->NdisAdapterHandle,
  2041. NDIS_ERROR_CODE_HARDWARE_FAILURE,
  2042. 4,
  2043. handleResetStaging,
  2044. IBMTOK_ERRMSG_BRINGUP_FAILURE,
  2045. FailureCode,
  2046. ResetStage);
  2047. }
  2048. else
  2049. {
  2050. //
  2051. // Set this to false, we will try again later.
  2052. //
  2053. Adapter->LobeWireFaultIndicated = TRUE;
  2054. Adapter->UnpluggedResetInProgress = FALSE;
  2055. }
  2056. //
  2057. // Set Abort
  2058. //
  2059. Adapter->CurrentResetStage = 4;
  2060. SetResetVariables(Adapter);
  2061. Adapter->OpenInProgress = FALSE;
  2062. Adapter->NotAcceptingRequests = TRUE;
  2063. Adapter->ResetInProgress = FALSE;
  2064. Adapter->ResetInterruptAllowed = FALSE;
  2065. Adapter->ResetInterruptHasArrived = FALSE;
  2066. if (Adapter->ResettingOpen != NULL)
  2067. {
  2068. PIBMTOK_OPEN Open = Adapter->ResettingOpen;
  2069. //
  2070. // Decrement the reference count that was incremented
  2071. // in SetupForReset.
  2072. //
  2073. Open->References--;
  2074. NdisReleaseSpinLock(&Adapter->Lock);
  2075. NdisCompleteReset(Open->NdisBindingContext, NDIS_STATUS_FAILURE);
  2076. NdisAcquireSpinLock(&Adapter->Lock);
  2077. }
  2078. }
  2079. STATIC
  2080. VOID
  2081. HandleResetStaging(
  2082. IN PIBMTOK_ADAPTER Adapter
  2083. )
  2084. /*++
  2085. Routine Description:
  2086. Handles the next stage of the transmit interrupt,
  2087. knowing that an SRB interrupt just came through.
  2088. Called with the lock held and returns with it held.
  2089. Arguments:
  2090. Adapter - The adapter that the reset is for.
  2091. Return Value:
  2092. None.
  2093. --*/
  2094. {
  2095. USHORT TmpUshort;
  2096. UCHAR TmpUchar;
  2097. switch (Adapter->CurrentResetStage)
  2098. {
  2099. case 1:
  2100. {
  2101. //
  2102. // The adapter just finished being reset.
  2103. //
  2104. USHORT WrbOffset;
  2105. PSRB_BRING_UP_RESULT BringUpSrb;
  2106. PSRB_OPEN_ADAPTER OpenSrb;
  2107. UCHAR Value1, Value2;
  2108. #if DBG
  2109. if (IbmtokDbg) DbgPrint("IBMTOK: RESET done\n");
  2110. #endif
  2111. READ_ADAPTER_REGISTER(Adapter, WRBR_LOW, &Value1);
  2112. READ_ADAPTER_REGISTER(Adapter, WRBR_HIGH, &Value2);
  2113. WrbOffset = (USHORT)(((USHORT)Value1) << 8) + (USHORT)Value2;
  2114. Adapter->InitialWrbOffset = WrbOffset;
  2115. BringUpSrb = (PSRB_BRING_UP_RESULT)(Adapter->SharedRam + WrbOffset);
  2116. NdisReadRegisterUshort(&(BringUpSrb->ReturnCode), &TmpUshort);
  2117. if (TmpUshort != 0x0000)
  2118. {
  2119. CleanupResetFailure (Adapter, NULL, TmpUshort, 1);
  2120. break;
  2121. }
  2122. //
  2123. // Now set up the open SRB request.
  2124. //
  2125. OpenSrb = (PSRB_OPEN_ADAPTER)
  2126. (Adapter->SharedRam + Adapter->InitialWrbOffset);
  2127. IBMTOK_ZERO_MAPPED_MEMORY(OpenSrb, sizeof(SRB_OPEN_ADAPTER));
  2128. NdisWriteRegisterUchar(&(OpenSrb->Command), SRB_CMD_OPEN_ADAPTER);
  2129. NdisWriteRegisterUshort(&(OpenSrb->OpenOptions),
  2130. (USHORT)(OPEN_CONTENDER |
  2131. (Adapter->EarlyTokenRelease ?
  2132. 0 :
  2133. OPEN_MODIFIED_TOKEN_RELEASE)));
  2134. NdisMoveToMappedMemory((PCHAR)OpenSrb->NodeAddress,
  2135. Adapter->NetworkAddress,
  2136. TR_LENGTH_OF_ADDRESS);
  2137. WRITE_IBMSHORT(OpenSrb->ReceiveBufferNum,
  2138. Adapter->NumberOfReceiveBuffers);
  2139. WRITE_IBMSHORT(OpenSrb->ReceiveBufferLen,
  2140. Adapter->ReceiveBufferLength);
  2141. WRITE_IBMSHORT(OpenSrb->TransmitBufferLen,
  2142. Adapter->TransmitBufferLength);
  2143. NdisWriteRegisterUchar(&(OpenSrb->TransmitBufferNum),
  2144. (UCHAR)Adapter->NumberOfTransmitBuffers);
  2145. Adapter->CurrentResetStage = 2;
  2146. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2147. ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
  2148. IF_LOG('1');
  2149. break;
  2150. }
  2151. case 2:
  2152. {
  2153. //
  2154. // Handle the result of the DIR.OPEN.ADAPTER command.
  2155. //
  2156. PSRB_OPEN_RESPONSE OpenResponseSrb;
  2157. #if DBG
  2158. if (IbmtokDbg) DbgPrint("IBMTOK: OPEN done\n");
  2159. #endif
  2160. OpenResponseSrb = (PSRB_OPEN_RESPONSE)
  2161. (Adapter->SharedRam + Adapter->InitialWrbOffset);
  2162. NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode), &TmpUchar);
  2163. if (TmpUchar != 0)
  2164. {
  2165. NDIS_STATUS IndicateStatus;
  2166. NdisReadRegisterUshort(&(OpenResponseSrb->ErrorCode),
  2167. &(Adapter->OpenErrorCode));
  2168. Adapter->OpenErrorCode = IBMSHORT_TO_USHORT(Adapter->OpenErrorCode);
  2169. IndicateStatus =
  2170. NDIS_STATUS_TOKEN_RING_OPEN_ERROR |
  2171. (NDIS_STATUS)(Adapter->OpenErrorCode);
  2172. CleanupResetFailure (Adapter, &IndicateStatus, Adapter->OpenErrorCode, 2);
  2173. break;
  2174. }
  2175. IF_LOG('2');
  2176. #if DBG
  2177. NdisReadRegisterUchar(&(OpenResponseSrb->ReturnCode),&TmpUchar);
  2178. if (IbmtokDbg) DbgPrint("IBMTOK: RESET OPEN, Return code = %x, at %lx\n",
  2179. TmpUchar,
  2180. OpenResponseSrb);
  2181. #endif
  2182. NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort);
  2183. Adapter->SrbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
  2184. NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort);
  2185. Adapter->SsbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
  2186. NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort);
  2187. Adapter->ArbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
  2188. NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort);
  2189. Adapter->AsbAddress = SRAM_PTR_TO_PVOID(Adapter,TmpUshort);
  2190. #if DBG
  2191. if (IbmtokDbg)
  2192. {
  2193. USHORT TmpUshort1;
  2194. USHORT TmpUshort2;
  2195. USHORT TmpUshort3;
  2196. USHORT TmpUshort4;
  2197. NdisReadRegisterUshort(&(OpenResponseSrb->SrbPointer), &TmpUshort1);
  2198. NdisReadRegisterUshort(&(OpenResponseSrb->SsbPointer), &TmpUshort2);
  2199. NdisReadRegisterUshort(&(OpenResponseSrb->ArbPointer), &TmpUshort3);
  2200. NdisReadRegisterUshort(&(OpenResponseSrb->AsbPointer), &TmpUshort4);
  2201. DbgPrint("IBMTOK: Offsets: SRB %x SSB %x ARB %x ASB %x\n",
  2202. IBMSHORT_TO_USHORT(TmpUshort1),
  2203. IBMSHORT_TO_USHORT(TmpUshort2),
  2204. IBMSHORT_TO_USHORT(TmpUshort3),
  2205. IBMSHORT_TO_USHORT(TmpUshort4));
  2206. }
  2207. #endif
  2208. //
  2209. // Now queue a SET.FUNCT.ADDRESS command if needed.
  2210. //
  2211. Adapter->CurrentCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
  2212. if (SetAdapterFunctionalAddress(Adapter) == NDIS_STATUS_SUCCESS)
  2213. {
  2214. //
  2215. // This means that the command did not have to be
  2216. // queued, so we are done with this step.
  2217. //
  2218. if (SetAdapterGroupAddress(Adapter) == NDIS_STATUS_SUCCESS)
  2219. {
  2220. //
  2221. // This one did not pend either, we are done.
  2222. //
  2223. IbmtokFinishAdapterReset(Adapter);
  2224. }
  2225. else
  2226. {
  2227. Adapter->CurrentResetStage = 4;
  2228. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2229. ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
  2230. }
  2231. }
  2232. else
  2233. {
  2234. Adapter->CurrentResetStage = 3;
  2235. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2236. ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
  2237. }
  2238. break;
  2239. }
  2240. case 3:
  2241. {
  2242. //
  2243. // The SET.FUNCT.ADDRESS command finished.
  2244. //
  2245. PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
  2246. UCHAR ReturnCode;
  2247. NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
  2248. IF_LOG('3');
  2249. #if DBG
  2250. if (IbmtokDbg) DbgPrint("IBMTOK: SET FUNCT done\n");
  2251. #endif
  2252. if (ReturnCode == 0x00)
  2253. {
  2254. if (SetAdapterGroupAddress(Adapter) == NDIS_STATUS_SUCCESS)
  2255. {
  2256. //
  2257. // This one did not pend, the dishes are done.
  2258. //
  2259. IbmtokFinishAdapterReset(Adapter);
  2260. }
  2261. else
  2262. {
  2263. Adapter->CurrentResetStage = 4;
  2264. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2265. ISRA_HIGH_COMMAND_IN_SRB | ISRA_HIGH_SRB_FREE_REQUEST);
  2266. }
  2267. }
  2268. else if (ReturnCode != 0xfe)
  2269. {
  2270. CleanupResetFailure (Adapter, NULL, (ULONG)ReturnCode, 3);
  2271. }
  2272. break;
  2273. }
  2274. case 4:
  2275. {
  2276. //
  2277. // The SET.GROUP.ADDRESS command finished.
  2278. //
  2279. PSRB_GENERIC GenericSrb = (PSRB_GENERIC)Adapter->SrbAddress;
  2280. UCHAR ReturnCode;
  2281. NdisReadRegisterUchar(&(GenericSrb->ReturnCode), &ReturnCode);
  2282. IF_LOG('4');
  2283. #if DBG
  2284. if (IbmtokDbg) DbgPrint("IBMTOK: SET GROUP done\n");
  2285. #endif
  2286. if (ReturnCode == 0x00)
  2287. {
  2288. IbmtokFinishAdapterReset(Adapter);
  2289. }
  2290. else if (ReturnCode != 0xfe)
  2291. {
  2292. CleanupResetFailure (Adapter, NULL, (ULONG)ReturnCode, 4);
  2293. }
  2294. break;
  2295. }
  2296. }
  2297. }
  2298. STATIC
  2299. PNDIS_PACKET
  2300. RemoveTransmitFromSrb(
  2301. IN PIBMTOK_ADAPTER Adapter,
  2302. OUT PBOOLEAN PacketRemoved
  2303. )
  2304. /*++
  2305. Routine Description:
  2306. Cleans a transmit out of the SRB if one was there.
  2307. NOTE : Should be called with the spinlock held!!!
  2308. Arguments:
  2309. Adapter - The adapter that this packet is coming through.
  2310. PacketRemoved - TRUE if the packet was removed from the SRB.
  2311. Return Value:
  2312. The packet removed.
  2313. --*/
  2314. {
  2315. PNDIS_PACKET TransmitPacket;
  2316. PIBMTOK_RESERVED Reserved;
  2317. UCHAR TmpUchar;
  2318. PSRB_TRANSMIT_DIR_FRAME TransmitSrb =
  2319. (PSRB_TRANSMIT_DIR_FRAME)Adapter->SrbAddress;
  2320. NdisReadRegisterUchar(&(TransmitSrb->ReturnCode), &TmpUchar);
  2321. if (TmpUchar == 0xfe)
  2322. {
  2323. //
  2324. // The TRANSMIT command was just put in the SRB, and
  2325. // the adapter has not yet had time to process it.
  2326. // We return now before setting SrbAvailable to TRUE,
  2327. // so the command is left to be processed.
  2328. //
  2329. // NOTE: If this happens on a call from inside the
  2330. // ARB_TRANSMIT_DATA interrupt handler, we will fail
  2331. // on an assertion when we return NULL.
  2332. //
  2333. *PacketRemoved = FALSE;
  2334. return (PNDIS_PACKET)NULL;
  2335. }
  2336. //
  2337. // if there was a packet in there, put it in
  2338. // the correlator array.
  2339. //
  2340. TransmitPacket = Adapter->TransmittingPacket;
  2341. Adapter->TransmittingPacket = (PNDIS_PACKET)NULL;
  2342. if (TransmitPacket == NULL)
  2343. {
  2344. *PacketRemoved = FALSE;
  2345. return(NULL);
  2346. }
  2347. //
  2348. // This will be TRUE whatever happens next.
  2349. //
  2350. *PacketRemoved = TRUE;
  2351. Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  2352. //
  2353. // Check that the return code is OK.
  2354. //
  2355. if (TmpUchar != 0xff)
  2356. {
  2357. PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  2358. //
  2359. // Fail the transmit.
  2360. //
  2361. //
  2362. // If doing LOOPBACK, this should really be a check
  2363. // of ReadyToComplete etc.
  2364. //
  2365. #if DBG
  2366. if (IbmtokDbg) {
  2367. UCHAR TmpUchar1, TmpUchar2;
  2368. NdisReadRegisterUchar(&TransmitSrb->ReturnCode, &TmpUchar1);
  2369. NdisReadRegisterUchar(&TransmitSrb->Command, &TmpUchar2);
  2370. DbgPrint("IBMTOK: Transmit failed in SRB: %x for %x\n", TmpUchar1, TmpUchar2);
  2371. }
  2372. #endif
  2373. #ifdef CHECK_DUP_SENDS
  2374. {
  2375. VOID IbmtokRemovePacketFromList(PIBMTOK_ADAPTER, PNDIS_PACKET);
  2376. IbmtokRemovePacketFromList(Adapter, TransmitPacket);
  2377. }
  2378. #endif
  2379. Adapter->FrameTransmitErrors++;
  2380. NdisReleaseSpinLock(&(Adapter->Lock));
  2381. NdisCompleteSend(Open->NdisBindingContext, Reserved->Packet, NDIS_STATUS_FAILURE);
  2382. NdisAcquireSpinLock(&(Adapter->Lock));
  2383. Adapter->SendTimeout = FALSE;
  2384. //
  2385. // Decrement the reference count for the open.
  2386. //
  2387. Open->References--;
  2388. //
  2389. // This will cause an assertion failure if we were
  2390. // called from the ARB_TRANSMIT_DATA handler.
  2391. //
  2392. return (PNDIS_PACKET)NULL;
  2393. }
  2394. //
  2395. // Put the packet in the correlator array.
  2396. //
  2397. Reserved->CorrelatorAssigned = TRUE;
  2398. NdisReadRegisterUchar(&(TransmitSrb->CommandCorrelator), &(Reserved->CommandCorrelator));
  2399. PutPacketInCorrelatorArray(Adapter, TransmitPacket);
  2400. return TransmitPacket;
  2401. }
  2402. VOID
  2403. SetupSrbCommand(
  2404. IN PIBMTOK_ADAPTER Adapter
  2405. )
  2406. /*++
  2407. Routine Description:
  2408. Fills in the SRB with the next request. It first checks
  2409. if there is a pended request outstanding, then
  2410. handles any queued transmits.
  2411. Called with the spinlock held.
  2412. NOTE: Should be called with Adapter->SrbAvailable == FALSE.
  2413. Arguments:
  2414. Adapter - The Adapter to process interrupts for.
  2415. Return Value:
  2416. None.
  2417. --*/
  2418. {
  2419. if (Adapter->PendQueue != NULL)
  2420. {
  2421. //
  2422. // This will copy the appropriate info out of the
  2423. // pend queue.
  2424. //
  2425. if (StartPendQueueOp(Adapter) == NDIS_STATUS_PENDING)
  2426. {
  2427. //
  2428. // Indicate the SRB command.
  2429. //
  2430. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2431. ISRA_HIGH_COMMAND_IN_SRB);
  2432. return;
  2433. }
  2434. }
  2435. //
  2436. // If we reach here, the pend queue was empty or
  2437. // else StartPendQueueOp drained the entire queue
  2438. // without an operation needing the SRB.
  2439. //
  2440. if (Adapter->FirstTransmit != NULL)
  2441. {
  2442. //
  2443. // Remove the packet from the queue.
  2444. //
  2445. PNDIS_PACKET TransmitPacket = Adapter->FirstTransmit;
  2446. PIBMTOK_RESERVED Reserved =
  2447. PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  2448. Adapter->FirstTransmit = Reserved->Next;
  2449. Adapter->TransmittingPacket = TransmitPacket;
  2450. //
  2451. // set up the send - this sets the packet equal
  2452. // to Adapter->TransmittingPacket;
  2453. //
  2454. SetupTransmitFrameSrb(Adapter, TransmitPacket);
  2455. //
  2456. // Indicate the SRB command.
  2457. //
  2458. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2459. ISRA_HIGH_COMMAND_IN_SRB);
  2460. }
  2461. else
  2462. {
  2463. Adapter->SrbAvailable = TRUE;
  2464. }
  2465. }
  2466. extern
  2467. VOID
  2468. IbmtokForceAdapterInterrupt(
  2469. IN PIBMTOK_ADAPTER Adapter
  2470. )
  2471. /*++
  2472. Routine Description:
  2473. This forces an adapter interrupt by queueing an
  2474. INTERRUPT SRB.
  2475. This is called with the spinlock held, and also
  2476. Adapter->SrbAvailable must be TRUE.
  2477. Arguments:
  2478. Adapter - The Adapter to force the interrupt on.
  2479. Return Value:
  2480. None.
  2481. --*/
  2482. {
  2483. PSRB_INTERRUPT InterruptSrb =
  2484. (PSRB_INTERRUPT)Adapter->SrbAddress;
  2485. ASSERT(Adapter->SrbAvailable);
  2486. Adapter->SrbAvailable = FALSE;
  2487. NdisWriteRegisterUchar(&(InterruptSrb->Command), SRB_CMD_INTERRUPT);
  2488. NdisWriteRegisterUchar(&(InterruptSrb->ReturnCode), 0xfe);
  2489. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2490. ISRA_HIGH_COMMAND_IN_SRB);
  2491. IF_LOG('O');
  2492. }
  2493. STATIC
  2494. VOID
  2495. SetupTransmitFrameSrb(
  2496. IN PIBMTOK_ADAPTER Adapter,
  2497. IN PNDIS_PACKET Packet
  2498. )
  2499. /*++
  2500. Routine Description:
  2501. This routine sets up the SRB for a TRANSMIT.DIR.FRAME.
  2502. Arguments:
  2503. Adapter - The adapter that this packet is coming through.
  2504. Packet - The packet that is being sent.
  2505. Return Value:
  2506. None.
  2507. --*/
  2508. {
  2509. PSRB_TRANSMIT_DIR_FRAME TransmitSrb =
  2510. (PSRB_TRANSMIT_DIR_FRAME)Adapter->SrbAddress;
  2511. UNREFERENCED_PARAMETER(Packet);
  2512. NdisWriteRegisterUchar(&(TransmitSrb->Command), SRB_CMD_TRANSMIT_DIR_FRAME);
  2513. NdisWriteRegisterUchar(&(TransmitSrb->CommandCorrelator), 0x00);
  2514. NdisWriteRegisterUchar(&(TransmitSrb->ReturnCode), 0xfe); // will change to 0xff or error
  2515. NdisWriteRegisterUshort(&(TransmitSrb->StationId), USHORT_TO_IBMSHORT(0x00));
  2516. IF_LOG('x');
  2517. }
  2518. STATIC
  2519. VOID
  2520. SetupTransmitStatusAsb(
  2521. IN PIBMTOK_ADAPTER Adapter,
  2522. IN PNDIS_PACKET Packet
  2523. )
  2524. /*++
  2525. Routine Description:
  2526. This routine sets up the ASB for a response from
  2527. a TRANSMIT.DATA.REQUEST.
  2528. Arguments:
  2529. Adapter - The adapter that this packet is coming through.
  2530. Packet - The packet that has been copied down.
  2531. Return Value:
  2532. None.
  2533. --*/
  2534. {
  2535. PASB_TRANSMIT_DATA_STATUS TransmitDataAsb;
  2536. UINT PacketLength;
  2537. PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
  2538. NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
  2539. TransmitDataAsb = (PASB_TRANSMIT_DATA_STATUS)
  2540. Adapter->AsbAddress;
  2541. NdisWriteRegisterUchar(&(TransmitDataAsb->Command), SRB_CMD_TRANSMIT_DIR_FRAME);
  2542. NdisWriteRegisterUchar(&(TransmitDataAsb->CommandCorrelator),
  2543. Reserved->CommandCorrelator);
  2544. NdisWriteRegisterUchar(&(TransmitDataAsb->ReturnCode), 0x00);
  2545. NdisWriteRegisterUshort(&(TransmitDataAsb->FrameLength),
  2546. USHORT_TO_IBMSHORT(PacketLength));
  2547. IF_LOG('X');
  2548. }
  2549. STATIC
  2550. VOID
  2551. SetupAdapterStatisticsSrb(
  2552. IN PIBMTOK_ADAPTER Adapter
  2553. )
  2554. /*++
  2555. Routine Description:
  2556. This routine sets up the SRB for a DLC.STATISTICS.
  2557. Arguments:
  2558. Adapter - A pointer to the adapter.
  2559. Return Value:
  2560. None.
  2561. --*/
  2562. {
  2563. PSRB_DLC_STATS StatsSrb = (PSRB_DLC_STATS)(Adapter->SrbAddress);
  2564. NdisWriteRegisterUchar(&(StatsSrb->Command), SRB_CMD_DLC_STATISTICS);
  2565. NdisWriteRegisterUshort(&(StatsSrb->StationId), USHORT_TO_IBMSHORT(0x00));
  2566. NdisWriteRegisterUchar((PUCHAR)(&(StatsSrb->ReturnCode)), 0x80); // Resets counters
  2567. }
  2568. STATIC
  2569. VOID
  2570. GetAdapterStatisticsFromSrb(
  2571. PIBMTOK_ADAPTER Adapter
  2572. )
  2573. /*++
  2574. Routine Description:
  2575. This routine reads the statistics after a DLC.STATISTICS has completed
  2576. and stores the results in the adapter structure.
  2577. Arguments:
  2578. Adapter - A pointer to the adapter.
  2579. Return Value:
  2580. None.
  2581. --*/
  2582. {
  2583. PSRB_DLC_STATS StatsSrb = (PSRB_DLC_STATS)(Adapter->SrbAddress);
  2584. PDLC_COUNTERS Counters;
  2585. USHORT TmpUshort;
  2586. UCHAR TmpUchar;
  2587. NdisReadRegisterUshort(&StatsSrb->CountersOffset, &TmpUshort);
  2588. Counters = (PDLC_COUNTERS) (((PUCHAR)(Adapter->SrbAddress)) +
  2589. IBMSHORT_TO_USHORT(TmpUshort));
  2590. NdisReadRegisterUshort(&Counters->TransmitCount, &TmpUshort);
  2591. Adapter->FramesTransmitted += IBMSHORT_TO_USHORT(TmpUshort);
  2592. NdisReadRegisterUshort(&Counters->ReceiveCount, &TmpUshort);
  2593. Adapter->FramesReceived += IBMSHORT_TO_USHORT(TmpUshort);
  2594. NdisReadRegisterUchar(&Counters->TransmitErrors, &TmpUchar);
  2595. Adapter->FrameTransmitErrors += TmpUchar;
  2596. NdisReadRegisterUchar(&Counters->ReceiveErrors, &TmpUchar);
  2597. Adapter->FrameReceiveErrors += TmpUchar;
  2598. }
  2599. STATIC
  2600. VOID
  2601. GetAdapterErrorsFromSrb(
  2602. PIBMTOK_ADAPTER Adapter
  2603. )
  2604. /*++
  2605. Routine Description:
  2606. This routine reads the statistics after a DIR.READ.LOG has completed
  2607. and stores the results in the adapter structure.
  2608. Arguments:
  2609. Adapter - A pointer to the adapter.
  2610. Return Value:
  2611. None.
  2612. --*/
  2613. {
  2614. PSRB_READ_LOG ReadLogSrb = (PSRB_READ_LOG)(Adapter->SrbAddress);
  2615. ULONG TmpUchar;
  2616. NdisReadRegisterUchar(&ReadLogSrb->LineErrors, &TmpUchar);
  2617. Adapter->LineErrors += TmpUchar;
  2618. NdisReadRegisterUchar(&ReadLogSrb->InternalErrors, &TmpUchar);
  2619. Adapter->InternalErrors += TmpUchar;
  2620. NdisReadRegisterUchar(&ReadLogSrb->BurstErrors, &TmpUchar);
  2621. Adapter->BurstErrors += TmpUchar;
  2622. NdisReadRegisterUchar(&ReadLogSrb->AcErrors, &TmpUchar);
  2623. Adapter->AcErrors += TmpUchar;
  2624. NdisReadRegisterUchar(&ReadLogSrb->AbortDelimeters, &TmpUchar);
  2625. Adapter->AbortDelimeters += TmpUchar;
  2626. NdisReadRegisterUchar(&ReadLogSrb->LostFrames, &TmpUchar);
  2627. Adapter->LostFrames += TmpUchar;
  2628. NdisReadRegisterUchar(&ReadLogSrb->ReceiveCongestionCount, &TmpUchar);
  2629. Adapter->ReceiveCongestionCount += TmpUchar;
  2630. NdisReadRegisterUchar(&ReadLogSrb->FrameCopiedErrors, &TmpUchar);
  2631. Adapter->FrameCopiedErrors += TmpUchar;
  2632. NdisReadRegisterUchar(&ReadLogSrb->FrequencyErrors, &TmpUchar);
  2633. Adapter->FrequencyErrors += TmpUchar;
  2634. NdisReadRegisterUchar(&ReadLogSrb->TokenErrors, &TmpUchar);
  2635. Adapter->TokenErrors += TmpUchar;
  2636. }
  2637. STATIC
  2638. VOID
  2639. SetupAdapterErrorsSrb(
  2640. PIBMTOK_ADAPTER Adapter
  2641. )
  2642. /*++
  2643. Routine Description:
  2644. This routine sets up the SRB for a DIR.READ.LOG command.
  2645. Arguments:
  2646. Adapter - A pointer to the adapter.
  2647. Return Value:
  2648. None.
  2649. --*/
  2650. {
  2651. PSRB_READ_LOG ReadLogSrb = (PSRB_READ_LOG)(Adapter->SrbAddress);
  2652. NdisWriteRegisterUchar(&(ReadLogSrb->Command), SRB_CMD_READ_LOG);
  2653. }
  2654. STATIC
  2655. NDIS_STATUS
  2656. StartPendQueueOp(
  2657. IN PIBMTOK_ADAPTER Adapter
  2658. )
  2659. /*++
  2660. Routine Description:
  2661. This routine goes through the pending queue until it
  2662. is empty or it finds a request that requires an SRB
  2663. command and hence pends.
  2664. NOTE: This routine is called with the lock held and
  2665. returns with it held.
  2666. Arguments:
  2667. Adapter - The adapter that the queue should be checked for.
  2668. Return Value:
  2669. NDIS_STATUS_SUCCESS - If the queue was drained completely.
  2670. NDIS_STATUS_PENDING - If a request required the SRB.
  2671. --*/
  2672. {
  2673. //
  2674. // Holds the operation on the head of the queue
  2675. // (we know it is not empty).
  2676. //
  2677. PIBMTOK_PEND_DATA PendOp;
  2678. //
  2679. // Holds status temporarily.
  2680. //
  2681. NDIS_STATUS RequestStatus;
  2682. while (Adapter->PendQueue != NULL)
  2683. {
  2684. //
  2685. // First take the head operation off the queue.
  2686. //
  2687. PendOp = Adapter->PendQueue;
  2688. Adapter->PendQueue = Adapter->PendQueue->Next;
  2689. if (Adapter->PendQueue == NULL)
  2690. {
  2691. //
  2692. // We have just emptied the list.
  2693. //
  2694. Adapter->EndOfPendQueue = NULL;
  2695. }
  2696. if (PendOp->RequestType == NdisRequestGeneric1)
  2697. {
  2698. //
  2699. // The pended operation is a result of the card having
  2700. // a counter overflow, and now we need to send the command.
  2701. //
  2702. if (PendOp->COMMAND.MAC.ReadLogPending)
  2703. {
  2704. //
  2705. // A DIR.READ.LOG command is needed.
  2706. //
  2707. SetupAdapterErrorsSrb(Adapter);
  2708. }
  2709. else
  2710. {
  2711. //
  2712. // A DLC.STATISTICS command is needed.
  2713. //
  2714. SetupAdapterStatisticsSrb(Adapter);
  2715. }
  2716. //
  2717. // Issue adapter command.
  2718. //
  2719. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2720. ISRA_HIGH_COMMAND_IN_SRB);
  2721. RequestStatus = NDIS_STATUS_PENDING;
  2722. }
  2723. else
  2724. {
  2725. switch (PendOp->RequestType)
  2726. {
  2727. case NdisRequestSetInformation:
  2728. //
  2729. // It's a set filter or set address command.
  2730. //
  2731. if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
  2732. OID_GEN_CURRENT_PACKET_FILTER)
  2733. {
  2734. //
  2735. // It's a set filter command.
  2736. //
  2737. Adapter->OldPacketFilter = Adapter->CurrentPacketFilter;
  2738. Adapter->CurrentPacketFilter =
  2739. PendOp->COMMAND.NDIS.SET_FILTER.NewFilterValue;
  2740. RequestStatus = SetAdapterFunctionalAddress(Adapter);
  2741. }
  2742. else
  2743. {
  2744. //
  2745. // It's a set address command.
  2746. //
  2747. #if DBG
  2748. if (IbmtokDbg)
  2749. {
  2750. DbgPrint("IBMTOK: Starting Command\n");
  2751. }
  2752. #endif
  2753. if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
  2754. OID_802_5_CURRENT_FUNCTIONAL)
  2755. {
  2756. Adapter->CurrentFunctionalAddress =
  2757. PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
  2758. RequestStatus = SetAdapterFunctionalAddress(Adapter);
  2759. }
  2760. else
  2761. {
  2762. Adapter->CurrentGroupAddress =
  2763. PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
  2764. RequestStatus = SetAdapterGroupAddress(Adapter);
  2765. }
  2766. }
  2767. break;
  2768. case NdisRequestClose:
  2769. //
  2770. // It's a set filter command.
  2771. //
  2772. Adapter->OldPacketFilter = Adapter->CurrentPacketFilter;
  2773. Adapter->CurrentPacketFilter =
  2774. PendOp->COMMAND.NDIS.CLOSE.NewFilterValue;
  2775. RequestStatus = SetAdapterFunctionalAddress(Adapter);
  2776. break;
  2777. case NdisRequestGeneric2:
  2778. //
  2779. // It's a set address command.
  2780. //
  2781. Adapter->CurrentFunctionalAddress =
  2782. PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
  2783. RequestStatus = SetAdapterFunctionalAddress(Adapter);
  2784. break;
  2785. case NdisRequestGeneric3:
  2786. //
  2787. // It's a set address command.
  2788. //
  2789. Adapter->CurrentGroupAddress =
  2790. PendOp->COMMAND.NDIS.SET_ADDRESS.NewAddressValue;
  2791. RequestStatus = SetAdapterGroupAddress(Adapter);
  2792. break;
  2793. case NdisRequestQueryStatistics:
  2794. //
  2795. // We know it's a request for statistics.
  2796. //
  2797. RequestStatus = NDIS_STATUS_PENDING;
  2798. SetupAdapterErrorsSrb(Adapter);
  2799. PendOp->COMMAND.NDIS.STATISTICS.ReadLogPending = TRUE;
  2800. //
  2801. // Issue adapter command.
  2802. //
  2803. WRITE_ADAPTER_REGISTER(Adapter, ISRA_HIGH_SET,
  2804. ISRA_HIGH_COMMAND_IN_SRB);
  2805. break;
  2806. default:
  2807. NdisWriteErrorLogEntry(
  2808. Adapter->NdisAdapterHandle,
  2809. NDIS_ERROR_CODE_DRIVER_FAILURE,
  2810. 3,
  2811. IBMTOK_ERRMSG_BAD_OP,
  2812. 1,
  2813. PendOp->RequestType);
  2814. }
  2815. }
  2816. if (RequestStatus == NDIS_STATUS_PENDING)
  2817. {
  2818. //
  2819. // Set this up for when the request completes.
  2820. //
  2821. Adapter->PendData = PendOp;
  2822. return NDIS_STATUS_PENDING;
  2823. }
  2824. else if (RequestStatus == NDIS_STATUS_SUCCESS)
  2825. {
  2826. PIBMTOK_OPEN TmpOpen;
  2827. switch (PendOp->RequestType)
  2828. {
  2829. case NdisRequestSetInformation:
  2830. //
  2831. // Complete the request.
  2832. //
  2833. TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
  2834. NdisReleaseSpinLock(&(Adapter->Lock));
  2835. NdisCompleteRequest(
  2836. PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
  2837. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  2838. NDIS_STATUS_SUCCESS);
  2839. NdisAcquireSpinLock(&(Adapter->Lock));
  2840. Adapter->RequestTimeout = FALSE;
  2841. TmpOpen->References--;
  2842. break;
  2843. case NdisRequestClose:
  2844. PendOp->COMMAND.NDIS.CLOSE.Open->References--;
  2845. break;
  2846. case NdisRequestGeneric2:
  2847. case NdisRequestGeneric3:
  2848. PendOp->COMMAND.NDIS.SET_ADDRESS.Open->References--;
  2849. break;
  2850. case NdisRequestQueryStatistics:
  2851. NdisReleaseSpinLock(&(Adapter->Lock));
  2852. NdisCompleteQueryStatistics(
  2853. Adapter->NdisMacHandle,
  2854. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  2855. NDIS_STATUS_SUCCESS);
  2856. NdisAcquireSpinLock(&(Adapter->Lock));
  2857. Adapter->RequestTimeout = FALSE;
  2858. Adapter->References--;
  2859. break;
  2860. default:
  2861. NdisWriteErrorLogEntry(
  2862. Adapter->NdisAdapterHandle,
  2863. NDIS_ERROR_CODE_DRIVER_FAILURE,
  2864. 3,
  2865. startPendQueueOp,
  2866. IBMTOK_ERRMSG_BAD_OP,
  2867. PendOp->RequestType);
  2868. }
  2869. }
  2870. else
  2871. {
  2872. NdisWriteErrorLogEntry(
  2873. Adapter->NdisAdapterHandle,
  2874. NDIS_ERROR_CODE_DRIVER_FAILURE,
  2875. 3,
  2876. startPendQueueOp,
  2877. IBMTOK_ERRMSG_INVALID_STATUS,
  2878. RequestStatus);
  2879. }
  2880. }
  2881. //
  2882. // We drained the entire queue without pending.
  2883. //
  2884. return NDIS_STATUS_SUCCESS;
  2885. }
  2886. STATIC
  2887. BOOLEAN
  2888. FinishPendQueueOp(
  2889. IN PIBMTOK_ADAPTER Adapter,
  2890. IN BOOLEAN Successful
  2891. )
  2892. /*++
  2893. Routine Description:
  2894. This routine is called when an SRB command completes.
  2895. It calles CompleteRequest if needed and does any other
  2896. cleanup required.
  2897. NOTE: This routine is called with the lock held and
  2898. returns with it held.
  2899. NOTE: This routine assumes that the pended operation to
  2900. be completed was specifically requested by the protocol
  2901. and, thus, that PendData->Request != NULL.
  2902. Arguments:
  2903. Adapter - The adapter that the queue should be checked for.
  2904. Successful - Was the SRB command completed successfully.
  2905. Return Value:
  2906. TRUE if the operation was completed, FALSE if another command
  2907. was submitted to the card to complete the operation.
  2908. --*/
  2909. {
  2910. PIBMTOK_PEND_DATA PendOp = Adapter->PendData;
  2911. ASSERT(PendOp != NULL);
  2912. switch (PendOp->RequestType)
  2913. {
  2914. case NdisRequestQueryStatistics:
  2915. //
  2916. // It was a request for global statistics.
  2917. //
  2918. if (Successful)
  2919. {
  2920. NDIS_STATUS StatusToReturn;
  2921. //
  2922. // Grab the data
  2923. //
  2924. GetAdapterErrorsFromSrb(Adapter);
  2925. //
  2926. // Fill in NdisRequest InformationBuffer
  2927. //
  2928. StatusToReturn = IbmtokFillInGlobalData(
  2929. Adapter,
  2930. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp));
  2931. //
  2932. // Complete statistics call
  2933. //
  2934. Adapter->PendData = NULL;
  2935. NdisReleaseSpinLock(&(Adapter->Lock));
  2936. NdisCompleteQueryStatistics(
  2937. Adapter->NdisMacHandle,
  2938. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  2939. StatusToReturn);
  2940. NdisAcquireSpinLock(&(Adapter->Lock));
  2941. Adapter->RequestTimeout = FALSE;
  2942. Adapter->References--;
  2943. }
  2944. else
  2945. {
  2946. //
  2947. // Complete statistics call
  2948. //
  2949. Adapter->PendData = NULL;
  2950. NdisReleaseSpinLock(&(Adapter->Lock));
  2951. NdisCompleteQueryStatistics(
  2952. Adapter->NdisMacHandle,
  2953. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  2954. NDIS_STATUS_FAILURE);
  2955. NdisAcquireSpinLock(&(Adapter->Lock));
  2956. Adapter->RequestTimeout = FALSE;
  2957. Adapter->References--;
  2958. }
  2959. break;
  2960. case NdisRequestSetInformation:
  2961. //
  2962. // It was a request for address change.
  2963. //
  2964. #if DBG
  2965. if (IbmtokDbg)
  2966. {
  2967. if (Successful)
  2968. {
  2969. DbgPrint("IBMTOK: SUCCESS\n\n");
  2970. }
  2971. else
  2972. {
  2973. DbgPrint("IBMTOK: FAILURE\n\n");
  2974. }
  2975. }
  2976. #endif
  2977. if (Successful)
  2978. {
  2979. PIBMTOK_OPEN TmpOpen;
  2980. //
  2981. // complete the operation.
  2982. //
  2983. if (PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(Adapter->PendData)->DATA.SET_INFORMATION.Oid ==
  2984. OID_802_5_CURRENT_GROUP)
  2985. {
  2986. //
  2987. // Store new group address
  2988. //
  2989. Adapter->CurrentCardGroup = Adapter->CurrentGroupAddress;
  2990. }
  2991. Adapter->PendData = NULL;
  2992. TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
  2993. NdisReleaseSpinLock(&(Adapter->Lock));
  2994. NdisCompleteRequest(
  2995. PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
  2996. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  2997. NDIS_STATUS_SUCCESS);
  2998. NdisAcquireSpinLock(&(Adapter->Lock));
  2999. Adapter->RequestTimeout = FALSE;
  3000. TmpOpen->References--;
  3001. }
  3002. else
  3003. {
  3004. //
  3005. // complete the operation.
  3006. //
  3007. PIBMTOK_OPEN TmpOpen;
  3008. Adapter->PendData = NULL;
  3009. TmpOpen = PendOp->COMMAND.NDIS.SET_FILTER.Open;
  3010. NdisReleaseSpinLock(&(Adapter->Lock));
  3011. NdisCompleteRequest(
  3012. PendOp->COMMAND.NDIS.SET_FILTER.Open->NdisBindingContext,
  3013. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  3014. NDIS_STATUS_FAILURE);
  3015. NdisAcquireSpinLock(&(Adapter->Lock));
  3016. Adapter->RequestTimeout = FALSE;
  3017. TmpOpen->References--;
  3018. }
  3019. break;
  3020. case NdisRequestClose:
  3021. case NdisRequestGeneric2:
  3022. case NdisRequestGeneric3:
  3023. PendOp->COMMAND.NDIS.CLOSE.Open->References--;
  3024. break;
  3025. }
  3026. //
  3027. // Now finish up unsuccessful operations based on the type.
  3028. //
  3029. // NOTE: If we ever have cleanup for successful operations,
  3030. // we probably have to copy that code into the
  3031. // 'RequestStatus == NDIS_STATUS_SUCCESS' section
  3032. // in the function above.
  3033. //
  3034. if (!Successful)
  3035. {
  3036. switch (PendOp->RequestType)
  3037. {
  3038. case NdisRequestSetInformation:
  3039. //
  3040. // We know it was a set filter or set address.
  3041. //
  3042. if ((PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp))->DATA.SET_INFORMATION.Oid ==
  3043. OID_GEN_CURRENT_PACKET_FILTER)
  3044. {
  3045. //
  3046. // It was a set filter.
  3047. //
  3048. Adapter->CurrentPacketFilter = Adapter->OldPacketFilter;
  3049. Adapter->CurrentCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
  3050. }
  3051. else
  3052. {
  3053. //
  3054. // It was a set address.
  3055. //
  3056. Adapter->CurrentFunctionalAddress = (TR_FUNCTIONAL_ADDRESS)0;
  3057. }
  3058. break;
  3059. case NdisRequestQueryStatistics:
  3060. break;
  3061. case NdisRequestClose:
  3062. case NdisRequestGeneric2:
  3063. case NdisRequestGeneric3:
  3064. break;
  3065. default:
  3066. NdisWriteErrorLogEntry(
  3067. Adapter->NdisAdapterHandle,
  3068. NDIS_ERROR_CODE_DRIVER_FAILURE,
  3069. 3,
  3070. finishPendQueueOp,
  3071. IBMTOK_ERRMSG_BAD_OP,
  3072. PendOp->RequestType);
  3073. break;
  3074. }
  3075. }
  3076. return(TRUE);
  3077. }
  3078. STATIC
  3079. NDIS_STATUS
  3080. SetAdapterFunctionalAddress(
  3081. IN PIBMTOK_ADAPTER Adapter
  3082. )
  3083. /*++
  3084. Routine Description:
  3085. This routine checks the functional address on the adapter
  3086. against what it should be given the current packet filter
  3087. and functional address specified, and queues an update
  3088. if necessary.
  3089. NOTE: This routine assumes that it is called with the lock
  3090. acquired.
  3091. Arguments:
  3092. Adapter - The adapter to check.
  3093. Return Value:
  3094. NDIS_STATUS_SUCCESS - If no change is necessary.
  3095. NDIS_STATUS_PENDING - If the change was queued.
  3096. --*/
  3097. {
  3098. //
  3099. // The new value we compute for the functional address that
  3100. // should be on the card.
  3101. //
  3102. TR_FUNCTIONAL_ADDRESS NewCardFunctional;
  3103. //
  3104. // Holds the value to be returned.
  3105. //
  3106. NDIS_STATUS StatusOfSet;
  3107. //
  3108. // Used if ALL_MULTICAST is selected.
  3109. //
  3110. ULONG AllFunctionalAddress = 0x7fffffff;
  3111. //
  3112. // First calculate what the new functional address
  3113. // should be.
  3114. //
  3115. #if DBG
  3116. if (IbmtokDbg)
  3117. {
  3118. DbgPrint("IBMTOK: Current packet filter : 0x%x\n", Adapter->CurrentPacketFilter);
  3119. }
  3120. #endif
  3121. if (Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL)
  3122. {
  3123. //
  3124. // We have to set all the bits in the address.
  3125. //
  3126. NewCardFunctional = AllFunctionalAddress;
  3127. }
  3128. else if (Adapter->CurrentPacketFilter & NDIS_PACKET_TYPE_FUNCTIONAL)
  3129. {
  3130. NewCardFunctional = Adapter->CurrentFunctionalAddress;
  3131. }
  3132. else
  3133. {
  3134. NewCardFunctional = (TR_FUNCTIONAL_ADDRESS)0;
  3135. }
  3136. #if DBG
  3137. if (IbmtokDbg)
  3138. {
  3139. DbgPrint("IBMTOK: NewFunc is 0x%x\n", NewCardFunctional);
  3140. }
  3141. #endif
  3142. //
  3143. // Now queue it up if needed.
  3144. //
  3145. if (NewCardFunctional == Adapter->CurrentCardFunctional)
  3146. {
  3147. #if DBG
  3148. if (IbmtokDbg)
  3149. {
  3150. DbgPrint("IBMTOK: SUCCESS\n\n");
  3151. }
  3152. #endif
  3153. StatusOfSet = NDIS_STATUS_SUCCESS;
  3154. }
  3155. else
  3156. {
  3157. SetupFunctionalSrb(Adapter, NewCardFunctional);
  3158. Adapter->CurrentCardFunctional = NewCardFunctional;
  3159. StatusOfSet = NDIS_STATUS_PENDING;
  3160. }
  3161. return StatusOfSet;
  3162. }
  3163. STATIC
  3164. VOID
  3165. SetupFunctionalSrb(
  3166. IN PIBMTOK_ADAPTER Adapter,
  3167. IN TR_FUNCTIONAL_ADDRESS FunctionalAddress
  3168. )
  3169. /*++
  3170. Routine Description:
  3171. This routine sets up the SRB for a DIR.SET.FUNCT.Address.
  3172. Arguments:
  3173. Adapter - The adapter that this packet is coming through.
  3174. FunctionalAddress - The address to set up.
  3175. Return Value:
  3176. None.
  3177. --*/
  3178. {
  3179. //
  3180. // Used to set up the SRB request.
  3181. //
  3182. PSRB_SET_FUNCT_ADDRESS FunctSrb =
  3183. (PSRB_SET_FUNCT_ADDRESS)Adapter->SrbAddress;
  3184. //
  3185. // Used to hold the functional address temporarily.
  3186. //
  3187. UCHAR TempAddress[4];
  3188. //
  3189. // Used to copy down the functional address.
  3190. //
  3191. UINT i;
  3192. NdisWriteRegisterUchar(&(FunctSrb->Command), SRB_CMD_SET_FUNCTIONAL_ADDRESS);
  3193. NdisWriteRegisterUchar(&(FunctSrb->ReturnCode), 0xfe);
  3194. //
  3195. // Have to worry about setting the functional address
  3196. // since it is not aligned correctly.
  3197. //
  3198. IBMTOK_STORE_ULONG(TempAddress, FunctionalAddress);
  3199. for (i = 0; i < 4; i++)
  3200. {
  3201. NdisWriteRegisterUchar(&(FunctSrb->FunctionalAddress[i]), TempAddress[i]);
  3202. }
  3203. }
  3204. STATIC
  3205. NDIS_STATUS
  3206. SetAdapterGroupAddress(
  3207. IN PIBMTOK_ADAPTER Adapter
  3208. )
  3209. /*++
  3210. Routine Description:
  3211. This routine takes the value in Adapter->CurrentGroupAddress and
  3212. puts it out to the card.
  3213. NOTE: This routine assumes that it is called with the lock
  3214. acquired.
  3215. Arguments:
  3216. Adapter - The adapter to check.
  3217. Return Value:
  3218. NDIS_STATUS_PENDING - If the change was queued.
  3219. --*/
  3220. {
  3221. //
  3222. // Holds the value to be returned.
  3223. //
  3224. SetupGroupSrb(Adapter, Adapter->CurrentGroupAddress);
  3225. return NDIS_STATUS_PENDING;
  3226. }
  3227. STATIC
  3228. VOID
  3229. SetupGroupSrb(
  3230. IN PIBMTOK_ADAPTER Adapter,
  3231. IN TR_FUNCTIONAL_ADDRESS GroupAddress
  3232. )
  3233. /*++
  3234. Routine Description:
  3235. This routine sets up the SRB for a DIR.SET.GROUP.ADDRESS.
  3236. Arguments:
  3237. Adapter - The adapter that this packet is coming through.
  3238. GroupAddress - The address to set up.
  3239. Return Value:
  3240. None.
  3241. --*/
  3242. {
  3243. //
  3244. // Used to set up the SRB request.
  3245. //
  3246. PSRB_SET_GROUP_ADDRESS GroupSrb = (PSRB_SET_GROUP_ADDRESS)Adapter->SrbAddress;
  3247. //
  3248. // Used to hold the group address temporarily.
  3249. //
  3250. UCHAR TempAddress[4];
  3251. //
  3252. // Used to copy down the group address.
  3253. //
  3254. UINT i;
  3255. NdisWriteRegisterUchar(&(GroupSrb->Command), SRB_CMD_SET_GROUP_ADDRESS);
  3256. NdisWriteRegisterUchar(&(GroupSrb->ReturnCode), 0xfe);
  3257. //
  3258. // Have to worry about setting the group address
  3259. // since it is not aligned correctly.
  3260. //
  3261. IBMTOK_STORE_ULONG(TempAddress, GroupAddress);
  3262. for (i = 0; i < 4; i++)
  3263. {
  3264. NdisWriteRegisterUchar(&(GroupSrb->GroupAddress[i]), TempAddress[i]);
  3265. }
  3266. }
  3267. STATIC
  3268. VOID
  3269. SetupReceivedDataAsb(
  3270. IN PIBMTOK_ADAPTER Adapter,
  3271. IN SRAM_PTR ReceiveBuffer
  3272. )
  3273. /*++
  3274. Routine Description:
  3275. This routine sets up the ASB for a response from
  3276. a RECEIVED.DATA ARB.
  3277. Arguments:
  3278. Adapter - The adapter that this packet is coming through.
  3279. ReceiveBuffer - The first receive buffer in the frame.
  3280. Return Value:
  3281. None.
  3282. --*/
  3283. {
  3284. PASB_RECEIVED_DATA_STATUS ReceivedDataAsb;
  3285. ReceivedDataAsb = (PASB_RECEIVED_DATA_STATUS)
  3286. Adapter->AsbAddress;
  3287. NdisWriteRegisterUchar(&(ReceivedDataAsb->Command), ARB_CMD_RECEIVED_DATA);
  3288. NdisWriteRegisterUchar(&(ReceivedDataAsb->ReturnCode), 0x00);
  3289. NdisWriteRegisterUshort(&(ReceivedDataAsb->StationId), 0x0000);
  3290. NdisWriteRegisterUshort(&(ReceivedDataAsb->ReceiveBuffer), ReceiveBuffer);
  3291. }
  3292. STATIC
  3293. VOID
  3294. PutPacketOnWaitingForAsb(
  3295. IN PIBMTOK_ADAPTER Adapter,
  3296. IN PNDIS_PACKET Packet
  3297. )
  3298. /*++
  3299. Routine Description:
  3300. This queues a packet on the Waiting To Copy queue.
  3301. It is called and returns with the spinlock held.
  3302. Arguments:
  3303. Adapter - The adapter that this packet is coming through.
  3304. Packet - The packet that is to be transmitted.
  3305. Return Value:
  3306. None.
  3307. --*/
  3308. {
  3309. //
  3310. // Points to the MAC reserved portion of this packet. This
  3311. // interpretation of the reserved section is only valid during
  3312. // the allocation phase of the packet.
  3313. //
  3314. PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
  3315. ASSERT(sizeof(IBMTOK_RESERVED) <= sizeof(Packet->MacReserved));
  3316. if (Adapter->FirstWaitingForAsb == NULL)
  3317. {
  3318. Adapter->FirstWaitingForAsb = Packet;
  3319. }
  3320. else
  3321. {
  3322. PIBMTOK_RESERVED_FROM_PACKET(Adapter->FirstWaitingForAsb)->Next = Packet;
  3323. }
  3324. Adapter->LastWaitingForAsb = Packet;
  3325. Reserved->Next = NULL;
  3326. }
  3327. extern
  3328. VOID
  3329. IbmtokHandleDeferred(
  3330. IN PIBMTOK_ADAPTER Adapter
  3331. )
  3332. /*++
  3333. Routine Description:
  3334. This routine handles any pending resets and closes.
  3335. It is called during interrupt processing and also at
  3336. the end of every routine if needed.
  3337. NOTE: This routine is called with the spinlock held
  3338. and returns with it held.
  3339. Arguments:
  3340. Adapter - The adapter to check deferred processing on.
  3341. Return Value:
  3342. None.
  3343. --*/
  3344. {
  3345. PIBMTOK_OPEN Open;
  3346. //
  3347. // Note that the following code depends on the fact that
  3348. // code above left the spinlock held.
  3349. //
  3350. //
  3351. // We will only come in here if the adapter's reference
  3352. // count is zero, so if a reset is in progress then we
  3353. // can start the reset.
  3354. //
  3355. //
  3356. // Make sure we don't start it twice!!
  3357. //
  3358. Adapter->References++;
  3359. if (Adapter->ResetInProgress && Adapter->CurrentResetStage == 0)
  3360. {
  3361. Adapter->CurrentResetStage = 1;
  3362. NdisReleaseSpinLock(&(Adapter->Lock));
  3363. IbmtokStartAdapterReset(Adapter);
  3364. NdisAcquireSpinLock(&(Adapter->Lock));
  3365. }
  3366. if (!Adapter->ResetInProgress && !IsListEmpty(&(Adapter->CloseDuringResetList)))
  3367. {
  3368. //
  3369. // Status of the Filter delete call.
  3370. //
  3371. NDIS_STATUS Status;
  3372. Open = CONTAINING_RECORD(
  3373. Adapter->CloseDuringResetList.Flink,
  3374. IBMTOK_OPEN,
  3375. OpenList);
  3376. Open->References++;
  3377. #if DBG
  3378. if (IbmtokDbg) DbgPrint("IBMTOK: Calling TrDelete\n");
  3379. #endif
  3380. Status = TrDeleteFilterOpenAdapter(
  3381. Adapter->FilterDB,
  3382. Open->NdisFilterHandle,
  3383. NULL);
  3384. #if DBG
  3385. if (IbmtokDbg) DbgPrint("IBMTOK: TrDelete returned\n");
  3386. #endif
  3387. //
  3388. // If the status is successful that merely implies that
  3389. // we were able to delete the reference to the open binding
  3390. // from the filtering code. If we have a successful status
  3391. // at this point we still need to check whether the reference
  3392. // count to determine whether we can close.
  3393. //
  3394. //
  3395. // The delete filter routine can return a "special" status
  3396. // that indicates that there is a current NdisIndicateReceive
  3397. // on this binding.
  3398. //
  3399. if (Status == NDIS_STATUS_SUCCESS)
  3400. {
  3401. //
  3402. // Check whether the reference count is two. If
  3403. // it is then we can get rid of the memory for
  3404. // this open.
  3405. //
  3406. // A count of two indicates one for this routine
  3407. // and one for the filter which we *know* we can
  3408. // get rid of.
  3409. //
  3410. if (Open->References == 2)
  3411. {
  3412. //
  3413. // We are the only reference to the open. Remove
  3414. // it from the list and delete the memory.
  3415. //
  3416. RemoveEntryList(&Open->OpenList);
  3417. //
  3418. // Complete the close here.
  3419. //
  3420. if (Adapter->LookAhead == Open->LookAhead)
  3421. {
  3422. IbmtokAdjustMaxLookAhead(Adapter);
  3423. }
  3424. NdisReleaseSpinLock(&Adapter->Lock);
  3425. NdisCompleteCloseAdapter(
  3426. Open->NdisBindingContext,
  3427. NDIS_STATUS_SUCCESS);
  3428. IBMTOK_FREE_PHYS(Open,sizeof(IBMTOK_OPEN));
  3429. NdisAcquireSpinLock(&Adapter->Lock);
  3430. }
  3431. else
  3432. {
  3433. //
  3434. // Remove the open from the list and put it on
  3435. // the closing list.
  3436. //
  3437. RemoveEntryList(&Open->OpenList);
  3438. InsertTailList(&Adapter->CloseList,&Open->OpenList);
  3439. //
  3440. // Account for this routines reference to the open
  3441. // as well as reference because of the filtering.
  3442. //
  3443. Open->References -= 2;
  3444. }
  3445. }
  3446. else if (Status == NDIS_STATUS_PENDING)
  3447. {
  3448. //
  3449. // If it pended, there may be
  3450. // operations queued.
  3451. // Returns with lock released
  3452. //
  3453. IbmtokProcessSrbRequests(Adapter);
  3454. //
  3455. // Now start closing down this open.
  3456. //
  3457. Open->BindingShuttingDown = TRUE;
  3458. //
  3459. // Remove the open from the open list and put it on
  3460. // the closing list.
  3461. //
  3462. RemoveEntryList(&Open->OpenList);
  3463. InsertTailList(&Adapter->CloseList,&Open->OpenList);
  3464. //
  3465. // Account for this routines reference to the open
  3466. // as well as reference because of the filtering.
  3467. //
  3468. Open->References -= 2;
  3469. }
  3470. else
  3471. {
  3472. //
  3473. // We should not get RESET_IN_PROGRESS or any other types.
  3474. //
  3475. NdisWriteErrorLogEntry(
  3476. Adapter->NdisAdapterHandle,
  3477. NDIS_ERROR_CODE_DRIVER_FAILURE,
  3478. 3,
  3479. handleDeferred,
  3480. IBMTOK_ERRMSG_INVALID_STATUS,
  3481. Status);
  3482. }
  3483. }
  3484. //
  3485. // If there are any opens on the closing list and their
  3486. // reference counts are zero then complete the close and
  3487. // delete them from the list.
  3488. //
  3489. //
  3490. if (!IsListEmpty(&(Adapter->CloseList))){
  3491. Open = CONTAINING_RECORD(
  3492. Adapter->CloseList.Flink,
  3493. IBMTOK_OPEN,
  3494. OpenList);
  3495. if (!Open->References)
  3496. {
  3497. if (Adapter->LookAhead == Open->LookAhead)
  3498. {
  3499. IbmtokAdjustMaxLookAhead(Adapter);
  3500. }
  3501. NdisReleaseSpinLock(&(Adapter->Lock));
  3502. NdisCompleteCloseAdapter(
  3503. Open->NdisBindingContext,
  3504. NDIS_STATUS_SUCCESS);
  3505. NdisAcquireSpinLock(&(Adapter->Lock));
  3506. RemoveEntryList(&(Open->OpenList));
  3507. IBMTOK_FREE_PHYS(Open, sizeof(IBMTOK_OPEN));
  3508. }
  3509. }
  3510. Adapter->References--;
  3511. }
  3512. extern
  3513. VOID
  3514. IbmtokAbortPending(
  3515. IN PIBMTOK_ADAPTER Adapter,
  3516. IN NDIS_STATUS AbortStatus
  3517. )
  3518. /*++
  3519. Routine Description:
  3520. This routine aborts any pending requests, and calls
  3521. IbmtokAbortSends to abort any pending sends.
  3522. NOTE: This routine is called with the spinlock held
  3523. and returns with it held.
  3524. Arguments:
  3525. Adapter - The adapter to abort.
  3526. AbortStatus - The status to complete requests with.
  3527. Return Value:
  3528. None.
  3529. --*/
  3530. {
  3531. PIBMTOK_OPEN Open;
  3532. PIBMTOK_PEND_DATA PendOp;
  3533. while (Adapter->PendQueue)
  3534. {
  3535. //
  3536. // Holds the operation on the head of the queue
  3537. //
  3538. PendOp = Adapter->PendQueue;
  3539. Adapter->PendQueue = Adapter->PendQueue->Next;
  3540. if (Adapter->PendQueue == NULL)
  3541. {
  3542. //
  3543. // We have just emptied the list.
  3544. //
  3545. Adapter->EndOfPendQueue = NULL;
  3546. }
  3547. switch (PendOp->RequestType)
  3548. {
  3549. case NdisRequestSetInformation:
  3550. //
  3551. // Complete the request.
  3552. //
  3553. Open = PendOp->COMMAND.NDIS.SET_FILTER.Open;
  3554. NdisDprReleaseSpinLock(&(Adapter->Lock));
  3555. NdisCompleteRequest(
  3556. Open->NdisBindingContext,
  3557. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  3558. AbortStatus);
  3559. NdisDprAcquireSpinLock(&(Adapter->Lock));
  3560. Adapter->RequestTimeout = FALSE;
  3561. Open->References--;
  3562. break;
  3563. case NdisRequestClose:
  3564. PendOp->COMMAND.NDIS.CLOSE.Open->References--;
  3565. break;
  3566. case NdisRequestGeneric1:
  3567. //
  3568. // Submitted by the driver
  3569. //
  3570. IBMTOK_FREE_PHYS(PendOp, sizeof(IBMTOK_PEND_DATA));
  3571. Adapter->PendData = NULL;
  3572. break;
  3573. case NdisRequestGeneric2:
  3574. case NdisRequestGeneric3:
  3575. //
  3576. // Changes in address and filters due to a close
  3577. //
  3578. PendOp->COMMAND.NDIS.SET_ADDRESS.Open->References--;
  3579. break;
  3580. case NdisRequestQueryStatistics:
  3581. NdisDprReleaseSpinLock(&(Adapter->Lock));
  3582. NdisCompleteQueryStatistics(
  3583. Adapter->NdisMacHandle,
  3584. PNDIS_REQUEST_FROM_PIBMTOK_PEND_DATA(PendOp),
  3585. AbortStatus);
  3586. NdisDprAcquireSpinLock(&(Adapter->Lock));
  3587. Adapter->RequestTimeout = FALSE;
  3588. Adapter->References--;
  3589. break;
  3590. }
  3591. }
  3592. IbmtokAbortSends (Adapter, AbortStatus);
  3593. }
  3594. extern
  3595. VOID
  3596. IbmtokAbortSends(
  3597. IN PIBMTOK_ADAPTER Adapter,
  3598. IN NDIS_STATUS AbortStatus
  3599. )
  3600. /*++
  3601. Routine Description:
  3602. This routine aborts any pending sends.
  3603. NOTE: This routine is called with the spinlock held
  3604. and returns with it held.
  3605. Arguments:
  3606. Adapter - The adapter to abort.
  3607. AbortStatus - The status to complete requests with.
  3608. Return Value:
  3609. None.
  3610. --*/
  3611. {
  3612. PIBMTOK_OPEN Open;
  3613. PNDIS_PACKET TransmitPacket;
  3614. PIBMTOK_RESERVED Reserved;
  3615. UINT i;
  3616. //
  3617. // First the packet in the SRB.
  3618. //
  3619. if (Adapter->TransmittingPacket != NULL)
  3620. {
  3621. TransmitPacket = Adapter->TransmittingPacket;
  3622. Adapter->TransmittingPacket = NULL;
  3623. Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  3624. Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  3625. NdisDprReleaseSpinLock(&Adapter->Lock);
  3626. NdisCompleteSend(Open->NdisBindingContext, TransmitPacket, AbortStatus);
  3627. NdisDprAcquireSpinLock(&Adapter->Lock);
  3628. Open->References--;
  3629. }
  3630. //
  3631. // Then any that are queued up waiting to be given to the card.
  3632. //
  3633. while (Adapter->FirstTransmit)
  3634. {
  3635. TransmitPacket = Adapter->FirstTransmit;
  3636. Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  3637. Adapter->FirstTransmit = Reserved->Next;
  3638. Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  3639. NdisDprReleaseSpinLock(&Adapter->Lock);
  3640. NdisCompleteSend(
  3641. Open->NdisBindingContext,
  3642. TransmitPacket,
  3643. AbortStatus);
  3644. NdisDprAcquireSpinLock(&Adapter->Lock);
  3645. Open->References--;
  3646. }
  3647. //
  3648. // Finally, the Correlator array (this will include any
  3649. // packets on WaitingForAsb).
  3650. //
  3651. for (i = 0; i < MAX_COMMAND_CORRELATOR; i++)
  3652. {
  3653. TransmitPacket = Adapter->CorrelatorArray[i];
  3654. if (TransmitPacket != NULL)
  3655. {
  3656. RemovePacketFromCorrelatorArray (Adapter, TransmitPacket);
  3657. Reserved = PIBMTOK_RESERVED_FROM_PACKET(TransmitPacket);
  3658. Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  3659. NdisDprReleaseSpinLock(&Adapter->Lock);
  3660. NdisCompleteSend(
  3661. Open->NdisBindingContext,
  3662. Reserved->Packet,
  3663. AbortStatus);
  3664. NdisDprAcquireSpinLock(&Adapter->Lock);
  3665. Open->References--;
  3666. }
  3667. }
  3668. Adapter->FirstWaitingForAsb = NULL;
  3669. }
  3670. VOID
  3671. IbmtokWakeUpDpc(
  3672. IN PVOID SystemSpecific1,
  3673. IN PVOID Context,
  3674. IN PVOID SystemSpecific2,
  3675. IN PVOID SystemSpecific3
  3676. )
  3677. /*++
  3678. Routine Description:
  3679. This DPC routine is queued every 2 seconds to check on the
  3680. queues. If an interrupt was not received
  3681. in the last two seconds and there should have been one,
  3682. then we abort all operations.
  3683. Arguments:
  3684. Context - Really a pointer to the adapter.
  3685. Return Value:
  3686. None.
  3687. --*/
  3688. {
  3689. PIBMTOK_ADAPTER Adapter = (PIBMTOK_ADAPTER)Context;
  3690. UNREFERENCED_PARAMETER(SystemSpecific1);
  3691. UNREFERENCED_PARAMETER(SystemSpecific2);
  3692. UNREFERENCED_PARAMETER(SystemSpecific3);
  3693. NdisDprAcquireSpinLock(&Adapter->Lock);
  3694. if ((Adapter->SendTimeout &&
  3695. ((Adapter->TransmittingPacket != NULL) ||
  3696. (Adapter->FirstTransmit != NULL))) ||
  3697. (Adapter->RequestTimeout && (Adapter->PendQueue != NULL)))
  3698. {
  3699. //
  3700. // We had a pending operation the last time we ran,
  3701. // and it has not been completed...we need to complete
  3702. // it now.
  3703. Adapter->NotAcceptingRequests = TRUE;
  3704. Adapter->SendTimeout = FALSE;
  3705. Adapter->RequestTimeout = FALSE;
  3706. //
  3707. // Complete any pending requests or sends.
  3708. //
  3709. IbmtokAbortPending(Adapter, STATUS_REQUEST_ABORTED);
  3710. Adapter->WakeUpErrorCount++;
  3711. IbmtokSetupForReset(Adapter, NULL);
  3712. IbmtokHandleDeferred(Adapter);
  3713. }
  3714. else
  3715. {
  3716. if ((Adapter->TransmittingPacket != NULL) ||
  3717. (Adapter->FirstTransmit != NULL))
  3718. {
  3719. Adapter->SendTimeout = TRUE;
  3720. }
  3721. if (Adapter->PendQueue != NULL)
  3722. {
  3723. Adapter->RequestTimeout = TRUE;
  3724. }
  3725. }
  3726. //
  3727. // If we've been unplugged, and there is not a reset in
  3728. // progress, try one.
  3729. //
  3730. if ((Adapter->LobeWireFaultIndicated) &&
  3731. (!Adapter->UnpluggedResetInProgress))
  3732. {
  3733. Adapter->UnpluggedResetInProgress = TRUE;
  3734. IbmtokSetupForReset(Adapter, NULL);
  3735. IbmtokHandleDeferred(Adapter);
  3736. }
  3737. NdisDprReleaseSpinLock(&Adapter->Lock);
  3738. //
  3739. // Fire off another Dpc to execute after 30 seconds
  3740. //
  3741. NdisSetTimer(&Adapter->WakeUpTimer, 30000);
  3742. }