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.

5070 lines
107 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. elanpkt.c
  6. Abstract:
  7. Revision History:
  8. Notes:
  9. --*/
  10. #include <precomp.h>
  11. #pragma hdrstop
  12. VOID
  13. AtmLaneSendConfigureRequest(
  14. IN PATMLANE_ELAN pElan
  15. )
  16. /*++
  17. Routine Description:
  18. Send an LE_CONFIGURE_REQUEST for the given ELAN to the LECS.
  19. It is assumed that caller holds a lock on the ELAN structure
  20. and it will be released here.
  21. Arguments:
  22. pElan - Pointer to ATMLANE elan structure
  23. Return Value:
  24. None
  25. --*/
  26. {
  27. PATMLANE_ATM_ENTRY pAtmEntry;
  28. PATMLANE_VC pVc;
  29. PNDIS_PACKET pNdisPacket;
  30. PNDIS_BUFFER pNdisBuffer;
  31. PUCHAR pPkt;
  32. LANE_CONTROL_FRAME UNALIGNED * pCf;
  33. ULONG ulTemp;
  34. NDIS_STATUS Status;
  35. ULONG rc;
  36. DBGP((3, "SendConfigureRequest: Elan %x\n", pElan));
  37. //
  38. // Initialize
  39. //
  40. pNdisPacket = (PNDIS_PACKET)NULL;
  41. pNdisBuffer = (PNDIS_BUFFER)NULL;
  42. Status = NDIS_STATUS_SUCCESS;
  43. pVc = NULL_PATMLANE_VC;
  44. do
  45. {
  46. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  47. pAtmEntry = pElan->pLecsAtmEntry;
  48. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  49. {
  50. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  51. Status = NDIS_STATUS_FAILURE;
  52. break;
  53. }
  54. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  55. pVc = pAtmEntry->pVcList;
  56. if (pVc == NULL_PATMLANE_VC)
  57. {
  58. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  59. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  60. break;
  61. }
  62. //
  63. // Reference the VC to keep it around
  64. //
  65. ACQUIRE_VC_LOCK_DPC(pVc);
  66. AtmLaneReferenceVc(pVc, "temp");
  67. RELEASE_VC_LOCK_DPC(pVc);
  68. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  69. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  70. //
  71. // Allocate the Ndis packet header.
  72. //
  73. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  74. if ((PNDIS_PACKET)NULL == pNdisPacket)
  75. {
  76. DBGP((0, "SendConfigureRequest: allocate packet failed\n"));
  77. Status = NDIS_STATUS_RESOURCES;
  78. break;
  79. }
  80. //
  81. // Allocate the protocol buffer
  82. //
  83. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  84. pElan,
  85. pElan->ProtocolBufSize,
  86. &(pPkt)
  87. );
  88. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  89. {
  90. DBGP((0, "SendConfigureRequest: allocate proto buffer failed\n"));
  91. Status = NDIS_STATUS_RESOURCES;
  92. break;
  93. }
  94. //
  95. // Fill in the packet with LE_CONFIGURE_REQUEST
  96. //
  97. NdisZeroMemory(pPkt, pElan->ProtocolBufSize);
  98. pCf = (PLANE_CONTROL_FRAME)pPkt;
  99. pCf->Marker = LANE_CONTROL_MARKER;
  100. pCf->Protocol = LANE_PROTOCOL;
  101. pCf->Version = LANE_VERSION;
  102. pCf->OpCode = LANE_CONFIGURE_REQUEST;
  103. ulTemp = NdisInterlockedIncrement(&pElan->TransactionId);
  104. pCf->Tid = SWAPULONG(ulTemp);
  105. pCf->SourceMacAddress.Type = LANE_MACADDRTYPE_MACADDR;
  106. if (pElan->LanType == LANE_LANTYPE_TR)
  107. {
  108. NdisMoveMemory(
  109. &pCf->SourceMacAddress.Byte,
  110. &pElan->MacAddressTr,
  111. sizeof(MAC_ADDRESS)
  112. );
  113. }
  114. else
  115. {
  116. NdisMoveMemory(
  117. &pCf->SourceMacAddress.Byte,
  118. &pElan->MacAddressEth,
  119. sizeof(MAC_ADDRESS)
  120. );
  121. }
  122. NdisMoveMemory(
  123. &pCf->SourceAtmAddr,
  124. &pElan->AtmAddress.Address,
  125. ATM_ADDRESS_LENGTH
  126. );
  127. DBGP((4, "%d: sending Config Req, Elan %x has LanType %d, CfgLanType %d\n",
  128. pElan->ElanNumber,
  129. pElan,
  130. pElan->LanType,
  131. pElan->CfgLanType));
  132. pCf->LanType = LANE_LANTYPE_UNSPEC;
  133. pCf->MaxFrameSize = (UCHAR) pElan->CfgMaxFrameSizeCode;
  134. pCf->ElanNameSize = pElan->ElanNameSize;
  135. NdisMoveMemory(
  136. &pCf->ElanName,
  137. pElan->ElanName,
  138. LANE_ELANNAME_SIZE_MAX
  139. );
  140. //
  141. // Link the ndis buffer to the ndis packet
  142. //
  143. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  144. //
  145. // Reacquire VC lock and if VC still connected send packet
  146. //
  147. ACQUIRE_VC_LOCK(pVc);
  148. if (IS_FLAG_SET(
  149. pVc->Flags,
  150. VC_CALL_STATE_MASK,
  151. VC_CALL_STATE_ACTIVE))
  152. {
  153. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  154. //
  155. // VC lock released in above
  156. //
  157. }
  158. else
  159. {
  160. Status = NDIS_STATUS_FAILURE;
  161. RELEASE_VC_LOCK(pVc);
  162. }
  163. }
  164. while (FALSE);
  165. //
  166. // Remove temp VC reference
  167. //
  168. if (pVc != NULL_PATMLANE_VC)
  169. {
  170. ACQUIRE_VC_LOCK(pVc);
  171. rc = AtmLaneDereferenceVc(pVc, "temp");
  172. if (rc > 0)
  173. {
  174. RELEASE_VC_LOCK(pVc);
  175. }
  176. //
  177. // else VC is gone
  178. //
  179. }
  180. //
  181. // Cleanup if failure
  182. //
  183. if (Status != NDIS_STATUS_SUCCESS)
  184. {
  185. if (pNdisPacket != (PNDIS_PACKET)NULL)
  186. {
  187. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  188. }
  189. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  190. {
  191. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  192. }
  193. }
  194. TRACEOUT(SendConfigureRequest);
  195. return;
  196. }
  197. VOID
  198. AtmLaneSendJoinRequest(
  199. IN PATMLANE_ELAN pElan
  200. )
  201. /*++
  202. Routine Description:
  203. Send an LE_JOIN_REQUEST for the given ELAN to the LES.
  204. It is assumed that caller holds a lock on the ELAN structure
  205. and it will be released here.
  206. Arguments:
  207. pElan - Pointer to ATMLANE elan structure
  208. Return Value:
  209. None
  210. --*/
  211. {
  212. PATMLANE_ATM_ENTRY pAtmEntry;
  213. PATMLANE_VC pVc;
  214. PNDIS_PACKET pNdisPacket;
  215. PNDIS_BUFFER pNdisBuffer;
  216. PUCHAR pPkt;
  217. LANE_CONTROL_FRAME UNALIGNED * pCf;
  218. ULONG ulTemp;
  219. NDIS_STATUS Status;
  220. ULONG rc;
  221. TRACEIN(SendJoinRequest);
  222. DBGP((3, "SendJoinRequest: Elan %x\n", pElan));
  223. //
  224. // Initialize
  225. //
  226. pNdisPacket = (PNDIS_PACKET)NULL;
  227. pNdisBuffer = (PNDIS_BUFFER)NULL;
  228. Status = NDIS_STATUS_SUCCESS;
  229. pVc = NULL_PATMLANE_VC;
  230. do
  231. {
  232. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  233. pAtmEntry = pElan->pLesAtmEntry;
  234. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  235. {
  236. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  237. Status = NDIS_STATUS_FAILURE;
  238. break;
  239. }
  240. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  241. pVc = pAtmEntry->pVcList;
  242. if (pVc == NULL_PATMLANE_VC)
  243. {
  244. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  245. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  246. break;
  247. }
  248. //
  249. // Reference the VC to keep it around
  250. //
  251. ACQUIRE_VC_LOCK_DPC(pVc);
  252. AtmLaneReferenceVc(pVc, "temp");
  253. RELEASE_VC_LOCK_DPC(pVc);
  254. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  255. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  256. //
  257. // Allocate the Ndis packet header.
  258. //
  259. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  260. if ((PNDIS_PACKET)NULL == pNdisPacket)
  261. {
  262. DBGP((0, "SendJoinRequest: allocate packet failed\n"));
  263. Status = NDIS_STATUS_RESOURCES;
  264. break;
  265. }
  266. //
  267. // Allocate the protocol buffer
  268. //
  269. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  270. pElan,
  271. pElan->ProtocolBufSize,
  272. &(pPkt)
  273. );
  274. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  275. {
  276. DBGP((0, "SendJoinRequest: allocate proto buffer failed\n"));
  277. Status = NDIS_STATUS_RESOURCES;
  278. break;
  279. }
  280. //
  281. // Fill in the packet with LE_JOIN_REQUEST
  282. //
  283. NdisZeroMemory(pPkt, pElan->ProtocolBufSize);
  284. pCf = (PLANE_CONTROL_FRAME)pPkt;
  285. pCf->Marker = LANE_CONTROL_MARKER;
  286. pCf->Protocol = LANE_PROTOCOL;
  287. pCf->Version = LANE_VERSION;
  288. pCf->OpCode = LANE_JOIN_REQUEST;
  289. ulTemp = NdisInterlockedIncrement(&pElan->TransactionId);
  290. pCf->Tid = SWAPULONG(ulTemp);
  291. pCf->SourceMacAddress.Type = LANE_MACADDRTYPE_MACADDR;
  292. if (pElan->LanType == LANE_LANTYPE_TR)
  293. {
  294. NdisMoveMemory(
  295. &pCf->SourceMacAddress.Byte,
  296. &pElan->MacAddressTr,
  297. sizeof(MAC_ADDRESS)
  298. );
  299. }
  300. else
  301. {
  302. DBGP((0, "%d Send Join with MAC addr: %s\n",
  303. pElan->ElanNumber,
  304. MacAddrToString(&pElan->MacAddressEth)));
  305. NdisMoveMemory(
  306. &pCf->SourceMacAddress.Byte,
  307. &pElan->MacAddressEth,
  308. sizeof(MAC_ADDRESS)
  309. );
  310. }
  311. NdisMoveMemory(
  312. &pCf->SourceAtmAddr,
  313. &pElan->AtmAddress.Address,
  314. ATM_ADDRESS_LENGTH
  315. );
  316. pCf->LanType = pElan->LanType;
  317. pCf->MaxFrameSize = pElan->MaxFrameSizeCode;
  318. pCf->ElanNameSize = pElan->ElanNameSize;
  319. NdisMoveMemory(
  320. &pCf->ElanName,
  321. pElan->ElanName,
  322. LANE_ELANNAME_SIZE_MAX
  323. );
  324. //
  325. // Link the ndis buffer to the ndis packet
  326. //
  327. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  328. //
  329. // Reacquire VC lock and if VC still connected send packet
  330. //
  331. ACQUIRE_VC_LOCK(pVc);
  332. if (IS_FLAG_SET(
  333. pVc->Flags,
  334. VC_CALL_STATE_MASK,
  335. VC_CALL_STATE_ACTIVE))
  336. {
  337. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  338. //
  339. // VC lock released in above
  340. //
  341. }
  342. else
  343. {
  344. Status = NDIS_STATUS_FAILURE;
  345. RELEASE_VC_LOCK(pVc);
  346. }
  347. }
  348. while (FALSE);
  349. //
  350. // Remove temp VC reference
  351. //
  352. if (pVc != NULL_PATMLANE_VC)
  353. {
  354. ACQUIRE_VC_LOCK(pVc);
  355. rc = AtmLaneDereferenceVc(pVc, "temp");
  356. if (rc > 0)
  357. {
  358. RELEASE_VC_LOCK(pVc);
  359. }
  360. //
  361. // else VC is gone
  362. //
  363. }
  364. //
  365. // Cleanup if failure
  366. //
  367. if (Status != NDIS_STATUS_SUCCESS)
  368. {
  369. if (pNdisPacket != (PNDIS_PACKET)NULL)
  370. {
  371. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  372. }
  373. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  374. {
  375. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  376. }
  377. }
  378. TRACEOUT(SendJoinRequest);
  379. return;
  380. }
  381. VOID
  382. AtmLaneSendArpRequest(
  383. IN PATMLANE_ELAN pElan,
  384. IN PATMLANE_MAC_ENTRY pMacEntry LOCKIN NOLOCKOUT
  385. )
  386. /*++
  387. Routine Description:
  388. Send an LE_ARP_REQUEST for a particular Mac Entry to the LES.
  389. Arguments:
  390. pElan - Pointer to ATMLANE elan structure
  391. pMacEntry - Pointer to ATMLANE Mac Entry for which
  392. to send the LE_ARP_REQUEST.
  393. Return Value:
  394. None
  395. --*/
  396. {
  397. PATMLANE_ATM_ENTRY pAtmEntry;
  398. PATMLANE_VC pVc;
  399. PNDIS_PACKET pNdisPacket;
  400. PNDIS_BUFFER pNdisBuffer;
  401. PUCHAR pPkt;
  402. LANE_CONTROL_FRAME UNALIGNED * pCf;
  403. ULONG ulTemp;
  404. NDIS_STATUS Status;
  405. ULONG rc;
  406. BOOLEAN MacEntryLockReleased;
  407. TRACEIN(SendArpRequest);
  408. DBGP((3, "SendArpRequest: Elan %x MacEntry %x\n",
  409. pElan, pMacEntry));
  410. //
  411. // Initialize
  412. //
  413. pNdisPacket = (PNDIS_PACKET)NULL;
  414. pNdisBuffer = (PNDIS_BUFFER)NULL;
  415. Status = NDIS_STATUS_SUCCESS;
  416. pVc = NULL_PATMLANE_VC;
  417. MacEntryLockReleased = FALSE;
  418. do
  419. {
  420. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  421. pAtmEntry = pElan->pLesAtmEntry;
  422. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  423. {
  424. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  425. Status = NDIS_STATUS_FAILURE;
  426. break;
  427. }
  428. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  429. pVc = pAtmEntry->pVcList;
  430. if (pVc == NULL_PATMLANE_VC)
  431. {
  432. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  433. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  434. break;
  435. }
  436. //
  437. // Reference the VC to keep it around
  438. //
  439. ACQUIRE_VC_LOCK_DPC(pVc);
  440. AtmLaneReferenceVc(pVc, "temp");
  441. RELEASE_VC_LOCK_DPC(pVc);
  442. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  443. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  444. //
  445. // Allocate the Ndis packet header.
  446. //
  447. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  448. if ((PNDIS_PACKET)NULL == pNdisPacket)
  449. {
  450. DBGP((0, "SendArpRequest: allocate packet failed\n"));
  451. Status = NDIS_STATUS_RESOURCES;
  452. break;
  453. }
  454. //
  455. // Allocate the protocol buffer
  456. //
  457. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  458. pElan,
  459. pElan->ProtocolBufSize,
  460. &(pPkt)
  461. );
  462. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  463. {
  464. DBGP((0, "SendArpRequest: allocate proto buffer failed\n"));
  465. Status = NDIS_STATUS_RESOURCES;
  466. break;
  467. }
  468. //
  469. // Fill in the packet with LE_ARP_REQUEST
  470. //
  471. NdisZeroMemory(pPkt, pElan->ProtocolBufSize);
  472. pCf = (PLANE_CONTROL_FRAME)pPkt;
  473. pCf->Marker = LANE_CONTROL_MARKER;
  474. pCf->Protocol = LANE_PROTOCOL;
  475. pCf->Version = LANE_VERSION;
  476. pCf->OpCode = LANE_ARP_REQUEST;
  477. ulTemp = NdisInterlockedIncrement(&pElan->TransactionId);
  478. pCf->Tid = SWAPULONG(ulTemp);
  479. pCf->LecId = pElan->LecId; // already swapped
  480. //
  481. // Leave SourceMacAddress zero (not present).
  482. // TargetMacAddress is what we are looking for!
  483. //
  484. pCf->TargetMacAddress.Type = (USHORT) pMacEntry->MacAddrType;
  485. NdisMoveMemory(
  486. &pCf->TargetMacAddress.Byte,
  487. &pMacEntry->MacAddress,
  488. sizeof(MAC_ADDRESS)
  489. );
  490. //
  491. // SourceAtmAddr is the Elan's
  492. //
  493. NdisMoveMemory(
  494. &pCf->SourceAtmAddr,
  495. &pElan->AtmAddress.Address,
  496. ATM_ADDRESS_LENGTH
  497. );
  498. //
  499. // Store swapped Tid in MacEntry for later matching!
  500. //
  501. pMacEntry->ArpTid = SWAPULONG(ulTemp);
  502. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  503. MacEntryLockReleased = TRUE;
  504. //
  505. // Link the ndis buffer to the ndis packet
  506. //
  507. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  508. //
  509. // Reacquire VC lock and if VC still connected send packet
  510. //
  511. ACQUIRE_VC_LOCK(pVc);
  512. if (IS_FLAG_SET(
  513. pVc->Flags,
  514. VC_CALL_STATE_MASK,
  515. VC_CALL_STATE_ACTIVE))
  516. {
  517. DBGP((2, "SendArpRequest: %s Sending ARP Request: Atm Entry %x pVc %x\n",
  518. MacAddrToString(&pMacEntry->MacAddress), pAtmEntry, pVc));
  519. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  520. //
  521. // VC lock released in above
  522. //
  523. }
  524. else
  525. {
  526. Status = NDIS_STATUS_FAILURE;
  527. RELEASE_VC_LOCK(pVc);
  528. }
  529. }
  530. while (FALSE);
  531. if (!MacEntryLockReleased)
  532. {
  533. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  534. }
  535. //
  536. // Remove temp VC reference
  537. //
  538. if (pVc != NULL_PATMLANE_VC)
  539. {
  540. ACQUIRE_VC_LOCK(pVc);
  541. rc = AtmLaneDereferenceVc(pVc, "temp");
  542. if (rc > 0)
  543. {
  544. RELEASE_VC_LOCK(pVc);
  545. }
  546. //
  547. // else VC is gone
  548. //
  549. }
  550. //
  551. // Cleanup if failure
  552. //
  553. if (Status != NDIS_STATUS_SUCCESS)
  554. {
  555. if (pNdisPacket != (PNDIS_PACKET)NULL)
  556. {
  557. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  558. }
  559. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  560. {
  561. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  562. }
  563. }
  564. TRACEOUT(SendArpRequest);
  565. return;
  566. }
  567. VOID
  568. AtmLaneSendReadyQuery(
  569. IN PATMLANE_ELAN pElan,
  570. IN PATMLANE_VC pVc LOCKIN NOLOCKOUT
  571. )
  572. /*++
  573. Routine Description:
  574. Sends a READY_QUERY frame on the VC.
  575. It is assumed that caller holds a lock on the VC structure
  576. and it will be released here.
  577. Arguments:
  578. pElan - Pointer to ATMLANE elan structure
  579. pVc - Pointer to the ATMLANE VC structure
  580. on which to send the frame.
  581. Return Value:
  582. None
  583. --*/
  584. {
  585. PNDIS_PACKET pNdisPacket;
  586. PNDIS_BUFFER pNdisBuffer;
  587. ULONG TotalLength;
  588. ULONG BufferLength;
  589. PLANE_READY_FRAME pQueryRf;
  590. NDIS_STATUS Status;
  591. TRACEIN(SendReadyQuery);
  592. //
  593. // Initialize
  594. //
  595. pNdisPacket = (PNDIS_PACKET)NULL;
  596. pNdisBuffer = (PNDIS_BUFFER)NULL;
  597. Status = NDIS_STATUS_SUCCESS;
  598. do
  599. {
  600. //
  601. // Allocate the Ndis packet header.
  602. //
  603. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  604. if ((PNDIS_PACKET)NULL == pNdisPacket)
  605. {
  606. DBGP((0, "SendReadyQuery: allocate packet failed\n"));
  607. Status = NDIS_STATUS_RESOURCES;
  608. break;
  609. }
  610. //
  611. // Allocate the protocol buffer
  612. //
  613. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  614. pElan,
  615. sizeof(LANE_READY_FRAME),
  616. &((PUCHAR)(pQueryRf))
  617. );
  618. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  619. {
  620. DBGP((0, "SendReadyQuery: allocate proto buffer failed\n"));
  621. Status = NDIS_STATUS_RESOURCES;
  622. break;
  623. }
  624. //
  625. // Fill in Indication
  626. //
  627. pQueryRf->Marker = LANE_CONTROL_MARKER;
  628. pQueryRf->Protocol = LANE_PROTOCOL;
  629. pQueryRf->Version = LANE_VERSION;
  630. pQueryRf->OpCode = LANE_READY_QUERY;
  631. //
  632. // Link the ndis buffer to the ndis packet
  633. //
  634. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  635. if (IS_FLAG_SET(
  636. pVc->Flags,
  637. VC_CALL_STATE_MASK,
  638. VC_CALL_STATE_ACTIVE))
  639. {
  640. //
  641. // Send it
  642. //
  643. DBGP((2, "SendReadyQuery: pVc %x sending READY QUERY\n", pVc));
  644. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  645. //
  646. // VC lock released in above
  647. //
  648. ASSERT(Status == NDIS_STATUS_SUCCESS);
  649. }
  650. else
  651. {
  652. //
  653. // The VC is being torn down.
  654. //
  655. Status = NDIS_STATUS_FAILURE;
  656. break;
  657. }
  658. break;
  659. }
  660. while (FALSE);
  661. //
  662. // Cleanup if failure
  663. //
  664. if (Status != NDIS_STATUS_SUCCESS)
  665. {
  666. RELEASE_VC_LOCK(pVc);
  667. if (pNdisPacket != (PNDIS_PACKET)NULL)
  668. {
  669. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  670. }
  671. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  672. {
  673. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  674. }
  675. }
  676. TRACEOUT(SendReadyQuery);
  677. return;
  678. }
  679. VOID
  680. AtmLaneSendReadyIndication(
  681. IN PATMLANE_ELAN pElan,
  682. IN PATMLANE_VC pVc LOCKIN NOLOCKOUT
  683. )
  684. /*++
  685. Routine Description:
  686. Sends a ready indication frame on the VC.
  687. It is assumed that caller holds a lock on the VC structure
  688. and it will be released here.
  689. Arguments:
  690. pElan - Pointer to ATMLANE elan structure
  691. pVc - Pointer to the ATMLANE VC structure
  692. on which to send the frame.
  693. Return Value:
  694. None
  695. --*/
  696. {
  697. ULONG TotalLength;
  698. ULONG BufferLength;
  699. PLANE_READY_FRAME pIndRf;
  700. PNDIS_PACKET pNdisPacket;
  701. PNDIS_BUFFER pNdisBuffer;
  702. NDIS_STATUS Status;
  703. TRACEIN(SendReadyIndication);
  704. //
  705. // Initialize
  706. //
  707. pNdisPacket = (PNDIS_PACKET)NULL;
  708. pNdisBuffer = (PNDIS_BUFFER)NULL;
  709. Status = NDIS_STATUS_SUCCESS;
  710. do
  711. {
  712. //
  713. // Allocate the Ndis packet header.
  714. //
  715. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  716. if ((PNDIS_PACKET)NULL == pNdisPacket)
  717. {
  718. DBGP((0, "SendReadyIndication: allocate packet failed\n"));
  719. Status = NDIS_STATUS_RESOURCES;
  720. break;
  721. }
  722. //
  723. // Allocate the protocol buffer
  724. //
  725. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  726. pElan,
  727. sizeof(LANE_READY_FRAME),
  728. &((PUCHAR)(pIndRf))
  729. );
  730. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  731. {
  732. DBGP((0, "SendReadyIndication: allocate proto buffer failed\n"));
  733. Status = NDIS_STATUS_RESOURCES;
  734. break;
  735. }
  736. //
  737. // Fill in Indication
  738. //
  739. pIndRf->Marker = LANE_CONTROL_MARKER;
  740. pIndRf->Protocol = LANE_PROTOCOL;
  741. pIndRf->Version = LANE_VERSION;
  742. pIndRf->OpCode = LANE_READY_IND;
  743. //
  744. // Link the ndis buffer to the ndis packet
  745. //
  746. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  747. if (IS_FLAG_SET(
  748. pVc->Flags,
  749. VC_CALL_STATE_MASK,
  750. VC_CALL_STATE_ACTIVE))
  751. {
  752. //
  753. // Send it
  754. //
  755. DBGP((2, "SendReadyIndication: pVc %x sending READY INDICATION\n", pVc));
  756. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  757. //
  758. // VC lock released in above
  759. //
  760. ASSERT(Status == NDIS_STATUS_SUCCESS);
  761. }
  762. else
  763. {
  764. //
  765. // The VC is being torn down.
  766. //
  767. Status = NDIS_STATUS_FAILURE;
  768. break;
  769. }
  770. break;
  771. }
  772. while (FALSE);
  773. //
  774. // Cleanup if failure
  775. //
  776. if (Status != NDIS_STATUS_SUCCESS)
  777. {
  778. RELEASE_VC_LOCK(pVc);
  779. if (pNdisPacket != (PNDIS_PACKET)NULL)
  780. {
  781. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  782. }
  783. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  784. {
  785. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  786. }
  787. }
  788. TRACEOUT(SendReadyIndication);
  789. return;
  790. }
  791. VOID
  792. AtmLaneSendFlushRequest(
  793. IN PATMLANE_ELAN pElan,
  794. IN PATMLANE_MAC_ENTRY pMacEntry LOCKIN NOLOCKOUT,
  795. IN PATMLANE_ATM_ENTRY pAtmEntry
  796. )
  797. /*++
  798. Routine Description:
  799. Sends a flush request to the BUS for a particular MAC Entry
  800. using the destination ATM address in the specified ATM Entry.
  801. Arguments:
  802. pElan - Pointer to ATMLANE Elan structure
  803. pMacEntry - Pointer to ATMLANE Mac entry structure
  804. pAtmEntry - Pointer to ATMLANE Atm entry structure
  805. Return Value:
  806. None
  807. --*/
  808. {
  809. PATMLANE_ATM_ENTRY pBusAtmEntry;
  810. PATMLANE_VC pVc;
  811. ULONG TotalLength;
  812. ULONG BufferLength;
  813. ULONG ulTemp;
  814. PLANE_CONTROL_FRAME pCf;
  815. PNDIS_PACKET pNdisPacket;
  816. PNDIS_BUFFER pNdisBuffer;
  817. NDIS_STATUS Status;
  818. ULONG rc;
  819. BOOLEAN MacEntryLockReleased;
  820. TRACEIN(SendFlushRequest);
  821. //
  822. // Initialize
  823. //
  824. pNdisPacket = (PNDIS_PACKET)NULL;
  825. pNdisBuffer = (PNDIS_BUFFER)NULL;
  826. Status = NDIS_STATUS_SUCCESS;
  827. pVc = NULL_PATMLANE_VC;
  828. MacEntryLockReleased = FALSE;
  829. do
  830. {
  831. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  832. pBusAtmEntry = pElan->pBusAtmEntry;
  833. if (pBusAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  834. {
  835. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  836. Status = NDIS_STATUS_FAILURE;
  837. break;
  838. }
  839. ACQUIRE_ATM_ENTRY_LOCK_DPC(pBusAtmEntry);
  840. pVc = pBusAtmEntry->pVcList;
  841. if (pVc == NULL_PATMLANE_VC)
  842. {
  843. RELEASE_ATM_ENTRY_LOCK_DPC(pBusAtmEntry);
  844. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  845. break;
  846. }
  847. //
  848. // Reference the VC to keep it around
  849. //
  850. ACQUIRE_VC_LOCK_DPC(pVc);
  851. AtmLaneReferenceVc(pVc, "temp");
  852. RELEASE_VC_LOCK_DPC(pVc);
  853. RELEASE_ATM_ENTRY_LOCK_DPC(pBusAtmEntry);
  854. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  855. //
  856. // Allocate the Ndis packet header.
  857. //
  858. pNdisPacket = AtmLaneAllocProtoPacket(pElan);
  859. if ((PNDIS_PACKET)NULL == pNdisPacket)
  860. {
  861. DBGP((0, "SendFlushRequest: allocate packet failed\n"));
  862. Status = NDIS_STATUS_RESOURCES;
  863. break;
  864. }
  865. //
  866. // Allocate the protocol buffer
  867. //
  868. pNdisBuffer = AtmLaneAllocateProtoBuffer(
  869. pElan,
  870. sizeof(LANE_CONTROL_FRAME),
  871. &((PUCHAR)(pCf))
  872. );
  873. if ((PNDIS_BUFFER)NULL == pNdisBuffer)
  874. {
  875. DBGP((0, "SendFlushRequest: allocate proto buffer failed\n"));
  876. Status = NDIS_STATUS_RESOURCES;
  877. break;
  878. }
  879. //
  880. // Fill in Flush Request
  881. //
  882. NdisZeroMemory((PUCHAR)pCf, sizeof(LANE_CONTROL_FRAME));
  883. pCf->Marker = LANE_CONTROL_MARKER;
  884. pCf->Protocol = LANE_PROTOCOL;
  885. pCf->Version = LANE_VERSION;
  886. pCf->OpCode = LANE_FLUSH_REQUEST;
  887. ulTemp = NdisInterlockedIncrement(&pElan->TransactionId);
  888. pCf->Tid = SWAPULONG(ulTemp);
  889. pCf->LecId = pElan->LecId; // already swapped
  890. NdisMoveMemory(
  891. &pCf->SourceAtmAddr,
  892. &pElan->AtmAddress.Address,
  893. ATM_ADDRESS_LENGTH
  894. );
  895. NdisMoveMemory(
  896. &pCf->TargetAtmAddr,
  897. &pAtmEntry->AtmAddress.Address,
  898. ATM_ADDRESS_LENGTH
  899. );
  900. //
  901. // Store swapped Tid in MacEntry for later matching!
  902. //
  903. pMacEntry->FlushTid = SWAPULONG(ulTemp);
  904. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  905. MacEntryLockReleased = TRUE;
  906. //
  907. // Link the ndis buffer to the ndis packet
  908. //
  909. NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
  910. //
  911. // Reacquire VC lock and if VC still connected send packet
  912. //
  913. ACQUIRE_VC_LOCK(pVc);
  914. if (IS_FLAG_SET(
  915. pVc->Flags,
  916. VC_CALL_STATE_MASK,
  917. VC_CALL_STATE_ACTIVE))
  918. {
  919. DBGP((2, "SendFlushRequest: sending FLUSH REQUEST for MacEntry %x\n", pMacEntry));
  920. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  921. //
  922. // VC lock released in above
  923. //
  924. }
  925. else
  926. {
  927. Status = NDIS_STATUS_FAILURE;
  928. RELEASE_VC_LOCK(pVc);
  929. }
  930. break;
  931. }
  932. while (FALSE);
  933. if (!MacEntryLockReleased)
  934. {
  935. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  936. }
  937. //
  938. // Remove temp VC reference
  939. //
  940. if (pVc != NULL_PATMLANE_VC)
  941. {
  942. ACQUIRE_VC_LOCK(pVc);
  943. rc = AtmLaneDereferenceVc(pVc, "temp");
  944. if (rc > 0)
  945. {
  946. RELEASE_VC_LOCK(pVc);
  947. }
  948. //
  949. // else VC is gone
  950. //
  951. }
  952. //
  953. // Cleanup if failure
  954. //
  955. if (Status != NDIS_STATUS_SUCCESS)
  956. {
  957. if (pNdisPacket != (PNDIS_PACKET)NULL)
  958. {
  959. AtmLaneFreeProtoPacket(pElan, pNdisPacket);
  960. }
  961. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  962. {
  963. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  964. }
  965. }
  966. TRACEOUT(SendFlushRequest);
  967. return;
  968. }
  969. VOID
  970. AtmLaneConfigureResponseHandler(
  971. IN PATMLANE_ELAN pElan,
  972. IN PATMLANE_VC pVc,
  973. IN PNDIS_PACKET pNdisPacket
  974. )
  975. /*++
  976. Routine Description:
  977. Handles incoming packets from the Configuration Direct VC.
  978. Arguments:
  979. pElan - Pointer to ATMLANE Elan structure
  980. pVc - Pointer to ATMLANE Vc structure
  981. pNdisPacket - Pointer to the Ndis Packet
  982. Return Value:
  983. None
  984. --*/
  985. {
  986. PNDIS_BUFFER pNdisBuffer;
  987. ULONG TotalLength;
  988. ULONG BufferLength;
  989. PLANE_CONTROL_FRAME pCf;
  990. ULONG NumTlvs;
  991. ULONG UNALIGNED * pType;
  992. PUCHAR pLength;
  993. USHORT UNALIGNED * pUShort;
  994. ULONG UNALIGNED * pULong;
  995. NDIS_STATUS EventCode;
  996. USHORT NumStrings;
  997. PWCHAR StringList[2];
  998. BOOLEAN FreeString[2];
  999. TRACEIN(ConfigureResponseHandler);
  1000. do
  1001. {
  1002. //
  1003. // Get initial buffer and total length of packet
  1004. //
  1005. NdisGetFirstBufferFromPacket(
  1006. pNdisPacket,
  1007. &pNdisBuffer,
  1008. (PVOID *)&pCf,
  1009. &BufferLength,
  1010. &TotalLength);
  1011. //
  1012. // Packet must be at least the size of a control frame.
  1013. // Could be larger with optional TLVs.
  1014. //
  1015. if (TotalLength < sizeof(LANE_CONTROL_FRAME))
  1016. {
  1017. DBGP((0,
  1018. "ConfigureResponseHandler: Received runt control frame (%d)\n",
  1019. TotalLength));
  1020. break;
  1021. }
  1022. //
  1023. // If buffer is not at least the size of a control frame
  1024. // we currently will not deal with it.
  1025. //
  1026. if (BufferLength < sizeof(LANE_CONTROL_FRAME))
  1027. {
  1028. DBGP((0, "ConfigureResponseHandler: Control frame is fragmented\n"));
  1029. break;
  1030. }
  1031. //
  1032. // Verify that this is really a configure reponse
  1033. //
  1034. if (pCf->Marker != LANE_CONTROL_MARKER ||
  1035. pCf->Protocol != LANE_PROTOCOL ||
  1036. pCf->Version != LANE_VERSION ||
  1037. pCf->OpCode != LANE_CONFIGURE_RESPONSE)
  1038. {
  1039. DBGP((0, "ConfigureResponseHandler: Not a configure response\n"));
  1040. //DbgPrintHexDump(0, (PUCHAR)pCf, BufferLength);
  1041. break;
  1042. }
  1043. //
  1044. // Check for successful configure status
  1045. //
  1046. if (pCf->Status != LANE_STATUS_SUCCESS)
  1047. {
  1048. //
  1049. // Failure
  1050. //
  1051. DBGP((0,
  1052. "ConfigureResponseHandler: Unsuccessful Status 0x%x (%d)\n",
  1053. SWAPUSHORT(pCf->Status), SWAPUSHORT(pCf->Status)));
  1054. //
  1055. // Setup to log event
  1056. //
  1057. StringList[0] = NULL;
  1058. FreeString[0] = FALSE;
  1059. StringList[1] = NULL;
  1060. FreeString[1] = FALSE;
  1061. switch (pCf->Status)
  1062. {
  1063. case LANE_STATUS_VERSNOSUPP:
  1064. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_VERSNOSUPP;
  1065. StringList[0] = pElan->CfgElanName.Buffer;
  1066. NumStrings = 1;
  1067. break;
  1068. case LANE_STATUS_REQPARMINVAL:
  1069. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_REQPARMINVAL;
  1070. StringList[0] = pElan->CfgElanName.Buffer;
  1071. NumStrings = 1;
  1072. break;
  1073. case LANE_STATUS_INSUFFRES:
  1074. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_INSUFFRES;
  1075. StringList[0] = pElan->CfgElanName.Buffer;
  1076. NumStrings = 1;
  1077. break;
  1078. case LANE_STATUS_NOACCESS:
  1079. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_NOACCESS;
  1080. StringList[0] = pElan->CfgElanName.Buffer;
  1081. NumStrings = 1;
  1082. break;
  1083. case LANE_STATUS_REQIDINVAL:
  1084. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_REQIDINVAL;
  1085. StringList[0] = pElan->CfgElanName.Buffer;
  1086. NumStrings = 1;
  1087. break;
  1088. case LANE_STATUS_LANDESTINVAL:
  1089. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_LANDESTINVAL;
  1090. StringList[0] = pElan->CfgElanName.Buffer;
  1091. if (pElan->LanType == LANE_LANTYPE_ETH)
  1092. {
  1093. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressEth);
  1094. FreeString[1] = TRUE;
  1095. }
  1096. else
  1097. {
  1098. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressTr);
  1099. FreeString[1] = TRUE;
  1100. }
  1101. NumStrings = 2;
  1102. break;
  1103. case LANE_STATUS_ATMADDRINVAL:
  1104. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_ATMADDRINVAL;
  1105. StringList[0] = pElan->CfgElanName.Buffer;
  1106. StringList[1] = AtmLaneAtmAddrToString(&pElan->AtmAddress);
  1107. FreeString[1] = TRUE;
  1108. NumStrings = 2;
  1109. break;
  1110. case LANE_STATUS_NOCONF:
  1111. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_NOCONF;
  1112. StringList[0] = pElan->CfgElanName.Buffer;
  1113. NumStrings = 1;
  1114. break;
  1115. case LANE_STATUS_CONFERROR:
  1116. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_CONFERROR;
  1117. StringList[0] = pElan->CfgElanName.Buffer;
  1118. NumStrings = 1;
  1119. break;
  1120. case LANE_STATUS_INSUFFINFO:
  1121. default:
  1122. EventCode = EVENT_ATMLANE_CFGREQ_FAIL_INSUFFINFO;
  1123. StringList[0] = pElan->CfgElanName.Buffer;
  1124. NumStrings = 1;
  1125. break;
  1126. }
  1127. //
  1128. // If not repeated event on this ELAN write the event to log
  1129. //
  1130. if (pElan->LastEventCode != EventCode)
  1131. {
  1132. pElan->LastEventCode = EventCode;
  1133. (VOID) NdisWriteEventLogEntry(
  1134. pAtmLaneGlobalInfo->pDriverObject,
  1135. EventCode, 0, NumStrings, StringList, 0, NULL);
  1136. }
  1137. //
  1138. // Free any strings allocated
  1139. //
  1140. if (FreeString[0] && StringList[0] != NULL)
  1141. {
  1142. FREE_MEM(StringList[0]);
  1143. }
  1144. if (FreeString[1] && StringList[1] != NULL)
  1145. {
  1146. FREE_MEM(StringList[1]);
  1147. }
  1148. //
  1149. // Notify event handler of failure
  1150. //
  1151. ACQUIRE_ELAN_LOCK(pElan);
  1152. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_CONFIGURE_RESPONSE, NDIS_STATUS_FAILURE);
  1153. RELEASE_ELAN_LOCK(pElan);
  1154. break;
  1155. }
  1156. //
  1157. // Successful Configure Response
  1158. //
  1159. //
  1160. // Extract the required Elan parameters
  1161. //
  1162. ACQUIRE_ELAN_LOCK(pElan);
  1163. pElan->LanType = pCf->LanType;
  1164. DBGP((1, "%d LanType = %x\n", pElan->ElanNumber, pElan->LanType));
  1165. if (pElan->LanType == LANE_LANTYPE_UNSPEC)
  1166. {
  1167. DBGP((1, "Defaulting to LanType 1 (Ethernet/802.3)\n"));
  1168. pElan->LanType = LANE_LANTYPE_ETH;
  1169. }
  1170. pElan->MaxFrameSizeCode = pCf->MaxFrameSize;
  1171. DBGP((1, "%d MaxFrameSizeCode = %x\n", pElan->ElanNumber, pElan->MaxFrameSizeCode));
  1172. if (pElan->MaxFrameSizeCode == LANE_MAXFRAMESIZE_CODE_UNSPEC)
  1173. {
  1174. DBGP((1, "Defaulting to MaxFrameSizeCode 1 (1516)\n"));
  1175. pElan->MaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_1516;
  1176. }
  1177. switch (pElan->MaxFrameSizeCode)
  1178. {
  1179. case LANE_MAXFRAMESIZE_CODE_18190:
  1180. pElan->MaxFrameSize = 18190;
  1181. break;
  1182. case LANE_MAXFRAMESIZE_CODE_9234:
  1183. pElan->MaxFrameSize = 9234;
  1184. break;
  1185. case LANE_MAXFRAMESIZE_CODE_4544:
  1186. pElan->MaxFrameSize = 4544;
  1187. break;
  1188. case LANE_MAXFRAMESIZE_CODE_1516:
  1189. case LANE_MAXFRAMESIZE_CODE_UNSPEC:
  1190. default:
  1191. pElan->MaxFrameSize = 1516;
  1192. break;
  1193. }
  1194. if (pElan->LanType == LANE_LANTYPE_ETH)
  1195. {
  1196. pElan->MinFrameSize = LANE_MIN_ETHPACKET;
  1197. }
  1198. else
  1199. {
  1200. pElan->MinFrameSize = LANE_MIN_TRPACKET;
  1201. }
  1202. NdisZeroMemory(
  1203. pElan->ElanName,
  1204. LANE_ELANNAME_SIZE_MAX);
  1205. NdisMoveMemory(
  1206. pElan->ElanName,
  1207. pCf->ElanName,
  1208. pCf->ElanNameSize);
  1209. pElan->ElanNameSize = pCf->ElanNameSize;
  1210. pElan->LesAddress.AddressType = ATM_NSAP;
  1211. pElan->LesAddress.NumberOfDigits = ATM_ADDRESS_LENGTH;
  1212. NdisMoveMemory(
  1213. pElan->LesAddress.Address,
  1214. &pCf->TargetAtmAddr,
  1215. ATM_ADDRESS_LENGTH);
  1216. DBGP((1, "%d LES ATMAddr: %s\n",
  1217. pElan->ElanNumber,
  1218. AtmAddrToString(pElan->LesAddress.Address)));
  1219. //
  1220. // Check for TLVs
  1221. //
  1222. if (pCf->NumTlvs > 0)
  1223. {
  1224. DBGP((2, "ConfigureReponseHandler: NumTlvs is %d\n", pCf->NumTlvs));
  1225. NumTlvs = pCf->NumTlvs;
  1226. pType = (ULONG UNALIGNED *)
  1227. (((PUCHAR)pCf) + sizeof(LANE_CONTROL_FRAME));
  1228. while (NumTlvs--)
  1229. {
  1230. pLength = (PUCHAR)pType + sizeof(*pType);
  1231. pUShort = (USHORT UNALIGNED *)
  1232. (((PUCHAR)pLength) + sizeof(*pLength));
  1233. pULong = (ULONG UNALIGNED *)
  1234. (((PUCHAR)pLength) + sizeof(*pLength));
  1235. switch (*pType)
  1236. {
  1237. case LANE_CFG_CONTROL_TIMEOUT: // C7
  1238. pElan->ControlTimeout = SWAPUSHORT(*pUShort);
  1239. if (pElan->ControlTimeout < LANE_C7_MIN ||
  1240. pElan->ControlTimeout > LANE_C7_MAX)
  1241. pElan->ControlTimeout = LANE_C7_DEF;
  1242. DBGP((1, "%d Control Time-out %d\n",
  1243. pElan->ElanNumber,
  1244. pElan->ControlTimeout));
  1245. break;
  1246. case LANE_CFG_UNK_FRAME_COUNT: // C10
  1247. pElan->MaxUnkFrameCount = SWAPUSHORT(*pUShort);
  1248. if (pElan->MaxUnkFrameCount < LANE_C10_MIN ||
  1249. pElan->MaxUnkFrameCount > LANE_C10_MAX)
  1250. pElan->MaxUnkFrameCount = LANE_C10_DEF;
  1251. DBGP((1, "%d Maximum Unknown Frame Count %d\n",
  1252. pElan->ElanNumber,
  1253. pElan->MaxUnkFrameCount));
  1254. break;
  1255. case LANE_CFG_UNK_FRAME_TIME: // C11
  1256. pElan->MaxUnkFrameTime = SWAPUSHORT(*pUShort);
  1257. if (pElan->MaxUnkFrameTime < LANE_C11_MIN ||
  1258. pElan->MaxUnkFrameTime > LANE_C11_MAX)
  1259. pElan->MaxUnkFrameTime = LANE_C11_DEF;
  1260. DBGP((1, "%d Maximum Unknown Frame Time %d\n",
  1261. pElan->ElanNumber,
  1262. pElan->MaxUnkFrameTime));
  1263. break;
  1264. case LANE_CFG_VCC_TIMEOUT: // C12
  1265. pElan->VccTimeout = SWAPULONG(*pULong);
  1266. if (pElan->VccTimeout < LANE_C12_MIN)
  1267. pElan->VccTimeout = LANE_C12_DEF;
  1268. DBGP((1, "%d VCC Timeout Period %d\n",
  1269. pElan->ElanNumber,
  1270. pElan->VccTimeout));
  1271. break;
  1272. case LANE_CFG_MAX_RETRY_COUNT: // C13
  1273. pElan->MaxRetryCount = SWAPUSHORT(*pUShort);
  1274. if (/* pElan->MaxRetryCount < LANE_C13_MIN || */
  1275. pElan->MaxRetryCount > LANE_C13_MAX)
  1276. pElan->MaxRetryCount = LANE_C13_DEF;
  1277. DBGP((1, "%d Maximum Retry Count %d\n",
  1278. pElan->ElanNumber,
  1279. pElan->MaxRetryCount));
  1280. break;
  1281. case LANE_CFG_AGING_TIME: // C17
  1282. pElan->AgingTime = SWAPULONG(*pULong);
  1283. if (pElan->AgingTime < LANE_C17_MIN ||
  1284. pElan->AgingTime > LANE_C17_MAX)
  1285. pElan->AgingTime = LANE_C17_DEF;
  1286. DBGP((1, "%d Aging Time %d\n",
  1287. pElan->ElanNumber,
  1288. pElan->AgingTime));
  1289. break;
  1290. case LANE_CFG_FWD_DELAY_TIME: // C18
  1291. pElan->ForwardDelayTime = SWAPUSHORT(*pUShort);
  1292. if (pElan->ForwardDelayTime < LANE_C18_MIN ||
  1293. pElan->ForwardDelayTime > LANE_C18_MAX)
  1294. pElan->ForwardDelayTime = LANE_C18_DEF;
  1295. DBGP((1, "%d Forward Delay Time %d\n",
  1296. pElan->ElanNumber,
  1297. pElan->ForwardDelayTime));
  1298. break;
  1299. case LANE_CFG_ARP_RESP_TIME: // C20
  1300. pElan->ArpResponseTime = SWAPUSHORT(*pUShort);
  1301. if (pElan->ArpResponseTime < LANE_C20_MIN ||
  1302. pElan->ArpResponseTime > LANE_C20_MAX)
  1303. pElan->ArpResponseTime = LANE_C20_DEF;
  1304. DBGP((1, "%d Arp Response Time %d\n",
  1305. pElan->ElanNumber,
  1306. pElan->ArpResponseTime));
  1307. break;
  1308. case LANE_CFG_FLUSH_TIMEOUT: // C21
  1309. pElan->FlushTimeout = SWAPUSHORT(*pUShort);
  1310. if (pElan->FlushTimeout < LANE_C21_MIN ||
  1311. pElan->FlushTimeout > LANE_C21_MAX)
  1312. pElan->FlushTimeout = LANE_C21_DEF;
  1313. DBGP((1, "%d Flush Time-out %d\n",
  1314. pElan->ElanNumber,
  1315. pElan->FlushTimeout));
  1316. break;
  1317. case LANE_CFG_PATH_SWITCH_DELAY: // C22
  1318. pElan->PathSwitchingDelay = SWAPUSHORT(*pUShort);
  1319. if (pElan->PathSwitchingDelay < LANE_C22_MIN ||
  1320. pElan->PathSwitchingDelay > LANE_C22_MAX)
  1321. pElan->PathSwitchingDelay = LANE_C22_DEF;
  1322. DBGP((1, "%d Path Switching Delay %d\n",
  1323. pElan->ElanNumber,
  1324. pElan->PathSwitchingDelay));
  1325. break;
  1326. case LANE_CFG_LOCAL_SEGMENT_ID: // C23
  1327. pElan->LocalSegmentId = SWAPUSHORT(*pUShort);
  1328. DBGP((1, "%d Local Segment ID %d\n",
  1329. pElan->ElanNumber,
  1330. pElan->LocalSegmentId));
  1331. break;
  1332. case LANE_CFG_MCAST_VCC_TYPE: // C24
  1333. pElan->McastSendVcType = SWAPUSHORT(*pUShort);
  1334. DBGP((1, "%d Mcast Send VCC Type %d\n",
  1335. pElan->ElanNumber,
  1336. pElan->McastSendVcType));
  1337. break;
  1338. case LANE_CFG_MCAST_VCC_AVG: // C25
  1339. pElan->McastSendVcAvgRate = SWAPULONG(*pULong);
  1340. DBGP((1, "%d Mcast Send VCC AvgRate %d\n",
  1341. pElan->ElanNumber,
  1342. pElan->McastSendVcAvgRate));
  1343. break;
  1344. case LANE_CFG_MCAST_VCC_PEAK: // C26
  1345. pElan->McastSendVcPeakRate = SWAPULONG(*pULong);
  1346. DBGP((1, "%d Mcast Send VCC PeakRate %d\n",
  1347. pElan->ElanNumber,
  1348. pElan->McastSendVcPeakRate));
  1349. break;
  1350. case LANE_CFG_CONN_COMPL_TIMER: // C28
  1351. pElan->ConnComplTimer = SWAPUSHORT(*pUShort);
  1352. if (pElan->ConnComplTimer < LANE_C28_MIN ||
  1353. pElan->ConnComplTimer > LANE_C28_MAX)
  1354. pElan->ConnComplTimer = LANE_C28_DEF;
  1355. DBGP((1, "%d Connection Completion Timer %d\n",
  1356. pElan->ElanNumber,
  1357. pElan->ConnComplTimer));
  1358. break;
  1359. }
  1360. pType = (ULONG UNALIGNED *)
  1361. (((PUCHAR)pType) + sizeof(pType) +
  1362. sizeof(*pLength) + *pLength);
  1363. } // while (NumTlvs--)
  1364. //
  1365. // Recalc the bus rate limiter parameters
  1366. //
  1367. pElan->LimitTime = pElan->MaxUnkFrameTime * 1000;
  1368. pElan->IncrTime = pElan->LimitTime / pElan->MaxUnkFrameCount;
  1369. }
  1370. //
  1371. // Notify event handler of success
  1372. //
  1373. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_CONFIGURE_RESPONSE, NDIS_STATUS_SUCCESS);
  1374. RELEASE_ELAN_LOCK(pElan);
  1375. }
  1376. while (FALSE);
  1377. TRACEOUT(ConfigureResponsehandler);
  1378. return;
  1379. }
  1380. VOID
  1381. AtmLaneControlPacketHandler(
  1382. IN PATMLANE_ELAN pElan,
  1383. IN PATMLANE_VC pVc,
  1384. IN PNDIS_PACKET pNdisPacket
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Handles incoming packets from the control VC(s) to/from the LES.
  1389. Arguments:
  1390. pElan - Pointer to ATMLANE Elan structure
  1391. pVc - Pointer to ATMLANE Vc structure
  1392. pNdisPacket - Pointer to the Ndis Packet
  1393. Return Value:
  1394. None
  1395. --*/
  1396. {
  1397. PNDIS_BUFFER pNdisBuffer;
  1398. ULONG TotalLength;
  1399. ULONG BufferLength;
  1400. PLANE_CONTROL_FRAME pCf;
  1401. NDIS_STATUS Status;
  1402. TRACEIN(ControlPacketHandler);
  1403. do
  1404. {
  1405. //
  1406. // Get initial buffer and total length of packet
  1407. //
  1408. NdisGetFirstBufferFromPacket(
  1409. pNdisPacket,
  1410. &pNdisBuffer,
  1411. (PVOID *)&pCf,
  1412. &BufferLength,
  1413. &TotalLength);
  1414. //
  1415. // Packet must be at least the size of a control frame.
  1416. //
  1417. if (TotalLength < sizeof(LANE_CONTROL_FRAME))
  1418. {
  1419. DBGP((0,
  1420. "ConPacketHandler: Received runt control frame (%d)\n",
  1421. TotalLength));
  1422. break;
  1423. }
  1424. //
  1425. // If buffer is not at least the size of a control frame
  1426. // we currently will not deal with it.
  1427. //
  1428. if (BufferLength < sizeof(LANE_CONTROL_FRAME))
  1429. {
  1430. DBGP((0, "ConfigureResponseHandler: Control frame is fragmented\n"));
  1431. break;
  1432. }
  1433. //
  1434. // Verify that this is really a control packet
  1435. //
  1436. if (pCf->Marker != LANE_CONTROL_MARKER ||
  1437. pCf->Protocol != LANE_PROTOCOL ||
  1438. pCf->Version != LANE_VERSION)
  1439. {
  1440. DBGP((0, "ControlPacketHandler: Not a control packet!\n"));
  1441. //DbgPrintHexDump(0, (PUCHAR)pCf, BufferLength);
  1442. break;
  1443. }
  1444. //
  1445. // Now handle by type of control packet
  1446. //
  1447. switch (pCf->OpCode)
  1448. {
  1449. case LANE_JOIN_RESPONSE:
  1450. DBGP((2, "ControlPacketHandler: Join Response\n"));
  1451. AtmLaneJoinResponseHandler(pElan, pCf);
  1452. break;
  1453. case LANE_ARP_RESPONSE:
  1454. DBGP((2, "ControlPacketHandler: ARP Response\n"));
  1455. AtmLaneArpResponseHandler(pElan, pCf);
  1456. break;
  1457. case LANE_ARP_REQUEST:
  1458. DBGP((1, "ControlPacketHandler: ARP Request\n"));
  1459. AtmLaneArpRequestHandler(pElan, pCf);
  1460. break;
  1461. case LANE_NARP_REQUEST:
  1462. DBGP((1, "ControlPacketHandler: NARP Request\n"));
  1463. // Drop it.
  1464. break;
  1465. case LANE_TOPOLOGY_REQUEST:
  1466. DBGP((1, "ControlPacketHandler: TOPOLOGY Request\n"));
  1467. AtmLaneTopologyRequestHandler(pElan, pCf);
  1468. break;
  1469. case LANE_FLUSH_RESPONSE:
  1470. DBGP((2, "ControlPacketHandler: FLUSH Response\n"));
  1471. AtmLaneFlushResponseHandler(pElan, pCf);
  1472. break;
  1473. default:
  1474. DBGP((0, "ControlPacketHandler: Unexpected OpCode %x!\n",
  1475. pCf->OpCode));
  1476. //DbgPrintHexDump(0, (PUCHAR)pCf, BufferLength);
  1477. break;
  1478. } // switch (pCf->OpCode)
  1479. break;
  1480. }
  1481. while (FALSE);
  1482. TRACEOUT(ControlPackethandler);
  1483. return;
  1484. }
  1485. VOID
  1486. AtmLaneJoinResponseHandler(
  1487. IN PATMLANE_ELAN pElan,
  1488. IN PLANE_CONTROL_FRAME pCf
  1489. )
  1490. /*++
  1491. Routine Description:
  1492. Handles incoming Join Response packets from the LES.
  1493. Arguments:
  1494. pElan - Pointer to ATMLANE Elan structure
  1495. pCf - Pointer to LANE Control Frame
  1496. Return Value:
  1497. None
  1498. --*/
  1499. {
  1500. PWCHAR StringList[2];
  1501. BOOLEAN FreeString[2];
  1502. NDIS_STATUS EventCode;
  1503. USHORT NumStrings;
  1504. TRACEIN(JoinResponseHandler);
  1505. ACQUIRE_ELAN_LOCK(pElan);
  1506. if (ELAN_STATE_JOIN == pElan->State)
  1507. {
  1508. //
  1509. // Only handle join response in JOIN state!
  1510. //
  1511. if (LANE_STATUS_SUCCESS == pCf->Status)
  1512. {
  1513. //
  1514. // Success.
  1515. //
  1516. // Extract the info we need
  1517. //
  1518. pElan->LecId = pCf->LecId; // leave in network byte order
  1519. DBGP((2,
  1520. "ControlPacketHandler: LECID %x\n",
  1521. SWAPUSHORT(pElan->LecId)));
  1522. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_JOIN_RESPONSE, NDIS_STATUS_SUCCESS);
  1523. }
  1524. else
  1525. {
  1526. //
  1527. // Failure
  1528. //
  1529. DBGP((0,
  1530. "ControlPacketHandler: Unsuccessful Status (%d)\n",
  1531. pCf->Status));
  1532. //
  1533. // Setup to write error to event log
  1534. //
  1535. StringList[0] = NULL;
  1536. FreeString[0] = FALSE;
  1537. StringList[1] = NULL;
  1538. FreeString[1] = FALSE;
  1539. switch (pCf->Status)
  1540. {
  1541. case LANE_STATUS_VERSNOSUPP:
  1542. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_VERSNOSUPP;
  1543. StringList[0] = pElan->CfgElanName.Buffer;
  1544. NumStrings = 1;
  1545. break;
  1546. case LANE_STATUS_DUPLANDEST:
  1547. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_DUPLANDEST;
  1548. StringList[0] = pElan->CfgElanName.Buffer;
  1549. if (pElan->LanType == LANE_LANTYPE_ETH)
  1550. {
  1551. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressEth);
  1552. FreeString[1] = TRUE;
  1553. }
  1554. else
  1555. {
  1556. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressTr);
  1557. FreeString[1] = TRUE;
  1558. }
  1559. NumStrings = 2;
  1560. break;
  1561. case LANE_STATUS_DUPATMADDR:
  1562. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_DUPATMADDR;
  1563. StringList[0] = pElan->CfgElanName.Buffer;
  1564. StringList[1] = AtmLaneAtmAddrToString(&pElan->AtmAddress);
  1565. FreeString[1] = TRUE;
  1566. NumStrings = 2;
  1567. break;
  1568. case LANE_STATUS_INSUFFRES:
  1569. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_INSUFFRES;
  1570. StringList[0] = pElan->CfgElanName.Buffer;
  1571. NumStrings = 1;
  1572. break;
  1573. case LANE_STATUS_NOACCESS:
  1574. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_NOACCESS;
  1575. StringList[0] = pElan->CfgElanName.Buffer;
  1576. NumStrings = 1;
  1577. break;
  1578. case LANE_STATUS_REQIDINVAL:
  1579. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_REQIDINVAL;
  1580. StringList[0] = pElan->CfgElanName.Buffer;
  1581. NumStrings = 1;
  1582. break;
  1583. case LANE_STATUS_LANDESTINVAL:
  1584. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_LANDESTINVAL;
  1585. StringList[0] = pElan->CfgElanName.Buffer;
  1586. if (pElan->LanType == LANE_LANTYPE_ETH)
  1587. {
  1588. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressEth);
  1589. FreeString[1] = TRUE;
  1590. }
  1591. else
  1592. {
  1593. StringList[1] = AtmLaneMacAddrToString(&pElan->MacAddressTr);
  1594. FreeString[1] = TRUE;
  1595. }
  1596. NumStrings = 2;
  1597. break;
  1598. case LANE_STATUS_ATMADDRINVAL:
  1599. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_ATMADDRINVAL;
  1600. StringList[0] = pElan->CfgElanName.Buffer;
  1601. StringList[1] = AtmLaneAtmAddrToString(&pElan->AtmAddress);
  1602. FreeString[1] = TRUE;
  1603. NumStrings = 2;
  1604. break;
  1605. case LANE_STATUS_REQPARMINVAL:
  1606. default:
  1607. EventCode = EVENT_ATMLANE_JOINREQ_FAIL_REQPARMINVAL;
  1608. StringList[0] = pElan->CfgElanName.Buffer;
  1609. NumStrings = 1;
  1610. break;
  1611. }
  1612. //
  1613. // If not repeated event on this ELAN write the event to log
  1614. //
  1615. if (pElan->LastEventCode != EventCode)
  1616. {
  1617. pElan->LastEventCode = EventCode;
  1618. (VOID) NdisWriteEventLogEntry(
  1619. pAtmLaneGlobalInfo->pDriverObject,
  1620. EventCode, 0, NumStrings, StringList, 0, NULL);
  1621. }
  1622. //
  1623. // Free any strings allocated
  1624. //
  1625. if (FreeString[0] && StringList[0] != NULL)
  1626. {
  1627. FREE_MEM(StringList[0]);
  1628. }
  1629. if (FreeString[1] && StringList[1] != NULL)
  1630. {
  1631. FREE_MEM(StringList[1]);
  1632. }
  1633. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_JOIN_RESPONSE, NDIS_STATUS_FAILURE);
  1634. }
  1635. }
  1636. else
  1637. {
  1638. //
  1639. // else bad elan state - ignore packet
  1640. //
  1641. DBGP((0,
  1642. "ControlPacketHandler: Elan state wrong - Ignoring packet\n",
  1643. pCf->Status));
  1644. }
  1645. RELEASE_ELAN_LOCK(pElan);
  1646. TRACEOUT(JoinResponseHandler);
  1647. return;
  1648. }
  1649. VOID
  1650. AtmLaneReadyQueryHandler(
  1651. IN PATMLANE_ELAN pElan,
  1652. IN PATMLANE_VC pVc,
  1653. IN PNDIS_PACKET pQueryNdisPacket
  1654. )
  1655. /*++
  1656. Routine Description:
  1657. Handles incoming READY_QUERY packets from peers.
  1658. Arguments:
  1659. pElan - Pointer to ATMLANE Elan structure
  1660. pVc - Pointer to ATMLANE VC for this packet
  1661. pQueryNdisPacket - Pointer to the Ndis Packet
  1662. Return Value:
  1663. None
  1664. --*/
  1665. {
  1666. PNDIS_BUFFER pNdisBuffer;
  1667. ULONG TotalLength;
  1668. ULONG BufferLength;
  1669. PLANE_READY_FRAME pQueryRf;
  1670. PLANE_READY_FRAME pIndRf;
  1671. PNDIS_PACKET pIndNdisPacket;
  1672. TRACEIN(ReadyQueryHandler);
  1673. do
  1674. {
  1675. //
  1676. // Get initial buffer and total length of packet
  1677. //
  1678. NdisGetFirstBufferFromPacket(
  1679. pQueryNdisPacket,
  1680. &pNdisBuffer,
  1681. &pQueryRf,
  1682. &BufferLength,
  1683. &TotalLength);
  1684. //
  1685. // Packet must be at least the size of a READY frame.
  1686. //
  1687. if (TotalLength < sizeof(LANE_READY_FRAME))
  1688. {
  1689. DBGP((0,
  1690. "ReadyQueryHandler: Received runt ready frame (%d)\n",
  1691. TotalLength));
  1692. break;
  1693. }
  1694. //
  1695. // If buffer is not at least the size of a ready frame
  1696. // we currently will not deal with it.
  1697. //
  1698. if (BufferLength < sizeof(LANE_READY_FRAME))
  1699. {
  1700. DBGP((0, "ReadyQueryHandler: Control frame is fragmented\n"));
  1701. break;
  1702. }
  1703. //
  1704. // Verify that this is really a ready query
  1705. //
  1706. if (pQueryRf->Marker != LANE_CONTROL_MARKER ||
  1707. pQueryRf->Protocol != LANE_PROTOCOL ||
  1708. pQueryRf->Version != LANE_VERSION ||
  1709. pQueryRf->OpCode != LANE_READY_QUERY)
  1710. {
  1711. DBGP((0, "ReadyQueryHandler: Not a ready query\n"));
  1712. //DbgPrintHexDump(0, (PUCHAR)pQueryRf, BufferLength);
  1713. break;
  1714. }
  1715. //
  1716. // Send Ready Indication back on VC
  1717. //
  1718. ACQUIRE_VC_LOCK(pVc);
  1719. AtmLaneSendReadyIndication(pElan, pVc);
  1720. //
  1721. // VC lock released in above
  1722. //
  1723. break;
  1724. }
  1725. while (FALSE);
  1726. TRACEOUT(ReadyQueryHandler);
  1727. return;
  1728. }
  1729. VOID
  1730. AtmLaneFlushRequestHandler(
  1731. IN PATMLANE_ELAN pElan,
  1732. IN PNDIS_PACKET pRequestNdisPacket
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. Handles incoming FLUSH_REQUEST packets from peers.
  1737. Arguments:
  1738. pElan - Pointer to ATMLANE Elan structure
  1739. pRequestNdisPacket - Pointer to the Ndis Packet
  1740. Return Value:
  1741. None
  1742. --*/
  1743. {
  1744. PATMLANE_ATM_ENTRY pAtmEntry;
  1745. PATMLANE_VC pVc;
  1746. PNDIS_BUFFER pRequestNdisBuffer;
  1747. PNDIS_PACKET pResponseNdisPacket;
  1748. PNDIS_BUFFER pResponseNdisBuffer;
  1749. ULONG TotalLength;
  1750. ULONG BufferLength;
  1751. PLANE_CONTROL_FRAME pRequestCf;
  1752. PLANE_CONTROL_FRAME pResponseCf;
  1753. NDIS_STATUS Status;
  1754. ULONG rc;
  1755. TRACEIN(FlushRequestHandler);
  1756. //
  1757. // Initialize
  1758. //
  1759. pResponseNdisPacket = (PNDIS_PACKET)NULL;
  1760. pResponseNdisBuffer = (PNDIS_BUFFER)NULL;
  1761. Status = NDIS_STATUS_SUCCESS;
  1762. pVc = NULL_PATMLANE_VC;
  1763. do
  1764. {
  1765. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  1766. pAtmEntry = pElan->pLesAtmEntry;
  1767. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  1768. {
  1769. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1770. Status = NDIS_STATUS_FAILURE;
  1771. break;
  1772. }
  1773. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  1774. pVc = pAtmEntry->pVcList;
  1775. if (pVc == NULL_PATMLANE_VC)
  1776. {
  1777. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  1778. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1779. break;
  1780. }
  1781. //
  1782. // Reference the VC to keep it around
  1783. //
  1784. ACQUIRE_VC_LOCK_DPC(pVc);
  1785. AtmLaneReferenceVc(pVc, "temp");
  1786. RELEASE_VC_LOCK_DPC(pVc);
  1787. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  1788. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1789. //
  1790. // Get initial buffer and total length of packet
  1791. //
  1792. NdisGetFirstBufferFromPacket(
  1793. pRequestNdisPacket,
  1794. &pRequestNdisBuffer,
  1795. (PVOID *)&pRequestCf,
  1796. &BufferLength,
  1797. &TotalLength);
  1798. //
  1799. // Packet must be at least the size of a control frame.
  1800. //
  1801. if (TotalLength < sizeof(LANE_CONTROL_FRAME))
  1802. {
  1803. DBGP((0,
  1804. "FlushRequestHandler: Received runt control frame (%d)\n",
  1805. TotalLength));
  1806. Status = NDIS_STATUS_FAILURE;
  1807. break;
  1808. }
  1809. //
  1810. // If buffer is not at least the size of a control frame
  1811. // we currently will not deal with it.
  1812. //
  1813. if (BufferLength < sizeof(LANE_CONTROL_FRAME))
  1814. {
  1815. DBGP((0, "FlushRequestHandler: Control frame is fragmented\n"));
  1816. Status = NDIS_STATUS_FAILURE;
  1817. break;
  1818. }
  1819. //
  1820. // Verify that this is really a flush request
  1821. //
  1822. if (pRequestCf->Marker != LANE_CONTROL_MARKER ||
  1823. pRequestCf->Protocol != LANE_PROTOCOL ||
  1824. pRequestCf->Version != LANE_VERSION ||
  1825. pRequestCf->OpCode != LANE_FLUSH_REQUEST)
  1826. {
  1827. DBGP((0, "FlushRequestHandler: Not a flush request\n"));
  1828. //DbgPrintHexDump(0, (PUCHAR)pRequestCf, BufferLength);
  1829. Status = NDIS_STATUS_FAILURE;
  1830. break;
  1831. }
  1832. //
  1833. // See if it is really destined for us
  1834. //
  1835. if (!ATM_ADDR_EQUAL(pRequestCf->TargetAtmAddr, pElan->AtmAddress.Address))
  1836. {
  1837. DBGP((1, "FlushRequestHandler: bad target addr, discarding, Vc %x\n", pVc));
  1838. Status = NDIS_STATUS_FAILURE;
  1839. break;
  1840. }
  1841. //
  1842. // Turn packet around and send it to the LES
  1843. //
  1844. do
  1845. {
  1846. //
  1847. // Allocate the Ndis packet header.
  1848. //
  1849. pResponseNdisPacket = AtmLaneAllocProtoPacket(pElan);
  1850. if ((PNDIS_PACKET)NULL == pResponseNdisPacket)
  1851. {
  1852. DBGP((0, "FlushRequestHandler: allocate packet failed\n"));
  1853. Status = NDIS_STATUS_RESOURCES;
  1854. break;
  1855. }
  1856. //
  1857. // Allocate the protocol buffer
  1858. //
  1859. pResponseNdisBuffer = AtmLaneAllocateProtoBuffer(
  1860. pElan,
  1861. pElan->ProtocolBufSize,
  1862. &((PUCHAR)(pResponseCf))
  1863. );
  1864. if ((PNDIS_BUFFER)NULL == pResponseNdisBuffer)
  1865. {
  1866. DBGP((0, "FlushRequestHandler: allocate proto buffer failed\n"));
  1867. Status = NDIS_STATUS_RESOURCES;
  1868. break;
  1869. }
  1870. //
  1871. // Copy in the request packet
  1872. //
  1873. NdisMoveMemory(
  1874. pResponseCf,
  1875. pRequestCf,
  1876. sizeof(LANE_CONTROL_FRAME)
  1877. );
  1878. //
  1879. // Change to a response opcode
  1880. //
  1881. pResponseCf->OpCode = LANE_FLUSH_RESPONSE;
  1882. //
  1883. // Link the ndis buffer to the ndis packet
  1884. //
  1885. NdisChainBufferAtFront(pResponseNdisPacket, pResponseNdisBuffer);
  1886. //
  1887. // Reacquire VC lock and if VC still connected send packet
  1888. //
  1889. ACQUIRE_VC_LOCK(pVc);
  1890. if (IS_FLAG_SET(
  1891. pVc->Flags,
  1892. VC_CALL_STATE_MASK,
  1893. VC_CALL_STATE_ACTIVE))
  1894. {
  1895. DBGP((2, "FlushRequestHandler: Sent FLUSH RESPONSE\n"));
  1896. AtmLaneSendPacketOnVc(pVc, pResponseNdisPacket, FALSE);
  1897. //
  1898. // VC lock released in above
  1899. //
  1900. }
  1901. else
  1902. {
  1903. Status = NDIS_STATUS_FAILURE;
  1904. RELEASE_VC_LOCK(pVc);
  1905. }
  1906. break;
  1907. }
  1908. while (FALSE);
  1909. break;
  1910. }
  1911. while (FALSE);
  1912. //
  1913. // Remove temp VC reference
  1914. //
  1915. if (pVc != NULL_PATMLANE_VC)
  1916. {
  1917. ACQUIRE_VC_LOCK(pVc);
  1918. rc = AtmLaneDereferenceVc(pVc, "temp");
  1919. if (rc > 0)
  1920. {
  1921. RELEASE_VC_LOCK(pVc);
  1922. }
  1923. //
  1924. // else VC is gone
  1925. //
  1926. }
  1927. //
  1928. // Cleanup if failure
  1929. //
  1930. if (Status != NDIS_STATUS_SUCCESS)
  1931. {
  1932. if (pResponseNdisPacket != (PNDIS_PACKET)NULL)
  1933. {
  1934. AtmLaneFreeProtoPacket(pElan, pResponseNdisPacket);
  1935. }
  1936. if (pResponseNdisBuffer != (PNDIS_BUFFER)NULL)
  1937. {
  1938. AtmLaneFreeProtoBuffer(pElan, pResponseNdisBuffer);
  1939. }
  1940. }
  1941. TRACEOUT(FlushRequestHandler);
  1942. return;
  1943. }
  1944. VOID
  1945. AtmLaneArpRequestHandler(
  1946. IN PATMLANE_ELAN pElan,
  1947. IN PLANE_CONTROL_FRAME pRequestCf
  1948. )
  1949. /*++
  1950. Routine Description:
  1951. Handles incoming Arp Request packets from the LES.
  1952. Arguments:
  1953. pRequestCf - Pointer to ARP Request Frame
  1954. Return Value:
  1955. None
  1956. --*/
  1957. {
  1958. PATMLANE_ATM_ENTRY pAtmEntry;
  1959. PATMLANE_VC pVc;
  1960. PNDIS_PACKET pResponseNdisPacket;
  1961. PNDIS_BUFFER pResponseNdisBuffer;
  1962. ULONG TotalLength;
  1963. ULONG BufferLength;
  1964. PLANE_CONTROL_FRAME pResponseCf;
  1965. NDIS_STATUS Status;
  1966. ULONG rc;
  1967. PMAC_ADDRESS pMacAddress;
  1968. TRACEIN(ArpRequestHandler);
  1969. //
  1970. // Initialize
  1971. //
  1972. pResponseNdisPacket = (PNDIS_PACKET)NULL;
  1973. pResponseNdisBuffer = (PNDIS_BUFFER)NULL;
  1974. Status = NDIS_STATUS_SUCCESS;
  1975. pVc = NULL_PATMLANE_VC;
  1976. pMacAddress = (PMAC_ADDRESS)pRequestCf->TargetMacAddress.Byte;
  1977. do
  1978. {
  1979. DBGP((2, "%d Arp Request for MAC %s\n",
  1980. pElan->ElanNumber, MacAddrToString(pMacAddress)));
  1981. //
  1982. // Check if this is a targetless ARP request. Drop it if so.
  1983. //
  1984. if (pRequestCf->TargetMacAddress.Type == LANE_MACADDRTYPE_NOTPRESENT)
  1985. {
  1986. DBGP((1, "%d dropping targetless ARP request for %s\n",
  1987. pElan->ElanNumber, MacAddrToString(pMacAddress)));
  1988. break;
  1989. }
  1990. //
  1991. // If not looking for our MAC address then done.
  1992. //
  1993. if (pElan->LanType == LANE_LANTYPE_TR)
  1994. {
  1995. if (!MAC_ADDR_EQUAL(pMacAddress, &pElan->MacAddressTr))
  1996. {
  1997. break;
  1998. }
  1999. }
  2000. else
  2001. {
  2002. if (!MAC_ADDR_EQUAL(pMacAddress, &pElan->MacAddressEth))
  2003. {
  2004. break;
  2005. }
  2006. }
  2007. DBGP((1, "%d ARP REQUEST\n", pElan->ElanNumber));
  2008. //
  2009. // Get the LES Vc
  2010. //
  2011. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  2012. pAtmEntry = pElan->pLesAtmEntry;
  2013. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2014. {
  2015. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2016. DBGP((0, "%d ARP REQUEST before we have an LES entry\n", pElan->ElanNumber));
  2017. Status = NDIS_STATUS_FAILURE;
  2018. break;
  2019. }
  2020. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2021. pVc = pAtmEntry->pVcList;
  2022. if (pVc == NULL_PATMLANE_VC)
  2023. {
  2024. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2025. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2026. DBGP((0, "%d ARP REQUEST with no VC to LES\n", pElan->ElanNumber));
  2027. break;
  2028. }
  2029. //
  2030. // Reference the VC to keep it around
  2031. //
  2032. ACQUIRE_VC_LOCK_DPC(pVc);
  2033. AtmLaneReferenceVc(pVc, "temp");
  2034. RELEASE_VC_LOCK_DPC(pVc);
  2035. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2036. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2037. //
  2038. // Send Arp Response to the LES
  2039. //
  2040. do
  2041. {
  2042. //
  2043. // Allocate the Ndis packet header.
  2044. //
  2045. pResponseNdisPacket = AtmLaneAllocProtoPacket(pElan);
  2046. if ((PNDIS_PACKET)NULL == pResponseNdisPacket)
  2047. {
  2048. DBGP((0, "ArpRequestHandler: allocate packet failed\n"));
  2049. Status = NDIS_STATUS_RESOURCES;
  2050. break;
  2051. }
  2052. //
  2053. // Allocate the protocol buffer
  2054. //
  2055. pResponseNdisBuffer = AtmLaneAllocateProtoBuffer(
  2056. pElan,
  2057. pElan->ProtocolBufSize,
  2058. &((PUCHAR)(pResponseCf))
  2059. );
  2060. if ((PNDIS_BUFFER)NULL == pResponseNdisBuffer)
  2061. {
  2062. DBGP((0, "ArpRequestHandler: allocate proto buffer failed\n"));
  2063. Status = NDIS_STATUS_RESOURCES;
  2064. break;
  2065. }
  2066. //
  2067. // Copy in the request packet
  2068. //
  2069. NdisMoveMemory(
  2070. pResponseCf,
  2071. pRequestCf,
  2072. sizeof(LANE_CONTROL_FRAME)
  2073. );
  2074. //
  2075. // Change to a response opcode
  2076. //
  2077. pResponseCf->OpCode = LANE_ARP_RESPONSE;
  2078. //
  2079. // Fill in our ATM Address
  2080. //
  2081. NdisMoveMemory(
  2082. &pResponseCf->TargetAtmAddr,
  2083. &pElan->AtmAddress.Address,
  2084. ATM_ADDRESS_LENGTH
  2085. );
  2086. //
  2087. // Link the ndis buffer to the ndis packet
  2088. //
  2089. NdisChainBufferAtFront(pResponseNdisPacket, pResponseNdisBuffer);
  2090. //
  2091. // Reacquire VC lock and if VC still connected send packet
  2092. //
  2093. ACQUIRE_VC_LOCK(pVc);
  2094. if (IS_FLAG_SET(
  2095. pVc->Flags,
  2096. VC_CALL_STATE_MASK,
  2097. VC_CALL_STATE_ACTIVE))
  2098. {
  2099. DBGP((2, "ArpRequestHandler: Sent ARP RESPONSE\n"));
  2100. AtmLaneSendPacketOnVc(pVc, pResponseNdisPacket, FALSE);
  2101. //
  2102. // VC lock released in above
  2103. //
  2104. }
  2105. else
  2106. {
  2107. Status = NDIS_STATUS_FAILURE;
  2108. RELEASE_VC_LOCK(pVc);
  2109. }
  2110. break;
  2111. }
  2112. while (FALSE);
  2113. break;
  2114. }
  2115. while (FALSE);
  2116. //
  2117. // Remove temp VC reference
  2118. //
  2119. if (pVc != NULL_PATMLANE_VC)
  2120. {
  2121. ACQUIRE_VC_LOCK(pVc);
  2122. rc = AtmLaneDereferenceVc(pVc, "temp");
  2123. if (rc > 0)
  2124. {
  2125. RELEASE_VC_LOCK(pVc);
  2126. }
  2127. //
  2128. // else VC is gone
  2129. //
  2130. }
  2131. //
  2132. // Cleanup if failure
  2133. //
  2134. if (Status != NDIS_STATUS_SUCCESS)
  2135. {
  2136. if (pResponseNdisPacket != (PNDIS_PACKET)NULL)
  2137. {
  2138. AtmLaneFreeProtoPacket(pElan, pResponseNdisPacket);
  2139. }
  2140. if (pResponseNdisBuffer != (PNDIS_BUFFER)NULL)
  2141. {
  2142. AtmLaneFreeProtoBuffer(pElan, pResponseNdisBuffer);
  2143. }
  2144. }
  2145. TRACEOUT(ArpRequestHandler);
  2146. return;
  2147. }
  2148. VOID
  2149. AtmLaneArpResponseHandler(
  2150. IN PATMLANE_ELAN pElan,
  2151. IN PLANE_CONTROL_FRAME pCf
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. Handle an LE_ARP Response frame.
  2156. The MAC Entry should already exist and the Tid in the
  2157. ARP frame should match the one in the MAC Entry.
  2158. If either is not true then the information is ignored.
  2159. An ATM Entry is created or and existing one is found.
  2160. The MAC Entry is linked to it and appropriate actions
  2161. are taken based on the MAC Entry state.
  2162. Arguments:
  2163. pElan - Pointer to ATMLANE Elan
  2164. pMacAddress - MAC Address
  2165. pAtmAddress - ATM Address
  2166. Return Value:
  2167. None.
  2168. --*/
  2169. {
  2170. PATMLANE_MAC_ENTRY pMacEntry;
  2171. PATMLANE_ATM_ENTRY pAtmEntry;
  2172. PMAC_ADDRESS pMacAddress;
  2173. PUCHAR pAtmAddress;
  2174. BOOLEAN WasRunning;
  2175. BOOLEAN bFound;
  2176. ULONG MacAddrType;
  2177. ULONG rc;
  2178. TRACEIN(ArpResponseHandler);
  2179. //
  2180. // Initialize
  2181. //
  2182. pMacEntry = NULL_PATMLANE_MAC_ENTRY;
  2183. pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2184. MacAddrType = pCf->TargetMacAddress.Type;
  2185. pMacAddress = (PMAC_ADDRESS)pCf->TargetMacAddress.Byte;
  2186. pAtmAddress = pCf->TargetAtmAddr;
  2187. do
  2188. {
  2189. //
  2190. // Check Status
  2191. //
  2192. if (pCf->Status != LANE_STATUS_SUCCESS)
  2193. {
  2194. DBGP((0,
  2195. "ArpResponseHandler: Unsuccessful Status (%d) for %s\n",
  2196. pCf->Status,
  2197. MacAddrToString(pMacAddress)));
  2198. break;
  2199. }
  2200. //
  2201. // Get an existing MAC Entry
  2202. //
  2203. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  2204. pMacEntry = AtmLaneSearchForMacAddress(
  2205. pElan,
  2206. MacAddrType,
  2207. pMacAddress,
  2208. FALSE
  2209. );
  2210. if (pMacEntry == NULL_PATMLANE_MAC_ENTRY)
  2211. {
  2212. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2213. DBGP((0, "ArpResponseHandler: non-existing MAC %s\n",
  2214. MacAddrToString(pMacAddress)));
  2215. break;
  2216. }
  2217. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2218. AtmLaneReferenceMacEntry(pMacEntry, "tmpArpResp");
  2219. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2220. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2221. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2222. rc = AtmLaneDereferenceMacEntry(pMacEntry, "tmpArpResp");
  2223. if (rc == 0)
  2224. {
  2225. //
  2226. // the MAC entry has been deref'ed away.
  2227. //
  2228. break;
  2229. }
  2230. //
  2231. // Verify that Tid matches
  2232. //
  2233. if (pMacEntry->ArpTid != pCf->Tid)
  2234. {
  2235. DBGP((0, "ArpResponseHandler: invalid Tid for MAC %s\n",
  2236. MacAddrToString(pMacAddress)));
  2237. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2238. break;
  2239. }
  2240. DBGP((1, "%d Resolved %s to %s\n",
  2241. pElan->ElanNumber,
  2242. MacAddrToString(pMacAddress),
  2243. AtmAddrToString(pAtmAddress)));
  2244. //
  2245. // Get an existing or create new ATM Entry
  2246. //
  2247. pAtmEntry = AtmLaneSearchForAtmAddress(
  2248. pElan,
  2249. pAtmAddress,
  2250. (((pMacEntry->Flags & MAC_ENTRY_BROADCAST) != 0)
  2251. ? ATM_ENTRY_TYPE_BUS
  2252. : ATM_ENTRY_TYPE_PEER),
  2253. TRUE
  2254. );
  2255. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2256. {
  2257. //
  2258. // resource problem - ARP timeout will clean up MAC Entry
  2259. //
  2260. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2261. break;
  2262. }
  2263. //
  2264. // Got both entries.
  2265. //
  2266. // If the MAC Entry is linked to a different
  2267. // ATM Entry, unlink it from the old entry.
  2268. //
  2269. if ((pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY) &&
  2270. (pMacEntry->pAtmEntry != pAtmEntry))
  2271. {
  2272. DBGP((0,
  2273. "LearnMacToAtm: MacEntry %x moving from ATM Entry %x to ATM Entry %x\n",
  2274. pMacEntry, pMacEntry->pAtmEntry, pAtmEntry));
  2275. SET_FLAG(
  2276. pMacEntry->Flags,
  2277. MAC_ENTRY_STATE_MASK,
  2278. MAC_ENTRY_NEW);
  2279. bFound = AtmLaneUnlinkMacEntryFromAtmEntry(pMacEntry);
  2280. pMacEntry->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2281. if (bFound)
  2282. {
  2283. rc = AtmLaneDereferenceMacEntry(pMacEntry, "atm");
  2284. if (rc == 0)
  2285. {
  2286. //
  2287. // The MAC entry is gone. Let the next outgoing packet
  2288. // cause a new entry to be created.
  2289. //
  2290. break;
  2291. }
  2292. }
  2293. }
  2294. if (IS_FLAG_SET(
  2295. pMacEntry->Flags,
  2296. MAC_ENTRY_STATE_MASK,
  2297. MAC_ENTRY_ARPING))
  2298. {
  2299. //
  2300. // MAC Entry is in ARPING state
  2301. //
  2302. ASSERT(pMacEntry->pAtmEntry == NULL_PATMLANE_ATM_ENTRY);
  2303. //
  2304. // Link MAC Entry and ATM Entry together
  2305. //
  2306. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2307. #if DBG1
  2308. {
  2309. PATMLANE_MAC_ENTRY pTmpMacEntry;
  2310. ULONG Count = 0;
  2311. for (pTmpMacEntry = pAtmEntry->pMacEntryList;
  2312. pTmpMacEntry != NULL;
  2313. pTmpMacEntry = pTmpMacEntry->pNextToAtm)
  2314. {
  2315. if (pTmpMacEntry == pMacEntry)
  2316. {
  2317. DBGP((0, "LearnMacToAtm: pMacEntry %x already in list for pAtmEntry %x\n",
  2318. pTmpMacEntry, pAtmEntry));
  2319. DbgBreakPoint();
  2320. }
  2321. Count++;
  2322. if (Count > 5000)
  2323. {
  2324. DBGP((0, "Loop in list on pAtmEntry %x\n", pAtmEntry));
  2325. DbgBreakPoint();
  2326. break;
  2327. }
  2328. }
  2329. }
  2330. #endif // DBG
  2331. pMacEntry->pAtmEntry = pAtmEntry;
  2332. AtmLaneReferenceAtmEntry(pAtmEntry, "mac");
  2333. pMacEntry->pNextToAtm = pAtmEntry->pMacEntryList;
  2334. pAtmEntry->pMacEntryList = pMacEntry;
  2335. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2336. AtmLaneReferenceMacEntry(pMacEntry, "atm");
  2337. DBGP((1, "%d Linked1 MAC %x to ATM %x\n",
  2338. pAtmEntry->pElan->ElanNumber,
  2339. pMacEntry,
  2340. pAtmEntry));
  2341. //
  2342. // Cancel ARP timer
  2343. //
  2344. WasRunning = AtmLaneStopTimer(&(pMacEntry->Timer), pElan);
  2345. if (WasRunning)
  2346. {
  2347. rc = AtmLaneDereferenceMacEntry(pMacEntry, "timer");
  2348. ASSERT(rc > 0);
  2349. }
  2350. //
  2351. // Transition to RESOLVED state
  2352. //
  2353. SET_FLAG(
  2354. pMacEntry->Flags,
  2355. MAC_ENTRY_STATE_MASK,
  2356. MAC_ENTRY_RESOLVED);
  2357. //
  2358. // Handle special case for broadcast address.
  2359. //
  2360. if ((pMacEntry->Flags & MAC_ENTRY_BROADCAST) != 0)
  2361. {
  2362. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2363. //
  2364. // Cache the AtmEntry in the Elan
  2365. //
  2366. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  2367. pElan->pBusAtmEntry = pAtmEntry;
  2368. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2369. //
  2370. // Copy the Atm Address into the AtmEntry
  2371. //
  2372. pAtmEntry->AtmAddress.AddressType = ATM_NSAP;
  2373. pAtmEntry->AtmAddress.NumberOfDigits = ATM_ADDRESS_LENGTH;
  2374. NdisMoveMemory(
  2375. pAtmEntry->AtmAddress.Address,
  2376. pAtmAddress,
  2377. ATM_ADDRESS_LENGTH
  2378. );
  2379. //
  2380. // Signal the event to the state machine
  2381. //
  2382. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_ARP_RESPONSE, NDIS_STATUS_SUCCESS);
  2383. //
  2384. // Event handler will initiate the call to the bus
  2385. //
  2386. break; // done
  2387. }
  2388. //
  2389. // Not broadcast address.
  2390. //
  2391. // Start the Aging timer.
  2392. // Use Elan AgingTime if TopologyChange is inactive.
  2393. // Use Elan ForwardDelayTime if TopologyChange is active.
  2394. //
  2395. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2396. AtmLaneStartTimer(
  2397. pElan,
  2398. &pMacEntry->Timer,
  2399. AtmLaneMacEntryAgingTimeout,
  2400. pElan->TopologyChange?pElan->ForwardDelayTime:pElan->AgingTime,
  2401. (PVOID)pMacEntry
  2402. );
  2403. //
  2404. // If ATM Entry not connected and a call not in progress
  2405. // then start a call
  2406. //
  2407. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2408. if (!IS_FLAG_SET(
  2409. pAtmEntry->Flags,
  2410. ATM_ENTRY_STATE_MASK,
  2411. ATM_ENTRY_CONNECTED))
  2412. {
  2413. if ((pAtmEntry->Flags & ATM_ENTRY_CALLINPROGRESS) == 0)
  2414. {
  2415. //
  2416. // Mark ATM entry with call in progress
  2417. //
  2418. pAtmEntry->Flags |= ATM_ENTRY_CALLINPROGRESS;
  2419. //
  2420. // Release the MAC lock and reacquire ATM lock
  2421. //
  2422. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2423. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2424. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2425. AtmLaneMakeCall(pElan, pAtmEntry, FALSE);
  2426. //
  2427. // ATM Entry released in above
  2428. //
  2429. }
  2430. else
  2431. {
  2432. //
  2433. // Call already in progress
  2434. //
  2435. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2436. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2437. }
  2438. break; // done
  2439. }
  2440. //
  2441. // ATM Entry is connected
  2442. //
  2443. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2444. //
  2445. // Transition to FLUSHING state
  2446. //
  2447. SET_FLAG(
  2448. pMacEntry->Flags,
  2449. MAC_ENTRY_STATE_MASK,
  2450. MAC_ENTRY_FLUSHING);
  2451. //
  2452. // Start flushing
  2453. //
  2454. pMacEntry->RetriesLeft = 0;
  2455. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2456. AtmLaneStartTimer(
  2457. pElan,
  2458. &pMacEntry->FlushTimer,
  2459. AtmLaneFlushTimeout,
  2460. pElan->FlushTimeout,
  2461. (PVOID)pMacEntry
  2462. );
  2463. AtmLaneSendFlushRequest(pElan, pMacEntry, pAtmEntry);
  2464. //
  2465. // MAC Entry released in above
  2466. //
  2467. break; // done
  2468. }
  2469. if (IS_FLAG_SET(
  2470. pMacEntry->Flags,
  2471. MAC_ENTRY_STATE_MASK,
  2472. MAC_ENTRY_AGED))
  2473. {
  2474. //
  2475. // MAC Entry is being revalidated
  2476. //
  2477. //
  2478. // Cancel ARP timer
  2479. //
  2480. WasRunning = AtmLaneStopTimer(&(pMacEntry->Timer), pElan);
  2481. if (WasRunning)
  2482. {
  2483. rc = AtmLaneDereferenceMacEntry(pMacEntry, "timer");
  2484. ASSERT(rc > 0);
  2485. }
  2486. //
  2487. // Start the Aging timer up again
  2488. //
  2489. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2490. AtmLaneStartTimer(
  2491. pElan,
  2492. &pMacEntry->Timer,
  2493. AtmLaneMacEntryAgingTimeout,
  2494. pElan->TopologyChange?pElan->ForwardDelayTime:pElan->AgingTime,
  2495. (PVOID)pMacEntry
  2496. );
  2497. //
  2498. // Check if MAC Entry is switching to new ATM Entry
  2499. if (pMacEntry->pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2500. {
  2501. //
  2502. // Link MAC Entry and new ATM Entry together
  2503. //
  2504. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2505. #if DBG1
  2506. {
  2507. PATMLANE_MAC_ENTRY pTmpMacEntry;
  2508. ULONG Count = 0;
  2509. for (pTmpMacEntry = pAtmEntry->pMacEntryList;
  2510. pTmpMacEntry != NULL;
  2511. pTmpMacEntry = pTmpMacEntry->pNextToAtm)
  2512. {
  2513. if (pTmpMacEntry == pMacEntry)
  2514. {
  2515. DBGP((0, "RespHandler: pMacEntry %x already in list for pAtmEntry %x\n",
  2516. pTmpMacEntry, pAtmEntry));
  2517. DbgBreakPoint();
  2518. }
  2519. Count++;
  2520. if (Count > 5000)
  2521. {
  2522. DBGP((0, "RespHandler: Loop in list on pAtmEntry %x\n", pAtmEntry));
  2523. DbgBreakPoint();
  2524. break;
  2525. }
  2526. }
  2527. }
  2528. #endif // DBG
  2529. pMacEntry->pAtmEntry = pAtmEntry;
  2530. AtmLaneReferenceAtmEntry(pAtmEntry, "mac");
  2531. pMacEntry->pNextToAtm = pAtmEntry->pMacEntryList;
  2532. pAtmEntry->pMacEntryList = pMacEntry;
  2533. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2534. AtmLaneReferenceMacEntry(pMacEntry, "atm");
  2535. DBGP((1, "%d Linked2 MAC %x to ATM %x\n",
  2536. pAtmEntry->pElan->ElanNumber,
  2537. pMacEntry,
  2538. pAtmEntry));
  2539. //
  2540. // Transition back to resolved state
  2541. //
  2542. SET_FLAG(
  2543. pMacEntry->Flags,
  2544. MAC_ENTRY_STATE_MASK,
  2545. MAC_ENTRY_RESOLVED);
  2546. }
  2547. //
  2548. // If ATM Entry not connected and a call not in progress
  2549. // then start a call
  2550. //
  2551. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2552. if (!IS_FLAG_SET(
  2553. pAtmEntry->Flags,
  2554. ATM_ENTRY_STATE_MASK,
  2555. ATM_ENTRY_CONNECTED))
  2556. {
  2557. if ((pAtmEntry->Flags & ATM_ENTRY_CALLINPROGRESS) == 0)
  2558. {
  2559. //
  2560. // Mark ATM entry with call in progress
  2561. //
  2562. pAtmEntry->Flags |= ATM_ENTRY_CALLINPROGRESS;
  2563. //
  2564. // Release the MAC lock and reacquire ATM lock
  2565. //
  2566. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2567. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2568. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2569. AtmLaneMakeCall(pElan, pAtmEntry, FALSE);
  2570. //
  2571. // ATM Entry released in above
  2572. //
  2573. }
  2574. else
  2575. {
  2576. //
  2577. // Call already in progress
  2578. //
  2579. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2580. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2581. }
  2582. break; // done
  2583. }
  2584. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2585. //
  2586. // MAC Entry is now either still AGED or
  2587. // transitioned to RESOLVED state.
  2588. //
  2589. ASSERT((pMacEntry->Flags & (MAC_ENTRY_AGED | MAC_ENTRY_RESOLVED)) != 0);
  2590. if (IS_FLAG_SET(
  2591. pMacEntry->Flags,
  2592. MAC_ENTRY_STATE_MASK,
  2593. MAC_ENTRY_RESOLVED))
  2594. {
  2595. //
  2596. // MAC entry must have moved to new, connected ATM Entry
  2597. // Do the flush
  2598. //
  2599. SET_FLAG(
  2600. pMacEntry->Flags,
  2601. MAC_ENTRY_STATE_MASK,
  2602. MAC_ENTRY_FLUSHING);
  2603. pMacEntry->RetriesLeft = 0;
  2604. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2605. AtmLaneStartTimer(
  2606. pElan,
  2607. &pMacEntry->FlushTimer,
  2608. AtmLaneFlushTimeout,
  2609. pElan->FlushTimeout,
  2610. (PVOID)pMacEntry
  2611. );
  2612. AtmLaneSendFlushRequest(pElan, pMacEntry, pAtmEntry);
  2613. //
  2614. // MAC Entry released in above
  2615. //
  2616. break; // done
  2617. }
  2618. //
  2619. // MAC Entry can just transition back to ACTIVE
  2620. //
  2621. SET_FLAG(
  2622. pMacEntry->Flags,
  2623. MAC_ENTRY_STATE_MASK,
  2624. MAC_ENTRY_ACTIVE);
  2625. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2626. break;
  2627. }
  2628. //
  2629. // Shouldn't get here
  2630. //
  2631. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2632. DBGP((0, "LearnMacToAtm: MacEntry in wrong state!\n"));
  2633. break;
  2634. }
  2635. while (FALSE);
  2636. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  2637. {
  2638. //
  2639. // Remove the temp ref added by SearchFor...
  2640. //
  2641. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2642. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "search");
  2643. if (rc != 0)
  2644. {
  2645. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2646. }
  2647. }
  2648. TRACEOUT(ArpResponseHandler);
  2649. return;
  2650. }
  2651. VOID
  2652. AtmLaneFlushResponseHandler(
  2653. IN PATMLANE_ELAN pElan,
  2654. IN PLANE_CONTROL_FRAME pCf
  2655. )
  2656. /*++
  2657. Routine Description:
  2658. Handles incoming Flush Response packets from peers.
  2659. Arguments:
  2660. pCf - Pointer to LANE Control Frame
  2661. Return Value:
  2662. None
  2663. --*/
  2664. {
  2665. PATMLANE_ATM_ENTRY pAtmEntry;
  2666. PATMLANE_MAC_ENTRY pMacEntry;
  2667. PNDIS_PACKET pNdisPacket;
  2668. PNDIS_PACKET pNextPacket;
  2669. PATMLANE_VC pVc;
  2670. BOOLEAN WasRunning;
  2671. ULONG rc;
  2672. TRACEIN(FlushResponseHandler);
  2673. pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2674. do
  2675. {
  2676. //
  2677. // Check that we originated the request
  2678. //
  2679. if (!ATM_ADDR_EQUAL(pCf->SourceAtmAddr, &pElan->AtmAddress.Address))
  2680. {
  2681. DBGP((0, "FlushResponseHandler: Response not addressed to us!\n"));
  2682. break;
  2683. }
  2684. //
  2685. // Find the Atm Entry for the target address
  2686. //
  2687. pAtmEntry = AtmLaneSearchForAtmAddress(
  2688. pElan,
  2689. pCf->TargetAtmAddr,
  2690. ATM_ENTRY_TYPE_PEER,
  2691. FALSE); // don't create a new one
  2692. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2693. {
  2694. DBGP((0, "FlushResponseHandler: No matching ATM entry\n"));
  2695. break;
  2696. }
  2697. //
  2698. // Grab and Reference the VC for this ATM Entry
  2699. //
  2700. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2701. pVc = pAtmEntry->pVcList;
  2702. if (pVc == NULL_PATMLANE_VC)
  2703. {
  2704. DBGP((0, "FlushResponseHandler: No VC on ATM Entry\n"));
  2705. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2706. break;
  2707. }
  2708. ACQUIRE_VC_LOCK_DPC(pVc);
  2709. AtmLaneReferenceVc(pVc, "temp");
  2710. RELEASE_VC_LOCK_DPC(pVc);
  2711. //
  2712. // Find the Mac Entry on this Atm Entry that matches the Tid
  2713. //
  2714. pMacEntry = pAtmEntry->pMacEntryList;
  2715. while(pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2716. {
  2717. if (pMacEntry->FlushTid == pCf->Tid)
  2718. break;
  2719. pMacEntry = pMacEntry->pNextToAtm;
  2720. }
  2721. if (pMacEntry == NULL_PATMLANE_MAC_ENTRY)
  2722. {
  2723. //
  2724. // No MAC Entry still exists that originated this flush
  2725. //
  2726. DBGP((0, "FlushResponseHandler: No MAC entry with matching TID\n"));
  2727. ACQUIRE_VC_LOCK(pVc);
  2728. rc = AtmLaneDereferenceVc(pVc, "temp");
  2729. if (rc > 0)
  2730. {
  2731. RELEASE_VC_LOCK(pVc);
  2732. }
  2733. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2734. break;
  2735. }
  2736. else
  2737. {
  2738. //
  2739. // Found it
  2740. //
  2741. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2742. }
  2743. //
  2744. // Mark MAC Entry ACTIVE
  2745. //
  2746. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2747. AtmLaneReferenceMacEntry(pMacEntry, "temp");
  2748. SET_FLAG(
  2749. pMacEntry->Flags,
  2750. MAC_ENTRY_STATE_MASK,
  2751. MAC_ENTRY_ACTIVE);
  2752. //
  2753. // Cancel the flush timer
  2754. //
  2755. WasRunning = AtmLaneStopTimer(&pMacEntry->FlushTimer, pElan);
  2756. if (WasRunning)
  2757. {
  2758. rc = AtmLaneDereferenceMacEntry(pMacEntry, "flush timer");
  2759. ASSERT(rc > 0);
  2760. }
  2761. //
  2762. // Send any queued packets
  2763. //
  2764. while ((pNdisPacket = AtmLaneDequeuePacketFromHead(pMacEntry)) !=
  2765. (PNDIS_PACKET)NULL)
  2766. {
  2767. //
  2768. // Send it
  2769. //
  2770. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2771. ACQUIRE_VC_LOCK(pVc);
  2772. if (IS_FLAG_SET(
  2773. pVc->Flags,
  2774. VC_CALL_STATE_MASK,
  2775. VC_CALL_STATE_ACTIVE))
  2776. {
  2777. AtmLaneSendPacketOnVc(pVc, pNdisPacket, TRUE);
  2778. }
  2779. else
  2780. {
  2781. //
  2782. // The VC is being torn down.
  2783. //
  2784. RELEASE_VC_LOCK(pVc);
  2785. //
  2786. // Queue this packet back, and abort.
  2787. //
  2788. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2789. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  2790. break;
  2791. }
  2792. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2793. }
  2794. //
  2795. // Dereference the MAC Entry
  2796. //
  2797. rc = AtmLaneDereferenceMacEntry(pMacEntry, "temp");
  2798. if (rc > 0)
  2799. {
  2800. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2801. }
  2802. //
  2803. // Dereference the VC
  2804. //
  2805. ACQUIRE_VC_LOCK(pVc);
  2806. rc = AtmLaneDereferenceVc(pVc, "temp");
  2807. if (rc > 0)
  2808. {
  2809. RELEASE_VC_LOCK(pVc);
  2810. }
  2811. break;
  2812. }
  2813. while (FALSE);
  2814. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  2815. {
  2816. //
  2817. // Remove the temp ref added by SearchFor...
  2818. //
  2819. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2820. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "search");
  2821. if (rc != 0)
  2822. {
  2823. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2824. }
  2825. }
  2826. TRACEOUT(FlushResponseHandler);
  2827. return;
  2828. }
  2829. VOID
  2830. AtmLaneReadyIndicationHandler(
  2831. IN PATMLANE_ELAN pElan,
  2832. IN PATMLANE_VC pVc,
  2833. IN PNDIS_PACKET pIndNdisPacket
  2834. )
  2835. /*++
  2836. Routine Description:
  2837. Handles incoming READY_INDICATION packets from peers.
  2838. Arguments:
  2839. pElan - Pointer to ATMLANE Elan structure
  2840. pVc - Pointer to ATMLANE VC for this packet
  2841. pIndNdisPacket - Pointer to the Ndis Packet
  2842. Return Value:
  2843. None
  2844. --*/
  2845. {
  2846. BOOLEAN WasRunning;
  2847. ULONG rc;
  2848. TRACEIN(ReadyIndicationHandler);
  2849. ACQUIRE_VC_LOCK(pVc);
  2850. //
  2851. // Cancel the ready timer on VC
  2852. //
  2853. WasRunning = AtmLaneStopTimer(&pVc->ReadyTimer, pElan);
  2854. if (WasRunning)
  2855. {
  2856. rc = AtmLaneDereferenceVc(pVc, "ready timer");
  2857. }
  2858. else
  2859. {
  2860. rc = pVc->RefCount;
  2861. }
  2862. //
  2863. // If VC still around update state
  2864. //
  2865. if (rc > 0)
  2866. {
  2867. DBGP((2, "ReadyIndicationHandler: pVc %x State to INDICATED\n", pVc));
  2868. SET_FLAG(
  2869. pVc->Flags,
  2870. VC_READY_STATE_MASK,
  2871. VC_READY_INDICATED
  2872. );
  2873. RELEASE_VC_LOCK(pVc);
  2874. }
  2875. //
  2876. // else VC is gone
  2877. //
  2878. TRACEOUT(ReadyIndicationHandler);
  2879. return;
  2880. }
  2881. VOID
  2882. AtmLaneTopologyRequestHandler(
  2883. IN PATMLANE_ELAN pElan,
  2884. IN PLANE_CONTROL_FRAME pCf
  2885. )
  2886. /*++
  2887. Routine Description:
  2888. Handles incoming Topology Request packets from the LES.
  2889. Arguments:
  2890. pRequestCf - Pointer to ARP Request Frame
  2891. Return Value:
  2892. None
  2893. --*/
  2894. {
  2895. ULONG i;
  2896. PATMLANE_MAC_ENTRY pMacEntry;
  2897. TRACEIN(TopologyRequestHandler);
  2898. if ((pCf->Flags & LANE_CONTROL_FLAGS_TOPOLOGY_CHANGE) == 0)
  2899. {
  2900. //
  2901. // Topology change state OFF
  2902. //
  2903. DBGP((1, "%d TOPOLOGY CHANGE OFF\n", pElan->ElanNumber));
  2904. pElan->TopologyChange = 0;
  2905. }
  2906. else
  2907. {
  2908. //
  2909. // Topology change state ON
  2910. //
  2911. DBGP((1, "%d TOPOLOGY CHANGE ON\n", pElan->ElanNumber));
  2912. pElan->TopologyChange = 1;
  2913. //
  2914. // Abort all MAC table entries.
  2915. //
  2916. for (i = 0; i < ATMLANE_MAC_TABLE_SIZE; i++)
  2917. {
  2918. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  2919. while (pElan->pMacTable[i] != NULL_PATMLANE_MAC_ENTRY)
  2920. {
  2921. pMacEntry = pElan->pMacTable[i];
  2922. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2923. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2924. AtmLaneAbortMacEntry(pMacEntry);
  2925. //
  2926. // MAC Entry Lock is released within the above.
  2927. //
  2928. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  2929. }
  2930. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2931. }
  2932. }
  2933. TRACEOUT(TopologyRequestHandler);
  2934. return;
  2935. }
  2936. BOOLEAN
  2937. AtmLaneDataPacketHandler(
  2938. IN PATMLANE_ELAN pElan,
  2939. IN PATMLANE_VC pVc,
  2940. IN PNDIS_PACKET pNdisPacket
  2941. )
  2942. /*++
  2943. Routine Description:
  2944. Handles incoming packets from the data VCs from peers and
  2945. unknown and multicast packets from the BUS.
  2946. Arguments:
  2947. pElan - Pointer to ATMLANE Elan structure
  2948. pVc - Pointer to ATMLANE Vc structure
  2949. pNdisPacket - Pointer to the Ndis Packet
  2950. Return Value:
  2951. TRUE - if packet will be retained (i.e. sent
  2952. up to protocols)
  2953. FALSE - if packet was a flush request packet and
  2954. can be reliquished back to adapter
  2955. immediately.
  2956. --*/
  2957. {
  2958. ULONG TotalLength;
  2959. ULONG TempLength;
  2960. PUCHAR pBuffer;
  2961. BOOLEAN RetainIt;
  2962. PLANE_CONTROL_FRAME pCf;
  2963. PNDIS_PACKET pNewNdisPacket;
  2964. PNDIS_BUFFER pFirstNdisBuffer;
  2965. PNDIS_BUFFER pTempNdisBuffer;
  2966. PNDIS_BUFFER pNewNdisBuffer;
  2967. PUCHAR pTempBuffer;
  2968. NDIS_STATUS Status;
  2969. ULONG MacHdrSize;
  2970. ULONG DestAddrType;
  2971. MAC_ADDRESS DestAddr;
  2972. BOOLEAN DestIsMulticast;
  2973. NDIS_HANDLE MiniportAdapterHandle;
  2974. TRACEIN(DataPacketHandler);
  2975. // Initialize
  2976. RetainIt = FALSE; // default is not to keep packet
  2977. pNewNdisPacket = NULL;
  2978. do
  2979. {
  2980. //
  2981. // Get initial buffer and total length of packet
  2982. //
  2983. NdisGetFirstBufferFromPacket(
  2984. pNdisPacket,
  2985. &pFirstNdisBuffer,
  2986. &pBuffer,
  2987. &TempLength,
  2988. &TotalLength);
  2989. DBGP((3, "DataPacketHandler: Pkt %x Length %d\n",
  2990. pNdisPacket, TotalLength));
  2991. //DbgPrintNdisPacket(pNdisPacket);
  2992. //
  2993. // Filter out flush request and ready query frames
  2994. //
  2995. if (TempLength < 6)
  2996. {
  2997. DBGP((0, "DataPacketHandler: pVc %x First fragment"
  2998. " < 6, discarding\n", pVc));
  2999. break;
  3000. }
  3001. pCf = (PLANE_CONTROL_FRAME)pBuffer;
  3002. if (pCf->Marker == LANE_CONTROL_MARKER &&
  3003. pCf->Protocol == LANE_PROTOCOL &&
  3004. pCf->Version == LANE_VERSION)
  3005. {
  3006. switch (pCf->OpCode)
  3007. {
  3008. case LANE_FLUSH_REQUEST:
  3009. DBGP((2, "DataPacketHandler: pVc %x FLUSH REQUEST\n", pVc));
  3010. AtmLaneFlushRequestHandler(pElan, pNdisPacket);
  3011. break;
  3012. case LANE_READY_QUERY:
  3013. DBGP((2, "DataPacketHandler: pVc %x READY QUERY\n", pVc));
  3014. AtmLaneReadyQueryHandler(pElan, pVc, pNdisPacket);
  3015. break;
  3016. case LANE_READY_IND:
  3017. DBGP((2, "DataPacketHandler: pVc %x READY INDICATION\n", pVc));
  3018. AtmLaneReadyIndicationHandler(pElan, pVc, pNdisPacket);
  3019. break;
  3020. default:
  3021. DBGP((2,
  3022. "DataPacketHandler: pVc %x Unexpected control"
  3023. " packet, opcode %x\n",
  3024. pVc, pCf->OpCode));
  3025. break;
  3026. }
  3027. break;
  3028. }
  3029. //
  3030. // If miniport is not operational - discard
  3031. //
  3032. if ((pElan->Flags & ELAN_MINIPORT_OPERATIONAL) == 0)
  3033. {
  3034. DBGP((2, "%d Dropping pkt %x, cuz Elan %x Flags are %x\n",
  3035. pElan->ElanNumber, pNdisPacket, pElan, pElan->Flags));
  3036. break;
  3037. }
  3038. //
  3039. // If no filters are set, discard.
  3040. //
  3041. if (pElan->CurPacketFilter == 0)
  3042. {
  3043. DBGP((2, "%d Dropping pkt %x, cuz Elan %x Filter is zero\n",
  3044. pElan->ElanNumber, pNdisPacket, pElan));
  3045. break;
  3046. }
  3047. MiniportAdapterHandle = pElan->MiniportAdapterHandle;
  3048. if (NULL == MiniportAdapterHandle)
  3049. {
  3050. DBGP((0, "%d Dropping pkt %x cuz ELAN %x has Null handle!\n",
  3051. pElan->ElanNumber, pNdisPacket, pElan));
  3052. break;
  3053. }
  3054. //
  3055. // Mark VC with fact that it has had data packet receive activity
  3056. //
  3057. // To avoid slowing down the receive path, MP issues with
  3058. // setting this flag are ignored. This flag is a VC aging
  3059. // optimization and not critical.
  3060. //
  3061. pVc->ReceiveActivity = 1;
  3062. //
  3063. // Repackage it and learn some stuff about it.
  3064. //
  3065. pNewNdisPacket = AtmLaneWrapRecvPacket(
  3066. pElan,
  3067. pNdisPacket,
  3068. &MacHdrSize,
  3069. &DestAddrType,
  3070. &DestAddr,
  3071. &DestIsMulticast);
  3072. //
  3073. // If wrap failed just discard packet
  3074. //
  3075. if (pNewNdisPacket == (PNDIS_PACKET)NULL)
  3076. {
  3077. DBGP((2, "%d Dropping pkt %x, len %d, VC %x, wrap failed\n",
  3078. pElan->ElanNumber, pNdisPacket, TotalLength, pVc));
  3079. break;
  3080. }
  3081. //
  3082. // Branch on Ethernet v.s. Token Ring
  3083. //
  3084. if (pElan->LanType == LANE_LANTYPE_ETH)
  3085. {
  3086. //
  3087. // Filter out BUS reflections that we originated.
  3088. //
  3089. if (pCf->Marker == pElan->LecId)
  3090. {
  3091. DBGP((2, "%d Dropping pkt %x, len %d, VC %x, BUS reflection\n",
  3092. pElan->ElanNumber, pNdisPacket, TotalLength, pVc));
  3093. break;
  3094. }
  3095. //
  3096. // Filter out Unicasts not addressed to us
  3097. //
  3098. if ((!DestIsMulticast) &&
  3099. (!MAC_ADDR_EQUAL(&DestAddr, &pElan->MacAddressEth)))
  3100. {
  3101. DBGP((2, "%d Dropping pkt %x, len %d, VC %x, unicast not for us\n",
  3102. pElan->ElanNumber, pNdisPacket, TotalLength, pVc));
  3103. break;
  3104. }
  3105. }
  3106. else
  3107. {
  3108. ASSERT(pElan->LanType == LANE_LANTYPE_TR);
  3109. //
  3110. // Filter out Non-Multicast BUS reflections that we originated
  3111. //
  3112. if ((pCf->Marker == pElan->LecId) && (!DestIsMulticast))
  3113. {
  3114. DBGP((2, "%d Dropping pkt %x, len %d, VC %x, TR Bus refln\n",
  3115. pElan->ElanNumber, pNdisPacket, TotalLength, pVc));
  3116. break;
  3117. }
  3118. //
  3119. // Filter out Unicasts not addressed to us
  3120. //
  3121. if ((!DestIsMulticast) &&
  3122. (!MAC_ADDR_EQUAL(&DestAddr, &pElan->MacAddressTr)))
  3123. {
  3124. DBGP((2, "%d Dropping pkt %x, len %d, VC %x, TR unicast not for us\n",
  3125. pElan->ElanNumber, pNdisPacket, TotalLength, pVc));
  3126. break;
  3127. }
  3128. }
  3129. //
  3130. // Filter out multicast/broadcast if we don't have these enabled.
  3131. //
  3132. if (DestIsMulticast)
  3133. {
  3134. if ((pElan->CurPacketFilter &
  3135. (NDIS_PACKET_TYPE_MULTICAST|
  3136. NDIS_PACKET_TYPE_BROADCAST|
  3137. NDIS_PACKET_TYPE_ALL_MULTICAST)) == 0)
  3138. {
  3139. DBGP((2, "%d Dropping multicast pkt %x, cuz CurPacketFilter is %x\n",
  3140. pElan->ElanNumber, pNdisPacket, pElan->CurPacketFilter));
  3141. break;
  3142. }
  3143. if (((pElan->CurPacketFilter & NDIS_PACKET_TYPE_BROADCAST) == 0) &&
  3144. MAC_ADDR_EQUAL(&DestAddr, &gMacBroadcastAddress))
  3145. {
  3146. DBGP((2, "%d Dropping broadcast pkt %x, cuz CurPacketFilter is %x\n",
  3147. pElan->ElanNumber, pNdisPacket, pElan->CurPacketFilter));
  3148. break;
  3149. }
  3150. }
  3151. //
  3152. // Count it
  3153. //
  3154. NdisInterlockedIncrement(&pElan->FramesRecvGood);
  3155. //
  3156. // Indicate it up to protocols and other interested parties
  3157. //
  3158. NDIS_SET_PACKET_HEADER_SIZE(pNewNdisPacket, MacHdrSize);
  3159. TRACELOGWRITE((&TraceLog,
  3160. TL_MINDPACKET,
  3161. pNewNdisPacket));
  3162. //
  3163. // Set the packet status according to what we received from the miniport.
  3164. //
  3165. Status = NDIS_GET_PACKET_STATUS(pNdisPacket);
  3166. NDIS_SET_PACKET_STATUS(pNewNdisPacket, Status);
  3167. NdisMIndicateReceivePacket(
  3168. MiniportAdapterHandle,
  3169. &pNewNdisPacket,
  3170. 1
  3171. );
  3172. if (Status != NDIS_STATUS_RESOURCES)
  3173. {
  3174. RetainIt = TRUE;
  3175. DBGP((2, "DataPacketHandler: Packet Retained!\n"));
  3176. }
  3177. //
  3178. // else our ReturnPackets handler is guaranteed to be called.
  3179. //
  3180. }
  3181. while (FALSE);
  3182. //
  3183. // Unwrap the packet if it was wrapped and we don't have to keep it.
  3184. //
  3185. if (pNewNdisPacket && !RetainIt)
  3186. {
  3187. (VOID)AtmLaneUnwrapRecvPacket(pElan, pNewNdisPacket);
  3188. }
  3189. TRACEOUT(DataPacketHandler);
  3190. return (RetainIt);
  3191. }
  3192. VOID
  3193. AtmLaneSendPacketOnVc(
  3194. IN PATMLANE_VC pVc LOCKIN NOLOCKOUT,
  3195. IN PNDIS_PACKET pNdisPacket,
  3196. IN BOOLEAN Refresh
  3197. )
  3198. /*++
  3199. Routine Description:
  3200. Send a packet on the specified VC.
  3201. Assumes caller has lock on VC structure.
  3202. Assumes caller has checked VC state for validity.
  3203. If requested, refresh the aging timer.
  3204. Sends the packet.
  3205. Returns the send status
  3206. Arguments:
  3207. pVc - Pointer to ATMLANE VC
  3208. pNdisPacket - Pointer to packet to be sent.
  3209. Refresh - If TRUE refresh the Aging Timer.
  3210. Return Value:
  3211. NDIS_STATUS value set on the packet by the miniport.
  3212. --*/
  3213. {
  3214. NDIS_HANDLE NdisVcHandle;
  3215. PATMLANE_ELAN pElan;
  3216. TRACEIN(SendPacketOnVc);
  3217. pElan = pVc->pElan;
  3218. STRUCT_ASSERT(pElan, atmlane_elan);
  3219. //
  3220. // If requested, refresh the aging timer
  3221. //
  3222. if (Refresh)
  3223. {
  3224. AtmLaneRefreshTimer(&pVc->AgingTimer);
  3225. }
  3226. #if SENDLIST
  3227. //
  3228. // Check list for duplicate send
  3229. //
  3230. NdisAcquireSpinLock(&pElan->SendListLock);
  3231. {
  3232. PNDIS_PACKET pDbgPkt;
  3233. pDbgPkt = pElan->pSendList;
  3234. while (pDbgPkt != (PNDIS_PACKET)NULL)
  3235. {
  3236. if (pNdisPacket == pDbgPkt)
  3237. {
  3238. DBGP((0, "SendPacketOnVc: Duplicate Send!\n"));
  3239. // DbgBreakPoint();
  3240. }
  3241. pDbgPkt = PSEND_RSVD(pDbgPkt)->pNextInSendList;
  3242. }
  3243. }
  3244. //
  3245. // Queue packet on list of outstanding sends
  3246. //
  3247. PSEND_RSVD(pNdisPacket)->pNextInSendList = pElan->pSendList;
  3248. pElan->pSendList = pNdisPacket;
  3249. NdisReleaseSpinLock(&pElan->SendListLock);
  3250. #endif // SENDLIST
  3251. //
  3252. // Reference the VC with the outstanding send
  3253. //
  3254. AtmLaneReferenceVc(pVc, "sendpkt");
  3255. //
  3256. // Note this outstanding send.
  3257. //
  3258. pVc->OutstandingSends++;
  3259. //
  3260. // Get the Ndis handle
  3261. //
  3262. NdisVcHandle = pVc->NdisVcHandle;
  3263. //
  3264. // Send it
  3265. //
  3266. DBGP((3, "SendPacketOnVc: pVc %x, Pkt %x, VcHandle %x\n",
  3267. pVc, pNdisPacket, NdisVcHandle));
  3268. TRACELOGWRITE((&TraceLog, TL_COSENDPACKET, pNdisPacket));
  3269. TRACELOGWRITEPKT((&TraceLog, pNdisPacket));
  3270. RELEASE_VC_LOCK(pVc);
  3271. NdisCoSendPackets(NdisVcHandle, &pNdisPacket, 1);
  3272. #if PROTECT_PACKETS
  3273. //
  3274. // Lock the packet
  3275. //
  3276. ACQUIRE_SENDPACKET_LOCK(pNdisPacket);
  3277. //
  3278. // Mark it with NdisCoSendPackets having returned
  3279. //
  3280. ASSERT((PSEND_RSVD(pNdisPacket)->Flags & PACKET_RESERVED_COSENDRETURNED) == 0);
  3281. PSEND_RSVD(pNdisPacket)->Flags |= PACKET_RESERVED_COSENDRETURNED;
  3282. //
  3283. // Complete the packet only if it is marked as having been completed
  3284. // by miniport.
  3285. //
  3286. if ((PSEND_RSVD(pNdisPacket)->Flags & PACKET_RESERVED_COMPLETED) != 0)
  3287. {
  3288. AtmLaneCompleteSendPacket(pElan, pNdisPacket,
  3289. PSEND_RSVD(pNdisPacket)->CompletionStatus);
  3290. //
  3291. // packet lock released in above
  3292. //
  3293. }
  3294. else
  3295. {
  3296. RELEASE_SENDPACKET_LOCK(pNdisPacket);
  3297. }
  3298. #endif // PROTECT_PACKETS
  3299. TRACEOUT(SendPacketOnVc);
  3300. return;
  3301. }
  3302. VOID
  3303. AtmLaneQueuePacketOnHead(
  3304. IN PATMLANE_MAC_ENTRY pMacEntry,
  3305. IN PNDIS_PACKET pNdisPacket
  3306. )
  3307. /*++
  3308. Routine Description:
  3309. Queue a packet at the head of the MAC Entry
  3310. packet queue for later transmit.
  3311. Assumes caller has lock on MAC Entry.
  3312. Arguments:
  3313. pMacEntry - Pointer to ATMLANE MAC Entry.
  3314. pNdisPacket - The packet to be queued.
  3315. Return Value:
  3316. None
  3317. --*/
  3318. {
  3319. PNDIS_PACKET pPrevPacket;
  3320. TRACEIN(QueuePacketOnHead);
  3321. SET_NEXT_PACKET(pNdisPacket, pMacEntry->PacketList);
  3322. pMacEntry->PacketList = pNdisPacket;
  3323. pMacEntry->PacketListCount++;
  3324. DBGP((2, "%d QueueHead Count %d on %s\n",
  3325. pMacEntry->pElan->ElanNumber,
  3326. pMacEntry->PacketListCount,
  3327. MacAddrToString(&pMacEntry->MacAddress)));
  3328. TRACEOUT(QueuePacketOnHead);
  3329. return;
  3330. }
  3331. VOID
  3332. AtmLaneQueuePacketOnTail(
  3333. IN PATMLANE_MAC_ENTRY pMacEntry,
  3334. IN PNDIS_PACKET pNdisPacket
  3335. )
  3336. /*++
  3337. Routine Description:
  3338. Queue a packet at the tail of the MAC Entry
  3339. packet queue for later transmit.
  3340. Assumes caller has lock on MAC Entry.
  3341. Arguments:
  3342. pMacEntry - Pointer to ATMLANE MAC Entry.
  3343. pNdisPacket - The packet to be queued.
  3344. Return Value:
  3345. None
  3346. --*/
  3347. {
  3348. PNDIS_PACKET pPrevPacket;
  3349. TRACEIN(QueuePacketOnTail);
  3350. if (pMacEntry->PacketList == (PNDIS_PACKET)NULL)
  3351. {
  3352. //
  3353. // Currently empty.
  3354. //
  3355. pMacEntry->PacketList = pNdisPacket;
  3356. }
  3357. else
  3358. {
  3359. //
  3360. // Go to the end of the packet list.
  3361. //
  3362. pPrevPacket = pMacEntry->PacketList;
  3363. while (GET_NEXT_PACKET(pPrevPacket) != (PNDIS_PACKET)NULL)
  3364. {
  3365. pPrevPacket = GET_NEXT_PACKET(pPrevPacket);
  3366. }
  3367. //
  3368. // Found the last packet in the list. Chain this packet
  3369. // to it.
  3370. //
  3371. SET_NEXT_PACKET(pPrevPacket, pNdisPacket);
  3372. }
  3373. //
  3374. // Set tail's next pointer to NULL.
  3375. //
  3376. SET_NEXT_PACKET(pNdisPacket, NULL);
  3377. pMacEntry->PacketListCount++;
  3378. DBGP((2, "%d QueueTail Count %d on %s\n",
  3379. pMacEntry->pElan->ElanNumber,
  3380. pMacEntry->PacketListCount,
  3381. MacAddrToString(&pMacEntry->MacAddress)));
  3382. TRACEOUT(QueuePacketOnTail);
  3383. return;
  3384. }
  3385. PNDIS_PACKET
  3386. AtmLaneDequeuePacketFromHead(
  3387. IN PATMLANE_MAC_ENTRY pMacEntry
  3388. )
  3389. /*++
  3390. Routine Description:
  3391. Dequeue a packet from the head of the MAC Entry packet queue.
  3392. Assumes caller has lock on MAC Entry.
  3393. Arguments:
  3394. pMacEntry - Pointer to ATMLANE MAC Entry.
  3395. Return Value:
  3396. First packet on the MAC Entry queue or NULL if queue is empty.
  3397. --*/
  3398. {
  3399. PNDIS_PACKET pNdisPacket;
  3400. TRACEIN(DequeuePacketFromHead);
  3401. do
  3402. {
  3403. //
  3404. // If queue is empty, setup to return NULL
  3405. //
  3406. if (pMacEntry->PacketList == (PNDIS_PACKET)NULL)
  3407. {
  3408. ASSERT(pMacEntry->PacketListCount == 0);
  3409. pNdisPacket = (PNDIS_PACKET)NULL;
  3410. break;
  3411. }
  3412. //
  3413. // Queue is not empty - remove head
  3414. //
  3415. ASSERT(pMacEntry->PacketListCount > 0);
  3416. pNdisPacket = pMacEntry->PacketList;
  3417. pMacEntry->PacketList = GET_NEXT_PACKET(pNdisPacket);
  3418. SET_NEXT_PACKET(pNdisPacket, NULL);
  3419. pMacEntry->PacketListCount--;
  3420. DBGP((2, "%d DequeueHead Count %d on %s\n",
  3421. pMacEntry->pElan->ElanNumber,
  3422. pMacEntry->PacketListCount,
  3423. MacAddrToString(&pMacEntry->MacAddress)));
  3424. break;
  3425. }
  3426. while (FALSE);
  3427. TRACEOUT(DequeuePacketFromHead);
  3428. return pNdisPacket;
  3429. }
  3430. NDIS_STATUS
  3431. AtmLaneSendUnicastPacket(
  3432. IN PATMLANE_ELAN pElan,
  3433. IN ULONG DestAddrType,
  3434. IN PMAC_ADDRESS pDestAddress,
  3435. IN PNDIS_PACKET pNdisPacket
  3436. )
  3437. /*++
  3438. Routine Description:
  3439. Send a unicast packet.
  3440. Arguments:
  3441. pElan - Pointer to ATMLANE elan structure
  3442. DestAddrType - Either LANE_MACADDRTYPE_MACADDR or
  3443. LANE_MACADDRTYPE_ROUTEDESCR.
  3444. pDestAddress - Pointer to Destination MAC Address
  3445. pNdisPacket - Pointer to packet to be sent.
  3446. Return Value:
  3447. NDIS_STATUS_PENDING - if packet queued or sent
  3448. NDIS_STATUS_FAILURE - if some error
  3449. --*/
  3450. {
  3451. PATMLANE_MAC_ENTRY pMacEntry;
  3452. PATMLANE_ATM_ENTRY pAtmEntry;
  3453. PATMLANE_VC pVc;
  3454. NDIS_STATUS Status;
  3455. ULONG rc;
  3456. TRACEIN(SendUnicastPacket);
  3457. //
  3458. // Initialize
  3459. //
  3460. pMacEntry = NULL_PATMLANE_MAC_ENTRY;
  3461. Status = NDIS_STATUS_PENDING;
  3462. do
  3463. {
  3464. //
  3465. // Find a MAC entry for this destination address
  3466. //
  3467. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  3468. pMacEntry = AtmLaneSearchForMacAddress(
  3469. pElan,
  3470. DestAddrType,
  3471. pDestAddress,
  3472. TRUE // Create new entry if not found
  3473. );
  3474. if (pMacEntry == NULL_PATMLANE_MAC_ENTRY)
  3475. {
  3476. Status = NDIS_STATUS_RESOURCES;
  3477. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3478. break;
  3479. }
  3480. //
  3481. // Add a temp ref so that this won't go away when we release
  3482. // the MAC table lock (#303602).
  3483. //
  3484. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3485. AtmLaneReferenceMacEntry(pMacEntry, "tempunicast");
  3486. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3487. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3488. //
  3489. // Lock the MAC Entry
  3490. //
  3491. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3492. //
  3493. // Check if it has been deref'ed away.
  3494. //
  3495. rc = AtmLaneDereferenceMacEntry(pMacEntry, "tempunicast");
  3496. if (rc == 0)
  3497. {
  3498. //
  3499. // The MAC entry is gone! Fail this send.
  3500. //
  3501. Status = NDIS_STATUS_FAILURE;
  3502. break;
  3503. }
  3504. //
  3505. // MAC Entry State - NEW
  3506. //
  3507. if (IS_FLAG_SET(
  3508. pMacEntry->Flags,
  3509. MAC_ENTRY_STATE_MASK,
  3510. MAC_ENTRY_NEW))
  3511. {
  3512. DBGP((2, "SendUnicastPacket: NEW Mac Entry %x for %s\n",
  3513. pMacEntry, MacAddrToString(pDestAddress)));
  3514. //
  3515. // Queue packet on MAC Entry
  3516. //
  3517. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  3518. //
  3519. // Transition to ARPING State
  3520. //
  3521. SET_FLAG(
  3522. pMacEntry->Flags,
  3523. MAC_ENTRY_STATE_MASK,
  3524. MAC_ENTRY_ARPING);
  3525. ASSERT(pMacEntry->pAtmEntry == NULL_PATMLANE_ATM_ENTRY);
  3526. //
  3527. // Start the BUS sends.
  3528. //
  3529. AtmLaneStartBusSends(pMacEntry);
  3530. //
  3531. // Lock released in above
  3532. //
  3533. //
  3534. // Reacquire the lock
  3535. //
  3536. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3537. //
  3538. // Start the ARP protocol
  3539. //
  3540. pMacEntry->RetriesLeft = pElan->MaxRetryCount;
  3541. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  3542. AtmLaneStartTimer(
  3543. pElan,
  3544. &pMacEntry->Timer,
  3545. AtmLaneArpTimeout,
  3546. pElan->ArpResponseTime,
  3547. (PVOID)pMacEntry
  3548. );
  3549. AtmLaneSendArpRequest(pElan, pMacEntry);
  3550. //
  3551. // MAC Entry lock released in above
  3552. //
  3553. break;
  3554. }
  3555. //
  3556. // MAC Entry State - ARPING
  3557. //
  3558. if (IS_FLAG_SET(
  3559. pMacEntry->Flags,
  3560. MAC_ENTRY_STATE_MASK,
  3561. MAC_ENTRY_ARPING))
  3562. {
  3563. DBGP((2, "SendUnicastPacket: ARPING Mac Entry %x for %s\n",
  3564. pMacEntry, MacAddrToString(pDestAddress)));
  3565. //
  3566. // Queue packet on MAC Entry
  3567. //
  3568. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  3569. //
  3570. // Start the BUS sends
  3571. //
  3572. AtmLaneStartBusSends(pMacEntry);
  3573. //
  3574. // Lock released in above
  3575. //
  3576. break;
  3577. }
  3578. //
  3579. // MAC Entry State - RESOLVED
  3580. //
  3581. if (IS_FLAG_SET(
  3582. pMacEntry->Flags,
  3583. MAC_ENTRY_STATE_MASK,
  3584. MAC_ENTRY_RESOLVED))
  3585. {
  3586. DBGP((2, "SendUnicastPacket: RESOLVED Mac Entry %x for %s\n",
  3587. pMacEntry, MacAddrToString(pDestAddress)));
  3588. //
  3589. // Queue packet on MAC Entry
  3590. //
  3591. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  3592. //
  3593. // Start the BUS sends
  3594. //
  3595. AtmLaneStartBusSends(pMacEntry);
  3596. //
  3597. // Lock released in above
  3598. //
  3599. break;
  3600. }
  3601. //
  3602. // MAC Entry State - FLUSHING
  3603. //
  3604. if (IS_FLAG_SET(
  3605. pMacEntry->Flags,
  3606. MAC_ENTRY_STATE_MASK,
  3607. MAC_ENTRY_FLUSHING))
  3608. {
  3609. DBGP((2, "SendUnicastPacket: FLUSHING Mac Entry %x for %s\n",
  3610. pMacEntry, MacAddrToString(pDestAddress)));
  3611. //
  3612. // Queue packet on MAC Entry
  3613. //
  3614. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  3615. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3616. break;
  3617. }
  3618. //
  3619. // MAC Entry State - ACTIVE
  3620. //
  3621. //
  3622. if (IS_FLAG_SET(
  3623. pMacEntry->Flags,
  3624. MAC_ENTRY_STATE_MASK,
  3625. MAC_ENTRY_ACTIVE))
  3626. {
  3627. DBGP((2, "SendUnicastPacket: ACTIVE Mac Entry %x for %s\n",
  3628. pMacEntry, MacAddrToString(pDestAddress)));
  3629. //
  3630. // Mark MAC Entry as having been used to send a packet.
  3631. // Will cause revalidation at aging time instead of deletion.
  3632. //
  3633. pMacEntry->Flags |= MAC_ENTRY_USED_FOR_SEND;
  3634. ASSERT(pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY);
  3635. pVc = pMacEntry->pAtmEntry->pVcList;
  3636. if (pVc == NULL_PATMLANE_VC)
  3637. {
  3638. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3639. Status = NDIS_STATUS_FAILURE;
  3640. break;
  3641. }
  3642. ACQUIRE_VC_LOCK(pVc);
  3643. AtmLaneReferenceVc(pVc, "unicast");
  3644. RELEASE_VC_LOCK(pVc);
  3645. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3646. ACQUIRE_VC_LOCK(pVc);
  3647. rc = AtmLaneDereferenceVc(pVc, "unicast");
  3648. if (rc == 0)
  3649. {
  3650. Status = NDIS_STATUS_FAILURE;
  3651. break;
  3652. }
  3653. if (IS_FLAG_SET(
  3654. pVc->Flags,
  3655. VC_CALL_STATE_MASK,
  3656. VC_CALL_STATE_ACTIVE))
  3657. {
  3658. AtmLaneSendPacketOnVc(pVc, pNdisPacket, TRUE);
  3659. //
  3660. // Vc lock released in above
  3661. //
  3662. NdisInterlockedIncrement(&pElan->FramesXmitGood); // count packet
  3663. }
  3664. else
  3665. {
  3666. //
  3667. // The VC is being torn down. Fail/complete this send.
  3668. //
  3669. RELEASE_VC_LOCK(pVc);
  3670. Status = NDIS_STATUS_FAILURE;
  3671. break;
  3672. }
  3673. break;
  3674. }
  3675. //
  3676. // MAC Entry State - AGED
  3677. //
  3678. //
  3679. if (IS_FLAG_SET(
  3680. pMacEntry->Flags,
  3681. MAC_ENTRY_STATE_MASK,
  3682. MAC_ENTRY_AGED))
  3683. {
  3684. DBGP((2, "SendUnicastPacket: AGED Mac Entry %x for %s\n",
  3685. pMacEntry, MacAddrToString(pDestAddress)));
  3686. ASSERT(pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY);
  3687. ASSERT(pMacEntry->pAtmEntry->pVcList != NULL_PATMLANE_VC);
  3688. pVc = pMacEntry->pAtmEntry->pVcList;
  3689. ACQUIRE_VC_LOCK(pVc);
  3690. AtmLaneReferenceVc(pVc, "unicast");
  3691. RELEASE_VC_LOCK(pVc);
  3692. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3693. ACQUIRE_VC_LOCK(pVc);
  3694. rc = AtmLaneDereferenceVc(pVc, "unicast");
  3695. if (rc == 0)
  3696. {
  3697. Status = NDIS_STATUS_FAILURE;
  3698. break;
  3699. }
  3700. AtmLaneSendPacketOnVc(pVc, pNdisPacket, TRUE);
  3701. //
  3702. // Vc lock released in above
  3703. //
  3704. NdisInterlockedIncrement(&pElan->FramesXmitGood); // count packet
  3705. break;
  3706. }
  3707. //
  3708. // MAC Entry State - ABORTING
  3709. //
  3710. //
  3711. if (IS_FLAG_SET(
  3712. pMacEntry->Flags,
  3713. MAC_ENTRY_STATE_MASK,
  3714. MAC_ENTRY_ABORTING))
  3715. {
  3716. DBGP((2, "SendUnicastPacket: ABORTING Mac Entry %x for %s\n",
  3717. pMacEntry, MacAddrToString(pDestAddress)));
  3718. Status = NDIS_STATUS_FAILURE;
  3719. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3720. break;
  3721. }
  3722. }
  3723. while (FALSE);
  3724. TRACEOUT(SendUnicastPacket);
  3725. return Status;
  3726. }
  3727. VOID
  3728. AtmLaneStartBusSends(
  3729. IN PATMLANE_MAC_ENTRY pMacEntry LOCKIN NOLOCKOUT
  3730. )
  3731. /*++
  3732. Routine Description:
  3733. Starts up the bus send process.
  3734. Arguments:
  3735. pMacEntry - A pointer to an ATMLANE MAC Entry structure
  3736. Return Value:
  3737. None
  3738. --*/
  3739. {
  3740. TRACEIN(StartBusSends);
  3741. do
  3742. {
  3743. //
  3744. // If timer set, just wait for it to go off
  3745. //
  3746. if (pMacEntry->Flags & MAC_ENTRY_BUS_TIMER)
  3747. {
  3748. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3749. break;
  3750. }
  3751. //
  3752. // Otherwise do the sends
  3753. //
  3754. AtmLaneDoBusSends(pMacEntry);
  3755. //
  3756. // lock released in above
  3757. //
  3758. }
  3759. while (FALSE);
  3760. TRACEOUT(StartBusSends);
  3761. return;
  3762. }
  3763. VOID
  3764. AtmLaneDoBusSends(
  3765. IN PATMLANE_MAC_ENTRY pMacEntry LOCKIN NOLOCKOUT
  3766. )
  3767. /*++
  3768. Routine Description:
  3769. Attempt to send the packets on the MAC Entry's queue.
  3770. Schedule a timer to send later if we exceed the BUS send limits.
  3771. The caller is assumed to have acquired the MAC entry lock,
  3772. which will be released here.
  3773. Arguments:
  3774. pMacEntry - A pointer to an ATMLANE MAC Entry structure
  3775. Return Value:
  3776. None
  3777. --*/
  3778. {
  3779. PATMLANE_ATM_ENTRY pAtmEntry;
  3780. PATMLANE_VC pVc;
  3781. PATMLANE_ELAN pElan;
  3782. PNDIS_PACKET pNdisPacket;
  3783. ULONG rc;
  3784. TRACEIN(DoBusSends);
  3785. pElan = pMacEntry->pElan;
  3786. //
  3787. // Initialize
  3788. //
  3789. pVc = NULL_PATMLANE_VC;
  3790. //
  3791. // Place a temp ref on this MAC entry so that it won't go away.
  3792. //
  3793. AtmLaneReferenceMacEntry(pMacEntry, "DoBusSends");
  3794. do
  3795. {
  3796. //
  3797. // If Elan state not operational then done
  3798. //
  3799. if (ELAN_STATE_OPERATIONAL != pElan->AdminState ||
  3800. ELAN_STATE_OPERATIONAL != pElan->State)
  3801. {
  3802. break;
  3803. }
  3804. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3805. pAtmEntry = pElan->pBusAtmEntry;
  3806. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  3807. {
  3808. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3809. break;
  3810. }
  3811. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3812. pVc = pAtmEntry->pVcList;
  3813. if (pVc == NULL_PATMLANE_VC)
  3814. {
  3815. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3816. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3817. break;
  3818. }
  3819. //
  3820. // Reference the VC to keep it around
  3821. //
  3822. ACQUIRE_VC_LOCK_DPC(pVc);
  3823. AtmLaneReferenceVc(pVc, "temp");
  3824. RELEASE_VC_LOCK_DPC(pVc);
  3825. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3826. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3827. //
  3828. // loop until no more packets or send limit reached
  3829. //
  3830. do
  3831. {
  3832. //
  3833. // If no more packets to send then done
  3834. //
  3835. if (pMacEntry->PacketList == (PNDIS_PACKET)NULL)
  3836. {
  3837. break;
  3838. }
  3839. //
  3840. // Check if ok to send a packet now
  3841. //
  3842. if (!AtmLaneOKToBusSend(pMacEntry))
  3843. {
  3844. //
  3845. // Not OK to send now, try later
  3846. //
  3847. // Reference the MAC Entry
  3848. //
  3849. AtmLaneReferenceMacEntry(pMacEntry, "bus timer");
  3850. //
  3851. // Reschedule the timer routine
  3852. //
  3853. pMacEntry->Flags |= MAC_ENTRY_BUS_TIMER;
  3854. NdisSetTimer(&pMacEntry->BusTimer, pMacEntry->IncrTime);
  3855. break;
  3856. }
  3857. //
  3858. // Dequeue a packet
  3859. //
  3860. pNdisPacket = AtmLaneDequeuePacketFromHead(pMacEntry);
  3861. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3862. ASSERT(pNdisPacket != (PNDIS_PACKET)NULL);
  3863. //
  3864. // Reacquire VC lock and if VC still connected send packet
  3865. //
  3866. ACQUIRE_VC_LOCK(pVc);
  3867. if (IS_FLAG_SET(
  3868. pVc->Flags,
  3869. VC_CALL_STATE_MASK,
  3870. VC_CALL_STATE_ACTIVE))
  3871. {
  3872. DBGP((2, "DoBusSends: pVc %x Pkt %x Sending to BUS\n",
  3873. pVc, pNdisPacket));
  3874. AtmLaneSendPacketOnVc(pVc, pNdisPacket, FALSE);
  3875. //
  3876. // VC lock released in above
  3877. //
  3878. NdisInterlockedIncrement(&pElan->FramesXmitGood); // count it
  3879. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3880. }
  3881. else
  3882. {
  3883. //
  3884. // Not sent, release lock, requeue packet, abort
  3885. //
  3886. DBGP((2, "DoBusSend: pVc %x, Flags %x not good, pkt %x\n",
  3887. pVc, pVc->Flags, pNdisPacket));
  3888. RELEASE_VC_LOCK(pVc);
  3889. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3890. AtmLaneQueuePacketOnHead(pMacEntry, pNdisPacket);
  3891. break;
  3892. }
  3893. }
  3894. while (FALSE);
  3895. //
  3896. // Remove temp VC reference
  3897. //
  3898. if (pVc != NULL_PATMLANE_VC)
  3899. {
  3900. DBGP((2, "DoBusSends: Vc %p, ref %d, removing temp ref\n",
  3901. pVc, pVc->RefCount));
  3902. ACQUIRE_VC_LOCK(pVc);
  3903. rc = AtmLaneDereferenceVc(pVc, "temp");
  3904. if (rc > 0)
  3905. {
  3906. RELEASE_VC_LOCK(pVc);
  3907. }
  3908. //
  3909. // else VC is gone
  3910. //
  3911. }
  3912. }
  3913. while (FALSE);
  3914. //
  3915. // Remove the temp ref we had added to the MAC entry on entering
  3916. // this function.
  3917. //
  3918. rc = AtmLaneDereferenceMacEntry(pMacEntry, "DoBusSends");
  3919. if (rc != 0)
  3920. {
  3921. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3922. }
  3923. //
  3924. // else the MAC entry is gone.
  3925. //
  3926. TRACEOUT(DoBusSends);
  3927. return;
  3928. }
  3929. VOID
  3930. AtmLaneBusSendTimer(
  3931. IN PVOID SystemSpecific1,
  3932. IN PVOID pContext,
  3933. IN PVOID SystemSpecific2,
  3934. IN PVOID SystemSpecific3
  3935. )
  3936. {
  3937. PATMLANE_MAC_ENTRY pMacEntry;
  3938. ULONG rc;
  3939. TRACEIN(BusSendTimer);
  3940. pMacEntry = (PATMLANE_MAC_ENTRY)pContext;
  3941. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  3942. do
  3943. {
  3944. //
  3945. // Grab the Mac Entry's lock
  3946. //
  3947. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3948. //
  3949. // Clear the bus timer flag
  3950. //
  3951. pMacEntry->Flags &= ~ MAC_ENTRY_BUS_TIMER;
  3952. //
  3953. // Dereference the Mac Entry
  3954. //
  3955. rc = AtmLaneDereferenceMacEntry(pMacEntry, "bus timer");
  3956. if (rc == 0)
  3957. {
  3958. break;
  3959. }
  3960. //
  3961. // Mac Entry still here, try to send more
  3962. //
  3963. AtmLaneDoBusSends(pMacEntry);
  3964. //
  3965. // lock released in above
  3966. //
  3967. break;
  3968. }
  3969. while (FALSE);
  3970. TRACEOUT(BusSendTimer);
  3971. return;
  3972. }
  3973. BOOLEAN
  3974. AtmLaneOKToBusSend(
  3975. IN PATMLANE_MAC_ENTRY pMacEntry
  3976. )
  3977. /*++
  3978. Routine Description:
  3979. Determines if, at the current time, it is OK to send
  3980. a packet to the BUS. Additionally, if it is OK to send
  3981. a packet, it updates the state variables in the MAC Entry
  3982. in preparation for another attempt to send a packet to
  3983. the Bus.
  3984. The LANE spec requires a LANE client to restrict the
  3985. sending of packets over the BUS to a specific LAN
  3986. destination address by using two parameters:
  3987. Maximum Unknown Packet Count
  3988. Maximum Unknown Packet Time
  3989. A LANE client can only send "Maximum Unknown Packet Count"
  3990. packets within the period of time "Maximum Unknown Packet
  3991. Time".
  3992. This function expects the MAC Entry to contain three
  3993. variables:
  3994. BusyTime
  3995. LimitTime
  3996. IncrTime
  3997. Arguments:
  3998. pMacEntry - Pointer to an ATMLANE MAC Entry.
  3999. Return Value:
  4000. TRUE - if ok to send packet on BUS
  4001. FALSE - if exceeded traffic to the BUS
  4002. --*/
  4003. {
  4004. ULONG Now;
  4005. ULONG BusyTime;
  4006. LONG TimeUntilIdle;
  4007. Now = AtmLaneSystemTimeMs();
  4008. BusyTime = pMacEntry->BusyTime;
  4009. TimeUntilIdle = BusyTime - Now;
  4010. //
  4011. // bring busy until time up to current; also handles
  4012. // wrapping. Under normal circumstances, TimeUntilIdle
  4013. // is either < 0 or no more than limitTime + incrtime.
  4014. // The value of limitTime * 8 is a little more conservative and
  4015. // cheaper to compute.
  4016. //
  4017. if (TimeUntilIdle < 0 ||
  4018. TimeUntilIdle > (LONG)(pMacEntry->LimitTime << 3))
  4019. {
  4020. BusyTime = Now;
  4021. }
  4022. else
  4023. {
  4024. if (TimeUntilIdle > (LONG)pMacEntry->LimitTime)
  4025. {
  4026. //
  4027. // channel is already estimated to be busy until past
  4028. // the burst time, so we can't overload it by sending
  4029. // more now.
  4030. //
  4031. return FALSE;
  4032. }
  4033. }
  4034. //
  4035. // mark channel as busy for another inter-packet arrival
  4036. // time, and return OK to send the new packet.
  4037. //
  4038. pMacEntry->BusyTime = BusyTime + pMacEntry->IncrTime;
  4039. return TRUE;
  4040. }
  4041. VOID
  4042. AtmLaneFreePacketQueue(
  4043. IN PATMLANE_MAC_ENTRY pMacEntry,
  4044. IN NDIS_STATUS Status
  4045. )
  4046. /*++
  4047. Routine Description:
  4048. Frees the list of packets queued on a MAC Entry.
  4049. Assumes caller holds lock on MAC Entry.
  4050. Arguments:
  4051. pMacEntry - Pointer to MAC Entry.
  4052. Status - The status to use if the packet is
  4053. protocol packet.
  4054. Return Value:
  4055. None
  4056. --*/
  4057. {
  4058. PNDIS_PACKET pNdisPacket;
  4059. TRACEIN(FreePacketQueue);
  4060. while ((pNdisPacket = AtmLaneDequeuePacketFromHead(pMacEntry)) != (PNDIS_PACKET)NULL)
  4061. {
  4062. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  4063. #if PROTECT_PACKETS
  4064. ACQUIRE_SENDPACKET_LOCK(pNdisPacket);
  4065. PSEND_RSVD(pNdisPacket)->Flags |= PACKET_RESERVED_COSENDRETURNED;
  4066. PSEND_RSVD(pNdisPacket)->Flags |= PACKET_RESERVED_COMPLETED;
  4067. #endif // PROTECT_PACKETS
  4068. AtmLaneCompleteSendPacket(pMacEntry->pElan, pNdisPacket, Status);
  4069. //
  4070. // packet lock released in above
  4071. //
  4072. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  4073. }
  4074. TRACEOUT(FreePacketQueue);
  4075. return;
  4076. }
  4077. VOID
  4078. AtmLaneCompleteSendPacket(
  4079. IN PATMLANE_ELAN pElan,
  4080. IN PNDIS_PACKET pNdisPacket LOCKIN NOLOCKOUT,
  4081. IN NDIS_STATUS Status
  4082. )
  4083. /*++
  4084. Routine Description:
  4085. Complete a send packet. The packet is one of the following types:
  4086. (a) Belonging to a protocol (b) Belonging to the ATMLANE module.
  4087. In the case of a protocol packet we unwrap it and complete it.
  4088. In the case of an ATMLANE packet we just free it.
  4089. Arguments:
  4090. pElan - Pointer to ATMLANE Elan.
  4091. pNdisPacket - Pointer to the packet
  4092. Status - The status to use if the packet is
  4093. protocol packet.
  4094. Return Value:
  4095. None
  4096. --*/
  4097. {
  4098. PNDIS_BUFFER pNdisBuffer;
  4099. PNDIS_PACKET pProtNdisPacket;
  4100. TRACEIN(CompleteSendPacket);
  4101. #if PROTECT_PACKETS
  4102. //
  4103. // Assert that we can release and/or complete all resources for this packet
  4104. //
  4105. ASSERT((PSEND_RSVD(pNdisPacket)->Flags &
  4106. (PACKET_RESERVED_COMPLETED | PACKET_RESERVED_COSENDRETURNED))
  4107. == (PACKET_RESERVED_COMPLETED | PACKET_RESERVED_COSENDRETURNED));
  4108. #endif // PROTECT_PACKETS
  4109. //
  4110. // Determine originator of packet
  4111. //
  4112. if (IS_FLAG_SET(
  4113. PSEND_RSVD(pNdisPacket)->Flags,
  4114. PACKET_RESERVED_OWNER_MASK,
  4115. PACKET_RESERVED_OWNER_ATMLANE
  4116. ))
  4117. {
  4118. //
  4119. // Packet originated by ATMLANE. Free the buffer.
  4120. //
  4121. NdisUnchainBufferAtFront(pNdisPacket, &pNdisBuffer);
  4122. ASSERT(NULL != pNdisBuffer);
  4123. AtmLaneFreeProtoBuffer(pElan, pNdisBuffer);
  4124. //
  4125. // Free the packet header.
  4126. //
  4127. DBGP((3, "CompleteSendPkt: Freeing AtmLane owned pkt %x\n", pNdisPacket));
  4128. #if PROTECT_PACKETS
  4129. RELEASE_SENDPACKET_LOCK(pNdisPacket);
  4130. FREE_SENDPACKET_LOCK(pNdisPacket);
  4131. #endif // PROTECT_PACKETS
  4132. NdisFreePacket(pNdisPacket);
  4133. #if PKT_HDR_COUNTS
  4134. InterlockedIncrement(&pElan->ProtPktCount);
  4135. if ((pElan->ProtPktCount % 20) == 0 &&
  4136. pElan->ProtPktCount != pElan->MaxProtocolBufs)
  4137. {
  4138. DBGP((1, "ProtPktCount %d\n", pElan->ProtPktCount));
  4139. }
  4140. #endif
  4141. }
  4142. else
  4143. {
  4144. //
  4145. // Packet orignated by a protocol.
  4146. // Unwrap it.
  4147. // Complete it to the protocol.
  4148. //
  4149. pProtNdisPacket = AtmLaneUnwrapSendPacket(pElan, pNdisPacket);
  4150. //
  4151. // packet lock released in above
  4152. //
  4153. TRACELOGWRITE((&TraceLog, TL_MSENDCOMPL, pProtNdisPacket, Status));
  4154. TRACELOGWRITEPKT((&TraceLog, pProtNdisPacket));
  4155. // DBGP((0, "NdisMSendComplete: Pkt %x Stat %x\n", pProtNdisPacket, Status));
  4156. NdisMSendComplete(
  4157. pElan->MiniportAdapterHandle,
  4158. pProtNdisPacket,
  4159. Status);
  4160. }
  4161. TRACEOUT(CompleteSendPacket);
  4162. return;
  4163. }
  4164. PWSTR
  4165. AtmLaneMacAddrToString(
  4166. IN VOID * pIn
  4167. )
  4168. {
  4169. static PWSTR WHexChars = L"0123456789abcdef";
  4170. PWSTR StrBuf;
  4171. ULONG Index;
  4172. PWSTR pWStr;
  4173. PUCHAR pMacAddr;
  4174. PWSTR punicodeMacAddrBuffer = ((PWSTR)0);
  4175. UNICODE_STRING unicodeString;
  4176. ANSI_STRING ansiString;
  4177. TRACEIN(MacAddrToString);
  4178. // alloc space for output unicode string
  4179. ALLOC_MEM(&punicodeMacAddrBuffer, (((sizeof(MAC_ADDRESS) * 2) + 1) * sizeof(WCHAR)));
  4180. if (((PWSTR)0) != punicodeMacAddrBuffer)
  4181. {
  4182. for (Index = 0, pWStr = punicodeMacAddrBuffer, pMacAddr = pIn;
  4183. Index < sizeof(MAC_ADDRESS);
  4184. Index++, pMacAddr++)
  4185. {
  4186. *pWStr++ = WHexChars[(*pMacAddr)>>4];
  4187. *pWStr++ = WHexChars[(*pMacAddr)&0xf];
  4188. }
  4189. *pWStr = L'\0';
  4190. }
  4191. TRACEOUT(MacAddrToString);
  4192. return punicodeMacAddrBuffer;
  4193. }
  4194. PWSTR
  4195. AtmLaneAtmAddrToString(
  4196. IN PATM_ADDRESS pIn
  4197. )
  4198. {
  4199. static PWSTR WHexChars = L"0123456789abcdef";
  4200. PWSTR StrBuf;
  4201. ULONG Index;
  4202. PWSTR pWStr;
  4203. PUCHAR pAtmAddr;
  4204. PWSTR punicodeAtmAddrBuffer = ((PWSTR)0);
  4205. UNICODE_STRING unicodeString;
  4206. ANSI_STRING ansiString;
  4207. TRACEIN(AtmAddrToString);
  4208. // alloc space for output unicode string
  4209. ALLOC_MEM(&punicodeAtmAddrBuffer, (((ATM_ADDRESS_LENGTH * 2) + 1) * sizeof(WCHAR)));
  4210. if (((PWSTR)0) != punicodeAtmAddrBuffer)
  4211. {
  4212. // format ATM addr into Unicode string buffer
  4213. for (Index = 0, pWStr = punicodeAtmAddrBuffer, pAtmAddr = pIn->Address;
  4214. Index < pIn->NumberOfDigits;
  4215. Index++, pAtmAddr++)
  4216. {
  4217. *pWStr++ = WHexChars[(*pAtmAddr)>>4];
  4218. *pWStr++ = WHexChars[(*pAtmAddr)&0xf];
  4219. }
  4220. *pWStr = L'\0';
  4221. }
  4222. TRACEOUT(AtmAddrToString);
  4223. return punicodeAtmAddrBuffer;
  4224. }