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.

669 lines
17 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. atkind.c
  5. Abstract:
  6. This module contains the Appletalk Internal Indication support.
  7. Author:
  8. Nikhil Kamkolkar (nikhilk@microsoft.com)
  9. Jameel Hyder (jameelh@microsoft.com)
  10. Revision History:
  11. 22 Oct 1993 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM ATKIND
  17. ATALK_ERROR
  18. AtalkIndAtpPkt(
  19. IN PPORT_DESCRIPTOR pPortDesc,
  20. IN PBYTE pLookahead,
  21. IN USHORT PktLen,
  22. IN OUT PUINT pXferOffset,
  23. IN PBYTE pLinkHdr,
  24. IN BOOLEAN ShortDdpHdr,
  25. OUT PBYTE pSubType,
  26. OUT PBYTE * ppPacket,
  27. OUT PNDIS_PACKET * pNdisPkt
  28. )
  29. /*++
  30. Routine Description:
  31. This routine clumps together DDP and ATP packet in functionality for
  32. optimizing response packet reception.
  33. Arguments:
  34. Return Value:
  35. --*/
  36. {
  37. USHORT dgramLen, hopCnt;
  38. ATALK_ADDR destAddr, srcAddr;
  39. PBYTE pAtpHdr, pDdpPkt;
  40. // Only for localtalk
  41. BYTE alapSrcNode=0;
  42. BYTE alapDestNode=0;
  43. NDIS_STATUS ndisStatus;
  44. PNDIS_PACKET ndisPkt;
  45. PNDIS_BUFFER ndisBuffer=NULL;
  46. USHORT atpDataSize, DataSize;
  47. USHORT seqNum, tid, startOffset;
  48. BYTE controlInfo, function, eomFlag;
  49. BYTE RespType;
  50. PPROTOCOL_RESD protocolResd; // Protocolresd field in ndisPkt
  51. PATP_ADDROBJ pAtpAddrObj;
  52. PATP_REQ pAtpReq;
  53. BOOLEAN refAtpAddr = FALSE, refAtpReq = FALSE;
  54. BOOLEAN Deref = FALSE;
  55. ATALK_ERROR error = ATALK_NO_ERROR;
  56. #ifdef PROFILING
  57. LARGE_INTEGER TimeS, TimeE, TimeD;
  58. TimeS = KeQueryPerformanceCounter(NULL);
  59. #endif
  60. do
  61. {
  62. #if 0 // Receive indication has already verified this !!
  63. // If we dont have atleast the ddp header and atp header, we
  64. // cant figure much out.
  65. if (LookaheadLen < ((ShortDdpHdr ? SDDP_HDR_LEN : LDDP_HDR_LEN) + ATP_HEADER_SIZE))
  66. {
  67. error = ATALK_FAILURE;
  68. break;
  69. }
  70. if (PktLen > (MAX_DGRAM_SIZE + LDDP_HDR_LEN))
  71. {
  72. error = ATALK_INVALID_PKT;
  73. break;
  74. }
  75. #endif
  76. // Short and long header formats have the length in the same place,
  77. pDdpPkt = pLookahead;
  78. dgramLen = DDP_GET_LEN(pDdpPkt);
  79. hopCnt = DDP_GET_HOP_COUNT(pDdpPkt);
  80. // Is the packet too long?
  81. if ((hopCnt > RTMP_MAX_HOPS) || (dgramLen > PktLen))
  82. {
  83. error = ATALK_INVALID_PKT;
  84. break;
  85. }
  86. switch (pPortDesc->pd_NdisPortType)
  87. {
  88. case NdisMedium802_5:
  89. case NdisMedium802_3:
  90. case NdisMediumFddi:
  91. // Check the length.
  92. if ((dgramLen < LDDP_HDR_LEN) ||
  93. (dgramLen > (MAX_DGRAM_SIZE + LDDP_HDR_LEN)))
  94. {
  95. error = ATALK_INVALID_PKT;
  96. break;
  97. }
  98. pAtpHdr = pDdpPkt + LDDP_HDR_LEN;
  99. atpDataSize = dgramLen - (LDDP_HDR_LEN + ATP_HEADER_SIZE);
  100. break;
  101. case NdisMediumLocalTalk:
  102. if (ShortDdpHdr)
  103. {
  104. // Short DDP header! If we are not the default port, dont indicate
  105. // packet, as we shouldn't be routing it to the default port, on
  106. // which all our cached sockets reside.
  107. if (!DEF_PORT(pPortDesc))
  108. {
  109. error = ATALK_FAILURE;
  110. break;
  111. }
  112. if ((alapDestNode = *(pLinkHdr + ALAP_DEST_OFFSET)) == ATALK_BROADCAST_NODE)
  113. {
  114. error = ATALK_FAILURE;
  115. break;
  116. }
  117. else if (alapDestNode != NODE_ON_NONEXTPORT(pPortDesc))
  118. {
  119. error = ATALK_FAILURE;
  120. break;
  121. }
  122. alapSrcNode = *(pLinkHdr + ALAP_SRC_OFFSET);
  123. if ((dgramLen < SDDP_HDR_LEN) ||
  124. (dgramLen > MAX_DGRAM_SIZE + SDDP_HDR_LEN))
  125. {
  126. error = ATALK_INVALID_PKT;
  127. break;
  128. }
  129. pAtpHdr = pDdpPkt + SDDP_HDR_LEN;
  130. atpDataSize = dgramLen - (SDDP_HDR_LEN + ATP_HEADER_SIZE);
  131. }
  132. else
  133. {
  134. pAtpHdr = pDdpPkt + LDDP_HDR_LEN;
  135. atpDataSize = dgramLen - (LDDP_HDR_LEN + ATP_HEADER_SIZE);
  136. }
  137. break;
  138. default:
  139. KeBugCheck(0);
  140. break;
  141. }
  142. if (!ATALK_SUCCESS(error))
  143. {
  144. break;
  145. }
  146. DataSize = atpDataSize + ATP_HEADER_SIZE;
  147. pDdpPkt += 2;
  148. if (ShortDdpHdr)
  149. {
  150. destAddr.ata_Node = alapDestNode;
  151. srcAddr.ata_Network = destAddr.ata_Network = NET_ON_NONEXTPORT(pPortDesc);
  152. srcAddr.ata_Node = alapSrcNode;
  153. // Get the socket numbers from the ddp header.
  154. destAddr.ata_Socket = *pDdpPkt++;
  155. srcAddr.ata_Socket = *pDdpPkt;
  156. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  157. ("AtalkDdpPacketIn: NonExtended Dest Net.Node %lx.%lx\n",
  158. destAddr.ata_Network, destAddr.ata_Node));
  159. // Now the destination node address could be
  160. // ALAP_BROADCAST_NODE (0xFF).
  161. if ((srcAddr.ata_Node < MIN_USABLE_ATALKNODE) ||
  162. (srcAddr.ata_Node > MAX_USABLE_ATALKNODE) ||
  163. (destAddr.ata_Node == UNKNOWN_NODE))
  164. {
  165. error = ATALK_INVALID_PKT;
  166. break;
  167. }
  168. if (destAddr.ata_Node == ATALK_BROADCAST_NODE)
  169. {
  170. error = ATALK_FAILURE;
  171. break;
  172. }
  173. }
  174. else
  175. {
  176. // If we have a checksum, we cannot optimize.
  177. if ((*pDdpPkt++ != 0) || (*pDdpPkt++ != 0))
  178. {
  179. error = ATALK_FAILURE;
  180. break;
  181. }
  182. // Build full source and destination AppleTalk address structures
  183. // from our DDP header.
  184. GETSHORT2SHORT(&destAddr.ata_Network, pDdpPkt);
  185. pDdpPkt += 2;
  186. GETSHORT2SHORT(&srcAddr.ata_Network, pDdpPkt);
  187. pDdpPkt += 2;
  188. destAddr.ata_Node = *pDdpPkt++;
  189. srcAddr.ata_Node = *pDdpPkt++;
  190. destAddr.ata_Socket = *pDdpPkt++;
  191. srcAddr.ata_Socket = *pDdpPkt;
  192. if (destAddr.ata_Node == ATALK_BROADCAST_NODE)
  193. {
  194. error = ATALK_FAILURE;
  195. break;
  196. }
  197. // Do we like what we see? Note "nnnn00" is now allowed and used by NBP.
  198. if ((srcAddr.ata_Network > LAST_VALID_NETWORK) ||
  199. (srcAddr.ata_Network < FIRST_VALID_NETWORK) ||
  200. (srcAddr.ata_Node < MIN_USABLE_ATALKNODE) ||
  201. (srcAddr.ata_Node > MAX_USABLE_ATALKNODE))
  202. {
  203. error = ATALK_INVALID_PKT;
  204. break;
  205. }
  206. } // Long DDP header
  207. } while (FALSE);
  208. if (!ATALK_SUCCESS(error))
  209. {
  210. DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_WARN,
  211. ("AtalkDdpPacketIn: drop packet in indication%lx\n", error));
  212. return error;
  213. }
  214. // Now for the ATP processing. We need to copy header into ndispkt.
  215. // Get the static fields from the ATP header.
  216. controlInfo = pAtpHdr[ATP_CMD_CONTROL_OFF];
  217. function = (controlInfo & ATP_FUNC_MASK);
  218. eomFlag = ((controlInfo & ATP_EOM_MASK) != 0);
  219. // Get the sequence number
  220. seqNum = (USHORT)(pAtpHdr[ATP_SEQ_NUM_OFF]);
  221. // Get the transaction id
  222. GETSHORT2SHORT(&tid, &pAtpHdr[ATP_TRANS_ID_OFF]);
  223. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  224. ("AtalkIndAtpPkt: Packet tid %x func %x ctrlinfo %x\n",
  225. tid, function, controlInfo));
  226. do
  227. {
  228. // See if we have a a cached ATP address for this destination address.
  229. AtalkIndAtpCacheLkUpSocket(&destAddr, &pAtpAddrObj, &error);
  230. if (!ATALK_SUCCESS(error))
  231. {
  232. error = ATALK_FAILURE;
  233. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  234. ("AtalkIndAtpPkt: CacheLkup failed - tid %x, func %x, ctrlinfo %x\n",
  235. tid, function, controlInfo));
  236. break;
  237. }
  238. refAtpAddr = TRUE;
  239. if (function != ATP_RESPONSE) // Is this a request or a release?
  240. {
  241. PBYTE packet;
  242. PBUFFER_HDR pBufferHdr = NULL;
  243. PPROTOCOL_RESD protocolResd;
  244. BLKID BlkId;
  245. // Allocate a small or large ddp buffer as appropriate.
  246. BlkId = BLKID_DDPSM;
  247. if (DataSize > (sizeof(DDP_SMBUFFER) - sizeof(BUFFER_HDR)))
  248. BlkId = BLKID_DDPLG;
  249. if ((pBufferHdr = (PBUFFER_HDR)AtalkBPAllocBlock(BlkId)) == NULL)
  250. {
  251. error = ATALK_FAILURE;
  252. break;
  253. }
  254. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  255. ("AtalkIndAtpPkt: Indicating request\n"));
  256. // Setup the ndis packet.
  257. packet = (PBYTE)pBufferHdr + sizeof(BUFFER_HDR);
  258. // Get a pointer to the NDIS packet descriptor from the buffer header.
  259. ndisPkt = pBufferHdr->bh_NdisPkt;
  260. protocolResd = (PPROTOCOL_RESD)(ndisPkt->ProtocolReserved);
  261. // All set! Set appropriate values in the packet descriptor.
  262. protocolResd->Receive.pr_OptimizeType = INDICATE_ATP;
  263. protocolResd->Receive.pr_OptimizeSubType= ATP_ALLOC_BUF;
  264. protocolResd->Receive.pr_AtpAddrObj = pAtpAddrObj;
  265. protocolResd->Receive.pr_SrcAddr = srcAddr;
  266. protocolResd->Receive.pr_DestAddr = destAddr;
  267. protocolResd->Receive.pr_DataLength = DataSize;
  268. protocolResd->Receive.pr_OptimizeCtx = (PVOID)NULL;
  269. protocolResd->Receive.pr_OffCablePkt = (BOOLEAN)(hopCnt > 0);
  270. *pNdisPkt = ndisPkt;
  271. *ppPacket = packet;
  272. *pSubType = function;
  273. *pXferOffset += (ShortDdpHdr ? SDDP_HDR_LEN : LDDP_HDR_LEN);
  274. // Done, break out.
  275. error = ATALK_NO_ERROR;
  276. break;
  277. }
  278. ASSERT (function == ATP_RESPONSE);
  279. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  280. ("AtalkIndAtpPkt: RESPONSE SeqNum %d tid %lx\n", seqNum, tid));
  281. if (seqNum > (ATP_MAX_RESP_PKTS-1))
  282. {
  283. error = ATALK_INVALID_PKT;
  284. break;
  285. }
  286. // See if there is a pending request.
  287. ACQUIRE_SPIN_LOCK_DPC(&pAtpAddrObj->atpao_Lock);
  288. atalkAtpReqReferenceByAddrTidDpc(pAtpAddrObj,
  289. &srcAddr,
  290. tid,
  291. &pAtpReq,
  292. &error);
  293. RELEASE_SPIN_LOCK_DPC(&pAtpAddrObj->atpao_Lock);
  294. if (!ATALK_SUCCESS(error))
  295. {
  296. // We dont have a corresponding pending request. Ignore.
  297. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_ERR,
  298. ("AtalkIndAtpPkt: NO pending request for tid %lx\n", tid));
  299. error = ATALK_DUP_PKT; // Do not add this to dropped packet statistic
  300. break;
  301. }
  302. refAtpReq = TRUE;
  303. do
  304. {
  305. // Check the request bitmap, which could be zero if the user only
  306. // wanted the user bytes and passed in a null response buffer.
  307. // Do we want to keep this response? Check the corresponding
  308. // bit in our current bitmap set.
  309. ACQUIRE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  310. pAtpReq->req_Flags |= ATP_REQ_REMOTE;
  311. do
  312. {
  313. if (((pAtpReq->req_RecdBitmap & AtpBitmapForSeqNum[seqNum]) != 0) ||
  314. ((pAtpReq->req_Bitmap & AtpBitmapForSeqNum[seqNum]) == 0))
  315. {
  316. error = ATALK_DUP_PKT; // Not an error condition
  317. break;
  318. }
  319. if (atpDataSize > 0)
  320. {
  321. startOffset = (USHORT)seqNum * pAtpAddrObj->atpao_MaxSinglePktSize;
  322. if (pAtpReq->req_RespBufLen < (startOffset + atpDataSize))
  323. {
  324. error = ATALK_FAILURE;
  325. break;
  326. }
  327. }
  328. // If we are the first packet, copy the response user bytes.
  329. if (seqNum == 0)
  330. {
  331. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  332. ("AtalkIndAtpPkt: Copying user bytes for tid %x\n", tid));
  333. RtlCopyMemory(pAtpReq->req_RespUserBytes,
  334. pAtpHdr + ATP_USER_BYTES_OFF,
  335. ATP_USERBYTES_SIZE);
  336. }
  337. // If this response packet does not cause the req_Bitmap to go to ZERO
  338. // i.e. we have not recvd. all the packets, just copy the data into
  339. // user's buffer, adjust the bitmaps (req_Bitmap & req_RecdBitmap) and
  340. // not indicate this packet up to Atp.
  341. pAtpReq->req_RecdBitmap |= AtpBitmapForSeqNum[seqNum];
  342. pAtpReq->req_Bitmap &= ~AtpBitmapForSeqNum[seqNum];
  343. pAtpReq->req_RespRecdLen += atpDataSize;
  344. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  345. ("AtalkIndAtpPkt: Bitmap %x, RecdBitmap %x, RecdLen %d for tid %x\n",
  346. pAtpReq->req_Bitmap, pAtpReq->req_RecdBitmap,
  347. pAtpReq->req_RespRecdLen, tid));
  348. // Now if eom is set, we need to reset all high order bits
  349. // of the req_Bitmap. req_RecdBitmap should now indicate all
  350. // the buffers we received. The two should be mutually exclusive
  351. // at this point.
  352. if (eomFlag)
  353. {
  354. pAtpReq->req_Bitmap &= AtpEomBitmapForSeqNum[seqNum];
  355. ASSERT((pAtpReq->req_Bitmap & pAtpReq->req_RecdBitmap) == 0);
  356. }
  357. RespType = ATP_USER_BUF;
  358. if (pAtpReq->req_Bitmap != 0)
  359. {
  360. RespType = ATP_USER_BUFX;
  361. Deref = TRUE;
  362. }
  363. else
  364. {
  365. pAtpReq->req_Flags |= ATP_REQ_RESPONSE_COMPLETE;
  366. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  367. ("AtalkIndAtpPkt: LAST Response for tid %x\n", tid));
  368. }
  369. // Allocate an NDIS packet descriptor.
  370. NdisDprAllocatePacket(&ndisStatus,
  371. &ndisPkt,
  372. AtalkNdisPacketPoolHandle);
  373. if (ndisStatus == NDIS_STATUS_SUCCESS)
  374. {
  375. RtlZeroMemory(ndisPkt->ProtocolReserved, sizeof(PROTOCOL_RESD));
  376. // It will be freed by receive completion now.
  377. ndisBuffer = pAtpReq->req_NdisBuf[seqNum];
  378. pAtpReq->req_NdisBuf[seqNum] = NULL;
  379. }
  380. else
  381. {
  382. error = ATALK_FAILURE;
  383. break;
  384. }
  385. } while (FALSE);
  386. RELEASE_SPIN_LOCK_DPC(&pAtpReq->req_Lock);
  387. if (!ATALK_SUCCESS(error))
  388. {
  389. break;
  390. }
  391. // Copy the data into the users buffer. Check if there's room.
  392. if ((atpDataSize > 0) || (ndisBuffer != NULL))
  393. {
  394. if (ndisBuffer == NULL)
  395. {
  396. // Allocate an NDIS buffer descriptor and chain into pkt desc.
  397. NdisCopyBuffer(&ndisStatus,
  398. &ndisBuffer,
  399. AtalkNdisBufferPoolHandle,
  400. (PVOID)pAtpReq->req_RespBuf,
  401. startOffset, // Offset
  402. (UINT)atpDataSize);
  403. if (ndisStatus != NDIS_STATUS_SUCCESS)
  404. {
  405. NdisDprFreePacket(ndisPkt);
  406. error = ATALK_FAILURE;
  407. break;
  408. }
  409. ATALK_DBG_INC_COUNT(AtalkDbgMdlsAlloced);
  410. }
  411. // Chain in the buffer.
  412. NdisChainBufferAtBack(ndisPkt, ndisBuffer);
  413. }
  414. // All set! Set appropriate values in the packet descriptor.
  415. protocolResd = (PPROTOCOL_RESD)&ndisPkt->ProtocolReserved;
  416. protocolResd->Receive.pr_OptimizeType = INDICATE_ATP;
  417. protocolResd->Receive.pr_OptimizeSubType= RespType;
  418. protocolResd->Receive.pr_AtpAddrObj = pAtpAddrObj;
  419. protocolResd->Receive.pr_SrcAddr = srcAddr;
  420. protocolResd->Receive.pr_DestAddr = destAddr;
  421. protocolResd->Receive.pr_DataLength = atpDataSize;
  422. protocolResd->Receive.pr_OptimizeCtx = (PVOID)pAtpReq;
  423. protocolResd->Receive.pr_OffCablePkt = (BOOLEAN)(hopCnt > 0);
  424. // Do not copy the Atp header unless AtalkAtpPacketIn will be called.
  425. if (RespType == ATP_USER_BUF)
  426. {
  427. ATALK_RECV_INDICATION_COPY(pPortDesc,
  428. protocolResd->Receive.pr_AtpHdr,
  429. pAtpHdr,
  430. ATP_HEADER_SIZE);
  431. DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO,
  432. ("AtalkIndAtpPkt: Last packet for request, indicating tid %x\n", tid));
  433. }
  434. *pNdisPkt = ndisPkt;
  435. *ppPacket = NULL;
  436. *pSubType = function;
  437. *pXferOffset += ((ShortDdpHdr ? SDDP_HDR_LEN : LDDP_HDR_LEN) + ATP_HEADER_SIZE);
  438. } while (FALSE);
  439. } while (FALSE);
  440. if (!ATALK_SUCCESS(error) || Deref)
  441. {
  442. if (refAtpReq)
  443. {
  444. AtalkAtpReqDereferenceDpc(pAtpReq);
  445. }
  446. if (refAtpAddr)
  447. {
  448. AtalkAtpAddrDereferenceDpc(pAtpAddrObj);
  449. }
  450. }
  451. #ifdef PROFILING
  452. TimeE = KeQueryPerformanceCounter(NULL);
  453. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  454. INTERLOCKED_ADD_LARGE_INTGR_DPC(&AtalkStatistics.stat_AtpIndicationProcessTime,
  455. TimeD,
  456. &AtalkStatsLock.SpinLock);
  457. INTERLOCKED_INCREMENT_LONG_DPC(&AtalkStatistics.stat_AtpNumIndications,
  458. &AtalkStatsLock.SpinLock);
  459. #endif
  460. return error;
  461. }
  462. ATALK_ERROR
  463. AtalkIndAtpCacheSocket(
  464. IN PATP_ADDROBJ pAtpAddr,
  465. IN PPORT_DESCRIPTOR pPortDesc
  466. )
  467. /*++
  468. Routine Description:
  469. Cache ATP socket routine. Have another one for ADSP when that is done.
  470. Arguments:
  471. Return Value:
  472. None
  473. --*/
  474. {
  475. USHORT i;
  476. KIRQL OldIrql;
  477. PDDP_ADDROBJ pDdpAddr;
  478. ATALK_ERROR error = ATALK_FAILURE;
  479. // Only cache if the net and node match the current net and node.
  480. ACQUIRE_SPIN_LOCK(&AtalkSktCacheLock, &OldIrql);
  481. pDdpAddr = pAtpAddr->atpao_DdpAddr;
  482. if ((AtalkSktCache.ac_Network == 0) &&
  483. (AtalkSktCache.ac_Node == 0) &&
  484. (AtalkDefaultPort == pPortDesc))
  485. {
  486. AtalkSktCache.ac_Network = pDdpAddr->ddpao_Addr.ata_Network;
  487. AtalkSktCache.ac_Node = pDdpAddr->ddpao_Addr.ata_Node;
  488. }
  489. if ((AtalkSktCache.ac_Network == pDdpAddr->ddpao_Addr.ata_Network) &&
  490. (AtalkSktCache.ac_Node == pDdpAddr->ddpao_Addr.ata_Node))
  491. {
  492. // First try to get a free slot
  493. for (i = 0; i < ATALK_CACHE_SKTMAX; i++)
  494. {
  495. if (AtalkSktCache.ac_Cache[i].Type == ATALK_CACHE_NOTINUSE)
  496. {
  497. ASSERT(AtalkSktCache.ac_Cache[i].u.pAtpAddr == NULL);
  498. // Use this slot
  499. AtalkSktCache.ac_Cache[i].Type = (ATALK_CACHE_INUSE | ATALK_CACHE_ATPSKT);
  500. AtalkSktCache.ac_Cache[i].Socket = pDdpAddr->ddpao_Addr.ata_Socket;
  501. // The caller must have referenced these before calling cache AND
  502. // must called uncache before removing those references. Also, if we
  503. // returned error from this routine, Caller must Dereference them.
  504. AtalkSktCache.ac_Cache[i].u.pAtpAddr = pAtpAddr;
  505. error = ATALK_NO_ERROR;
  506. break;
  507. }
  508. }
  509. }
  510. RELEASE_SPIN_LOCK(&AtalkSktCacheLock, OldIrql);
  511. return error;
  512. }
  513. VOID
  514. AtalkIndAtpUnCacheSocket(
  515. IN PATP_ADDROBJ pAtpAddr
  516. )
  517. /*++
  518. Routine Description:
  519. Cache ATP socket routine. Have another one for ADSP when that is done.
  520. Arguments:
  521. Return Value:
  522. None
  523. --*/
  524. {
  525. USHORT i;
  526. KIRQL OldIrql;
  527. ACQUIRE_SPIN_LOCK(&AtalkSktCacheLock, &OldIrql);
  528. for (i = 0; i < ATALK_CACHE_SKTMAX; i++)
  529. {
  530. if ((AtalkSktCache.ac_Cache[i].Type == (ATALK_CACHE_INUSE | ATALK_CACHE_ATPSKT)) &&
  531. (AtalkSktCache.ac_Cache[i].Socket == pAtpAddr->atpao_DdpAddr->ddpao_Addr.ata_Socket))
  532. {
  533. ASSERT(AtalkSktCache.ac_Cache[i].u.pAtpAddr == pAtpAddr);
  534. AtalkSktCache.ac_Cache[i].Type = ATALK_CACHE_NOTINUSE;
  535. AtalkSktCache.ac_Cache[i].u.pAtpAddr = NULL;
  536. break;
  537. }
  538. }
  539. if (i == ATALK_CACHE_SKTMAX)
  540. {
  541. // We didnt find the socket! References will get all messed up!
  542. ASSERT(0);
  543. }
  544. RELEASE_SPIN_LOCK(&AtalkSktCacheLock, OldIrql);
  545. }