Leaked source code of windows server 2003
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.

3300 lines
78 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. atp.c
  5. Abstract:
  6. This module contains the Appletalk Transaction Protocol code.
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 19 Jun 1992 Initial Version
  12. Notes: Tab stop: 4
  13. 25 Mar 1994 JH - Changed the request response paradigm. It now works as follows:
  14. When a request comes in, a response structure is allocated, initialized
  15. and linked into the address object either in the hash table if it is a
  16. XO request or the ALO linear list if it an ALO.
  17. The GetReq handler is passed a pointer to the response structure. This
  18. is referenced for the GetReq handler. The GetReq handler must Dereference
  19. it explicity either in its release handler if a response was posted or
  20. after a CancelResp is called.
  21. The respDeref notifies the release handler when the reference goes to 1
  22. and frees it up when it goes to zero.
  23. The GetReq structure is now re-used if the handler so specifies. This
  24. avoids the free-ing and re-allocing of these structures as well as
  25. the need to call AtalkAtpGetReq() from within the handler.
  26. Retry and release timers are per-atp-address now instead of one per
  27. request and one per response. The release handler is not 'started'
  28. till a response is posted.
  29. --*/
  30. #include <atalk.h>
  31. #pragma hdrstop
  32. #define FILENUM ATP
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text(PAGE_PAP, AtalkAtpOpenAddress) // Since PAP is the only one which calls
  35. // at DISPATCH_LEVEL
  36. #pragma alloc_text(PAGE_ATP, AtalkAtpCleanupAddress)
  37. #pragma alloc_text(PAGE_ATP, AtalkAtpCloseAddress)
  38. #pragma alloc_text(PAGE_ATP, AtalkAtpPostReq)
  39. #pragma alloc_text(PAGE_ATP, AtalkAtpSetReqHandler)
  40. #pragma alloc_text(PAGE_ATP, AtalkAtpPostResp)
  41. #pragma alloc_text(PAGE_ATP, AtalkAtpCancelReq)
  42. #pragma alloc_text(PAGE_ATP, AtalkAtpIsReqComplete)
  43. #pragma alloc_text(PAGE_ATP, AtalkAtpCancelResp)
  44. #pragma alloc_text(PAGE_ATP, AtalkAtpCancelRespByTid)
  45. #pragma alloc_text(PAGE_ATP, AtalkAtpPacketIn)
  46. #pragma alloc_text(PAGE_ATP, atalkAtpTransmitReq)
  47. #pragma alloc_text(PAGE_ATP, atalkAtpSendReqComplete)
  48. #pragma alloc_text(PAGE_ATP, atalkAtpTransmitResp)
  49. #pragma alloc_text(PAGE_ATP, atalkAtpSendRespComplete)
  50. #pragma alloc_text(PAGE_ATP, atalkAtpTransmitRel)
  51. #pragma alloc_text(PAGE_ATP, atalkAtpSendRelComplete)
  52. #pragma alloc_text(PAGE_ATP, atalkAtpRespComplete)
  53. #pragma alloc_text(PAGE_ATP, atalkAtpReqComplete)
  54. #pragma alloc_text(PAGE_ATP, atalkAtpGetNextTidForAddr)
  55. #pragma alloc_text(PAGE_ATP, atalkAtpReqRefNextNc)
  56. #pragma alloc_text(PAGE_ATP, atalkAtpReqDeref)
  57. #pragma alloc_text(PAGE_ATP, atalkAtpRespRefNextNc)
  58. #pragma alloc_text(PAGE_ATP, AtalkAtpRespDeref)
  59. #pragma alloc_text(PAGE_ATP, atalkAtpReqTimer)
  60. #pragma alloc_text(PAGE_ATP, atalkAtpRelTimer)
  61. #pragma alloc_text(PAGE_ATP, AtalkAtpGenericRespComplete)
  62. #endif
  63. ATALK_ERROR
  64. AtalkAtpOpenAddress(
  65. IN PPORT_DESCRIPTOR pPort,
  66. IN BYTE Socket,
  67. IN OUT PATALK_NODEADDR pDesiredNode OPTIONAL,
  68. IN USHORT MaxSinglePktSize,
  69. IN BOOLEAN SendUserBytesAll,
  70. IN PATALK_DEV_CTX pDevCtx OPTIONAL,
  71. IN BOOLEAN CacheSocket,
  72. OUT PATP_ADDROBJ * ppAtpAddr
  73. )
  74. /*++
  75. Routine Description:
  76. Arguments:
  77. Return Value:
  78. --*/
  79. {
  80. PATP_ADDROBJ pAtpAddr;
  81. ATALK_ERROR error;
  82. do
  83. {
  84. if ((pAtpAddr = AtalkAllocZeroedMemory(sizeof(ATP_ADDROBJ))) == NULL)
  85. {
  86. error = ATALK_RESR_MEM;
  87. break;
  88. }
  89. // Initialize this structure. Note that packet handler could
  90. // entered with this context even before secondary initialization
  91. // completes. So we make sure, that it will not touch anything
  92. // until then by using the OPEN flag.
  93. #if DBG
  94. pAtpAddr->atpao_Signature = ATPAO_SIGNATURE;
  95. #endif
  96. // Set creation reference count, include one each for release and retry timers
  97. pAtpAddr->atpao_RefCount = (CacheSocket ? 4 : 3);
  98. pAtpAddr->atpao_NextTid = 1;
  99. pAtpAddr->atpao_MaxSinglePktSize = MaxSinglePktSize;
  100. pAtpAddr->atpao_DevCtx = pDevCtx;
  101. if (SendUserBytesAll)
  102. {
  103. pAtpAddr->atpao_Flags |= ATPAO_SENDUSERBYTESALL;
  104. }
  105. InitializeListHead(&pAtpAddr->atpao_ReqList);
  106. AtalkTimerInitialize(&pAtpAddr->atpao_RelTimer,
  107. atalkAtpRelTimer,
  108. ATP_RELEASE_TIMER_INTERVAL);
  109. InitializeListHead(&pAtpAddr->atpao_RespList);
  110. AtalkTimerInitialize(&pAtpAddr->atpao_RetryTimer,
  111. atalkAtpReqTimer,
  112. ATP_RETRY_TIMER_INTERVAL);
  113. // Open the ddp socket
  114. error = AtalkDdpOpenAddress(pPort,
  115. Socket,
  116. pDesiredNode,
  117. AtalkAtpPacketIn,
  118. pAtpAddr,
  119. DDPPROTO_ANY,
  120. pDevCtx,
  121. &pAtpAddr->atpao_DdpAddr);
  122. if (!ATALK_SUCCESS(error))
  123. {
  124. // Socket open error will be logged at the ddp level.
  125. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  126. ("AtalkAtpOpenAddress: AtalkDdpOpenAddress failed %ld\n", error));
  127. AtalkFreeMemory(pAtpAddr);
  128. break;
  129. }
  130. // Activate the atp socket. Cache the socket if desired.
  131. // This takes port lock on default port.
  132. if (CacheSocket)
  133. {
  134. if (!ATALK_SUCCESS(AtalkIndAtpCacheSocket(pAtpAddr, pPort)))
  135. {
  136. pAtpAddr->atpao_RefCount--;
  137. CacheSocket = FALSE;
  138. }
  139. }
  140. pAtpAddr->atpao_Flags |= (ATPAO_OPEN | ATPAO_TIMERS | (CacheSocket ? ATPAO_CACHED : 0));
  141. AtalkLockAtpIfNecessary();
  142. // Start the release timer for responses on this address
  143. AtalkTimerScheduleEvent(&pAtpAddr->atpao_RelTimer);
  144. // Start the retry timer for requests on this address
  145. AtalkTimerScheduleEvent(&pAtpAddr->atpao_RetryTimer);
  146. *ppAtpAddr = pAtpAddr;
  147. } while (FALSE);
  148. return error;
  149. }
  150. ATALK_ERROR
  151. AtalkAtpCleanupAddress(
  152. IN PATP_ADDROBJ pAtpAddr
  153. )
  154. /*++
  155. Routine Description:
  156. Arguments:
  157. Return Value:
  158. --*/
  159. {
  160. PATP_REQ pAtpReq, pAtpReqNext;
  161. PATP_RESP pAtpResp, pAtpRespNext;
  162. ATP_REQ_HANDLER ReqHandler;
  163. ATALK_ERROR error = ATALK_PENDING;
  164. KIRQL OldIrql;
  165. USHORT i;
  166. BOOLEAN cached, CancelTimers, done, ReEnqueue;
  167. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  168. CancelTimers = FALSE;
  169. done = FALSE;
  170. if (pAtpAddr->atpao_Flags & ATPAO_TIMERS)
  171. {
  172. pAtpAddr->atpao_Flags &= ~ATPAO_TIMERS;
  173. CancelTimers = TRUE;
  174. }
  175. if (pAtpAddr->atpao_Flags & ATPAO_CLEANUP)
  176. {
  177. done = TRUE;
  178. }
  179. else
  180. {
  181. // put a Cleanup refcount for this routine, since we are going to cleanup
  182. pAtpAddr->atpao_RefCount++;
  183. }
  184. pAtpAddr->atpao_Flags |= ATPAO_CLEANUP;
  185. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  186. if (done)
  187. {
  188. return error;
  189. }
  190. if (CancelTimers)
  191. {
  192. // Cancel the release timer
  193. if (AtalkTimerCancelEvent(&pAtpAddr->atpao_RelTimer, NULL))
  194. {
  195. AtalkAtpAddrDereference(pAtpAddr);
  196. }
  197. else
  198. {
  199. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  200. ("AtalkAtpCleanupAddress: couldn't cancel release timer\n"));
  201. }
  202. // And also the retry timer
  203. if (AtalkTimerCancelEvent(&pAtpAddr->atpao_RetryTimer, NULL))
  204. {
  205. AtalkAtpAddrDereference(pAtpAddr);
  206. }
  207. else
  208. {
  209. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  210. ("AtalkAtpCleanupAddress: couldn't cancel retry timer\n"));
  211. }
  212. }
  213. ASSERT (pAtpAddr->atpao_RefCount >= 1); // creation ref
  214. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  215. // Call requests handler if set
  216. if ((ReqHandler = pAtpAddr->atpao_ReqHandler) != NULL)
  217. {
  218. pAtpAddr->atpao_ReqHandler = NULL;
  219. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  220. (*ReqHandler)(ATALK_ATP_CLOSING,
  221. pAtpAddr->atpao_ReqCtx,
  222. NULL,
  223. NULL,
  224. 0,
  225. NULL,
  226. NULL);
  227. // Dereference address object.
  228. AtalkAtpAddrDereference(pAtpAddr);
  229. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  230. }
  231. // Cancel all the requests.
  232. for (i = 0; i < ATP_REQ_HASH_SIZE; i++)
  233. {
  234. if ((pAtpReq = pAtpAddr->atpao_ReqHash[i]) == NULL)
  235. {
  236. // If empty, go on to the next index in hash table.
  237. continue;
  238. }
  239. // Includes the one we are starting with.
  240. atalkAtpReqRefNextNc(pAtpReq, &pAtpReqNext, &error);
  241. if (!ATALK_SUCCESS(error))
  242. {
  243. // No requests left on this index. Go to the next one.
  244. continue;
  245. }
  246. while (TRUE)
  247. {
  248. if ((pAtpReq = pAtpReqNext) == NULL)
  249. {
  250. break;
  251. }
  252. if ((pAtpReqNext = pAtpReq->req_Next) != NULL)
  253. {
  254. atalkAtpReqRefNextNc(pAtpReq->req_Next, &pAtpReqNext, &error);
  255. if (!ATALK_SUCCESS(error))
  256. {
  257. // No requests left on this index. Go to the next one.
  258. pAtpReqNext = NULL;
  259. }
  260. }
  261. // Cancel this request.
  262. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  263. AtalkAtpCancelReq(pAtpAddr,
  264. pAtpReq->req_Tid,
  265. &pAtpReq->req_Dest);
  266. ASSERTMSG("RefCount incorrect\n", (pAtpReq->req_RefCount >= 1));
  267. // remove the refcount added in the beginning of the loop
  268. AtalkAtpReqDereference(pAtpReq);
  269. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  270. }
  271. }
  272. // Cancel all pending responses.
  273. for (i = 0; i < ATP_RESP_HASH_SIZE; i++)
  274. {
  275. if ((pAtpResp = pAtpAddr->atpao_RespHash[i]) == NULL)
  276. {
  277. // If empty, go on to the next index in hash table.
  278. continue;
  279. }
  280. // Includes the one we are starting with.
  281. atalkAtpRespRefNextNc(pAtpResp, &pAtpRespNext, &error);
  282. if (!ATALK_SUCCESS(error))
  283. {
  284. // No requests left on this index. Go to the next one.
  285. continue;
  286. }
  287. while (TRUE)
  288. {
  289. if ((pAtpResp = pAtpRespNext) == NULL)
  290. {
  291. break;
  292. }
  293. if ((pAtpRespNext = pAtpResp->resp_Next) != NULL)
  294. {
  295. atalkAtpRespRefNextNc(pAtpResp->resp_Next, &pAtpRespNext, &error);
  296. if (!ATALK_SUCCESS(error))
  297. {
  298. // No requests left on this index. Go to the next one.
  299. pAtpRespNext = NULL;
  300. }
  301. }
  302. // Cancel this response
  303. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  304. AtalkAtpCancelResp(pAtpResp);
  305. // remove the refcount added in the beginning of the loop
  306. AtalkAtpRespDereference(pAtpResp);
  307. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  308. }
  309. }
  310. // if the socket was cached, uncache it, remove reference.
  311. cached = FALSE;
  312. if (pAtpAddr->atpao_Flags & ATPAO_CACHED)
  313. {
  314. cached = TRUE;
  315. pAtpAddr->atpao_Flags &= ~ATPAO_CACHED;
  316. }
  317. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  318. if (cached)
  319. {
  320. AtalkIndAtpUnCacheSocket(pAtpAddr);
  321. AtalkAtpAddrDereference(pAtpAddr);
  322. }
  323. // remove the Cleanup refcount we put at the beginning of this routine
  324. AtalkAtpAddrDereference(pAtpAddr);
  325. return error;
  326. }
  327. ATALK_ERROR
  328. AtalkAtpCloseAddress(
  329. IN PATP_ADDROBJ pAtpAddr,
  330. IN ATPAO_CLOSECOMPLETION pCloseCmp OPTIONAL,
  331. IN PVOID pCloseCtx OPTIONAL
  332. )
  333. /*++
  334. Routine Description:
  335. Arguments:
  336. Return Value:
  337. --*/
  338. {
  339. KIRQL OldIrql;
  340. BOOLEAN cleanup;
  341. // Cancel all the pending get requests.
  342. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  343. if ((pAtpAddr->atpao_Flags & ATPAO_CLOSING) == 0)
  344. {
  345. cleanup = TRUE;
  346. if (pAtpAddr->atpao_Flags & ATPAO_CLEANUP)
  347. cleanup = FALSE;
  348. pAtpAddr->atpao_Flags |= ATPAO_CLOSING;
  349. pAtpAddr->atpao_CloseComp = pCloseCmp;
  350. pAtpAddr->atpao_CloseCtx = pCloseCtx;
  351. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  352. if (cleanup)
  353. AtalkAtpCleanupAddress(pAtpAddr);
  354. // Remove the creation reference
  355. AtalkAtpAddrDereference(pAtpAddr);
  356. }
  357. else
  358. {
  359. // We are already closing! this should never happen!
  360. ASSERT ((pAtpAddr->atpao_Flags & ATPAO_CLOSING) != 0);
  361. KeBugCheck(0);
  362. }
  363. return ATALK_PENDING;
  364. }
  365. ATALK_ERROR
  366. AtalkAtpPostReq(
  367. IN PATP_ADDROBJ pAtpAddr,
  368. IN PATALK_ADDR pDest,
  369. OUT PUSHORT pTid,
  370. IN USHORT Flags,
  371. IN PAMDL pReq,
  372. IN USHORT ReqLen,
  373. IN PBYTE pUserBytes OPTIONAL,
  374. IN OUT PAMDL pResp OPTIONAL,
  375. IN USHORT RespLen OPTIONAL,
  376. IN SHORT RetryCnt,
  377. IN LONG RetryInterval OPTIONAL, // In timer ticks
  378. IN RELEASE_TIMERVALUE RelTimerVal,
  379. IN ATP_RESP_HANDLER pCmpRoutine OPTIONAL,
  380. IN PVOID pCtx OPTIONAL
  381. )
  382. /*++
  383. Routine Description:
  384. Arguments:
  385. Return Value:
  386. --*/
  387. {
  388. PATP_REQ pAtpReq;
  389. KIRQL OldIrql;
  390. ULONG index;
  391. ATALK_ERROR error = ATALK_NO_ERROR;
  392. // Verify relevant parameters.
  393. do
  394. {
  395. #ifdef ATP_STRICT
  396. // NOTE: These checks need to be added to the TDI interface if/when ATP is
  397. // opened upto user mode.
  398. if ((ReqLen < 0) ||
  399. (ReqLen > pAtpAddr->atpao_MaxSinglePktSize) ||
  400. (RespLen < 0) ||
  401. (RespLen > (pAtpAddr->atpao_MaxSinglePktSize * ATP_MAX_RESP_PKTS)))
  402. {
  403. error = ATALK_BUFFER_TOO_BIG;
  404. break;
  405. }
  406. if ((RetryCnt < 0) && (RetryCnt != ATP_INFINITE_RETRIES))
  407. {
  408. error = ATALK_ATP_INVALID_RETRYCNT;
  409. break;
  410. }
  411. if ((RelTimerVal < FIRSTVALID_TIMER) || (RelTimerVal > LAST_VALID_TIMER))
  412. {
  413. error = ATALK_ATP_INVALID_TIMERVAL;
  414. break;
  415. }
  416. if (RetryInterval < 0)
  417. {
  418. error = ATALK_ATP_INVALID_RELINT;
  419. break;
  420. }
  421. #endif
  422. // The only valid values for Flags are ATP_REQ_EXACTLY_ONCE and ATP_REQ_REMOTE
  423. ASSERT ((Flags & ~(ATP_REQ_EXACTLY_ONCE | ATP_REQ_REMOTE)) == 0);
  424. if (RetryInterval == 0)
  425. {
  426. RetryInterval = ATP_DEF_RETRY_INTERVAL;
  427. }
  428. // Reference the address object.
  429. AtalkAtpAddrReference(pAtpAddr, &error);
  430. if (!ATALK_SUCCESS(error))
  431. {
  432. break;
  433. }
  434. if ((pAtpReq = (PATP_REQ)AtalkBPAllocBlock(BLKID_ATPREQ)) == NULL)
  435. {
  436. AtalkAtpAddrDereference(pAtpAddr);
  437. error = ATALK_RESR_MEM;
  438. break;
  439. }
  440. } while (FALSE);
  441. if (!ATALK_SUCCESS(error))
  442. return error;
  443. // We have memory allocated and the address object referenced at this
  444. // point. Initialize the request structure.
  445. #if DBG
  446. RtlZeroMemory(pAtpReq, sizeof(ATP_REQ));
  447. pAtpReq->req_Signature = ATP_REQ_SIGNATURE;
  448. #endif
  449. // Initial reference count - for creation.
  450. // Also another ref for this routine itself. Ran into a situation
  451. // where a thread posting the request was preempted and a close called.
  452. // So at the point where the first thread is doing the transmit call,
  453. // the request structure is already freed.
  454. pAtpReq->req_RefCount = 2;
  455. pAtpReq->req_pAtpAddr = pAtpAddr;
  456. pAtpReq->req_RetryInterval = RetryInterval;
  457. pAtpReq->req_RetryCnt = RetryCnt;
  458. pAtpReq->req_RelTimerValue = RelTimerVal;
  459. pAtpReq->req_Dest = *pDest;
  460. pAtpReq->req_Buf = pReq;
  461. pAtpReq->req_BufLen = ReqLen;
  462. if (RetryCnt != 0)
  463. Flags |= ATP_REQ_RETRY_TIMER;
  464. pAtpReq->req_Flags = Flags;
  465. if (pUserBytes != NULL)
  466. {
  467. RtlCopyMemory(pAtpReq->req_UserBytes,
  468. pUserBytes,
  469. ATP_USERBYTES_SIZE);
  470. }
  471. else
  472. {
  473. pAtpReq->req_dwUserBytes = 0;
  474. }
  475. pAtpReq->req_RespBuf = pResp;
  476. pAtpReq->req_RespBufLen = RespLen;
  477. atalkAtpBufferSizeToBitmap( pAtpReq->req_Bitmap,
  478. RespLen,
  479. pAtpAddr->atpao_MaxSinglePktSize);
  480. pAtpReq->req_RespRecdLen = 0;
  481. pAtpReq->req_RecdBitmap = 0;
  482. // Setup the ndis buffer descriptors for the response buffer
  483. AtalkIndAtpSetupNdisBuffer(pAtpReq, pAtpAddr->atpao_MaxSinglePktSize);
  484. pAtpReq->req_Comp = pCmpRoutine;
  485. pAtpReq->req_Ctx = pCtx;
  486. INITIALIZE_SPIN_LOCK(&pAtpReq->req_Lock);
  487. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  488. atalkAtpGetNextTidForAddr(pAtpAddr,
  489. pDest,
  490. &pAtpReq->req_Tid,
  491. &index);
  492. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  493. ("AtalkAtpPostReq: Tid %lx for %lx.%lx.%lx\n",
  494. pAtpReq->req_Tid, pDest->ata_Network,
  495. pDest->ata_Node, pDest->ata_Socket));
  496. // Get the index where this request is supposed to go.
  497. // Need to know the tid.
  498. index = ATP_HASH_TID_DESTADDR(pAtpReq->req_Tid, pDest, ATP_REQ_HASH_SIZE);
  499. // Put this in the request queue
  500. AtalkLinkDoubleAtHead(pAtpAddr->atpao_ReqHash[index],
  501. pAtpReq,
  502. req_Next,
  503. req_Prev);
  504. if (RetryCnt != 0)
  505. {
  506. // Set the time stamp when this should be retried
  507. pAtpReq->req_RetryTimeStamp = AtalkGetCurrentTick() + RetryInterval;
  508. InsertTailList(&pAtpAddr->atpao_ReqList, &pAtpReq->req_List);
  509. }
  510. #ifdef PROFILING
  511. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumRequests,
  512. &AtalkStatsLock.SpinLock);
  513. #endif
  514. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  515. // Return the tid
  516. *pTid = pAtpReq->req_Tid;
  517. // Now send the request
  518. atalkAtpTransmitReq(pAtpReq);
  519. // Remove the ref added at the beginning of this routine.
  520. AtalkAtpReqDereference(pAtpReq);
  521. return ATALK_NO_ERROR;
  522. }
  523. VOID
  524. AtalkAtpSetReqHandler(
  525. IN PATP_ADDROBJ pAtpAddr,
  526. IN ATP_REQ_HANDLER ReqHandler,
  527. IN PVOID ReqCtx OPTIONAL
  528. )
  529. /*++
  530. Routine Description:
  531. Arguments:
  532. Return Value:
  533. --*/
  534. {
  535. KIRQL OldIrql;
  536. ATALK_ERROR error;
  537. ASSERT (ReqHandler != NULL);
  538. // Set the request handler in the address object
  539. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  540. ASSERT((pAtpAddr->atpao_Flags & ATPAO_CLOSING) == 0);
  541. pAtpAddr->atpao_RefCount++;
  542. pAtpAddr->atpao_ReqHandler = ReqHandler;
  543. pAtpAddr->atpao_ReqCtx = ReqCtx;
  544. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  545. }
  546. ATALK_ERROR
  547. AtalkAtpPostResp(
  548. IN PATP_RESP pAtpResp,
  549. IN PATALK_ADDR pDest,
  550. IN OUT PAMDL pResp,
  551. IN USHORT RespLen,
  552. IN PBYTE pUserBytes OPTIONAL,
  553. IN ATP_REL_HANDLER pCmpRoutine,
  554. IN PVOID pCtx OPTIONAL
  555. )
  556. /*++
  557. Routine Description:
  558. Arguments:
  559. Return Value:
  560. --*/
  561. {
  562. PATP_ADDROBJ pAtpAddr;
  563. BOOLEAN addrlocked = FALSE, resplocked = FALSE;
  564. BOOLEAN DerefAddr = FALSE, DerefResp = FALSE;
  565. SHORT ResponseLen;
  566. KIRQL OldIrql;
  567. ATALK_ERROR error;
  568. ASSERT(VALID_ATPRS(pAtpResp));
  569. ASSERT ((pAtpResp->resp_Flags & (ATP_RESP_VALID_RESP |
  570. ATP_RESP_REL_TIMER |
  571. ATP_RESP_HANDLER_NOTIFIED)) == 0);
  572. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  573. ("AtalkAtpPostResp: Posting response for Resp %lx, Tid %x %s\n",
  574. pAtpResp, pAtpResp->resp_Tid,
  575. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  576. pAtpAddr = pAtpResp->resp_pAtpAddr;
  577. ASSERT(VALID_ATPAO(pAtpAddr));
  578. do
  579. {
  580. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  581. if ((RespLen < 0) ||
  582. (RespLen > (pAtpAddr->atpao_MaxSinglePktSize * ATP_MAX_RESP_PKTS)))
  583. {
  584. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  585. ("AtalkAtpPostResp: Invalid buffer size %ld", RespLen));
  586. error = ATALK_BUFFER_INVALID_SIZE;
  587. break;
  588. }
  589. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  590. addrlocked = TRUE;
  591. atalkAtpAddrRefNonInterlock(pAtpAddr, &error);
  592. if (!ATALK_SUCCESS(error))
  593. {
  594. break;
  595. }
  596. DerefAddr = TRUE;
  597. atalkAtpBitmapToBufferSize( ResponseLen,
  598. pAtpResp->resp_Bitmap,
  599. pAtpAddr->atpao_MaxSinglePktSize);
  600. if (ResponseLen < RespLen)
  601. {
  602. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  603. ("AtalkAtpPostResp: bitmap resplen (%d) < specified (%d)\n",
  604. ResponseLen, RespLen));
  605. error = ATALK_BUFFER_TOO_BIG;
  606. break;
  607. }
  608. AtalkAtpRespReferenceByPtrDpc(pAtpResp, &error);
  609. if (!ATALK_SUCCESS(error))
  610. {
  611. break;
  612. }
  613. DerefResp = TRUE;
  614. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  615. resplocked = TRUE;
  616. if (pAtpResp->resp_Flags & (ATP_RESP_CLOSING | ATP_RESP_CANCELLED))
  617. {
  618. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  619. ("AtalkAtpPostResp: Closing/Cancelled %x", pAtpResp->resp_Flags));
  620. error = ATALK_ATP_RESP_CLOSING;
  621. break;
  622. }
  623. if (pAtpResp->resp_Flags & ATP_RESP_VALID_RESP)
  624. {
  625. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  626. ("AtalkAtpPostResp: Already posted !\n"));
  627. error = ATALK_ATP_RESP_TOOMANY;
  628. break;
  629. }
  630. // No response was previously posted. OK to proceed.
  631. pAtpResp->resp_Flags |= ATP_RESP_VALID_RESP;
  632. pAtpResp->resp_Buf = pResp;
  633. pAtpResp->resp_BufLen = RespLen;
  634. pAtpResp->resp_Comp = pCmpRoutine;
  635. ASSERT(pCmpRoutine != NULL);
  636. pAtpResp->resp_Ctx = pCtx;
  637. pAtpResp->resp_Dest = *pDest;
  638. pAtpResp->resp_UserBytesOnly = (pAtpResp->resp_Bitmap == 0) ? TRUE : FALSE;
  639. if (ARGUMENT_PRESENT(pUserBytes))
  640. {
  641. pAtpResp->resp_dwUserBytes = *(UNALIGNED ULONG *)pUserBytes;
  642. }
  643. else
  644. {
  645. pAtpResp->resp_dwUserBytes = 0;
  646. }
  647. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  648. ("AtalkAtpPostResp: Posting response for %s request id %x\n",
  649. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO",
  650. pAtpResp->resp_Tid));
  651. // Now setup to start the release timer, but only for XO
  652. if (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE)
  653. {
  654. pAtpResp->resp_Flags |= ATP_RESP_REL_TIMER;
  655. InsertTailList(&pAtpAddr->atpao_RespList, &pAtpResp->resp_List);
  656. }
  657. // For ALO set the comp status right here.
  658. pAtpResp->resp_CompStatus = error = ATALK_NO_ERROR;
  659. } while (FALSE);
  660. if (addrlocked)
  661. {
  662. if (resplocked)
  663. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  664. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  665. }
  666. if (ATALK_SUCCESS(error))
  667. {
  668. // Send the response.
  669. ASSERT(pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  670. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  671. ("AtalkAtpPostResp: Transmitting response %lx\n", pAtpResp));
  672. atalkAtpTransmitResp(pAtpResp);
  673. }
  674. // Dereference the address object.
  675. if (DerefAddr)
  676. AtalkAtpAddrDereferenceDpc(pAtpAddr);
  677. if (DerefResp)
  678. AtalkAtpRespDereferenceDpc(pAtpResp);
  679. // for ALO transactions, we are done so take away the creation reference
  680. if ((pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) == 0)
  681. {
  682. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  683. ("AtalkAtpPostResp: Removing creation reference for ALO request %lx Tid %x\n",
  684. pAtpResp, pAtpResp->resp_Tid));
  685. AtalkAtpRespDereferenceDpc(pAtpResp);
  686. }
  687. if (OldIrql != DISPATCH_LEVEL)
  688. KeLowerIrql(OldIrql);
  689. return error;
  690. }
  691. ATALK_ERROR
  692. AtalkAtpCancelReq(
  693. IN PATP_ADDROBJ pAtpAddr,
  694. IN USHORT Tid,
  695. IN PATALK_ADDR pDest
  696. )
  697. /*++
  698. Routine Description:
  699. Arguments:
  700. Return Value:
  701. --*/
  702. {
  703. ATALK_ERROR error;
  704. KIRQL OldIrql;
  705. PATP_REQ pAtpReq;
  706. // Find the request.
  707. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  708. atalkAtpReqReferenceByAddrTidDpc(pAtpAddr,
  709. pDest,
  710. Tid,
  711. &pAtpReq,
  712. &error);
  713. if (ATALK_SUCCESS(error))
  714. {
  715. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  716. ("AtalkAtpCancelReq: Cancelling req tid %x\n", Tid));
  717. // Request is referenced for us. Remove the creation reference.
  718. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  719. // Do not cancel a request that has just about been satisfied anyway !!!
  720. if (pAtpReq->req_Flags & ATP_REQ_RESPONSE_COMPLETE)
  721. {
  722. error = ATALK_ATP_REQ_CLOSING;
  723. }
  724. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  725. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  726. if (ATALK_SUCCESS(error))
  727. {
  728. // Try to remove the creation reference
  729. atalkAtpReqComplete(pAtpReq, ATALK_ATP_REQ_CANCELLED);
  730. }
  731. // Remove the reference added at the beginning.
  732. AtalkAtpReqDereference(pAtpReq);
  733. }
  734. else RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  735. return error;
  736. }
  737. BOOLEAN
  738. AtalkAtpIsReqComplete(
  739. IN PATP_ADDROBJ pAtpAddr,
  740. IN USHORT Tid,
  741. IN PATALK_ADDR pDest
  742. )
  743. /*++
  744. Routine Description:
  745. This is always called at DISPATCH_LEVEL - only by PAP.
  746. Arguments:
  747. Return Value:
  748. --*/
  749. {
  750. PATP_REQ pAtpReq;
  751. ATALK_ERROR error;
  752. BOOLEAN rc = FALSE;
  753. ASSERT (KeGetCurrentIrql() == DISPATCH_LEVEL);
  754. // Find the request.
  755. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  756. atalkAtpReqReferenceByAddrTidDpc(pAtpAddr,
  757. pDest,
  758. Tid,
  759. &pAtpReq,
  760. &error);
  761. if (ATALK_SUCCESS(error))
  762. {
  763. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  764. // Do not cancel a request that has just about been satisfied anyway !!!
  765. if (pAtpReq->req_Flags & ATP_REQ_RESPONSE_COMPLETE)
  766. {
  767. rc = TRUE;
  768. }
  769. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  770. AtalkAtpReqDereferenceDpc(pAtpReq);
  771. }
  772. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  773. return rc;
  774. }
  775. ATALK_ERROR
  776. AtalkAtpCancelResp(
  777. IN PATP_RESP pAtpResp
  778. )
  779. /*++
  780. Routine Description:
  781. NOTE: A Response can be cancelled in two states:
  782. - *before* a response is posted
  783. In this case no release handler is there so an extra dereference needs to be done
  784. - *after* a response is posted
  785. In this case a release handler is associated which will do the final dereference.
  786. Arguments:
  787. Return Value:
  788. --*/
  789. {
  790. BOOLEAN extraDeref = FALSE, CompleteResp = FALSE;
  791. KIRQL OldIrql;
  792. ATALK_ERROR error;
  793. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  794. ("AtalkAtpCancelResp: Cancelling response for tid %x %s\n",
  795. pAtpResp->resp_Tid,
  796. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  797. AtalkAtpRespReferenceByPtr(pAtpResp, &error);
  798. if (ATALK_SUCCESS(error))
  799. {
  800. // Remove the creation reference for it.
  801. // Only XO responses can be cancelled, if a repsonse has been posted.
  802. ACQUIRE_SPIN_LOCK(&pAtpResp->resp_Lock, &OldIrql);
  803. if ((pAtpResp->resp_Flags & ATP_RESP_VALID_RESP) == 0)
  804. extraDeref = TRUE;
  805. pAtpResp->resp_Flags |= ATP_RESP_CANCELLED;
  806. if (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE)
  807. {
  808. if (pAtpResp->resp_Flags & ATP_RESP_REL_TIMER)
  809. {
  810. ASSERT (pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  811. }
  812. CompleteResp = TRUE;
  813. }
  814. else if ((pAtpResp->resp_Flags & ATP_RESP_VALID_RESP) == 0)
  815. CompleteResp = TRUE;
  816. RELEASE_SPIN_LOCK(&pAtpResp->resp_Lock, OldIrql);
  817. if (extraDeref)
  818. AtalkAtpRespDereference(pAtpResp);
  819. if (CompleteResp)
  820. {
  821. // Try to remove the creation reference
  822. atalkAtpRespComplete(pAtpResp, ATALK_ATP_RESP_CANCELLED);
  823. }
  824. // Remove the reference added at the beginning.
  825. AtalkAtpRespDereference(pAtpResp);
  826. }
  827. else
  828. {
  829. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  830. ("AtalkAtpCancelResp: Failed to reference resp %lx, flags %x, tid %x\n",
  831. pAtpResp, pAtpResp->resp_Flags, pAtpResp->resp_Tid));
  832. }
  833. return error;
  834. }
  835. ATALK_ERROR
  836. AtalkAtpCancelRespByTid(
  837. IN PATP_ADDROBJ pAtpAddr,
  838. IN PATALK_ADDR pSrcAddr,
  839. IN USHORT Tid
  840. /*++
  841. Routine Description:
  842. Arguments:
  843. Return Value:
  844. --*/
  845. )
  846. {
  847. ATALK_ERROR error;
  848. PATP_RESP pAtpResp;
  849. ASSERT (VALID_ATPAO(pAtpAddr));
  850. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  851. atalkAtpRespReferenceByAddrTidDpc(pAtpAddr, pSrcAddr, Tid, &pAtpResp, &error);
  852. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  853. if (ATALK_SUCCESS(error))
  854. {
  855. error = AtalkAtpCancelResp(pAtpResp);
  856. AtalkAtpRespDereferenceDpc(pAtpResp);
  857. }
  858. return error;
  859. }
  860. VOID
  861. AtalkAtpPacketIn(
  862. IN PPORT_DESCRIPTOR pPortDesc,
  863. IN PDDP_ADDROBJ pDdpAddr,
  864. IN PBYTE pPkt,
  865. IN USHORT PktLen,
  866. IN PATALK_ADDR pSrcAddr,
  867. IN PATALK_ADDR pDstAddr,
  868. IN ATALK_ERROR ErrorCode,
  869. IN BYTE DdpType,
  870. IN PATP_ADDROBJ pAtpAddr,
  871. IN BOOLEAN OptimizedPath,
  872. IN PVOID OptimizeCtx
  873. )
  874. /*++
  875. Routine Description:
  876. Arguments:
  877. Return Value:
  878. --*/
  879. {
  880. ATALK_ERROR error;
  881. NTSTATUS ntStatus;
  882. USHORT atpDataSize;
  883. ULONG index;
  884. BYTE controlInfo, function, relTimer, bitmap;
  885. USHORT seqNum, tid, startOffset;
  886. SHORT expectedRespSize;
  887. ULONG bytesCopied;
  888. BOOLEAN sendSts, eomFlag, xoFlag;
  889. BOOLEAN RetransmitResp = FALSE;
  890. PATP_REQ pAtpReq;
  891. ATP_REQ_HANDLER ReqHandler;
  892. PATP_RESP pAtpResp;
  893. BOOLEAN UnlockAddr = FALSE, DerefAddr = FALSE;
  894. PBYTE pDgram = pPkt;
  895. TIME TimeS, TimeE, TimeD;
  896. TimeS = KeQueryPerformanceCounter(NULL);
  897. ASSERT(VALID_ATPAO(pAtpAddr));
  898. do
  899. {
  900. // Check for incoming errors
  901. if ((!ATALK_SUCCESS(ErrorCode) &&
  902. (ErrorCode != ATALK_SOCKET_CLOSED)) ||
  903. (DdpType != DDPPROTO_ATP))
  904. {
  905. // Drop the packet. Invalid packet error log.
  906. TMPLOGERR();
  907. error = ATALK_ATP_INVALID_PKT;
  908. break;
  909. }
  910. if (ErrorCode == ATALK_SOCKET_CLOSED)
  911. {
  912. // Our ddp address pointer is no longer valid. It will be potentially
  913. // be freed after return from this call! Only valid request on this
  914. // ATP request will now be AtpCloseAddress(). Also, we should never
  915. // be called with this address object by DDP.
  916. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  917. pAtpAddr->atpao_DdpAddr = NULL;
  918. pAtpAddr->atpao_Flags &= ~ATPAO_OPEN;
  919. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  920. // If we are coming in via the optimized path and socket closed
  921. // deref the address object since it was referenced within the
  922. // indication code.
  923. if (OptimizedPath)
  924. {
  925. AtalkAtpAddrDereferenceDpc(pAtpAddr);
  926. }
  927. error = ErrorCode;
  928. break;
  929. }
  930. // Make sure that we are not called after the ddp socket is closed.
  931. ASSERT(pAtpAddr->atpao_Flags & ATPAO_OPEN);
  932. if (PktLen < ATP_HEADER_SIZE)
  933. {
  934. error = ATALK_ATP_INVALID_PKT;
  935. break;
  936. }
  937. // This must fail if OPEN is not set/initialization.
  938. error = ATALK_NO_ERROR;
  939. if (!OptimizedPath)
  940. {
  941. AtalkAtpAddrReferenceDpc(pAtpAddr, &error);
  942. }
  943. } while (FALSE);
  944. if (!ATALK_SUCCESS(error))
  945. {
  946. return;
  947. }
  948. // Dereference address at the end,unless we want to keep it for some reason.
  949. DerefAddr = TRUE;
  950. // Get the static fields from the ATP header.
  951. controlInfo = *pDgram++;
  952. function = (controlInfo & ATP_FUNC_MASK);
  953. relTimer = (controlInfo & ATP_REL_TIMER_MASK);
  954. xoFlag = ((controlInfo & ATP_XO_MASK) != 0);
  955. eomFlag = ((controlInfo & ATP_EOM_MASK) != 0);
  956. sendSts = ((controlInfo & ATP_STS_MASK) != 0);
  957. // Get the bitmap/sequence number
  958. bitmap = *pDgram++;
  959. seqNum = (USHORT)bitmap;
  960. // Get the transaction id
  961. GETSHORT2SHORT(&tid, pDgram);
  962. pDgram += sizeof(USHORT);
  963. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  964. ("AtalkAtpPacketIn: Packet tid %lx fu %lx ci %lx\n",
  965. tid, function, controlInfo));
  966. // pDgram now points to the user bytes.
  967. do
  968. {
  969. // Check all the values
  970. if (relTimer > LAST_VALID_TIMER)
  971. {
  972. // Use a thirty second timer value.
  973. relTimer = THIRTY_SEC_TIMER;
  974. }
  975. atpDataSize = PktLen - ATP_HEADER_SIZE;
  976. if (atpDataSize > pAtpAddr->atpao_MaxSinglePktSize)
  977. {
  978. error = ATALK_ATP_INVALID_PKT;
  979. break;
  980. }
  981. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  982. UnlockAddr = TRUE;
  983. switch (function)
  984. {
  985. case ATP_REQUEST:
  986. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  987. ("AtalkAtpPacketIn: Received REQUEST from %lx.%lx.%lx (%d.%d.%d)\n",
  988. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket,
  989. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket));
  990. if (xoFlag)
  991. {
  992. // ExactlyOnce Transaction
  993. // Check for a queued response. If available use it.
  994. atalkAtpRespReferenceByAddrTidDpc(pAtpAddr,
  995. pSrcAddr,
  996. tid,
  997. &pAtpResp,
  998. &error);
  999. if (ATALK_SUCCESS(error))
  1000. {
  1001. ASSERT (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE);
  1002. // Found a response corresponding to this request. It
  1003. // is referenced for us. Retransmit it, if there is a
  1004. // response posted on it.
  1005. // Check to see if this response has a valid response
  1006. // posted by the atp client yet. If so reset the release timer.
  1007. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1008. if (pAtpResp->resp_Flags & ATP_RESP_VALID_RESP)
  1009. {
  1010. if ((pAtpResp->resp_Flags & (ATP_RESP_TRANSMITTING | ATP_RESP_SENT)) == ATP_RESP_SENT)
  1011. {
  1012. RetransmitResp = TRUE;
  1013. if (pAtpResp->resp_Flags & ATP_RESP_REL_TIMER)
  1014. {
  1015. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1016. ("AtalkAtpPacketIn: Retransmitting request %lx, tid %x (%x)\n",
  1017. pAtpResp, pAtpResp->resp_Tid, pAtpResp->resp_Flags));
  1018. pAtpResp->resp_RelTimeStamp = AtalkGetCurrentTick() +
  1019. pAtpResp->resp_RelTimerTicks;
  1020. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  1021. ("AtalkAtpPacketIn: Restarted reltimer %lx\n", pAtpResp->resp_Tid));
  1022. // Set the latest bitmap for the request! We
  1023. // shouldn't touch this if no valid response is yet
  1024. // posted, so that we use the one in the first request
  1025. // packet received.
  1026. pAtpResp->resp_Bitmap = bitmap;
  1027. }
  1028. else
  1029. {
  1030. error = ATALK_ATP_RESP_CLOSING;
  1031. // Timer already fired. Drop the request.
  1032. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1033. ("AtalkAtpPacketIn: Req recv after Reltimer fired ? Flags %lx\n",
  1034. pAtpResp->resp_Flags));
  1035. ASSERT (pAtpResp->resp_Flags & ATP_RESP_CLOSING);
  1036. }
  1037. }
  1038. }
  1039. else
  1040. {
  1041. error = ATALK_ATP_NO_VALID_RESP;
  1042. }
  1043. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1044. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  1045. UnlockAddr = FALSE;
  1046. if (ATALK_SUCCESS(error))
  1047. {
  1048. ASSERT(pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  1049. if (RetransmitResp)
  1050. {
  1051. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  1052. ("AtalkAtpPacketIn: Retransmitting response %lx\n", pAtpResp));
  1053. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumRemoteRetries,
  1054. &AtalkStatsLock.SpinLock);
  1055. atalkAtpTransmitResp(pAtpResp);
  1056. }
  1057. }
  1058. // Remove the refererence on this response structure.
  1059. AtalkAtpRespDereferenceDpc(pAtpResp);
  1060. break;
  1061. }
  1062. }
  1063. // make sure the 4 bytes (pAtpResp->resp_dwUserBytes) exist
  1064. if (PktLen < (ATP_USERBYTES_SIZE + sizeof(ULONG)))
  1065. {
  1066. error = ATALK_ATP_INVALID_PKT;
  1067. ASSERT(0);
  1068. break;
  1069. }
  1070. // Its either an ALO request or an XO request which we have not seen it before
  1071. // Decode the response bitmap. We're still holding the address spinlock
  1072. atalkAtpBitmapToBufferSize( expectedRespSize,
  1073. bitmap,
  1074. pAtpAddr->atpao_MaxSinglePktSize);
  1075. if (expectedRespSize < 0)
  1076. {
  1077. error = ATALK_ATP_INVALID_PKT;
  1078. break;
  1079. }
  1080. if (xoFlag)
  1081. {
  1082. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumXoResponse,
  1083. &AtalkStatsLock.SpinLock);
  1084. }
  1085. else
  1086. {
  1087. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumAloResponse,
  1088. &AtalkStatsLock.SpinLock);
  1089. }
  1090. // New request. Check for request handler set
  1091. if ((ReqHandler = pAtpAddr->atpao_ReqHandler) == NULL)
  1092. {
  1093. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1094. ("AtalkAtpPacketIn: No GetRequests for request\n"));
  1095. error = ATALK_ATP_NO_GET_REQ;
  1096. break;
  1097. }
  1098. // Allocate memory for a send response structure.
  1099. if ((pAtpResp =(PATP_RESP)AtalkBPAllocBlock(BLKID_ATPRESP)) == NULL)
  1100. {
  1101. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1102. ("AtalkAtpPacketIn: Could not alloc mem for resp\n"));
  1103. error = ATALK_RESR_MEM;
  1104. break;
  1105. }
  1106. #if DBG
  1107. RtlZeroMemory(pAtpResp, sizeof(ATP_RESP));
  1108. pAtpResp->resp_Signature = ATP_RESP_SIGNATURE;
  1109. #endif
  1110. // Initialize the send response structure. Note that we do
  1111. // not have a posted response yet for XO or this is an ALO
  1112. // Initialize spinlock/list
  1113. INITIALIZE_SPIN_LOCK(&pAtpResp->resp_Lock);
  1114. // Reference for Creation and indication
  1115. pAtpResp->resp_RefCount = 2;
  1116. // Remember the destination of this response.
  1117. pAtpResp->resp_Dest = *pSrcAddr;
  1118. pAtpResp->resp_Tid = tid;
  1119. pAtpResp->resp_Bitmap = bitmap;
  1120. // Backpointer to the address object
  1121. pAtpResp->resp_pAtpAddr = pAtpAddr;
  1122. // Remember a response needs to be posted by the atp client.
  1123. pAtpResp->resp_Flags = (OptimizedPath ? ATP_RESP_REMOTE : 0);
  1124. pAtpResp->resp_UserBytesOnly = (bitmap == 0) ? TRUE : FALSE;
  1125. pAtpResp->resp_Comp = NULL;
  1126. pAtpResp->resp_Ctx = NULL;
  1127. pAtpResp->resp_dwUserBytes = *(UNALIGNED ULONG *)(pDgram + ATP_USERBYTES_SIZE);
  1128. if (xoFlag)
  1129. {
  1130. // Get the index into the hash response array where this
  1131. // response would be.
  1132. index = ATP_HASH_TID_DESTADDR(tid, pSrcAddr, ATP_RESP_HASH_SIZE);
  1133. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1134. ("AtalkAtpPacketIn: XO Req Index %lx resp for %lx-%lx.%lx.%lx %d\n",
  1135. index, tid, pSrcAddr->ata_Network, pSrcAddr->ata_Node,
  1136. pSrcAddr->ata_Socket, AtalkAtpRelTimerTicks[relTimer]));
  1137. // Put this in the XO response queue - LOCK Should be acquired!
  1138. AtalkLinkDoubleAtHead(pAtpAddr->atpao_RespHash[index],
  1139. pAtpResp,
  1140. resp_Next,
  1141. resp_Prev);
  1142. pAtpResp->resp_Flags |= ATP_RESP_EXACTLY_ONCE;
  1143. pAtpResp->resp_RelTimerTicks = (LONG)AtalkAtpRelTimerTicks[relTimer];
  1144. pAtpResp->resp_RelTimeStamp = AtalkGetCurrentTick() + pAtpResp->resp_RelTimerTicks;
  1145. }
  1146. else
  1147. {
  1148. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1149. ("AtalkAtpPacketIn: ALO Req resp for %lx-%lx.%lx %d\n",
  1150. tid, pSrcAddr->ata_Network, pSrcAddr->ata_Node,
  1151. pSrcAddr->ata_Socket));
  1152. // Put this in the ALO response queue - LOCK Should be acquired!
  1153. AtalkLinkDoubleAtHead(pAtpAddr->atpao_AloRespLinkage,
  1154. pAtpResp,
  1155. resp_Next,
  1156. resp_Prev);
  1157. }
  1158. // We dont want to have the initial ref go away, as we have
  1159. // inserted a resp into the addr resp list.
  1160. DerefAddr = FALSE;
  1161. error = ATALK_NO_ERROR;
  1162. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  1163. UnlockAddr = FALSE;
  1164. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1165. ("AtalkAtpPacketIn: Indicating request %lx, tid %x %s\n",
  1166. pAtpResp, tid,
  1167. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  1168. #ifdef PROFILING
  1169. TimeD = KeQueryPerformanceCounter(NULL);
  1170. #endif
  1171. (*ReqHandler)(ATALK_NO_ERROR,
  1172. pAtpAddr->atpao_ReqCtx,
  1173. pAtpResp,
  1174. pSrcAddr,
  1175. atpDataSize,
  1176. pDgram + ATP_USERBYTES_SIZE,
  1177. pDgram);
  1178. #ifdef PROFILING
  1179. TimeE = KeQueryPerformanceCounter(NULL);
  1180. TimeE.QuadPart -= TimeD.QuadPart;
  1181. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumReqHndlr,
  1182. &AtalkStatsLock.SpinLock);
  1183. INTERLOCKED_ADD_LARGE_INTGR(&AtalkStatistics.stat_AtpReqHndlrProcessTime,
  1184. TimeE,
  1185. &AtalkStatsLock.SpinLock);
  1186. #endif
  1187. break;
  1188. case ATP_RESPONSE:
  1189. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1190. ("AtalkAtpPacketIn: Received RESPONSE from %lx.%lx.%lx, SeqNum %d tid %lx ss %lx\n",
  1191. pSrcAddr->ata_Network, pSrcAddr->ata_Node, pSrcAddr->ata_Socket,
  1192. seqNum, tid, sendSts));
  1193. if (seqNum > (ATP_MAX_RESP_PKTS-1))
  1194. {
  1195. // Drop the packet. Invalid packet error log.
  1196. TMPLOGERR();
  1197. break;
  1198. }
  1199. // See if we have a request for this tid and remote address.
  1200. if (OptimizedPath)
  1201. {
  1202. pAtpReq = (PATP_REQ)OptimizeCtx;
  1203. ASSERT (VALID_ATPRQ(pAtpReq));
  1204. ASSERT (pAtpReq->req_Bitmap == 0);
  1205. }
  1206. else
  1207. {
  1208. atalkAtpReqReferenceByAddrTidDpc(pAtpAddr,
  1209. pSrcAddr,
  1210. tid,
  1211. &pAtpReq,
  1212. &error);
  1213. }
  1214. if (!ATALK_SUCCESS(error))
  1215. {
  1216. // We dont have a corresponding pending request. Ignore.
  1217. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  1218. ("AtalkAtpPacketIn: No pending request for tid %lx\n", tid));
  1219. break;
  1220. }
  1221. do
  1222. {
  1223. if (!OptimizedPath)
  1224. {
  1225. // Check the request bitmap, which could be zero if the user only
  1226. // wanted the user bytes and passed in a null response buffer.
  1227. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  1228. // If we are the first packet, copy the response user bytes.
  1229. if (seqNum == 0)
  1230. {
  1231. RtlCopyMemory(pAtpReq->req_RespUserBytes,
  1232. pDgram,
  1233. ATP_USERBYTES_SIZE);
  1234. }
  1235. // Now skip over the user bytes
  1236. pDgram += ATP_USERBYTES_SIZE;
  1237. // Do we want to keep this response? Check the corresponding
  1238. // bit in our current bitmap set.
  1239. if (((pAtpReq->req_RecdBitmap & AtpBitmapForSeqNum[seqNum]) != 0) ||
  1240. ((pAtpReq->req_Bitmap & AtpBitmapForSeqNum[seqNum]) == 0))
  1241. {
  1242. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  1243. // We dont care about this packet. We already received it or weren't
  1244. // expecting it.
  1245. break;
  1246. }
  1247. // We want this response. Set bit in the recd bitmap. And
  1248. // Clear it in the expected packets req_Bitmap.
  1249. // !!!NOTE!!! We can release the spinlock even though the copy
  1250. // is not done. We have a ref to the req, and it wont
  1251. // get completed before that is done.
  1252. pAtpReq->req_Bitmap &= ~AtpBitmapForSeqNum[seqNum];
  1253. pAtpReq->req_RecdBitmap |= AtpBitmapForSeqNum[seqNum];
  1254. pAtpReq->req_RespRecdLen += atpDataSize;
  1255. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1256. ("AtalkAtpPacketIn: req_Bitmap %x, req_RecdBitmap %x\n",
  1257. pAtpReq->req_Bitmap, pAtpReq->req_RecdBitmap));
  1258. // Now if eom is set, we need to reset all high order bits
  1259. // of the req_Bitmap. req_RecdBitmap should now indicate all
  1260. // the buffers we received. The two should be mutually exclusive
  1261. // at this point.
  1262. if (eomFlag)
  1263. {
  1264. pAtpReq->req_Bitmap &= AtpEomBitmapForSeqNum[seqNum];
  1265. ASSERT((pAtpReq->req_Bitmap & pAtpReq->req_RecdBitmap) == 0);
  1266. }
  1267. if (sendSts)
  1268. {
  1269. // Reset timer since we are going to retransmit the request
  1270. pAtpReq->req_RetryTimeStamp = AtalkGetCurrentTick() +
  1271. pAtpReq->req_RetryInterval;
  1272. }
  1273. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  1274. // Copy the data into the users buffer. Check if there's room.
  1275. startOffset = (USHORT)seqNum * pAtpAddr->atpao_MaxSinglePktSize;
  1276. if (pAtpReq->req_RespBufLen < (startOffset + atpDataSize))
  1277. {
  1278. // This should be a rare case; packet was in bitmap limits,
  1279. // but still wouldn't fit into user space.The other way this
  1280. // could occure is if the responder is sending less than full
  1281. // responses -- we don't "synch" up the user buffer until all
  1282. // packets have been received.
  1283. // We want to give up now, call the comp rotuine signaling
  1284. // the error -- unthread and free the request control block
  1285. // cancel the retry timer.
  1286. ASSERT(0);
  1287. error = ATALK_RESR_MEM;
  1288. atalkAtpReqComplete(pAtpReq, error);
  1289. break;
  1290. }
  1291. if ((atpDataSize > 0) && (pAtpReq->req_RespBuf != NULL))
  1292. {
  1293. // We have room to copy the data into the users buffer.
  1294. ntStatus = TdiCopyBufferToMdl(pDgram,
  1295. 0,
  1296. atpDataSize,
  1297. pAtpReq->req_RespBuf,
  1298. startOffset,
  1299. &bytesCopied);
  1300. ASSERT(bytesCopied == atpDataSize);
  1301. ASSERT(NT_SUCCESS(ntStatus));
  1302. }
  1303. if (sendSts)
  1304. {
  1305. // We have reset the retry timer above
  1306. atalkAtpTransmitReq(pAtpReq);
  1307. }
  1308. // If the bitmap is non-zero, we are still awaiting more responses.
  1309. if (pAtpReq->req_Bitmap != 0)
  1310. {
  1311. break;
  1312. }
  1313. }
  1314. else
  1315. {
  1316. ASSERT (pAtpReq->req_Bitmap == 0);
  1317. }
  1318. // Ok, we have the entire response !
  1319. // If an XO request send a release, synch up the user buffer,
  1320. // Deref the request to have it complete.
  1321. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  1322. UnlockAddr = FALSE;
  1323. if (pAtpReq->req_Flags & ATP_REQ_EXACTLY_ONCE)
  1324. {
  1325. atalkAtpTransmitRel(pAtpReq);
  1326. }
  1327. // Do the synch up! USE RECD_BITMAP!!
  1328. // Set the response length, the user bytes in the request buffer.
  1329. // See if we can grab ownership of this request to remove
  1330. // the creation reference and complete it.
  1331. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1332. ("AtalkAtpPacketIn: Completing req %lx tid %x\n",
  1333. pAtpReq, pAtpReq->req_Tid));
  1334. atalkAtpReqComplete(pAtpReq, error);
  1335. } while (FALSE);
  1336. // Remove reference on the request added at the beginning.
  1337. AtalkAtpReqDereferenceDpc(pAtpReq);
  1338. break;
  1339. case ATP_RELEASE:
  1340. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1341. ("AtalkAtpPacketIn: Received release for tid %lx!\n", tid));
  1342. atalkAtpRespReferenceByAddrTidDpc(pAtpAddr,
  1343. pSrcAddr,
  1344. tid,
  1345. &pAtpResp,
  1346. &error);
  1347. if (ATALK_SUCCESS(error))
  1348. {
  1349. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1350. ("AtalkAtpPacketIn: Found resp for release for tid %lx!\n",
  1351. pAtpResp->resp_Tid));
  1352. // We received a release for this response. Cleanup and
  1353. // complete.
  1354. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1355. pAtpResp->resp_Flags |= ATP_RESP_RELEASE_RECD;
  1356. if (pAtpResp->resp_Flags & ATP_RESP_REL_TIMER)
  1357. {
  1358. ASSERT (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE);
  1359. }
  1360. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1361. }
  1362. else
  1363. {
  1364. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1365. ("AtalkAtpPacketIn: resp not found - release for tid %lx!\n", tid));
  1366. }
  1367. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  1368. UnlockAddr = FALSE;
  1369. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumRecdRelease,
  1370. &AtalkStatsLock.SpinLock);
  1371. if (ATALK_SUCCESS(error))
  1372. {
  1373. ATALK_ERROR ErrorCode = ATALK_NO_ERROR;
  1374. // if client (mac) cancelled the request (possibly because session
  1375. // went away), make sure our completion routine gets called
  1376. if ((pAtpResp->resp_Flags & ATP_RESP_VALID_RESP) == 0)
  1377. {
  1378. ErrorCode = ATALK_ATP_RESP_CANCELLED;
  1379. pAtpResp->resp_Flags |= ATP_RESP_VALID_RESP;
  1380. }
  1381. // Try to have the creation reference removed
  1382. atalkAtpRespComplete(pAtpResp, ErrorCode);
  1383. // Remove the reference we added at the beginning.
  1384. AtalkAtpRespDereferenceDpc(pAtpResp);
  1385. }
  1386. break;
  1387. default:
  1388. break;
  1389. }
  1390. if (UnlockAddr)
  1391. {
  1392. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  1393. }
  1394. } while (FALSE);
  1395. // Deref addr added at the beginning of this routine.
  1396. if (DerefAddr)
  1397. {
  1398. AtalkAtpAddrDereferenceDpc(pAtpAddr);
  1399. }
  1400. TimeE = KeQueryPerformanceCounter(NULL);
  1401. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  1402. INTERLOCKED_ADD_LARGE_INTGR_DPC(&AtalkStatistics.stat_AtpPacketInProcessTime,
  1403. TimeD,
  1404. &AtalkStatsLock.SpinLock);
  1405. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumPackets,
  1406. &AtalkStatsLock.SpinLock);
  1407. }
  1408. VOID FASTCALL
  1409. atalkAtpTransmitReq(
  1410. IN PATP_REQ pAtpReq
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Arguments:
  1415. Return Value:
  1416. --*/
  1417. {
  1418. ATALK_ERROR error;
  1419. ATP_HEADER atpHeader;
  1420. BOOLEAN remote;
  1421. BOOLEAN DerefReq = FALSE;
  1422. PBUFFER_DESC pBufDesc = NULL;
  1423. SEND_COMPL_INFO SendInfo;
  1424. // Reference the request. This goes away in request send completion.
  1425. AtalkAtpReqReferenceByPtr(pAtpReq, &error);
  1426. if (ATALK_SUCCESS(error))
  1427. {
  1428. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1429. ("atalkAtpTransmitReq: Transmitting req %lx tid %x\n",
  1430. pAtpReq, pAtpReq->req_Tid));
  1431. // Build the atp header.
  1432. atpHeader.atph_CmdCtrl = ATP_REQUEST | (UCHAR)(ATP_REL_TIMER_MASK & pAtpReq->req_RelTimerValue);
  1433. if (pAtpReq->req_Flags & ATP_REQ_EXACTLY_ONCE)
  1434. atpHeader.atph_CmdCtrl |= ATP_XO_MASK;
  1435. // Put in the expected packets bitmap.
  1436. atpHeader.atph_Bitmap = pAtpReq->req_Bitmap;
  1437. // Put in the tid.
  1438. PUTSHORT2SHORT(&atpHeader.atph_Tid, pAtpReq->req_Tid);
  1439. // Copy the user bytes.
  1440. atpHeader.atph_dwUserBytes = pAtpReq->req_dwUserBytes;
  1441. // Build a buffer descriptor, this should hold the above mdl.
  1442. if (pAtpReq->req_BufLen > 0)
  1443. {
  1444. if ((pBufDesc = AtalkAllocBuffDesc(pAtpReq->req_Buf,
  1445. pAtpReq->req_BufLen,
  1446. 0)) == NULL)
  1447. {
  1448. DerefReq = TRUE;
  1449. error = ATALK_RESR_MEM;
  1450. }
  1451. }
  1452. remote = (pAtpReq->req_Flags & ATP_REQ_REMOTE) ? TRUE : FALSE;
  1453. // Call ddp to send the packet. Dont touch request after this call,
  1454. // as the send completion could potentially lead to it being freed.
  1455. SendInfo.sc_TransmitCompletion = atalkAtpSendReqComplete;
  1456. SendInfo.sc_Ctx1 = pAtpReq;
  1457. SendInfo.sc_Ctx2 = pBufDesc;
  1458. // SendInfo.sc_Ctx3 = NULL;
  1459. if (ATALK_SUCCESS(error) &&
  1460. !ATALK_SUCCESS(error = AtalkDdpSend(pAtpReq->req_pAtpAddr->atpao_DdpAddr,
  1461. &pAtpReq->req_Dest,
  1462. (BYTE)DDPPROTO_ATP,
  1463. remote,
  1464. pBufDesc,
  1465. (PBYTE)&atpHeader,
  1466. ATP_HEADER_SIZE,
  1467. NULL,
  1468. &SendInfo)))
  1469. {
  1470. DerefReq = TRUE;
  1471. if (pBufDesc != NULL)
  1472. {
  1473. // The flags will indicate that the data buffer is not to be
  1474. // freed.
  1475. AtalkFreeBuffDesc(pBufDesc);
  1476. }
  1477. }
  1478. if (DerefReq)
  1479. {
  1480. pAtpReq->req_CompStatus = error;
  1481. AtalkAtpReqDereference(pAtpReq);
  1482. }
  1483. }
  1484. }
  1485. VOID FASTCALL
  1486. atalkAtpSendReqComplete(
  1487. IN NDIS_STATUS Status,
  1488. IN PSEND_COMPL_INFO pSendInfo
  1489. )
  1490. /*++
  1491. Routine Description:
  1492. Arguments:
  1493. Return Value:
  1494. --*/
  1495. {
  1496. if (pSendInfo->sc_Ctx2 != NULL)
  1497. {
  1498. AtalkFreeBuffDesc((PBUFFER_DESC)(pSendInfo->sc_Ctx2));
  1499. }
  1500. AtalkAtpReqDereference((PATP_REQ)(pSendInfo->sc_Ctx1));
  1501. }
  1502. VOID FASTCALL
  1503. atalkAtpTransmitResp(
  1504. IN PATP_RESP pAtpResp
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. Arguments:
  1509. Return Value:
  1510. --*/
  1511. {
  1512. ATALK_ERROR error;
  1513. KIRQL OldIrql;
  1514. BYTE i, bitmap, currentBit, seqNum, pktstosend;
  1515. BOOLEAN RemoteAddr;
  1516. USHORT bytesSent, bytesToSend, maxSinglePktSize;
  1517. SHORT remainingBytes;
  1518. PATP_ADDROBJ pAtpAddr;
  1519. PAMDL pAmdl[ATP_MAX_RESP_PKTS];
  1520. PBUFFER_DESC pBufDesc[ATP_MAX_RESP_PKTS];
  1521. ATP_HEADER atpHeader;
  1522. SEND_COMPL_INFO SendInfo;
  1523. // Verify we have a response posted
  1524. ASSERT(pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  1525. pAtpAddr = pAtpResp->resp_pAtpAddr;
  1526. ASSERT(VALID_ATPAO(pAtpAddr));
  1527. RemoteAddr = ((pAtpResp->resp_Flags & ATP_RESP_REMOTE) == 0) ? FALSE : TRUE;
  1528. // send each response packet that is needed.
  1529. seqNum = 0;
  1530. pktstosend = 0;
  1531. currentBit = 1;
  1532. // Get the max packet size for this atp object
  1533. maxSinglePktSize = pAtpAddr->atpao_MaxSinglePktSize;
  1534. bitmap = pAtpResp->resp_Bitmap;
  1535. remainingBytes = pAtpResp->resp_BufLen;
  1536. bytesSent = 0;
  1537. // Indicate response type.
  1538. atpHeader.atph_CmdCtrl = ATP_RESPONSE;
  1539. // Put in the tid.
  1540. PUTSHORT2SHORT(&atpHeader.atph_Tid, pAtpResp->resp_Tid);
  1541. ASSERTMSG("atalkAtpTransmitResp: resp len is negative\n", (remainingBytes >= 0));
  1542. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1543. do
  1544. {
  1545. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1546. pAtpResp->resp_Flags |= ATP_RESP_TRANSMITTING;
  1547. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1548. do
  1549. {
  1550. pAmdl[seqNum] = NULL;
  1551. pBufDesc[seqNum] = NULL;
  1552. if (((bitmap & currentBit) != 0) ||
  1553. ((seqNum == 0) && pAtpResp->resp_UserBytesOnly))
  1554. {
  1555. ASSERT(pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  1556. bytesToSend = MIN(remainingBytes, maxSinglePktSize);
  1557. if (bytesToSend != 0)
  1558. {
  1559. ASSERT (pAtpResp->resp_Buf != NULL);
  1560. // Make an mdl for the proper subsection of the response mdl.
  1561. // Make a buffer descriptor for the mdl.
  1562. if (((pAmdl[seqNum] = AtalkSubsetAmdl(pAtpResp->resp_Buf,
  1563. bytesSent,
  1564. bytesToSend)) == NULL) ||
  1565. ((pBufDesc[seqNum] = AtalkAllocBuffDesc(pAmdl[seqNum],
  1566. bytesToSend,
  1567. 0)) == NULL))
  1568. {
  1569. ASSERTMSG("atalkAtpTransmitResp: Create mdl or BD failed\n", 0);
  1570. if (pAmdl[seqNum] != NULL)
  1571. {
  1572. AtalkFreeAMdl(pAmdl[seqNum]);
  1573. pAmdl[seqNum] = NULL;
  1574. }
  1575. if (seqNum > 0)
  1576. seqNum --; // Adjust this.
  1577. break;
  1578. }
  1579. }
  1580. pktstosend ++;
  1581. }
  1582. else
  1583. {
  1584. // We are omitting this. Let us mark it appropriately
  1585. pBufDesc[seqNum] = (PBUFFER_DESC)-1;
  1586. }
  1587. seqNum ++;
  1588. currentBit <<= 1;
  1589. remainingBytes -= maxSinglePktSize;
  1590. bytesSent += maxSinglePktSize;
  1591. } while (remainingBytes > 0);
  1592. ASSERT (seqNum <= ATP_MAX_RESP_PKTS);
  1593. // Attempt to reference the response structure. If we fail, we abort.
  1594. // This will go away in the completion routine.
  1595. atalkAtpRespReferenceNDpc(pAtpResp, pktstosend, &error);
  1596. if (!ATALK_SUCCESS(error))
  1597. {
  1598. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1599. ("atalkAtpTransmitResp: response %lx ref (%d) failed\n",
  1600. pAtpResp, seqNum, error));
  1601. // Need to free up the Mdls/Buffdescs
  1602. for (i = 0; i < seqNum; i++)
  1603. {
  1604. if (pAmdl[i] != NULL)
  1605. AtalkFreeAMdl(pAmdl[i]);
  1606. if ((pBufDesc[i] != NULL) && (pBufDesc[i] != (PBUFFER_DESC)-1))
  1607. AtalkFreeBuffDesc(pBufDesc[i]);
  1608. }
  1609. break;
  1610. }
  1611. // Now blast off all the packets
  1612. SendInfo.sc_TransmitCompletion = atalkAtpSendRespComplete;
  1613. SendInfo.sc_Ctx1 = pAtpResp;
  1614. // SendInfo.sc_Ctx3 = pAmdl[i];
  1615. for (i = 0; i < seqNum; i++)
  1616. {
  1617. if (pBufDesc[i] == (PBUFFER_DESC)-1)
  1618. continue;
  1619. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1620. ("atalkAtpTransmitResp: Sending seq #%d for tid %lx\n",
  1621. i, pAtpResp->resp_Tid));
  1622. // Indicate if this is the last packet of the response.
  1623. if (i == (seqNum-1))
  1624. {
  1625. atpHeader.atph_CmdCtrl |= ATP_EOM_MASK;
  1626. }
  1627. // Put in the sequence number
  1628. atpHeader.atph_SeqNum = i;
  1629. // User bytes only go in the first packet of the response
  1630. // unless otherwise indicated for this atp object.
  1631. if ((i == 0) ||
  1632. (pAtpAddr->atpao_Flags & ATPAO_SENDUSERBYTESALL))
  1633. {
  1634. atpHeader.atph_dwUserBytes = pAtpResp->resp_dwUserBytes;
  1635. }
  1636. else
  1637. {
  1638. // Zero the user bytes
  1639. atpHeader.atph_dwUserBytes = 0;
  1640. }
  1641. ASSERT(pAtpResp->resp_Flags & ATP_RESP_VALID_RESP);
  1642. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1643. ("atalkAtpTransmitResp: Sending seq #%d, BufDesc %lx, Resp %lx\n",
  1644. i, pBufDesc[i], pAtpResp));
  1645. ASSERT ((pBufDesc[i] == NULL) ||
  1646. VALID_BUFFDESC(pBufDesc[i]));
  1647. SendInfo.sc_Ctx2 = pBufDesc[i];
  1648. error = AtalkDdpSend(pAtpAddr->atpao_DdpAddr,
  1649. &pAtpResp->resp_Dest,
  1650. (BYTE)DDPPROTO_ATP,
  1651. RemoteAddr,
  1652. pBufDesc[i],
  1653. (PBYTE)&atpHeader,
  1654. ATP_HEADER_SIZE,
  1655. NULL,
  1656. &SendInfo);
  1657. if (!ATALK_SUCCESS(error))
  1658. {
  1659. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  1660. ("atalkAtpTransmitResp: AtalkDdpSend Failed %ld\n", error));
  1661. // Call completion so the buffer/mdl can get freed up,
  1662. // and the reference is removed.
  1663. atalkAtpSendRespComplete(error,
  1664. &SendInfo);
  1665. }
  1666. }
  1667. } while (FALSE);
  1668. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1669. pAtpResp->resp_Flags |= ATP_RESP_SENT;
  1670. pAtpResp->resp_Flags &= ~ATP_RESP_TRANSMITTING;
  1671. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  1672. if (OldIrql != DISPATCH_LEVEL)
  1673. KeLowerIrql(OldIrql);
  1674. }
  1675. VOID FASTCALL
  1676. atalkAtpSendRespComplete(
  1677. IN NDIS_STATUS Status,
  1678. IN PSEND_COMPL_INFO pSendInfo
  1679. )
  1680. /*++
  1681. Routine Description:
  1682. Arguments:
  1683. Return Value:
  1684. --*/
  1685. {
  1686. if (pSendInfo->sc_Ctx2 != NULL)
  1687. {
  1688. PAMDL pMdl;
  1689. if ((pMdl = ((PBUFFER_DESC)(pSendInfo->sc_Ctx2))->bd_OpaqueBuffer) != NULL)
  1690. AtalkFreeAMdl(pMdl);
  1691. AtalkFreeBuffDesc((PBUFFER_DESC)(pSendInfo->sc_Ctx2));
  1692. }
  1693. AtalkAtpRespDereference((PATP_RESP)(pSendInfo->sc_Ctx1));
  1694. }
  1695. // This is used to perform a retry when a release send fails in completion.
  1696. #define ATP_TID_RETRY_MASK 0xF0000000
  1697. #define ATP_TID_MASK 0xFFFF
  1698. VOID FASTCALL
  1699. atalkAtpTransmitRel(
  1700. IN PATP_REQ pAtpReq
  1701. )
  1702. /*++
  1703. Routine Description:
  1704. Arguments:
  1705. Return Value:
  1706. --*/
  1707. {
  1708. ATALK_ERROR error;
  1709. ATP_HEADER atpHeader;
  1710. BOOLEAN remote;
  1711. SEND_COMPL_INFO SendInfo;
  1712. AtalkAtpAddrReferenceDpc(pAtpReq->req_pAtpAddr, &error);
  1713. if (ATALK_SUCCESS(error))
  1714. {
  1715. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1716. ("atalkAtpTransmitRel: Sending release for %lx\n", pAtpReq->req_Tid));
  1717. // Build header for this packet.
  1718. atpHeader.atph_dwUserBytes = 0;
  1719. // Indicate response type.
  1720. atpHeader.atph_CmdCtrl = ATP_RELEASE;
  1721. // Put in the bitmap
  1722. atpHeader.atph_Bitmap = pAtpReq->req_RecdBitmap;
  1723. // Put in the tid.
  1724. PUTSHORT2SHORT(&atpHeader.atph_Tid, pAtpReq->req_Tid);
  1725. remote = (pAtpReq->req_Flags & ATP_REQ_REMOTE) ? TRUE : FALSE;
  1726. SendInfo.sc_TransmitCompletion = atalkAtpSendRelComplete;
  1727. SendInfo.sc_Ctx1 = pAtpReq->req_pAtpAddr;
  1728. SendInfo.sc_Ctx2 = (PVOID)((ULONG_PTR)(ATP_TID_RETRY_MASK | pAtpReq->req_Tid));
  1729. SendInfo.sc_Ctx3 = (PVOID)((ULONG_PTR)(pAtpReq->req_Dest.ata_Address));
  1730. error = AtalkDdpSend(pAtpReq->req_pAtpAddr->atpao_DdpAddr,
  1731. &pAtpReq->req_Dest,
  1732. (BYTE)DDPPROTO_ATP,
  1733. remote,
  1734. NULL,
  1735. (PBYTE)&atpHeader,
  1736. ATP_HEADER_SIZE,
  1737. NULL,
  1738. &SendInfo);
  1739. if (!ATALK_SUCCESS(error))
  1740. {
  1741. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1742. ("atalkAtpTransmitRel: Send release failed %lx\n", error));
  1743. AtalkAtpAddrDereferenceDpc(pAtpReq->req_pAtpAddr);
  1744. }
  1745. }
  1746. }
  1747. VOID FASTCALL
  1748. atalkAtpSendRelComplete(
  1749. IN NDIS_STATUS Status,
  1750. IN PSEND_COMPL_INFO pSendInfo
  1751. )
  1752. /*++
  1753. Routine Description:
  1754. Arguments:
  1755. Return Value:
  1756. --*/
  1757. {
  1758. ATALK_ERROR error;
  1759. ATP_HEADER atpHeader;
  1760. #define pAtpAddr ((PATP_ADDROBJ)(pSendInfo->sc_Ctx1))
  1761. #define TidAndRetry (ULONG_PTR)(pSendInfo->sc_Ctx2)
  1762. #define DestAddr (ULONG_PTR)(pSendInfo->sc_Ctx3)
  1763. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1764. ("atalkAtpSendRelComplete: Send status %lx\n", Status));
  1765. if ((Status == NDIS_STATUS_SUCCESS) ||
  1766. ((TidAndRetry & ATP_TID_RETRY_MASK) == 0))
  1767. {
  1768. // Either successful, or we have already retried.
  1769. AtalkAtpAddrDereference(pAtpAddr);
  1770. return;
  1771. }
  1772. // Go ahead and retry!
  1773. // Build header for this packet.
  1774. atpHeader.atph_dwUserBytes = 0;
  1775. // Indicate response type.
  1776. atpHeader.atph_CmdCtrl = ATP_RELEASE;
  1777. // Put in the tid.
  1778. PUTSHORT2SHORT(&atpHeader.atph_Tid, (TidAndRetry & ATP_TID_MASK));
  1779. pSendInfo->sc_Ctx2 = NULL;
  1780. pSendInfo->sc_Ctx3 = NULL;
  1781. error = AtalkDdpSend(pAtpAddr->atpao_DdpAddr,
  1782. (PATALK_ADDR)&DestAddr,
  1783. (BYTE)DDPPROTO_ATP,
  1784. FALSE,
  1785. NULL,
  1786. (PBYTE)&atpHeader,
  1787. ATP_HEADER_SIZE,
  1788. NULL,
  1789. pSendInfo);
  1790. if (!ATALK_SUCCESS(error))
  1791. {
  1792. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1793. ("atalkAtpSendRelComplete: Send release failed %lx\n", error));
  1794. AtalkAtpAddrDereference(pAtpAddr);
  1795. }
  1796. #undef pAtpAddr
  1797. #undef TidAndRetry
  1798. #undef DestAddr
  1799. }
  1800. VOID FASTCALL
  1801. atalkAtpRespComplete(
  1802. IN OUT PATP_RESP pAtpResp,
  1803. IN ATALK_ERROR CompletionStatus
  1804. )
  1805. {
  1806. KIRQL OldIrql;
  1807. BOOLEAN ownResp = TRUE;
  1808. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1809. ("atalkAtpRespComplete: Completing %lx.%lx\n",
  1810. pAtpResp->resp_Tid, CompletionStatus));
  1811. // See if we can grab ownership of this response to remove
  1812. // the creation reference and complete it.
  1813. ACQUIRE_SPIN_LOCK(&pAtpResp->resp_Lock, &OldIrql);
  1814. if (pAtpResp->resp_Flags & ATP_RESP_CLOSING)
  1815. {
  1816. ownResp = FALSE;
  1817. }
  1818. pAtpResp->resp_Flags |= ATP_RESP_CLOSING;
  1819. pAtpResp->resp_CompStatus = CompletionStatus;
  1820. RELEASE_SPIN_LOCK(&pAtpResp->resp_Lock, OldIrql);
  1821. // If we managed to get ownership of the request, call the
  1822. // Deref for creation.
  1823. if (ownResp)
  1824. {
  1825. AtalkAtpRespDereference(pAtpResp);
  1826. }
  1827. }
  1828. VOID FASTCALL
  1829. atalkAtpReqComplete(
  1830. IN OUT PATP_REQ pAtpReq,
  1831. IN ATALK_ERROR CompletionStatus
  1832. )
  1833. {
  1834. KIRQL OldIrql;
  1835. BOOLEAN ownReq = TRUE;
  1836. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1837. ("atalkAtpReqComplete: Completing %lx\n", pAtpReq->req_Tid));
  1838. // See if we can grab ownership of this resquest to remove
  1839. // the creation reference and complete it.
  1840. ACQUIRE_SPIN_LOCK(&pAtpReq->req_Lock, &OldIrql);
  1841. if (pAtpReq->req_Flags & ATP_REQ_CLOSING)
  1842. {
  1843. ownReq = FALSE;
  1844. }
  1845. pAtpReq->req_CompStatus = CompletionStatus;
  1846. pAtpReq->req_Flags |= ATP_REQ_CLOSING;
  1847. RELEASE_SPIN_LOCK(&pAtpReq->req_Lock, OldIrql);
  1848. // If we managed to get ownership of the request, call the deref for creation.
  1849. if (ownReq)
  1850. {
  1851. AtalkAtpReqDereference(pAtpReq);
  1852. }
  1853. }
  1854. VOID
  1855. atalkAtpGetNextTidForAddr(
  1856. IN PATP_ADDROBJ pAtpAddr,
  1857. IN PATALK_ADDR pRemoteAddr,
  1858. OUT PUSHORT pTid,
  1859. OUT PULONG pIndex
  1860. )
  1861. /*++
  1862. Routine Description:
  1863. Arguments:
  1864. Return Value:
  1865. --*/
  1866. {
  1867. USHORT TentativeTid;
  1868. ULONG index;
  1869. PATP_REQ pAtpReq;
  1870. do
  1871. {
  1872. TentativeTid = pAtpAddr->atpao_NextTid++;
  1873. if (pAtpAddr->atpao_NextTid == 0)
  1874. pAtpAddr->atpao_NextTid = 1;
  1875. // Check to see if this tid is in use for this address.
  1876. // !!!NOTE!!!
  1877. // This will be true even if the tid is in use for a closing
  1878. // request or a response.
  1879. // Calculate the hash value of the destination address of this request
  1880. // and the tid.
  1881. index = ATP_HASH_TID_DESTADDR(TentativeTid, pRemoteAddr, ATP_REQ_HASH_SIZE);
  1882. for (pAtpReq = pAtpAddr->atpao_ReqHash[index];
  1883. pAtpReq != NULL;
  1884. pAtpReq = pAtpReq->req_Next)
  1885. {
  1886. if ((ATALK_ADDRS_EQUAL(&pAtpReq->req_Dest, pRemoteAddr)) &&
  1887. (pAtpReq->req_Tid == TentativeTid))
  1888. {
  1889. break;
  1890. }
  1891. }
  1892. } while (pAtpReq != NULL);
  1893. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1894. ("atalkAtpGetNextTidForAddr: Tid %lx for %lx.%lx.%lx\n",
  1895. TentativeTid, pRemoteAddr->ata_Network, pRemoteAddr->ata_Node,
  1896. pRemoteAddr->ata_Socket));
  1897. *pTid = TentativeTid;
  1898. *pIndex = index;
  1899. }
  1900. VOID
  1901. atalkAtpReqRefNextNc(
  1902. IN PATP_REQ pAtpReq,
  1903. OUT PATP_REQ * ppNextNcReq,
  1904. OUT PATALK_ERROR pError
  1905. )
  1906. /*++
  1907. Routine Description:
  1908. MUST BE CALLED WITH THE ADDRESS LOCK HELD!
  1909. Arguments:
  1910. Return Value:
  1911. --*/
  1912. {
  1913. for (NOTHING; pAtpReq != NULL; pAtpReq = pAtpReq->req_Next)
  1914. {
  1915. AtalkAtpReqReferenceByPtrDpc(pAtpReq, pError);
  1916. if (ATALK_SUCCESS(*pError))
  1917. {
  1918. // Ok, this request is referenced!
  1919. *ppNextNcReq = pAtpReq;
  1920. break;
  1921. }
  1922. }
  1923. }
  1924. VOID FASTCALL
  1925. atalkAtpReqDeref(
  1926. IN PATP_REQ pAtpReq,
  1927. IN BOOLEAN AtDpc
  1928. )
  1929. /*++
  1930. Routine Description:
  1931. Arguments:
  1932. Return Value:
  1933. --*/
  1934. {
  1935. KIRQL OldIrql;
  1936. BOOLEAN done = FALSE;
  1937. // This will call the completion routine and remove it from the
  1938. // list when ref count goes to 0.
  1939. ASSERT(VALID_ATPRQ(pAtpReq));
  1940. if (AtDpc)
  1941. {
  1942. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  1943. }
  1944. else
  1945. {
  1946. ACQUIRE_SPIN_LOCK(&pAtpReq->req_Lock, &OldIrql);
  1947. }
  1948. if ((--pAtpReq->req_RefCount) == 0)
  1949. {
  1950. ASSERT(pAtpReq->req_Flags & ATP_REQ_CLOSING);
  1951. done = TRUE;
  1952. }
  1953. if (AtDpc)
  1954. {
  1955. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  1956. }
  1957. else
  1958. {
  1959. RELEASE_SPIN_LOCK(&pAtpReq->req_Lock, OldIrql);
  1960. }
  1961. if (done)
  1962. {
  1963. if (AtDpc)
  1964. {
  1965. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_pAtpAddr->atpao_Lock);
  1966. }
  1967. else
  1968. {
  1969. ACQUIRE_SPIN_LOCK(&pAtpReq->req_pAtpAddr->atpao_Lock, &OldIrql);
  1970. }
  1971. // Remove it from the list.
  1972. AtalkUnlinkDouble(pAtpReq, req_Next, req_Prev);
  1973. if (pAtpReq->req_Flags & ATP_REQ_RETRY_TIMER)
  1974. {
  1975. pAtpReq->req_Flags &= ~ATP_REQ_RETRY_TIMER;
  1976. RemoveEntryList(&pAtpReq->req_List);
  1977. }
  1978. if (AtDpc)
  1979. {
  1980. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_pAtpAddr->atpao_Lock);
  1981. }
  1982. else
  1983. {
  1984. RELEASE_SPIN_LOCK(&pAtpReq->req_pAtpAddr->atpao_Lock, OldIrql);
  1985. }
  1986. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  1987. ("atalkAtpReqDeref: Completing req for tid %lx.%d\n",
  1988. pAtpReq->req_Tid, pAtpReq->req_Tid));
  1989. // Call the completion routine for the request.
  1990. if (pAtpReq->req_Comp != NULL)
  1991. {
  1992. KIRQL OldIrql;
  1993. // Resp handlers expect to be called at DISPATCH. If the
  1994. // request was cancelled, make it so.
  1995. if (pAtpReq->req_CompStatus == ATALK_ATP_REQ_CANCELLED)
  1996. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1997. (*pAtpReq->req_Comp)(pAtpReq->req_CompStatus,
  1998. pAtpReq->req_Ctx,
  1999. pAtpReq->req_Buf,
  2000. pAtpReq->req_RespBuf,
  2001. pAtpReq->req_RespRecdLen,
  2002. pAtpReq->req_RespUserBytes);
  2003. if (pAtpReq->req_CompStatus == ATALK_ATP_REQ_CANCELLED)
  2004. KeLowerIrql(OldIrql);
  2005. }
  2006. // Deref the address object
  2007. if (AtDpc)
  2008. {
  2009. AtalkAtpAddrDereferenceDpc(pAtpReq->req_pAtpAddr);
  2010. }
  2011. else
  2012. {
  2013. AtalkAtpAddrDereference(pAtpReq->req_pAtpAddr);
  2014. }
  2015. // Release the ndis buffer descriptors, if any
  2016. AtalkIndAtpReleaseNdisBuffer(pAtpReq);
  2017. AtalkBPFreeBlock(pAtpReq);
  2018. }
  2019. }
  2020. VOID
  2021. atalkAtpRespRefNextNc(
  2022. IN PATP_RESP pAtpResp,
  2023. OUT PATP_RESP * ppNextNcResp,
  2024. OUT PATALK_ERROR pError
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. MUST BE CALLED WITH THE ADDRESS LOCK HELD!
  2029. Arguments:
  2030. Return Value:
  2031. --*/
  2032. {
  2033. PATP_RESP pNextResp = NULL;
  2034. ATALK_ERROR error = ATALK_FAILURE;
  2035. for (; pAtpResp != NULL; pAtpResp = pAtpResp->resp_Next)
  2036. {
  2037. AtalkAtpRespReferenceByPtrDpc(pAtpResp, pError);
  2038. if (ATALK_SUCCESS(*pError))
  2039. {
  2040. // Ok, this request is referenced!
  2041. *ppNextNcResp = pAtpResp;
  2042. break;
  2043. }
  2044. }
  2045. }
  2046. VOID FASTCALL
  2047. AtalkAtpRespDeref(
  2048. IN PATP_RESP pAtpResp,
  2049. IN BOOLEAN AtDpc
  2050. )
  2051. /*++
  2052. Routine Description:
  2053. Arguments:
  2054. Return Value:
  2055. --*/
  2056. {
  2057. PATP_ADDROBJ pAtpAddr;
  2058. KIRQL OldIrql;
  2059. BOOLEAN done = FALSE;
  2060. BOOLEAN NotifyRelHandler = FALSE;
  2061. // This will call the completion routine when the ref count goes to 1
  2062. // and remove it from the list when ref count goes to 0. The assumption
  2063. // here is that the release handler will be the last to Dereference.
  2064. if (AtDpc)
  2065. {
  2066. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  2067. }
  2068. else
  2069. {
  2070. ACQUIRE_SPIN_LOCK(&pAtpResp->resp_Lock, &OldIrql);
  2071. }
  2072. pAtpResp->resp_RefCount--;
  2073. if (pAtpResp->resp_RefCount == 0)
  2074. {
  2075. ASSERT(pAtpResp->resp_Flags & (ATP_RESP_HANDLER_NOTIFIED | ATP_RESP_CANCELLED));
  2076. done = TRUE;
  2077. }
  2078. else if ((pAtpResp->resp_RefCount == 1) &&
  2079. (pAtpResp->resp_Flags & ATP_RESP_VALID_RESP) &&
  2080. ((pAtpResp->resp_Flags & ATP_RESP_HANDLER_NOTIFIED) == 0))
  2081. {
  2082. NotifyRelHandler = TRUE;
  2083. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  2084. ("AtalkAtpRespDereference: Notifying release handler for Resp %lx, tid %x %s\n",
  2085. pAtpResp, pAtpResp->resp_Tid,
  2086. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  2087. pAtpResp->resp_Flags |= ATP_RESP_HANDLER_NOTIFIED;
  2088. }
  2089. if (AtDpc)
  2090. {
  2091. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  2092. }
  2093. else
  2094. {
  2095. RELEASE_SPIN_LOCK(&pAtpResp->resp_Lock, OldIrql);
  2096. }
  2097. if (NotifyRelHandler)
  2098. {
  2099. ASSERT (!done);
  2100. // Call the completion routine.
  2101. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  2102. ("AtalkAtpRespDereference: Calling resp handler for tid %lx %s\n",
  2103. pAtpResp->resp_Tid,
  2104. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  2105. //
  2106. // if Mac cancels its request before a response is posted by the client,
  2107. // the compl. routine won't be set yet.
  2108. //
  2109. if (pAtpResp->resp_Comp != NULL)
  2110. {
  2111. (*pAtpResp->resp_Comp)(pAtpResp->resp_CompStatus, pAtpResp->resp_Ctx);
  2112. }
  2113. }
  2114. else if (done)
  2115. {
  2116. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  2117. ("AtalkAtpRespDereference: Freeing resp for tid %lx - %lx %s\n",
  2118. pAtpResp->resp_Tid, pAtpResp->resp_CompStatus,
  2119. (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE) ? "XO" : "ALO"));
  2120. pAtpAddr = pAtpResp->resp_pAtpAddr;
  2121. if (AtDpc)
  2122. {
  2123. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2124. }
  2125. else
  2126. {
  2127. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  2128. }
  2129. // Remove it from the list.
  2130. AtalkUnlinkDouble(pAtpResp, resp_Next, resp_Prev);
  2131. if (pAtpResp->resp_Flags & ATP_RESP_REL_TIMER)
  2132. {
  2133. ASSERT (pAtpResp->resp_Flags & ATP_RESP_EXACTLY_ONCE);
  2134. pAtpResp->resp_Flags &= ~ATP_RESP_REL_TIMER;
  2135. RemoveEntryList(&pAtpResp->resp_List);
  2136. }
  2137. if (AtDpc)
  2138. {
  2139. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2140. }
  2141. else
  2142. {
  2143. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  2144. }
  2145. // Deref the address object
  2146. if (AtDpc)
  2147. {
  2148. AtalkAtpAddrDereferenceDpc(pAtpResp->resp_pAtpAddr);
  2149. }
  2150. else
  2151. {
  2152. AtalkAtpAddrDereference(pAtpResp->resp_pAtpAddr);
  2153. }
  2154. AtalkBPFreeBlock(pAtpResp);
  2155. }
  2156. }
  2157. VOID FASTCALL
  2158. AtalkAtpAddrDeref(
  2159. IN OUT PATP_ADDROBJ pAtpAddr,
  2160. IN BOOLEAN AtDpc
  2161. )
  2162. /*++
  2163. Routine Description:
  2164. Arguments:
  2165. Return Value:
  2166. --*/
  2167. {
  2168. KIRQL OldIrql;
  2169. BOOLEAN done = FALSE;
  2170. if (AtDpc)
  2171. {
  2172. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2173. }
  2174. else
  2175. {
  2176. ACQUIRE_SPIN_LOCK(&pAtpAddr->atpao_Lock, &OldIrql);
  2177. }
  2178. ASSERT(pAtpAddr->atpao_RefCount > 0);
  2179. if (--(pAtpAddr->atpao_RefCount) == 0)
  2180. {
  2181. done = TRUE;
  2182. ASSERT(pAtpAddr->atpao_Flags & ATPAO_CLOSING);
  2183. }
  2184. if (AtDpc)
  2185. {
  2186. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2187. }
  2188. else
  2189. {
  2190. RELEASE_SPIN_LOCK(&pAtpAddr->atpao_Lock, OldIrql);
  2191. }
  2192. if (done)
  2193. {
  2194. // Call the close completion routine.
  2195. if (pAtpAddr->atpao_CloseComp != NULL)
  2196. {
  2197. (*pAtpAddr->atpao_CloseComp)(ATALK_NO_ERROR, pAtpAddr->atpao_CloseCtx);
  2198. }
  2199. // This address is done for. Close the ddp socket.
  2200. AtalkDdpCloseAddress(pAtpAddr->atpao_DdpAddr, NULL, NULL);
  2201. // Free up the memory
  2202. AtalkFreeMemory(pAtpAddr);
  2203. AtalkUnlockAtpIfNecessary();
  2204. }
  2205. }
  2206. VOID FASTCALL
  2207. AtalkIndAtpSetupNdisBuffer(
  2208. IN OUT PATP_REQ pAtpReq,
  2209. IN ULONG MaxSinglePktSize
  2210. )
  2211. {
  2212. NDIS_STATUS ndisStatus;
  2213. PNDIS_BUFFER ndisBuffer;
  2214. PNDIS_BUFFER ndisFirstBuffer;
  2215. PNDIS_BUFFER ndisPrevBuffer;
  2216. UINT ndisBufLen;
  2217. USHORT seqNum = 0;
  2218. USHORT startOffset = 0;
  2219. USHORT Offset;
  2220. USHORT BytesRemaining;
  2221. USHORT PartialBytesNeeded=0;
  2222. USHORT PacketRoom;
  2223. PMDL pCurrentMdl;
  2224. BOOLEAN fPartialMdl;
  2225. SHORT BufLen = (SHORT)pAtpReq->req_RespBufLen;
  2226. RtlZeroMemory(pAtpReq->req_NdisBuf,
  2227. sizeof(PVOID) * ATP_MAX_RESP_PKTS);
  2228. if (BufLen == 0)
  2229. {
  2230. return;
  2231. }
  2232. //
  2233. // BytesRemaining: bytes remaining in the current Mdl
  2234. // PacketRoom: bytes required to complete setting up the
  2235. // Atp request corresponding to seqNum
  2236. // ndisBufLen: bytes that will describe the (partial) mdl,
  2237. // obtained via NdisCopyBuffer
  2238. //
  2239. pCurrentMdl = pAtpReq->req_RespBuf;
  2240. ASSERT(pCurrentMdl != NULL);
  2241. BytesRemaining = (USHORT)MmGetMdlByteCount(pCurrentMdl);
  2242. Offset = 0;
  2243. ndisFirstBuffer = NULL;
  2244. while (BufLen > 0 && seqNum < ATP_MAX_RESP_PKTS)
  2245. {
  2246. PacketRoom = MIN(BufLen, (USHORT)MaxSinglePktSize);
  2247. while (PacketRoom > 0)
  2248. {
  2249. // are all the bytes there or are we at an Mdl boundary?
  2250. if (BytesRemaining >= PacketRoom)
  2251. {
  2252. ndisBufLen = (UINT)PacketRoom;
  2253. fPartialMdl = FALSE;
  2254. }
  2255. // looks like we are at boundary: need to get a partial mdl
  2256. else
  2257. {
  2258. ndisBufLen = (UINT)BytesRemaining;
  2259. fPartialMdl = TRUE;
  2260. }
  2261. ASSERT(ndisBufLen > 0);
  2262. NdisCopyBuffer(&ndisStatus,
  2263. &ndisBuffer,
  2264. AtalkNdisBufferPoolHandle,
  2265. (PVOID)pCurrentMdl,
  2266. Offset,
  2267. ndisBufLen);
  2268. if (ndisStatus != NDIS_STATUS_SUCCESS)
  2269. {
  2270. DBGPRINT(DBG_COMP_ASP, DBG_LEVEL_ERR,
  2271. ("AtalkIndAtpSetupNdisBuffer: NdisCopyBuffer failed!\n"));
  2272. break;
  2273. }
  2274. ASSERT(ndisBufLen == MmGetMdlByteCount(ndisBuffer));
  2275. ATALK_DBG_INC_COUNT(AtalkDbgMdlsAlloced);
  2276. // first buffer for this packet?
  2277. if (!ndisFirstBuffer)
  2278. {
  2279. ndisFirstBuffer = ndisBuffer;
  2280. ndisPrevBuffer = ndisBuffer;
  2281. }
  2282. // no, it's not the first. Chain it in!
  2283. else
  2284. {
  2285. ndisPrevBuffer->Next = ndisBuffer;
  2286. ndisPrevBuffer = ndisBuffer;
  2287. }
  2288. BufLen -= (SHORT)ndisBufLen;
  2289. Offset += (USHORT)ndisBufLen;
  2290. BytesRemaining -= (USHORT)ndisBufLen;
  2291. PacketRoom -= (USHORT)ndisBufLen;
  2292. // did we exhaust the current Mdl? move to the next mdl then!
  2293. if (fPartialMdl)
  2294. {
  2295. ASSERT(PacketRoom > 0);
  2296. pCurrentMdl = pCurrentMdl->Next;
  2297. ASSERT(pCurrentMdl != NULL);
  2298. BytesRemaining = (USHORT)MmGetMdlByteCount(pCurrentMdl);
  2299. Offset = 0;
  2300. }
  2301. }
  2302. if (PacketRoom > 0)
  2303. {
  2304. DBGPRINT(DBG_COMP_ASP, DBG_LEVEL_ERR,
  2305. ("AtalkIndAtpSetupNdisBuffer: couldn't get Mdl!\n"));
  2306. // if an mdl was allocated (describing part of buffer), free it
  2307. if (ndisFirstBuffer)
  2308. {
  2309. AtalkNdisFreeBuffer(ndisFirstBuffer);
  2310. }
  2311. break;
  2312. }
  2313. ASSERT(ndisFirstBuffer != NULL);
  2314. pAtpReq->req_NdisBuf[seqNum++] = ndisFirstBuffer;
  2315. ndisFirstBuffer = NULL;
  2316. }
  2317. }
  2318. VOID FASTCALL
  2319. AtalkIndAtpReleaseNdisBuffer(
  2320. IN OUT PATP_REQ pAtpReq
  2321. )
  2322. {
  2323. LONG i;
  2324. PNDIS_BUFFER ndisBuffer;
  2325. PNDIS_BUFFER ndisNextBuffer;
  2326. for (i = 0; i < ATP_MAX_RESP_PKTS; i++)
  2327. {
  2328. if ((ndisBuffer = pAtpReq->req_NdisBuf[i]) != NULL)
  2329. {
  2330. AtalkNdisFreeBuffer(ndisBuffer);
  2331. }
  2332. }
  2333. }
  2334. LOCAL LONG FASTCALL
  2335. atalkAtpReqTimer(
  2336. IN PTIMERLIST pTimer,
  2337. IN BOOLEAN TimerShuttingDown
  2338. )
  2339. /*++
  2340. Routine Description:
  2341. Arguments:
  2342. Return Value:
  2343. --*/
  2344. {
  2345. PATP_REQ pAtpReq;
  2346. PATP_ADDROBJ pAtpAddr;
  2347. PLIST_ENTRY pList, pListNext;
  2348. ATALK_ERROR error;
  2349. LONG now;
  2350. BOOLEAN retry;
  2351. #ifdef PROFILING
  2352. LARGE_INTEGER TimeS, TimeE, TimeD;
  2353. TimeS = KeQueryPerformanceCounter(NULL);
  2354. #endif
  2355. pAtpAddr = CONTAINING_RECORD(pTimer, ATP_ADDROBJ, atpao_RetryTimer);
  2356. ASSERT(VALID_ATPAO(pAtpAddr));
  2357. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  2358. ("atalkAtpReqTimer: Entered for address %lx\n", pAtpAddr));
  2359. if (TimerShuttingDown ||
  2360. (pAtpAddr->atpao_Flags & (ATPAO_CLOSING|ATPAO_CLEANUP)))
  2361. {
  2362. AtalkAtpAddrDereferenceDpc(pAtpAddr);
  2363. return ATALK_TIMER_NO_REQUEUE;
  2364. }
  2365. now = AtalkGetCurrentTick();
  2366. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2367. for (pList = pAtpAddr->atpao_ReqList.Flink;
  2368. pList != &pAtpAddr->atpao_ReqList;
  2369. pList = pListNext)
  2370. {
  2371. pAtpReq = CONTAINING_RECORD(pList, ATP_REQ, req_List);
  2372. ASSERT (VALID_ATPRQ(pAtpReq));
  2373. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  2374. pListNext = pAtpReq->req_List.Flink;
  2375. // If either we are closing this request or have not timed out yet, skip.
  2376. if (((pAtpReq->req_Flags & (ATP_REQ_CLOSING |
  2377. ATP_REQ_RETRY_TIMER |
  2378. ATP_REQ_RESPONSE_COMPLETE)) != ATP_REQ_RETRY_TIMER) ||
  2379. (now < pAtpReq->req_RetryTimeStamp))
  2380. {
  2381. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  2382. continue;
  2383. }
  2384. // If retry count == 0, we have reached the end of the road.
  2385. if ((pAtpReq->req_RetryCnt == ATP_INFINITE_RETRIES) ||
  2386. (--(pAtpReq->req_RetryCnt) > 0))
  2387. {
  2388. // Transmit the request again!
  2389. retry = TRUE;
  2390. pAtpReq->req_RetryTimeStamp = (now + pAtpReq->req_RetryInterval);
  2391. }
  2392. else
  2393. {
  2394. // We should now be Dereferenced for creation.
  2395. retry = FALSE;
  2396. }
  2397. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  2398. if (retry)
  2399. {
  2400. // We do not want to update statistics for requests are that are never going to
  2401. // be responded to (like tickle packets). Detect these and skip updating the
  2402. // stats for these
  2403. if (pAtpReq->req_RespBufLen > 0) // i.e. response expected
  2404. {
  2405. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumLocalRetries,
  2406. &AtalkStatsLock.SpinLock);
  2407. }
  2408. AtalkAtpReqReferenceByPtrDpc(pAtpReq, &error);
  2409. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2410. if (ATALK_SUCCESS(error))
  2411. {
  2412. atalkAtpTransmitReq(pAtpReq);
  2413. AtalkAtpReqDereferenceDpc(pAtpReq);
  2414. }
  2415. }
  2416. else
  2417. {
  2418. // We have run out of retries - complete with an error
  2419. ASSERT (pAtpReq->req_RetryCnt == 0);
  2420. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  2421. ("atalkAtpReqTimer: Request %lx, tid %x timed out !!!\n",
  2422. pAtpReq, pAtpReq->req_Tid));
  2423. AtalkAtpReqReferenceByPtrDpc(pAtpReq, &error);
  2424. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2425. if (ATALK_SUCCESS(error))
  2426. {
  2427. atalkAtpReqComplete(pAtpReq, ATALK_ATP_REQ_TIMEOUT);
  2428. AtalkAtpReqDereferenceDpc(pAtpReq);
  2429. }
  2430. else
  2431. {
  2432. DBGPRINT(DBG_COMP_ASP, DBG_LEVEL_ERR,
  2433. ("atalkAtpReqTimer: couldn't reference pAtpReq %lx :nothing done!\n",pAtpReq));
  2434. }
  2435. }
  2436. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2437. // Start over
  2438. pListNext = pAtpAddr->atpao_ReqList.Flink;
  2439. }
  2440. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2441. #ifdef PROFILING
  2442. TimeE = KeQueryPerformanceCounter(NULL);
  2443. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  2444. INTERLOCKED_ADD_LARGE_INTGR_DPC(&AtalkStatistics.stat_AtpReqTimerProcessTime,
  2445. TimeD,
  2446. &AtalkStatsLock.SpinLock);
  2447. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumReqTimer,
  2448. &AtalkStatsLock.SpinLock);
  2449. #endif
  2450. return ATALK_TIMER_REQUEUE;
  2451. }
  2452. LOCAL LONG FASTCALL
  2453. atalkAtpRelTimer(
  2454. IN PTIMERLIST pTimer,
  2455. IN BOOLEAN TimerShuttingDown
  2456. )
  2457. /*++
  2458. Routine Description:
  2459. Arguments:
  2460. Return Value:
  2461. --*/
  2462. {
  2463. PATP_ADDROBJ pAtpAddr;
  2464. PATP_RESP pAtpResp;
  2465. PLIST_ENTRY pList, pListNext;
  2466. LONG now;
  2467. #ifdef PROFILING
  2468. LARGE_INTEGER TimeS, TimeE, TimeD;
  2469. TimeS = KeQueryPerformanceCounter(NULL);
  2470. #endif
  2471. pAtpAddr = CONTAINING_RECORD(pTimer, ATP_ADDROBJ, atpao_RelTimer);
  2472. ASSERT(VALID_ATPAO(pAtpAddr));
  2473. if (TimerShuttingDown ||
  2474. (pAtpAddr->atpao_Flags & (ATPAO_CLOSING|ATPAO_CLEANUP)))
  2475. {
  2476. AtalkAtpAddrDereferenceDpc(pAtpAddr);
  2477. return ATALK_TIMER_NO_REQUEUE;
  2478. }
  2479. now = AtalkGetCurrentTick();
  2480. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2481. for (pList = pAtpAddr->atpao_RespList.Flink;
  2482. pList != &pAtpAddr->atpao_RespList;
  2483. pList = pListNext)
  2484. {
  2485. BOOLEAN derefResp;
  2486. pAtpResp = CONTAINING_RECORD(pList, ATP_RESP, resp_List);
  2487. ACQUIRE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  2488. derefResp = TRUE;
  2489. ASSERT (VALID_ATPRS(pAtpResp));
  2490. ASSERT (pAtpResp->resp_Flags & (ATP_RESP_EXACTLY_ONCE|ATP_RESP_VALID_RESP|ATP_RESP_REL_TIMER));
  2491. pListNext = pAtpResp->resp_List.Flink;
  2492. if ((pAtpResp->resp_Flags &
  2493. (ATP_RESP_CLOSING |
  2494. ATP_RESP_REL_TIMER |
  2495. ATP_RESP_TRANSMITTING |
  2496. ATP_RESP_SENT |
  2497. ATP_RESP_HANDLER_NOTIFIED |
  2498. ATP_RESP_RELEASE_RECD)) == (ATP_RESP_REL_TIMER | ATP_RESP_SENT))
  2499. {
  2500. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  2501. ("atalkAtpRelTimer: Checking req tid %lx (%x)\n",
  2502. pAtpResp->resp_Tid, pAtpResp->resp_Flags));
  2503. if (now >= pAtpResp->resp_RelTimeStamp)
  2504. {
  2505. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN,
  2506. ("atalkAtpRelTimer: Releasing req %lx tid %lx (%x)\n",
  2507. pAtpResp, pAtpResp->resp_Tid, pAtpResp->resp_Flags));
  2508. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  2509. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2510. derefResp = FALSE;
  2511. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumRespTimeout,
  2512. &AtalkStatsLock.SpinLock);
  2513. // Try to have the creation reference removed
  2514. atalkAtpRespComplete(pAtpResp, ATALK_ATP_RESP_TIMEOUT);
  2515. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2516. // Start over
  2517. pListNext = pAtpAddr->atpao_RespList.Flink;
  2518. }
  2519. }
  2520. if (derefResp)
  2521. {
  2522. RELEASE_SPIN_LOCK_DPC(&pAtpResp->resp_Lock);
  2523. }
  2524. }
  2525. RELEASE_SPIN_LOCK_DPC(&pAtpAddr->atpao_Lock);
  2526. #ifdef PROFILING
  2527. TimeE = KeQueryPerformanceCounter(NULL);
  2528. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  2529. INTERLOCKED_ADD_LARGE_INTGR_DPC(&AtalkStatistics.stat_AtpRelTimerProcessTime,
  2530. TimeD,
  2531. &AtalkStatsLock.SpinLock);
  2532. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumRelTimer,
  2533. &AtalkStatsLock.SpinLock);
  2534. #endif
  2535. return ATALK_TIMER_REQUEUE;
  2536. }
  2537. VOID FASTCALL
  2538. AtalkAtpGenericRespComplete(
  2539. IN ATALK_ERROR ErrorCode,
  2540. IN PATP_RESP pAtpResp
  2541. )
  2542. /*++
  2543. Routine Description:
  2544. Arguments:
  2545. Return Value:
  2546. --*/
  2547. {
  2548. AtalkAtpRespDereference(pAtpResp);
  2549. }
  2550.