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.

2358 lines
57 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. miniport.c
  6. Abstract:
  7. Miniport upper-edge functions.
  8. Author:
  9. Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. //
  17. // List of supported OIDs for this driver when an Ethernet Elan.
  18. //
  19. static
  20. NDIS_OID EthernetSupportedOids[] = {
  21. OID_GEN_SUPPORTED_LIST,
  22. OID_GEN_HARDWARE_STATUS,
  23. OID_GEN_MEDIA_CONNECT_STATUS,
  24. OID_GEN_MEDIA_SUPPORTED,
  25. OID_GEN_MEDIA_IN_USE,
  26. OID_GEN_MAXIMUM_LOOKAHEAD,
  27. OID_GEN_MAXIMUM_FRAME_SIZE,
  28. OID_GEN_MAXIMUM_TOTAL_SIZE,
  29. OID_GEN_MAC_OPTIONS,
  30. OID_GEN_PROTOCOL_OPTIONS,
  31. OID_GEN_LINK_SPEED,
  32. OID_GEN_TRANSMIT_BUFFER_SPACE,
  33. OID_GEN_RECEIVE_BUFFER_SPACE,
  34. OID_GEN_TRANSMIT_BLOCK_SIZE,
  35. OID_GEN_RECEIVE_BLOCK_SIZE,
  36. OID_GEN_MAXIMUM_SEND_PACKETS,
  37. OID_GEN_VENDOR_DESCRIPTION,
  38. OID_GEN_VENDOR_ID,
  39. OID_GEN_DRIVER_VERSION,
  40. OID_GEN_VENDOR_DRIVER_VERSION,
  41. OID_GEN_CURRENT_PACKET_FILTER,
  42. OID_GEN_CURRENT_LOOKAHEAD,
  43. OID_GEN_XMIT_OK,
  44. OID_GEN_RCV_OK,
  45. OID_GEN_XMIT_ERROR,
  46. OID_GEN_RCV_ERROR,
  47. OID_GEN_RCV_NO_BUFFER,
  48. OID_802_3_PERMANENT_ADDRESS,
  49. OID_802_3_CURRENT_ADDRESS,
  50. OID_802_3_MULTICAST_LIST,
  51. OID_802_3_MAXIMUM_LIST_SIZE,
  52. OID_802_3_RCV_ERROR_ALIGNMENT,
  53. OID_802_3_XMIT_ONE_COLLISION,
  54. OID_802_3_XMIT_MORE_COLLISIONS,
  55. OID_GEN_NETWORK_LAYER_ADDRESSES,
  56. };
  57. static
  58. NDIS_OID TokenRingSupportedOids[] = {
  59. OID_GEN_SUPPORTED_LIST,
  60. OID_GEN_HARDWARE_STATUS,
  61. OID_GEN_MEDIA_CONNECT_STATUS,
  62. OID_GEN_MEDIA_SUPPORTED,
  63. OID_GEN_MEDIA_IN_USE,
  64. OID_GEN_MAXIMUM_LOOKAHEAD,
  65. OID_GEN_MAXIMUM_FRAME_SIZE,
  66. OID_GEN_MAXIMUM_TOTAL_SIZE,
  67. OID_GEN_MAC_OPTIONS,
  68. OID_GEN_PROTOCOL_OPTIONS,
  69. OID_GEN_LINK_SPEED,
  70. OID_GEN_TRANSMIT_BUFFER_SPACE,
  71. OID_GEN_RECEIVE_BUFFER_SPACE,
  72. OID_GEN_TRANSMIT_BLOCK_SIZE,
  73. OID_GEN_RECEIVE_BLOCK_SIZE,
  74. OID_GEN_MAXIMUM_SEND_PACKETS,
  75. OID_GEN_VENDOR_ID,
  76. OID_GEN_VENDOR_DESCRIPTION,
  77. OID_GEN_DRIVER_VERSION,
  78. OID_GEN_VENDOR_DRIVER_VERSION,
  79. OID_GEN_CURRENT_PACKET_FILTER,
  80. OID_GEN_CURRENT_LOOKAHEAD,
  81. OID_GEN_XMIT_OK,
  82. OID_GEN_RCV_OK,
  83. OID_GEN_XMIT_ERROR,
  84. OID_GEN_RCV_ERROR,
  85. OID_GEN_RCV_NO_BUFFER,
  86. OID_802_5_PERMANENT_ADDRESS,
  87. OID_802_5_CURRENT_ADDRESS,
  88. OID_802_5_CURRENT_FUNCTIONAL,
  89. OID_802_5_CURRENT_GROUP,
  90. OID_802_5_LAST_OPEN_STATUS,
  91. OID_802_5_CURRENT_RING_STATUS,
  92. OID_802_5_CURRENT_RING_STATE,
  93. OID_802_5_LINE_ERRORS,
  94. OID_802_5_LOST_FRAMES,
  95. OID_802_5_BURST_ERRORS,
  96. OID_802_5_FRAME_COPIED_ERRORS,
  97. OID_802_5_TOKEN_ERRORS,
  98. OID_GEN_NETWORK_LAYER_ADDRESSES,
  99. };
  100. NDIS_STATUS
  101. AtmLaneMInitialize(
  102. OUT PNDIS_STATUS OpenErrorStatus,
  103. OUT PUINT SelectedMediumIndex,
  104. IN PNDIS_MEDIUM MediumArray,
  105. IN UINT MediumArraySize,
  106. IN NDIS_HANDLE MiniportAdapterHandle,
  107. IN NDIS_HANDLE WrapperConfigurationContext
  108. )
  109. {
  110. UINT i;
  111. NDIS_MEDIUM MediumToFind;
  112. NDIS_STATUS Status;
  113. PATMLANE_ELAN pElan;
  114. PUCHAR pMacAddr;
  115. UINT MacAddrLength;
  116. TRACEIN(MInitialize);
  117. //
  118. // Get context (Elan) supplied with NdisIMInitializeDeviceEx
  119. //
  120. pElan = NdisIMGetDeviceContext(MiniportAdapterHandle);
  121. STRUCT_ASSERT(pElan, atmlane_elan);
  122. ASSERT(pElan->Flags & ELAN_MINIPORT_INIT_PENDING);
  123. DBGP((1, "%d MInitialize\n", pElan->ElanNumber));
  124. do
  125. {
  126. Status = NDIS_STATUS_SUCCESS;
  127. //
  128. // Are we Ethernet or Token Ring?
  129. //
  130. if (pElan->LanType == LANE_LANTYPE_ETH)
  131. {
  132. MediumToFind = NdisMedium802_3;
  133. }
  134. else
  135. {
  136. MediumToFind = NdisMedium802_5;
  137. }
  138. //
  139. // Look for MediumToFind in MediumArray.
  140. //
  141. for (i = 0; i < MediumArraySize; i++)
  142. {
  143. if (MediumArray[i] == MediumToFind)
  144. break;
  145. }
  146. //
  147. // Not found, return error.
  148. if (i == MediumArraySize)
  149. {
  150. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  151. break;
  152. }
  153. Status = NDIS_STATUS_SUCCESS;
  154. //
  155. // Output select medium
  156. //
  157. *SelectedMediumIndex = i;
  158. //
  159. // Set my attributes
  160. //
  161. NdisMSetAttributesEx(
  162. MiniportAdapterHandle, // MiniportAdapterHandle
  163. (NDIS_HANDLE)pElan, // MiniportAdapterContext
  164. 0, // CheckForHangTimeInSeconds
  165. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT | // AttributeFlags
  166. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  167. NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
  168. NDIS_ATTRIBUTE_DESERIALIZE,
  169. 0 // AdapterType
  170. );
  171. ACQUIRE_ELAN_LOCK(pElan);
  172. AtmLaneReferenceElan(pElan, "miniport");
  173. //
  174. // Save away the MiniportAdapterHandle now. This is so that we
  175. // don't call NdisMIndicateStatus before calling NdisMSetAttributesEx.
  176. //
  177. pElan->MiniportAdapterHandle = MiniportAdapterHandle;
  178. RELEASE_ELAN_LOCK(pElan);
  179. break;
  180. }
  181. while (FALSE);
  182. //
  183. // Wake up any thread (i.e. AtmLaneShutdownElan) waiting for
  184. // a pending Init to be over.
  185. //
  186. ACQUIRE_ELAN_LOCK(pElan);
  187. pElan->Flags &= ~ELAN_MINIPORT_INIT_PENDING;
  188. RELEASE_ELAN_LOCK(pElan);
  189. DBGP((2, "%d MInitialize ELAN %p/%x, Ref %d, Status %x\n",
  190. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, Status));
  191. SIGNAL_BLOCK_STRUCT(&pElan->InitBlock, NDIS_STATUS_SUCCESS);
  192. TRACEOUT(MInitialize);
  193. return Status;
  194. }
  195. VOID
  196. AtmLaneMSendPackets(
  197. IN NDIS_HANDLE MiniportAdapterContext,
  198. IN PPNDIS_PACKET PacketArray,
  199. IN UINT NumberOfPackets
  200. )
  201. {
  202. PATMLANE_ELAN pElan;
  203. UINT PacketIndex;
  204. PNDIS_PACKET pSendNdisPacket;
  205. PNDIS_PACKET pNewNdisPacket;
  206. PNDIS_BUFFER pHeaderNdisBuffer;
  207. PUCHAR pHeaderBuffer;
  208. PUCHAR pPktHeader;
  209. PNDIS_BUFFER pTempNdisBuffer;
  210. PATMLANE_VC pVc;
  211. ULONG TotalLength;
  212. ULONG BufferLength;
  213. NDIS_STATUS Status;
  214. ULONG DestAddrType;
  215. MAC_ADDRESS DestAddress;
  216. BOOLEAN SendViaBUS;
  217. PATMLANE_MAC_ENTRY pMacEntry;
  218. PATMLANE_ATM_ENTRY pAtmEntry;
  219. ULONG rc;
  220. #if DEBUG_IRQL
  221. KIRQL EntryIrql;
  222. #endif
  223. GET_ENTRY_IRQL(EntryIrql);
  224. TRACEIN(MSendPackets);
  225. pElan = (PATMLANE_ELAN)MiniportAdapterContext;
  226. STRUCT_ASSERT(pElan, atmlane_elan);
  227. TRACELOGWRITE((&TraceLog, TL_MSENDPKTIN, NumberOfPackets));
  228. DBGP((2, "MSendPackets: Count %d\n", NumberOfPackets));
  229. //
  230. // loop thru the array of packets to send
  231. //
  232. for (PacketIndex = 0; PacketIndex < NumberOfPackets; PacketIndex++)
  233. {
  234. pSendNdisPacket = PacketArray[PacketIndex];
  235. pNewNdisPacket = (PNDIS_PACKET)NULL;
  236. SendViaBUS = FALSE;
  237. pMacEntry = NULL_PATMLANE_MAC_ENTRY;
  238. pVc = NULL_PATMLANE_VC;
  239. Status = NDIS_STATUS_PENDING;
  240. // DBGP((0, "MSendPackets: Pkt %x\n", pSendNdisPacket));
  241. TRACELOGWRITE((&TraceLog, TL_MSENDPKTBEGIN, PacketIndex, pSendNdisPacket));
  242. TRACELOGWRITEPKT((&TraceLog, pSendNdisPacket));
  243. //
  244. // ALWAYS set packet status to NDIS_STATUS_PENDING
  245. //
  246. NDIS_SET_PACKET_STATUS(pSendNdisPacket, NDIS_STATUS_PENDING);
  247. do
  248. {
  249. //
  250. // If Elan is down then just set local status to failure
  251. //
  252. if (ELAN_STATE_OPERATIONAL != pElan->State ||
  253. ELAN_STATE_OPERATIONAL != pElan->AdminState)
  254. {
  255. DBGP((0, "%d Send failure on ELAN %x flags %x state %d AdminSt %d\n",
  256. pElan->ElanNumber,
  257. pElan,
  258. pElan->Flags,
  259. pElan->State,
  260. pElan->AdminState));
  261. pNewNdisPacket = NULL;
  262. Status = NDIS_STATUS_FAILURE;
  263. break;
  264. }
  265. //
  266. // Wrap it up for sending
  267. //
  268. pNewNdisPacket = AtmLaneWrapSendPacket(
  269. pElan,
  270. pSendNdisPacket,
  271. &DestAddrType,
  272. &DestAddress,
  273. &SendViaBUS
  274. );
  275. if (pNewNdisPacket == (PNDIS_PACKET)NULL)
  276. {
  277. //
  278. // Out of resources
  279. //
  280. Status = NDIS_STATUS_RESOURCES;
  281. break;
  282. }
  283. if (SendViaBUS)
  284. {
  285. //
  286. // Packet is multicast so send it to the bus
  287. //
  288. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  289. pAtmEntry = pElan->pBusAtmEntry;
  290. if (pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  291. {
  292. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  293. Status = NDIS_STATUS_FAILURE;
  294. break;
  295. }
  296. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  297. pVc = pAtmEntry->pVcList;
  298. if (pVc == NULL_PATMLANE_VC)
  299. {
  300. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  301. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  302. Status = NDIS_STATUS_FAILURE;
  303. break;
  304. }
  305. //
  306. // Reference the VC to keep it around
  307. //
  308. ACQUIRE_VC_LOCK_DPC(pVc);
  309. AtmLaneReferenceVc(pVc, "temp");
  310. RELEASE_VC_LOCK_DPC(pVc);
  311. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  312. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  313. //
  314. // Reacquire VC lock and dereference it
  315. //
  316. ACQUIRE_VC_LOCK(pVc);
  317. rc = AtmLaneDereferenceVc(pVc, "temp");
  318. if (rc == 0)
  319. {
  320. //
  321. // Vc pulled out from under us.
  322. //
  323. Status = NDIS_STATUS_FAILURE;
  324. break;
  325. }
  326. if (IS_FLAG_SET(
  327. pVc->Flags,
  328. VC_CALL_STATE_MASK,
  329. VC_CALL_STATE_ACTIVE))
  330. {
  331. //
  332. // Send it!
  333. //
  334. DBGP((2, "MSendPackets: Sending to BUS, VC %x\n", pVc));
  335. AtmLaneSendPacketOnVc(pVc, pNewNdisPacket, FALSE);
  336. //
  337. // VC lock released in above
  338. //
  339. }
  340. else
  341. {
  342. //
  343. // The VC is being torn down. This should be a rare
  344. // occurrance, so simply drop this packet.
  345. //
  346. RELEASE_VC_LOCK(pVc);
  347. Status = NDIS_STATUS_FAILURE;
  348. break;
  349. }
  350. break;
  351. }
  352. //
  353. // Packet is unicast
  354. //
  355. DBGP((2, "MSendPackets: Sending unicast, dest %x:%x:%x:%x:%x:%x\n",
  356. ((PUCHAR)&DestAddress)[0],
  357. ((PUCHAR)&DestAddress)[1],
  358. ((PUCHAR)&DestAddress)[2],
  359. ((PUCHAR)&DestAddress)[3],
  360. ((PUCHAR)&DestAddress)[4],
  361. ((PUCHAR)&DestAddress)[5]
  362. ));
  363. Status = AtmLaneSendUnicastPacket(
  364. pElan,
  365. DestAddrType,
  366. &DestAddress,
  367. pNewNdisPacket
  368. );
  369. break;
  370. }
  371. while (FALSE);
  372. //
  373. // If no new packet header than it must be a resource failure
  374. // or Elan is down.
  375. // Complete the packet with NDIS_STATUS_SUCCESS.
  376. //
  377. if (pNewNdisPacket == (PNDIS_PACKET)NULL)
  378. {
  379. ASSERT(Status != NDIS_STATUS_PENDING);
  380. // DBGP((0, "NdisMSendComplete: Pkt %x Stat %x\n", pSendNdisPacket, NDIS_STATUS_SUCCESS));
  381. NdisMSendComplete(
  382. pElan->MiniportAdapterHandle,
  383. pSendNdisPacket,
  384. NDIS_STATUS_SUCCESS);
  385. TRACELOGWRITE((&TraceLog, TL_MSENDPKTEND, PacketIndex, pSendNdisPacket, Status));
  386. continue;
  387. }
  388. //
  389. // If status isn't pending then some other failure to send occurred.
  390. // Complete the packet with NDIS_STATUS_SUCCESS.
  391. //
  392. if (Status != NDIS_STATUS_PENDING)
  393. {
  394. #if PROTECT_PACKETS
  395. ACQUIRE_SENDPACKET_LOCK(pNewNdisPacket);
  396. ASSERT((PSEND_RSVD(pNewNdisPacket)->Flags & PACKET_RESERVED_COSENDRETURNED) == 0);
  397. ASSERT((PSEND_RSVD(pNewNdisPacket)->Flags & PACKET_RESERVED_COMPLETED) == 0);
  398. PSEND_RSVD(pNewNdisPacket)->Flags |= PACKET_RESERVED_COSENDRETURNED;
  399. PSEND_RSVD(pNewNdisPacket)->Flags |= PACKET_RESERVED_COMPLETED;
  400. #endif // PROTECT_PACKETS
  401. AtmLaneCompleteSendPacket(pElan, pNewNdisPacket, NDIS_STATUS_SUCCESS);
  402. //
  403. // packet lock released in above
  404. //
  405. TRACELOGWRITE((&TraceLog, TL_MSENDPKTEND, PacketIndex, pSendNdisPacket, Status));
  406. continue;
  407. }
  408. //
  409. // Otherwise do nothing
  410. //
  411. ASSERT(Status == NDIS_STATUS_PENDING);
  412. TRACELOGWRITE((&TraceLog, TL_MSENDPKTEND, PacketIndex, pSendNdisPacket, Status));
  413. } // for(...next packet
  414. TRACELOGWRITE((&TraceLog, TL_MSENDPKTOUT));
  415. TRACEOUT(MSendPackets);
  416. CHECK_EXIT_IRQL(EntryIrql);
  417. return;
  418. }
  419. VOID
  420. AtmLaneMReturnPacket(
  421. IN NDIS_HANDLE MiniportAdapterContext,
  422. IN PNDIS_PACKET pNdisPacket
  423. )
  424. /*++
  425. Routine Description:
  426. This function is called by a protocol or by NDIS on
  427. behalf of a protocol to return a packet that was
  428. retained beyond the context of the receive indication.
  429. Arguments:
  430. MiniportAdapterContext - Pointer to ATMLANE elan structure
  431. pNdisPacket - Pointer to NDIS packet
  432. Return Value:
  433. none.
  434. --*/
  435. {
  436. PATMLANE_ELAN pElan;
  437. PNDIS_PACKET pOrigNdisPacket;
  438. PNDIS_BUFFER pTempNdisBuffer;
  439. ULONG Length;
  440. #if DEBUG_IRQL
  441. KIRQL EntryIrql;
  442. #endif
  443. GET_ENTRY_IRQL(EntryIrql);
  444. TRACEIN(MReturnPacket);
  445. pElan = (PATMLANE_ELAN)MiniportAdapterContext;
  446. STRUCT_ASSERT(pElan, atmlane_elan);
  447. TRACELOGWRITE((&TraceLog,
  448. TL_MRETNPACKET,
  449. pNdisPacket));
  450. ASSERT(NDIS_GET_PACKET_STATUS(pNdisPacket) != NDIS_STATUS_RESOURCES);
  451. pOrigNdisPacket = AtmLaneUnwrapRecvPacket(pElan, pNdisPacket);
  452. TRACELOGWRITE((&TraceLog,
  453. TL_CORETNPACKET,
  454. pOrigNdisPacket));
  455. //
  456. // Return original packet to ATM miniport.
  457. //
  458. NdisReturnPackets(
  459. &pOrigNdisPacket,
  460. 1);
  461. TRACEOUT(MReturnPacket);
  462. CHECK_EXIT_IRQL(EntryIrql);
  463. return;
  464. }
  465. NDIS_STATUS
  466. AtmLaneMQueryInformation(
  467. IN NDIS_HANDLE MiniportAdapterContext,
  468. IN NDIS_OID Oid,
  469. IN PVOID InformationBuffer,
  470. IN ULONG InformationBufferLength,
  471. OUT PULONG BytesWritten,
  472. OUT PULONG BytesNeeded
  473. )
  474. /*++
  475. Routine Description:
  476. The QueryInformation Handler for the virtual miniport.
  477. Arguments:
  478. MiniportAdapterContext - a pointer to the Elan.
  479. Oid - the NDIS_OID to process.
  480. InformationBuffer - a pointer into the NdisRequest->InformationBuffer
  481. into which store the result of the query.
  482. InformationBufferLength - a pointer to the number of bytes left in the
  483. InformationBuffer.
  484. BytesWritten - a pointer to the number of bytes written into the
  485. InformationBuffer.
  486. BytesNeeded - If there is not enough room in the information
  487. buffer then this will contain the number of bytes
  488. needed to complete the request.
  489. Return Value:
  490. The function value is the status of the operation.
  491. --*/
  492. {
  493. UINT BytesLeft = InformationBufferLength;
  494. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  495. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  496. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  497. NDIS_MEDIA_STATE MediaState;
  498. NDIS_MEDIUM Medium;
  499. PATMLANE_ELAN pElan;
  500. PATMLANE_ADAPTER pAdapter;
  501. ULONG GenericULong;
  502. USHORT GenericUShort;
  503. UCHAR GenericArray[6];
  504. UINT MoveBytes = sizeof(ULONG);
  505. PVOID MoveSource = (PVOID)(&GenericULong);
  506. ULONG i;
  507. PATMLANE_MAC_ENTRY pMacEntry;
  508. PATMLANE_ATM_ENTRY pAtmEntry;
  509. BOOLEAN IsShuttingDown;
  510. #if DEBUG_IRQL
  511. KIRQL EntryIrql;
  512. #endif
  513. GET_ENTRY_IRQL(EntryIrql);
  514. TRACEIN(MQueryInformation);
  515. pElan = (PATMLANE_ELAN)MiniportAdapterContext;
  516. STRUCT_ASSERT(pElan, atmlane_elan);
  517. DBGP((1, "%d Query OID %x %s\n", pElan->ElanNumber, Oid, OidToString(Oid)));
  518. ACQUIRE_ELAN_LOCK(pElan);
  519. IsShuttingDown = (ELAN_STATE_OPERATIONAL != pElan->AdminState);
  520. pAdapter = pElan->pAdapter;
  521. RELEASE_ELAN_LOCK(pElan);
  522. //
  523. // Switch on request type
  524. //
  525. switch (Oid)
  526. {
  527. case OID_GEN_MAC_OPTIONS:
  528. GenericULong =
  529. NDIS_MAC_OPTION_NO_LOOPBACK;
  530. DBGP((2, "Value %d\n", GenericULong));
  531. break;
  532. case OID_GEN_SUPPORTED_LIST:
  533. if (pElan->LanType == LANE_LANTYPE_ETH)
  534. {
  535. MoveSource = (PVOID)(EthernetSupportedOids);
  536. MoveBytes = sizeof(EthernetSupportedOids);
  537. }
  538. else
  539. {
  540. MoveSource = (PVOID)(TokenRingSupportedOids);
  541. MoveBytes = sizeof(TokenRingSupportedOids);
  542. }
  543. break;
  544. case OID_GEN_HARDWARE_STATUS:
  545. HardwareStatus = NdisHardwareStatusReady;
  546. MoveSource = (PVOID)(&HardwareStatus);
  547. MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
  548. break;
  549. case OID_GEN_MEDIA_CONNECT_STATUS:
  550. if (ELAN_STATE_OPERATIONAL == pElan->State)
  551. {
  552. MediaState = NdisMediaStateConnected;
  553. }
  554. else
  555. {
  556. MediaState = NdisMediaStateDisconnected;
  557. }
  558. DBGP((2, "%d Elan %p returning conn status %d: %s\n",
  559. pElan->ElanNumber,
  560. pElan,
  561. MediaState,
  562. ((MediaState == NdisMediaStateConnected)?
  563. "Connected": "Disconnected")));
  564. MoveSource = (PVOID)(&MediaState);
  565. MoveBytes = sizeof(NDIS_MEDIA_STATE);
  566. break;
  567. case OID_GEN_MEDIA_SUPPORTED:
  568. case OID_GEN_MEDIA_IN_USE:
  569. if (pElan->LanType == LANE_LANTYPE_ETH)
  570. {
  571. Medium = NdisMedium802_3;
  572. DBGP((2, "Media is NdisMedium802_3\n"));
  573. }
  574. else
  575. {
  576. Medium = NdisMedium802_5;
  577. DBGP((2, "Media is NdisMedium802_5\n"));
  578. }
  579. MoveSource = (PVOID) (&Medium);
  580. MoveBytes = sizeof(NDIS_MEDIUM);
  581. break;
  582. case OID_GEN_MAXIMUM_LOOKAHEAD:
  583. if (pAdapter != NULL_PATMLANE_ADAPTER)
  584. {
  585. GenericULong = pElan->pAdapter->MaxAAL5PacketSize;
  586. }
  587. else
  588. {
  589. GenericULong = pElan->CurLookAhead;
  590. }
  591. DBGP((2, "Value %d\n", GenericULong));
  592. break;
  593. case OID_GEN_CURRENT_LOOKAHEAD:
  594. if (pElan->CurLookAhead == 0)
  595. {
  596. if (pAdapter != NULL_PATMLANE_ADAPTER)
  597. {
  598. pElan->CurLookAhead = pAdapter->MaxAAL5PacketSize;
  599. }
  600. }
  601. GenericULong = pElan->CurLookAhead;
  602. DBGP((2, "Value %d\n", GenericULong));
  603. break;
  604. case OID_GEN_MAXIMUM_FRAME_SIZE:
  605. GenericULong = (pElan->MaxFrameSize - LANE_ETH_HEADERSIZE);
  606. DBGP((2, "Value %d\n", GenericULong));
  607. break;
  608. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  609. GenericULong = (pElan->MaxFrameSize - LANE_HEADERSIZE);
  610. DBGP((2, "Value %d\n", GenericULong));
  611. break;
  612. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  613. GenericULong = (pElan->MaxFrameSize - LANE_HEADERSIZE);
  614. DBGP((2, "Value %d\n", GenericULong));
  615. break;
  616. case OID_GEN_RECEIVE_BLOCK_SIZE:
  617. GenericULong = (pElan->MaxFrameSize - LANE_HEADERSIZE);
  618. DBGP((2, "Value %d\n", GenericULong));
  619. break;
  620. case OID_GEN_MAXIMUM_SEND_PACKETS:
  621. GenericULong = 32; // XXX What is our limit? From adapter?
  622. DBGP((2, "Value %d\n", GenericULong));
  623. break;
  624. case OID_GEN_LINK_SPEED:
  625. if (pAdapter != NULL_PATMLANE_ADAPTER)
  626. {
  627. GenericULong = pElan->pAdapter->LinkSpeed.Outbound;
  628. }
  629. else
  630. {
  631. GenericULong = ATM_USER_DATA_RATE_SONET_155;
  632. }
  633. DBGP((2, "Value %d\n", GenericULong));
  634. break;
  635. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  636. case OID_GEN_RECEIVE_BUFFER_SPACE:
  637. GenericULong = 32 * 1024; // XXX What should this really be?
  638. DBGP((2, "Value %d\n", GenericULong));
  639. break;
  640. case OID_GEN_VENDOR_ID:
  641. NdisMoveMemory(
  642. (PVOID)&GenericULong,
  643. &pElan->MacAddressEth,
  644. 3
  645. );
  646. GenericULong &= 0xFFFFFF00;
  647. MoveSource = (PVOID)(&GenericULong);
  648. MoveBytes = sizeof(GenericULong);
  649. break;
  650. case OID_GEN_VENDOR_DESCRIPTION:
  651. MoveSource = (PVOID)"Microsoft ATM LAN Emulation";
  652. MoveBytes = 28;
  653. break;
  654. case OID_GEN_DRIVER_VERSION:
  655. case OID_GEN_VENDOR_DRIVER_VERSION:
  656. GenericUShort = ((USHORT)5 << 8) | 0;
  657. MoveSource = (PVOID)(&GenericUShort);
  658. MoveBytes = sizeof(GenericUShort);
  659. DBGP((2, "Value %x\n", GenericUShort));
  660. break;
  661. case OID_802_3_PERMANENT_ADDRESS:
  662. case OID_802_3_CURRENT_ADDRESS:
  663. NdisMoveMemory((PCHAR)GenericArray,
  664. &pElan->MacAddressEth,
  665. sizeof(MAC_ADDRESS));
  666. MoveSource = (PVOID)(GenericArray);
  667. MoveBytes = sizeof(MAC_ADDRESS);
  668. DBGP((1, "%d Address is %s\n", pElan->ElanNumber,
  669. MacAddrToString(MoveSource)));
  670. break;
  671. case OID_802_5_PERMANENT_ADDRESS:
  672. case OID_802_5_CURRENT_ADDRESS:
  673. NdisMoveMemory((PCHAR)GenericArray,
  674. &pElan->MacAddressTr,
  675. sizeof(MAC_ADDRESS));
  676. MoveSource = (PVOID)(GenericArray);
  677. MoveBytes = sizeof(MAC_ADDRESS);
  678. DBGP((1, "%d Address is %s\n", pElan->ElanNumber,
  679. MacAddrToString(MoveSource)));
  680. break;
  681. case OID_802_3_MULTICAST_LIST:
  682. MoveSource = (PVOID) &pElan->McastAddrs[0];
  683. MoveBytes = pElan->McastAddrCount * sizeof(MAC_ADDRESS);
  684. break;
  685. case OID_802_3_MAXIMUM_LIST_SIZE:
  686. GenericULong = MCAST_LIST_SIZE;
  687. DBGP((2, "Value %d\n", GenericULong));
  688. break;
  689. case OID_802_5_CURRENT_FUNCTIONAL:
  690. case OID_802_5_CURRENT_GROUP:
  691. NdisZeroMemory((PCHAR)GenericArray,
  692. sizeof(MAC_ADDRESS));
  693. MoveSource = (PVOID)(GenericArray);
  694. MoveBytes = sizeof(MAC_ADDRESS);
  695. DBGP((2, "Address is %s\n", MacAddrToString(MoveSource)));
  696. break;
  697. case OID_802_5_LAST_OPEN_STATUS:
  698. case OID_802_5_CURRENT_RING_STATUS:
  699. case OID_802_5_CURRENT_RING_STATE:
  700. GenericULong = 0;
  701. DBGP((2, "Value %d\n", GenericULong));
  702. break;
  703. case OID_GEN_XMIT_OK:
  704. GenericULong = (UINT)(pElan->FramesXmitGood);
  705. DBGP((2, "Value %d\n", GenericULong));
  706. break;
  707. case OID_GEN_RCV_OK:
  708. GenericULong = (UINT)(pElan->FramesRecvGood);
  709. DBGP((2, "Value %d\n", GenericULong));
  710. break;
  711. case OID_GEN_XMIT_ERROR:
  712. case OID_GEN_RCV_ERROR:
  713. case OID_GEN_RCV_NO_BUFFER:
  714. case OID_802_3_RCV_ERROR_ALIGNMENT:
  715. case OID_802_3_XMIT_ONE_COLLISION:
  716. case OID_802_3_XMIT_MORE_COLLISIONS:
  717. case OID_802_5_LINE_ERRORS:
  718. case OID_802_5_LOST_FRAMES:
  719. case OID_802_5_BURST_ERRORS:
  720. case OID_802_5_FRAME_COPIED_ERRORS:
  721. case OID_802_5_TOKEN_ERRORS:
  722. GenericULong = 0;
  723. DBGP((2, "Value %d\n", GenericULong));
  724. break;
  725. default:
  726. StatusToReturn = NDIS_STATUS_INVALID_OID;
  727. break;
  728. }
  729. if (StatusToReturn == NDIS_STATUS_SUCCESS)
  730. {
  731. if (MoveBytes > BytesLeft)
  732. {
  733. //
  734. // Not enough room in InformationBuffer. Punt
  735. //
  736. *BytesNeeded = MoveBytes;
  737. *BytesWritten = 0;
  738. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  739. }
  740. else
  741. {
  742. //
  743. // Store result.
  744. //
  745. NdisMoveMemory(InfoBuffer, MoveSource, MoveBytes);
  746. *BytesWritten = MoveBytes;
  747. }
  748. }
  749. DBGP((2, "Query Status %x\n", StatusToReturn));
  750. TRACEOUT(MQueryInformation);
  751. CHECK_EXIT_IRQL(EntryIrql);
  752. return StatusToReturn;
  753. }
  754. NDIS_STATUS
  755. AtmLaneMSetInformation(
  756. IN NDIS_HANDLE MiniportAdapterContext,
  757. IN NDIS_OID Oid,
  758. IN PVOID InformationBuffer,
  759. IN ULONG InformationBufferLength,
  760. OUT PULONG BytesRead,
  761. OUT PULONG BytesNeeded
  762. )
  763. /*++
  764. Routine Description:
  765. Handles a set operation for a single OID.
  766. Arguments:
  767. MiniportAdapterContext - a pointer to the Elan.
  768. Oid - the NDIS_OID to process.
  769. InformationBuffer - Holds the data to be set.
  770. InformationBufferLength - The length of InformationBuffer.
  771. BytesRead - If the call is successful, returns the number
  772. of bytes read from InformationBuffer.
  773. BytesNeeded - If there is not enough data in InformationBuffer
  774. to satisfy the OID, returns the amount of storage
  775. needed.
  776. Return Value:
  777. NDIS_STATUS_SUCCESS
  778. NDIS_STATUS_PENDING
  779. NDIS_STATUS_INVALID_LENGTH
  780. NDIS_STATUS_INVALID_OID
  781. --*/
  782. {
  783. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  784. UINT BytesLeft = InformationBufferLength;
  785. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  786. UINT OidLength;
  787. ULONG LookAhead;
  788. ULONG Filter;
  789. PATMLANE_ELAN pElan;
  790. BOOLEAN IsShuttingDown;
  791. #if DEBUG_IRQL
  792. KIRQL EntryIrql;
  793. #endif
  794. GET_ENTRY_IRQL(EntryIrql);
  795. TRACEIN(MSetInformation);
  796. pElan = (PATMLANE_ELAN)MiniportAdapterContext;
  797. STRUCT_ASSERT(pElan, atmlane_elan);
  798. DBGP((1, "%d Set OID %x %s\n", pElan->ElanNumber, Oid, OidToString(Oid)));
  799. ACQUIRE_ELAN_LOCK(pElan);
  800. IsShuttingDown = (ELAN_STATE_OPERATIONAL != pElan->AdminState);
  801. RELEASE_ELAN_LOCK(pElan);
  802. if (IsShuttingDown)
  803. {
  804. DBGP((1, "%d ELAN shutting down. Trivially succeeding Set OID %x %s\n",
  805. pElan->ElanNumber, Oid, OidToString(Oid)));
  806. *BytesRead = 0;
  807. *BytesNeeded = 0;
  808. StatusToReturn = NDIS_STATUS_SUCCESS;
  809. return (StatusToReturn);
  810. }
  811. //
  812. // Get Oid and Length of request
  813. //
  814. OidLength = BytesLeft;
  815. switch (Oid)
  816. {
  817. case OID_802_3_MULTICAST_LIST:
  818. if (OidLength % sizeof(MAC_ADDRESS))
  819. {
  820. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  821. *BytesRead = 0;
  822. *BytesNeeded = 0;
  823. break;
  824. }
  825. if (OidLength > (MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)))
  826. {
  827. StatusToReturn = NDIS_STATUS_MULTICAST_FULL;
  828. *BytesRead = 0;
  829. *BytesNeeded = 0;
  830. break;
  831. }
  832. NdisZeroMemory(
  833. &pElan->McastAddrs[0],
  834. MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)
  835. );
  836. NdisMoveMemory(
  837. &pElan->McastAddrs[0],
  838. InfoBuffer,
  839. OidLength
  840. );
  841. pElan->McastAddrCount = OidLength / sizeof(MAC_ADDRESS);
  842. #if DBG
  843. {
  844. ULONG i;
  845. for (i = 0; i < pElan->McastAddrCount; i++)
  846. {
  847. DBGP((2, "%s\n", MacAddrToString(&pElan->McastAddrs[i])));
  848. }
  849. }
  850. #endif // DBG
  851. break;
  852. case OID_GEN_CURRENT_PACKET_FILTER:
  853. //
  854. // Verify length
  855. //
  856. if (OidLength != sizeof(ULONG))
  857. {
  858. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  859. *BytesRead = 0;
  860. *BytesNeeded = sizeof(ULONG);
  861. break;
  862. }
  863. //
  864. // Store the new value.
  865. //
  866. NdisMoveMemory(&Filter, InfoBuffer, sizeof(ULONG));
  867. //
  868. // Don't allow promisc mode, because we can't support that.
  869. //
  870. if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
  871. {
  872. StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
  873. break;
  874. }
  875. ACQUIRE_ELAN_LOCK(pElan);
  876. pElan->CurPacketFilter = Filter;
  877. //
  878. // Mark Miniport Running if not already
  879. //
  880. if ((pElan->Flags & ELAN_MINIPORT_OPERATIONAL) == 0)
  881. {
  882. pElan->Flags |= ELAN_MINIPORT_OPERATIONAL;
  883. DBGP((1, "%d Miniport OPERATIONAL\n", pElan->ElanNumber));
  884. }
  885. RELEASE_ELAN_LOCK(pElan);
  886. DBGP((2, "CurPacketFilter now %x\n", Filter));
  887. break;
  888. case OID_802_5_CURRENT_FUNCTIONAL:
  889. case OID_802_5_CURRENT_GROUP:
  890. // XXX just accept whatever for now ???
  891. break;
  892. case OID_GEN_CURRENT_LOOKAHEAD:
  893. //
  894. // Verify length
  895. //
  896. if (OidLength != 4)
  897. {
  898. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  899. *BytesRead = 0;
  900. *BytesNeeded = 0;
  901. break;
  902. }
  903. //
  904. // Store the new value.
  905. //
  906. NdisMoveMemory(&LookAhead, InfoBuffer, 4);
  907. if ((pElan->pAdapter == NULL_PATMLANE_ADAPTER) ||
  908. (LookAhead <= pElan->pAdapter->MaxAAL5PacketSize))
  909. {
  910. pElan->CurLookAhead = LookAhead;
  911. DBGP((2, "CurLookAhead now %d\n", LookAhead));
  912. }
  913. else
  914. {
  915. StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
  916. }
  917. break;
  918. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  919. StatusToReturn = AtmLaneMSetNetworkAddresses(
  920. pElan,
  921. InformationBuffer,
  922. InformationBufferLength,
  923. BytesRead,
  924. BytesNeeded);
  925. break;
  926. default:
  927. StatusToReturn = NDIS_STATUS_INVALID_OID;
  928. *BytesRead = 0;
  929. *BytesNeeded = 0;
  930. break;
  931. }
  932. if (StatusToReturn == NDIS_STATUS_SUCCESS)
  933. {
  934. *BytesRead = BytesLeft;
  935. *BytesNeeded = 0;
  936. }
  937. DBGP((2, "Set Status %x\n", StatusToReturn));
  938. TRACEOUT(MSetInformation);
  939. CHECK_EXIT_IRQL(EntryIrql);
  940. return StatusToReturn;
  941. }
  942. NDIS_STATUS
  943. AtmLaneMReset(
  944. OUT PBOOLEAN AddressingReset,
  945. IN NDIS_HANDLE MiniportAdapterContext
  946. )
  947. {
  948. TRACEIN(MReset);
  949. TRACEOUT(MReset);
  950. return NDIS_STATUS_NOT_RESETTABLE;
  951. }
  952. VOID
  953. AtmLaneMHalt(
  954. IN NDIS_HANDLE MiniportAdapterContext
  955. )
  956. {
  957. PATMLANE_ELAN pElan;
  958. ULONG rc;
  959. #if DEBUG_IRQL
  960. KIRQL EntryIrql;
  961. #endif
  962. GET_ENTRY_IRQL(EntryIrql);
  963. TRACEIN(MHalt);
  964. pElan = (PATMLANE_ELAN)MiniportAdapterContext;
  965. STRUCT_ASSERT(pElan, atmlane_elan);
  966. ACQUIRE_ELAN_LOCK(pElan);
  967. DBGP((1, "%d MHalt pElan %x, ref count %d, Admin state %d, State %d\n",
  968. pElan->ElanNumber, pElan, pElan->RefCount, pElan->AdminState, pElan->State));
  969. pElan->MiniportAdapterHandle = NULL;
  970. rc = AtmLaneDereferenceElan(pElan, "miniport"); // Miniport handle is gone.
  971. if (rc != 0)
  972. {
  973. AtmLaneShutdownElan(pElan, FALSE);
  974. // lock released in above
  975. }
  976. //
  977. // else the Elan is gone.
  978. //
  979. TRACEOUT(MHalt);
  980. CHECK_EXIT_IRQL(EntryIrql);
  981. return;
  982. }
  983. PNDIS_PACKET
  984. AtmLaneWrapSendPacket(
  985. IN PATMLANE_ELAN pElan,
  986. IN PNDIS_PACKET pSendNdisPacket,
  987. OUT ULONG * pAddressType,
  988. OUT PMAC_ADDRESS pDestAddress,
  989. OUT BOOLEAN * pSendViaBUS
  990. )
  991. /*++
  992. Routine Description:
  993. This function repackages a protocol sent NDIS packet.
  994. It puts on a new NDIS packet header and a buffer for
  995. the LANE header. It saves away the original packet
  996. header in the ProtocolReserved area of the new packet header.
  997. Additionally, it determines if packet is to be sent via
  998. the BUS and the destination address of the packet.
  999. Arguments:
  1000. pElan - Pointer to ATMLANE elan structure
  1001. pSendNdisPacket - Pointer to NDIS packet
  1002. pAddressType - Pointer to ULONG that gets one of
  1003. (LANE_MACADDRTYPE_MACADDR,
  1004. LANE_MACADDRTYPE_ROUTEDESCR).
  1005. pDestAddress - Pointer to 6-byte buffer that gets
  1006. destination address.
  1007. pSendViaBus - Pointer to boolean
  1008. Return Value:
  1009. New NDIS packet header or NULL if out of resources.
  1010. --*/
  1011. {
  1012. PNDIS_PACKET pNewNdisPacket;
  1013. PNDIS_BUFFER pTempNdisBuffer;
  1014. PUCHAR pHeaderBuffer;
  1015. PUCHAR pNewHeaderBuffer;
  1016. PUCHAR pNewPadBuffer;
  1017. ULONG BufferLength;
  1018. ULONG TotalLength;
  1019. PNDIS_BUFFER pHeaderNdisBuffer;
  1020. PNDIS_BUFFER pPadNdisBuffer;
  1021. NDIS_STATUS Status;
  1022. PSEND_PACKET_RESERVED pNewPacketContext;
  1023. ULONG OrigBufferCount;
  1024. ULONG WrappedBufferCount;
  1025. ULONG RILength;
  1026. BOOLEAN DirectionBit;
  1027. PUCHAR pCurRouteDescr;
  1028. PUCHAR pNextRouteDescr;
  1029. TRACEIN(WrapSendPacket);
  1030. //
  1031. // Initialize
  1032. //
  1033. pNewNdisPacket = (PNDIS_PACKET)NULL;
  1034. pHeaderNdisBuffer = (PNDIS_BUFFER)NULL;
  1035. pPadNdisBuffer = (PNDIS_BUFFER)NULL;
  1036. Status = NDIS_STATUS_SUCCESS;
  1037. OrigBufferCount = 0;
  1038. WrappedBufferCount = 0;
  1039. do
  1040. {
  1041. //
  1042. // Get first buffer and total length of packet
  1043. //
  1044. NdisGetFirstBufferFromPacket(
  1045. pSendNdisPacket,
  1046. &pTempNdisBuffer,
  1047. &pHeaderBuffer,
  1048. &BufferLength,
  1049. &TotalLength);
  1050. DBGP((3, "WrapSendPacket: SendPkt %x Length %d\n",
  1051. pSendNdisPacket, TotalLength));
  1052. ASSERT(pTempNdisBuffer != NULL);
  1053. //
  1054. // Allocate a new transmit packet descriptor
  1055. //
  1056. NdisAllocatePacket(&Status, &pNewNdisPacket, pElan->TransmitPacketPool);
  1057. if (Status != NDIS_STATUS_SUCCESS)
  1058. {
  1059. DBGP((0, "WrapSendPacket: Alloc xmit NDIS Packet failed\n"));
  1060. Status = NDIS_STATUS_RESOURCES;
  1061. break;
  1062. }
  1063. #if PKT_HDR_COUNTS
  1064. InterlockedDecrement(&pElan->XmitPktCount);
  1065. if ((pElan->XmitPktCount % 20) == 0)
  1066. {
  1067. DBGP((1, "XmitPktCount %d\n", pElan->XmitPktCount));
  1068. }
  1069. #endif
  1070. //
  1071. // Allocate a Header Buffer
  1072. //
  1073. pHeaderNdisBuffer = AtmLaneAllocateHeader(pElan, &pNewHeaderBuffer);
  1074. if (pHeaderNdisBuffer == (PNDIS_BUFFER)NULL)
  1075. {
  1076. DBGP((0, "WrapSendPacket: Alloc Header Buffer failed\n"));
  1077. Status = NDIS_STATUS_RESOURCES;
  1078. break;
  1079. }
  1080. //
  1081. // Spec says we can put zero or our LECID in the header.
  1082. // We'll put our LECID in the header for echo-filtering purposes.
  1083. //
  1084. ASSERT(pElan->HeaderBufSize == LANE_HEADERSIZE);
  1085. *((PUSHORT)pNewHeaderBuffer) = pElan->LecId;
  1086. //
  1087. // Allocate a pad buffer now, if necessary, before we get all tied
  1088. // up in knots.
  1089. //
  1090. if ((TotalLength + LANE_HEADERSIZE) < pElan->MinFrameSize)
  1091. {
  1092. pPadNdisBuffer = AtmLaneAllocatePadBuf(pElan, &pNewPadBuffer);
  1093. if (pPadNdisBuffer == (PNDIS_BUFFER)NULL)
  1094. {
  1095. DBGP((0, "WrapSendPacket: Alloc Pad Buffer failed\n"));
  1096. Status = NDIS_STATUS_RESOURCES;
  1097. break;
  1098. }
  1099. }
  1100. //
  1101. // Put new header buffer at head of new NDIS Packet
  1102. //
  1103. NdisChainBufferAtFront(pNewNdisPacket, pHeaderNdisBuffer);
  1104. WrappedBufferCount++;
  1105. //
  1106. // Chain buffers from send packet onto tail of new NDIS Packet
  1107. //
  1108. do
  1109. {
  1110. NdisUnchainBufferAtFront(pSendNdisPacket, &pTempNdisBuffer);
  1111. if (pTempNdisBuffer == (PNDIS_BUFFER)NULL)
  1112. break;
  1113. ASSERT(pTempNdisBuffer->Next == NULL);
  1114. OrigBufferCount++;
  1115. NdisChainBufferAtBack(pNewNdisPacket, pTempNdisBuffer);
  1116. WrappedBufferCount++;
  1117. }
  1118. while (TRUE);
  1119. //
  1120. // Chain pad buffer on tail if needed (it would be allocated already)
  1121. //
  1122. if (pPadNdisBuffer != (PNDIS_BUFFER)NULL)
  1123. {
  1124. NdisChainBufferAtBack(pNewNdisPacket, pPadNdisBuffer);
  1125. WrappedBufferCount++;
  1126. //
  1127. // Set size of pad buffer to minimum necessary
  1128. //
  1129. NdisAdjustBufferLength(pPadNdisBuffer,
  1130. pElan->MinFrameSize - TotalLength - LANE_HEADERSIZE);
  1131. }
  1132. //
  1133. // Save away pointer to original NDIS Packet header in reserved
  1134. // area of our new NDIS Packet header.
  1135. //
  1136. // NOTE use of ProtocolReserved in this case!
  1137. //
  1138. // Also set Owner and Multicast flags appropriately.
  1139. //
  1140. pNewPacketContext =
  1141. (PSEND_PACKET_RESERVED)&pNewNdisPacket->ProtocolReserved;
  1142. NdisZeroMemory(pNewPacketContext, sizeof(SEND_PACKET_RESERVED));
  1143. #if PROTECT_PACKETS
  1144. INIT_SENDPACKET_LOCK(pNewNdisPacket);
  1145. #endif // PROTECT_PACKETS
  1146. #if DBG
  1147. pNewPacketContext->Signature = 'ENAL';
  1148. #endif
  1149. pNewPacketContext->pOrigNdisPacket = pSendNdisPacket;
  1150. pNewPacketContext->OrigBufferCount = OrigBufferCount;
  1151. pNewPacketContext->OrigPacketLength = TotalLength;
  1152. pNewPacketContext->WrappedBufferCount = WrappedBufferCount;
  1153. SET_FLAG(
  1154. pNewPacketContext->Flags,
  1155. PACKET_RESERVED_OWNER_MASK,
  1156. PACKET_RESERVED_OWNER_PROTOCOL
  1157. );
  1158. ASSERT(pNewPacketContext->Flags == PACKET_RESERVED_OWNER_PROTOCOL);
  1159. //
  1160. // Branch on Ethernet v.s. Token Ring to sniff pkt contents
  1161. //
  1162. if (pElan->LanType == LANE_LANTYPE_ETH)
  1163. {
  1164. // Send packet via BUS if it has a multicast
  1165. // Destination Address. If low-order bit in
  1166. // first byte of the Destination Address is set then
  1167. // it's a multicast or broadcast address.
  1168. // Destination Address is first in packet header and it's
  1169. // always a MAC address.
  1170. //
  1171. *pSendViaBUS = ((*pHeaderBuffer) & 1) != 0;
  1172. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1173. NdisMoveMemory(pDestAddress, pHeaderBuffer, 6);
  1174. }
  1175. else
  1176. {
  1177. ASSERT(pElan->LanType == LANE_LANTYPE_TR);
  1178. //
  1179. // now the very complicated sorting of TR packets
  1180. //
  1181. do
  1182. {
  1183. //
  1184. // Section 8.5.3 of LANE Specification.
  1185. // Multicast frames go to the BUS.
  1186. //
  1187. if ((*(pHeaderBuffer+2) & 0x80) != 0) // DA multicast bit present?
  1188. {
  1189. *pSendViaBUS = TRUE;
  1190. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1191. NdisMoveMemory(pDestAddress, pHeaderBuffer+2, 6);
  1192. break;
  1193. }
  1194. //
  1195. // Section 8.5.2 of LANE Specification.
  1196. // NSR frames go to destination address.
  1197. //
  1198. if ( (*(pHeaderBuffer+8) & 0x80) == 0) // SA RI bit not present?
  1199. {
  1200. *pSendViaBUS = FALSE;
  1201. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1202. NdisMoveMemory(pDestAddress, pHeaderBuffer+2, 6);
  1203. break;
  1204. }
  1205. //
  1206. // Section 8.5.4 of LANE Specification.
  1207. // ARE or STE frames go to the BUS.
  1208. //
  1209. if ( ((*(pHeaderBuffer+8) & 0x80) != 0) && // SA RI bit present and
  1210. ((*(pHeaderBuffer+14) & 0xe0) !=0) ) // RI type field upper bits on?
  1211. {
  1212. *pSendViaBUS = TRUE;
  1213. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1214. NdisMoveMemory(pDestAddress, pHeaderBuffer+2, 6);
  1215. break;
  1216. }
  1217. //
  1218. // Frame is source routed so extract Routing Information (RI) length.
  1219. //
  1220. RILength = *(pHeaderBuffer+14) & 0x1f;
  1221. //
  1222. // Section 8.5.7 of LANE Specification.
  1223. // SR frame with a RI length less than 6 contains no hops.
  1224. // Send to destination address.
  1225. //
  1226. if (RILength < 6)
  1227. {
  1228. *pSendViaBUS = FALSE;
  1229. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1230. NdisMoveMemory(pDestAddress, pHeaderBuffer+2, 6);
  1231. break;
  1232. }
  1233. //
  1234. // Section 8.5.6 of LANE Specification.
  1235. // Odd RILength is invalid, we choose to send via BUS.
  1236. //
  1237. if ((RILength & 1) != 0)
  1238. {
  1239. *pSendViaBUS = FALSE;
  1240. *pAddressType = LANE_MACADDRTYPE_MACADDR;
  1241. NdisMoveMemory(pDestAddress, pHeaderBuffer+2, 6);
  1242. break;
  1243. }
  1244. //
  1245. // Section 8.5.5 of LANE Specification.
  1246. // At this point we have a SR frame with RI Length >= 6;
  1247. // We are never a bridge so frame should go to "next RD".
  1248. //
  1249. *pSendViaBUS = FALSE;
  1250. *pAddressType = LANE_MACADDRTYPE_ROUTEDESCR;
  1251. NdisZeroMemory(pDestAddress, 4);
  1252. DirectionBit = (*(pHeaderBuffer+15) & 0x80) != 0;
  1253. if (DirectionBit)
  1254. {
  1255. //
  1256. // Frame is traversing LAN in reverse order of RDs.
  1257. // "next RD" is the next-to-last RD in the packet.
  1258. // Use Segment ID and Bridge Num from this RD.
  1259. //
  1260. pNextRouteDescr = pHeaderBuffer+14+RILength-4;
  1261. pDestAddress->Byte[4] = pNextRouteDescr[0];
  1262. pDestAddress->Byte[5] = pNextRouteDescr[1];
  1263. }
  1264. else
  1265. {
  1266. //
  1267. // Frame is traversing LAN in the order of the RDs.
  1268. // "next RD" straddles the first and second RD in the packet.
  1269. // Use Segment ID from second RD and Bridge Num from first RD.
  1270. //
  1271. pCurRouteDescr = pHeaderBuffer+14+2; // first RD
  1272. pNextRouteDescr = pHeaderBuffer+14+4; // second RD
  1273. pDestAddress->Byte[4] = pNextRouteDescr[0];
  1274. pDestAddress->Byte[5] = (pNextRouteDescr[1] & 0xf0) | (pCurRouteDescr[1] & 0x0f);
  1275. }
  1276. break;
  1277. }
  1278. while (FALSE);
  1279. }
  1280. NdisQueryPacket(pNewNdisPacket, NULL, NULL, NULL, &TotalLength);
  1281. DBGP((3, "WrapSendPacket: SendPkt %x NewPkt %x Bufs %d Length %d\n",
  1282. pSendNdisPacket, pNewNdisPacket, WrappedBufferCount, TotalLength));
  1283. TRACELOGWRITE((&TraceLog,
  1284. TL_WRAPSEND,
  1285. pSendNdisPacket,
  1286. pNewNdisPacket,
  1287. WrappedBufferCount,
  1288. TotalLength));
  1289. TRACELOGWRITEPKT((&TraceLog, pNewNdisPacket));
  1290. break;
  1291. }
  1292. while (FALSE);
  1293. if (Status != NDIS_STATUS_SUCCESS)
  1294. {
  1295. if (pNewNdisPacket != (PNDIS_PACKET)NULL)
  1296. {
  1297. #if PROTECT_PACKETS
  1298. FREE_SENDPACKET_LOCK(pNewNdisPacket);
  1299. #endif // PROTECT_PACKETS
  1300. NdisFreePacket(pNewNdisPacket);
  1301. pNewNdisPacket = (PNDIS_PACKET)NULL;
  1302. #if PKT_HDR_COUNTS
  1303. InterlockedIncrement(&pElan->XmitPktCount);
  1304. if ((pElan->XmitPktCount % 20) == 0 &&
  1305. pElan->XmitPktCount != pElan->MaxHeaderBufs)
  1306. {
  1307. DBGP((1, "XmitPktCount %d\n", pElan->XmitPktCount));
  1308. }
  1309. #endif
  1310. }
  1311. if (pHeaderNdisBuffer != (PNDIS_BUFFER)NULL)
  1312. {
  1313. AtmLaneFreeHeader(pElan, pHeaderNdisBuffer, FALSE);
  1314. pHeaderNdisBuffer = (PNDIS_BUFFER)NULL;
  1315. }
  1316. if (pPadNdisBuffer != (PNDIS_BUFFER)NULL)
  1317. {
  1318. AtmLaneFreePadBuf(pElan, pPadNdisBuffer, FALSE);
  1319. pPadNdisBuffer = (PNDIS_BUFFER)NULL;
  1320. }
  1321. }
  1322. TRACEOUT(WrapSendPacket);
  1323. return pNewNdisPacket;
  1324. }
  1325. PNDIS_PACKET
  1326. AtmLaneUnwrapSendPacket(
  1327. IN PATMLANE_ELAN pElan,
  1328. IN PNDIS_PACKET pNdisPacket LOCKIN NOLOCKOUT
  1329. )
  1330. /*++
  1331. Routine Description:
  1332. This function basically undoes what AtmLaneWrapSendPacket
  1333. does. It removes the new NDIS packet header and the LANE
  1334. header and frees them. It restores the original packet header.
  1335. Arguments:
  1336. pElan - Pointer to ATMLANE elan structure
  1337. pNdisPacket - Pointer to NDIS packet
  1338. Return Value:
  1339. Original NDIS packet header.
  1340. --*/
  1341. {
  1342. PSEND_PACKET_RESERVED pPacketContext;
  1343. UINT TotalLength;
  1344. PNDIS_PACKET pOrigNdisPacket;
  1345. PNDIS_BUFFER pTempNdisBuffer;
  1346. ULONG OrigPacketLength;
  1347. ULONG OrigBufferCount;
  1348. ULONG WrappedBufferCount;
  1349. ULONG BufferCount;
  1350. BOOLEAN First;
  1351. TRACEIN(UnwrapSendPacket);
  1352. //
  1353. // Get original packet header from reserved area.
  1354. //
  1355. pPacketContext = PSEND_RSVD(pNdisPacket);
  1356. pOrigNdisPacket = pPacketContext->pOrigNdisPacket;
  1357. OrigBufferCount = pPacketContext->OrigBufferCount;
  1358. OrigPacketLength = pPacketContext->OrigPacketLength;
  1359. WrappedBufferCount = pPacketContext->WrappedBufferCount;
  1360. ASSERT(pPacketContext->Signature == 'ENAL');
  1361. ASSERT((pPacketContext->Flags & PACKET_RESERVED_OWNER_PROTOCOL) != 0);
  1362. ASSERT(pPacketContext->pOrigNdisPacket != NULL);
  1363. //
  1364. // Unchain first buffer (ours) and free it.
  1365. //
  1366. pTempNdisBuffer = (PNDIS_BUFFER)NULL;
  1367. NdisUnchainBufferAtFront(pNdisPacket, &pTempNdisBuffer);
  1368. ASSERT(pTempNdisBuffer != (PNDIS_BUFFER)NULL);
  1369. AtmLaneFreeHeader(pElan, pTempNdisBuffer, FALSE);
  1370. //
  1371. // If padded, unchain last buffer (ours) and free it.
  1372. //
  1373. if ((WrappedBufferCount - OrigBufferCount) > 1)
  1374. {
  1375. pTempNdisBuffer = (PNDIS_BUFFER)NULL;
  1376. NdisUnchainBufferAtBack(pNdisPacket, &pTempNdisBuffer);
  1377. ASSERT(pTempNdisBuffer != (PNDIS_BUFFER)NULL);
  1378. AtmLaneFreePadBuf(pElan, pTempNdisBuffer, FALSE);
  1379. }
  1380. //
  1381. // Put rest of buffers back on original packet header.
  1382. //
  1383. First = TRUE;
  1384. BufferCount = 0;
  1385. do
  1386. {
  1387. NdisUnchainBufferAtFront(pNdisPacket, &pTempNdisBuffer);
  1388. ASSERT(!((pTempNdisBuffer == NULL) && First));
  1389. First = FALSE;
  1390. if (pTempNdisBuffer == (PNDIS_BUFFER)NULL)
  1391. break;
  1392. NdisChainBufferAtBack(pOrigNdisPacket, pTempNdisBuffer);
  1393. BufferCount++;
  1394. }
  1395. while (TRUE);
  1396. NdisQueryPacket(pOrigNdisPacket, NULL, NULL, NULL, &TotalLength);
  1397. DBGP((3, "UnwrapSendPacket: SendPkt %x Bufcnt %d Length %d\n",
  1398. pOrigNdisPacket, BufferCount, TotalLength));
  1399. TRACELOGWRITE((&TraceLog,
  1400. TL_UNWRAPSEND,
  1401. pNdisPacket,
  1402. pOrigNdisPacket,
  1403. BufferCount,
  1404. TotalLength));
  1405. TRACELOGWRITEPKT((&TraceLog, pOrigNdisPacket));
  1406. ASSERT(OrigBufferCount == BufferCount);
  1407. // ASSERT(OrigPacketLength == TotalLength);
  1408. //
  1409. // Free the packet header
  1410. //
  1411. #if PROTECT_PACKETS
  1412. RELEASE_SENDPACKET_LOCK(pNdisPacket);
  1413. FREE_SENDPACKET_LOCK(pNdisPacket);
  1414. #endif // PROTECT_PACKETS
  1415. NdisFreePacket(pNdisPacket);
  1416. #if PKT_HDR_COUNTS
  1417. InterlockedIncrement(&pElan->XmitPktCount);
  1418. if ((pElan->XmitPktCount % 20) == 0 &&
  1419. pElan->XmitPktCount != pElan->MaxHeaderBufs)
  1420. {
  1421. DBGP((1, "XmitPktCount %d\n", pElan->XmitPktCount));
  1422. }
  1423. #endif
  1424. TRACEOUT(UnwrapSendPacket);
  1425. return pOrigNdisPacket;
  1426. }
  1427. PNDIS_PACKET
  1428. AtmLaneWrapRecvPacket(
  1429. IN PATMLANE_ELAN pElan,
  1430. IN PNDIS_PACKET pRecvNdisPacket,
  1431. OUT ULONG * pMacHdrSize,
  1432. OUT ULONG * pDestAddrType,
  1433. OUT PMAC_ADDRESS pDestAddr,
  1434. OUT BOOLEAN * pDestIsMulticast
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. This function repackages an adapter received NDIS packet.
  1439. It puts on a new packet header and creates a new buffer
  1440. descriptor for the first fragment that skips the 2-byte
  1441. LANE header. It then saves away the original packet
  1442. header with the original first buffer descriptor in the
  1443. MiniportReserved area of the new packet header.
  1444. Additionally, it outputs the destination address, the
  1445. destination's address type if the packet is a destination
  1446. address is a multicast address.
  1447. Arguments:
  1448. pElan - Pointer to ATMLANE elan structure
  1449. pRecvNdisPacket - Pointer to NDIS packet
  1450. pMacHdrSize - Pointer to ULONG that get the length
  1451. of the MAC header.
  1452. pDestAddrType - Pointer to ULONG that gets one of
  1453. (LANE_MACADDRTYPE_MACADDR,
  1454. LANE_MACADDRTYPE_ROUTEDESCR).
  1455. pDestAddr - Pointer to 6-byte buffer that gets
  1456. destination address.
  1457. pDestIsMulticast - Pointer to boolean that gets TRUE if
  1458. destination address is a multicast.
  1459. Return Value:
  1460. New NDIS packet header or NULL if out of resources.
  1461. --*/
  1462. {
  1463. ULONG TotalLength;
  1464. ULONG TempLength;
  1465. PUCHAR pHeaderBuffer;
  1466. PUCHAR pBuffer;
  1467. PNDIS_PACKET pNewNdisPacket;
  1468. PNDIS_BUFFER pFirstNdisBuffer;
  1469. PNDIS_BUFFER pTempNdisBuffer;
  1470. PNDIS_BUFFER pNewNdisBuffer;
  1471. PUCHAR pTempBuffer;
  1472. PRECV_PACKET_RESERVED pNewPacketContext;
  1473. NDIS_STATUS Status;
  1474. ULONG BufferCount;
  1475. TRACEIN(WrapRecvPacket);
  1476. //
  1477. // Initialize
  1478. //
  1479. pNewNdisPacket = (PNDIS_PACKET)NULL;
  1480. pNewNdisBuffer = (PNDIS_BUFFER)NULL;
  1481. Status = NDIS_STATUS_SUCCESS;
  1482. BufferCount = 0;
  1483. do
  1484. {
  1485. //
  1486. // Get first buffer and total length of packet
  1487. //
  1488. NdisGetFirstBufferFromPacket(
  1489. pRecvNdisPacket,
  1490. &pTempNdisBuffer,
  1491. &pHeaderBuffer,
  1492. &TempLength,
  1493. &TotalLength);
  1494. DBGP((3, "WrapRecvPacket: RecvPkt %x Length %d\n",
  1495. pRecvNdisPacket, TotalLength));
  1496. //
  1497. // Allocate a new recv packet descriptor
  1498. //
  1499. NdisAllocatePacket(&Status, &pNewNdisPacket, pElan->ReceivePacketPool);
  1500. if (Status != NDIS_STATUS_SUCCESS)
  1501. {
  1502. DBGP((0, "WrapRecvPacket: Alloc recv NDIS Packet failed\n"));
  1503. break;
  1504. }
  1505. #if PKT_HDR_COUNTS
  1506. InterlockedDecrement(&pElan->RecvPktCount);
  1507. if ((pElan->RecvPktCount % 20) == 0)
  1508. {
  1509. DBGP((1, "RecvPktCount %d\n", pElan->RecvPktCount));
  1510. }
  1511. #endif
  1512. //
  1513. // Unchain first buffer
  1514. //
  1515. NdisUnchainBufferAtFront(pRecvNdisPacket, &pFirstNdisBuffer);
  1516. ASSERT(pFirstNdisBuffer != (PNDIS_BUFFER)NULL);
  1517. NdisQueryBuffer(pFirstNdisBuffer, &pTempBuffer, &TempLength);
  1518. ASSERT(TempLength > 2);
  1519. //
  1520. // "Copy" it to another buffer header skipping the first 2 bytes
  1521. //
  1522. NdisCopyBuffer(
  1523. &Status,
  1524. &pNewNdisBuffer,
  1525. pElan->ReceiveBufferPool,
  1526. pFirstNdisBuffer,
  1527. 2,
  1528. (TempLength - 2)
  1529. );
  1530. if (Status != NDIS_STATUS_SUCCESS)
  1531. {
  1532. DBGP((0, "DataPacketHandler: NdisCopyBuffer failed (%x)\n",
  1533. Status));
  1534. Status = NDIS_STATUS_RESOURCES;
  1535. break;
  1536. }
  1537. //
  1538. // Chain new buffer onto new packet header.
  1539. //
  1540. NdisChainBufferAtFront(pNewNdisPacket, pNewNdisBuffer);
  1541. BufferCount++;
  1542. //
  1543. // Chain rest of buffers onto tail of new NDIS Packet
  1544. //
  1545. do
  1546. {
  1547. NdisUnchainBufferAtFront(pRecvNdisPacket, &pTempNdisBuffer);
  1548. if (pTempNdisBuffer == (PNDIS_BUFFER)NULL)
  1549. break;
  1550. ASSERT(pTempNdisBuffer->Next == NULL);
  1551. NdisChainBufferAtBack(pNewNdisPacket, pTempNdisBuffer);
  1552. BufferCount++;
  1553. }
  1554. while (TRUE);
  1555. //
  1556. // Chain original first buffer back on original packet
  1557. //
  1558. NdisChainBufferAtFront(pRecvNdisPacket, pFirstNdisBuffer);
  1559. //
  1560. // Save away pointer to original NDIS Packet header in reserved
  1561. // area of our new NDIS Packet header.
  1562. //
  1563. // NOTE use of MiniportReserved in this case!
  1564. //
  1565. // Also set Owner flag appropriately.
  1566. pNewPacketContext =
  1567. (PRECV_PACKET_RESERVED)&pNewNdisPacket->MiniportReserved;
  1568. NdisZeroMemory(pNewPacketContext, sizeof(*pNewPacketContext));
  1569. pNewPacketContext->pNdisPacket = pRecvNdisPacket;
  1570. SET_FLAG(
  1571. pNewPacketContext->Flags,
  1572. PACKET_RESERVED_OWNER_MASK,
  1573. PACKET_RESERVED_OWNER_MINIPORT
  1574. );
  1575. //
  1576. // Increment the frame header pointer past the
  1577. // LANE header (+2 bytes)
  1578. //
  1579. pHeaderBuffer += 2;
  1580. //
  1581. // Output the MAC header length.
  1582. // Output the address type.
  1583. // Output the destination address.
  1584. // Determine if packet is a multicast.
  1585. //
  1586. if (pElan->LanType == LANE_LANTYPE_ETH)
  1587. {
  1588. //
  1589. // Ethernet/802.3 is simple.
  1590. //
  1591. // Header size is always 14.
  1592. // Type is always a MAC address.
  1593. // Dest Addr is first 6 bytes of header.
  1594. // DestAddress is Multicast if low-order bit in
  1595. // first byte of the Destination Address is set.
  1596. //
  1597. *pMacHdrSize = 14;
  1598. *pDestAddrType = LANE_MACADDRTYPE_MACADDR;
  1599. NdisMoveMemory(pDestAddr, pHeaderBuffer, 6);
  1600. *pDestIsMulticast = (((*pHeaderBuffer) & 1) != 0);
  1601. }
  1602. else
  1603. {
  1604. //
  1605. // Token Ring/802.5 is a slightly less simple (understatement!).
  1606. //
  1607. do
  1608. {
  1609. //
  1610. // Calculate MAC header size.
  1611. //
  1612. *pMacHdrSize = 14; // start with minimum
  1613. if (pHeaderBuffer[8] & 0x80) // if SR info present
  1614. {
  1615. *pMacHdrSize += (pHeaderBuffer[14] & 0x1F);// add on SR info length
  1616. }
  1617. //
  1618. // Is it a true Multicast?
  1619. //
  1620. if ((*(pHeaderBuffer+2) & 0x80) != 0) // DA multicast bit present?
  1621. {
  1622. *pDestIsMulticast = TRUE;
  1623. *pDestAddrType = LANE_MACADDRTYPE_MACADDR;
  1624. NdisMoveMemory(pDestAddr, pHeaderBuffer+2, 6);
  1625. break;
  1626. }
  1627. //
  1628. // Is it an All Routes Explorer (ARE) or Spanning Tree Explorer (STE)?
  1629. // If so treat it as a multicast.
  1630. //
  1631. if ( ((*(pHeaderBuffer+8) & 0x80) != 0) && // SA RI bit present and
  1632. ((*(pHeaderBuffer+14) & 0xe0) !=0) ) // RI type field upper bits on?
  1633. {
  1634. *pDestIsMulticast = TRUE;
  1635. *pDestAddrType = LANE_MACADDRTYPE_MACADDR;
  1636. NdisMoveMemory(pDestAddr, pHeaderBuffer+2, 6);
  1637. break;
  1638. }
  1639. //
  1640. // Otherwise it is unicast, Source Routed or not.
  1641. //
  1642. *pDestIsMulticast = FALSE;
  1643. *pDestAddrType = LANE_MACADDRTYPE_MACADDR;
  1644. NdisMoveMemory(pDestAddr, pHeaderBuffer+2, 6);
  1645. break;
  1646. }
  1647. while (FALSE);
  1648. } // if (pElan->LanType == LANE_LANTYPE_ETH)
  1649. NdisQueryPacket(pNewNdisPacket, NULL, NULL, NULL, &TotalLength);
  1650. DBGP((3, "WrapRecvPacket: RecvPkt %x NewPkt %x Length %d\n",
  1651. pRecvNdisPacket, pNewNdisPacket, TempLength));
  1652. TRACELOGWRITE((&TraceLog,
  1653. TL_WRAPRECV,
  1654. pRecvNdisPacket,
  1655. pNewNdisPacket,
  1656. BufferCount,
  1657. TotalLength));
  1658. break;
  1659. }
  1660. while (FALSE);
  1661. if (Status != NDIS_STATUS_SUCCESS)
  1662. {
  1663. if (pNewNdisPacket != (PNDIS_PACKET)NULL)
  1664. {
  1665. NdisFreePacket(pNewNdisPacket);
  1666. #if PKT_HDR_COUNTS
  1667. InterlockedIncrement(&pElan->RecvPktCount);
  1668. if ((pElan->RecvPktCount % 20) == 0 &&
  1669. pElan->RecvPktCount != pElan->MaxHeaderBufs)
  1670. {
  1671. DBGP((1, "RecvPktCount %d\n", pElan->RecvPktCount));
  1672. }
  1673. #endif
  1674. pNewNdisPacket = NULL;
  1675. }
  1676. if (pNewNdisBuffer != (PNDIS_BUFFER)NULL)
  1677. {
  1678. AtmLaneFreeProtoBuffer(pElan, pNewNdisBuffer);
  1679. }
  1680. }
  1681. TRACEOUT(WrapRecvPacket);
  1682. return pNewNdisPacket;
  1683. }
  1684. PNDIS_PACKET
  1685. AtmLaneUnwrapRecvPacket(
  1686. IN PATMLANE_ELAN pElan,
  1687. IN PNDIS_PACKET pNdisPacket
  1688. )
  1689. /*++
  1690. Routine Description:
  1691. This function basically undoes what AtmLaneWrapRecvPacket
  1692. does. It removes the new NDIS packet header and the
  1693. 2-byte offset buffer descriptor. It restores the original
  1694. packet header and first buffer descriptor.
  1695. Arguments:
  1696. pElan - Pointer to ATMLANE elan structure
  1697. pNdisPacket - Pointer to NDIS packet
  1698. Return Value:
  1699. Original NDIS packet header.
  1700. --*/
  1701. {
  1702. PRECV_PACKET_RESERVED pPacketContext;
  1703. PNDIS_PACKET pOrigNdisPacket;
  1704. PNDIS_BUFFER pTempNdisBuffer;
  1705. ULONG BufferCount;
  1706. ULONG TotalLength;
  1707. TRACEIN(UnwrapRecvPacket);
  1708. //
  1709. // Get original packet from MiniportReserved.
  1710. // Should have original first buffer on it still.
  1711. //
  1712. pPacketContext = (PRECV_PACKET_RESERVED)&pNdisPacket->MiniportReserved;
  1713. pOrigNdisPacket = pPacketContext->pNdisPacket;
  1714. ASSERT(pOrigNdisPacket != (PNDIS_PACKET)NULL);
  1715. ASSERT(pOrigNdisPacket->Private.Head != (PNDIS_BUFFER)NULL);
  1716. BufferCount = 1;
  1717. //
  1718. // Unchain first buffer (ours) and free it.
  1719. //
  1720. NdisUnchainBufferAtFront(pNdisPacket, &pTempNdisBuffer);
  1721. NdisFreeBuffer(pTempNdisBuffer);
  1722. //
  1723. // Put rest of buffers back on original packet header.
  1724. //
  1725. do
  1726. {
  1727. NdisUnchainBufferAtFront(pNdisPacket, &pTempNdisBuffer);
  1728. if (pTempNdisBuffer == (PNDIS_BUFFER)NULL)
  1729. break;
  1730. ASSERT(pTempNdisBuffer->Next == NULL);
  1731. NdisChainBufferAtBack(pOrigNdisPacket, pTempNdisBuffer);
  1732. BufferCount++;
  1733. }
  1734. while (TRUE);
  1735. NdisQueryPacket(pOrigNdisPacket, NULL, NULL, NULL, &TotalLength);
  1736. DBGP((3, "UnwrapRecvPacket: Pkt %x Length %d\n", pOrigNdisPacket, TotalLength));
  1737. TRACELOGWRITE((&TraceLog,
  1738. TL_UNWRAPRECV,
  1739. pNdisPacket,
  1740. pOrigNdisPacket,
  1741. BufferCount,
  1742. TotalLength));
  1743. //
  1744. // Free the recv packet descriptor.
  1745. //
  1746. NdisFreePacket(pNdisPacket);
  1747. #if PKT_HDR_COUNTS
  1748. InterlockedIncrement(&pElan->RecvPktCount);
  1749. if ((pElan->RecvPktCount % 20) == 0 &&
  1750. pElan->RecvPktCount != pElan->MaxHeaderBufs)
  1751. {
  1752. DBGP((1, "RecvPktCount %d\n", pElan->RecvPktCount));
  1753. }
  1754. #endif
  1755. TRACEOUT(UnwrapRecvPacket);
  1756. return pOrigNdisPacket;
  1757. }
  1758. NDIS_STATUS
  1759. AtmLaneMSetNetworkAddresses(
  1760. IN PATMLANE_ELAN pElan,
  1761. IN PVOID InformationBuffer,
  1762. IN ULONG InformationBufferLength,
  1763. OUT PULONG BytesRead,
  1764. OUT PULONG BytesNeeded
  1765. )
  1766. /*++
  1767. Routine Description:
  1768. Called when the protocol above us wants to let us know about
  1769. the network address(es) assigned to this interface. If this is TCP/IP,
  1770. then we reformat and send a request to the ATM Call Manager to set
  1771. its atmfMyIpNmAddress object. We pick the first IP address given to us.
  1772. Arguments:
  1773. pElan - Pointer to the ELAN
  1774. InformationBuffer - Holds the data to be set.
  1775. InformationBufferLength - The length of InformationBuffer.
  1776. BytesRead - If the call is successful, returns the number
  1777. of bytes read from InformationBuffer.
  1778. BytesNeeded - If there is not enough data in InformationBuffer
  1779. to satisfy the OID, returns the amount of storage
  1780. needed.
  1781. Return Value:
  1782. NDIS_STATUS_SUCCESS
  1783. NDIS_STATUS_PENDING
  1784. NDIS_STATUS_INVALID_LENGTH
  1785. --*/
  1786. {
  1787. NETWORK_ADDRESS_LIST UNALIGNED * pAddrList;
  1788. NETWORK_ADDRESS UNALIGNED * pAddr;
  1789. NETWORK_ADDRESS_IP UNALIGNED * pIpAddr;
  1790. PNDIS_REQUEST pNdisRequest;
  1791. ULONG RequestSize;
  1792. PUCHAR pNetworkAddr;
  1793. NDIS_HANDLE NdisAdapterHandle;
  1794. NDIS_HANDLE NdisAfHandle;
  1795. NDIS_STATUS Status;
  1796. //
  1797. // Initialize.
  1798. //
  1799. *BytesRead = 0;
  1800. Status = NDIS_STATUS_SUCCESS;
  1801. pAddrList = (NETWORK_ADDRESS_LIST UNALIGNED *)InformationBuffer;
  1802. do
  1803. {
  1804. ACQUIRE_ELAN_LOCK(pElan);
  1805. if (NULL_PATMLANE_ADAPTER != pElan->pAdapter)
  1806. {
  1807. NdisAfHandle = pElan->NdisAfHandle;
  1808. NdisAdapterHandle = pElan->pAdapter->NdisAdapterHandle;
  1809. }
  1810. else
  1811. {
  1812. Status = NDIS_STATUS_FAILURE;
  1813. }
  1814. RELEASE_ELAN_LOCK(pElan);
  1815. if (NDIS_STATUS_SUCCESS != Status)
  1816. {
  1817. break;
  1818. }
  1819. *BytesNeeded = sizeof(*pAddrList) -
  1820. FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
  1821. sizeof(NETWORK_ADDRESS) -
  1822. FIELD_OFFSET(NETWORK_ADDRESS, Address);
  1823. if (InformationBufferLength < *BytesNeeded)
  1824. {
  1825. Status = NDIS_STATUS_INVALID_LENGTH;
  1826. break;
  1827. }
  1828. if (pAddrList->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
  1829. {
  1830. // Not interesting.
  1831. break;
  1832. }
  1833. if (pAddrList->AddressCount <= 0)
  1834. {
  1835. Status = NDIS_STATUS_INVALID_DATA;
  1836. break;
  1837. }
  1838. pAddr = (NETWORK_ADDRESS UNALIGNED *)&pAddrList->Address[0];
  1839. if ((pAddr->AddressLength > InformationBufferLength - *BytesNeeded) ||
  1840. (pAddr->AddressLength == 0))
  1841. {
  1842. Status = NDIS_STATUS_INVALID_LENGTH;
  1843. break;
  1844. }
  1845. if (pAddr->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
  1846. {
  1847. // Not interesting.
  1848. break;
  1849. }
  1850. if (pAddr->AddressLength < sizeof(NETWORK_ADDRESS_IP))
  1851. {
  1852. Status = NDIS_STATUS_INVALID_LENGTH;
  1853. break;
  1854. }
  1855. pIpAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
  1856. //
  1857. // Allocate an NDIS request to send down to the call manager.
  1858. //
  1859. RequestSize = sizeof(NDIS_REQUEST) + sizeof(pIpAddr->in_addr);
  1860. ALLOC_MEM(&pNdisRequest, RequestSize);
  1861. if (pNdisRequest == NULL)
  1862. {
  1863. Status = NDIS_STATUS_RESOURCES;
  1864. break;
  1865. }
  1866. //
  1867. // Copy the network address in.
  1868. //
  1869. pNetworkAddr = ((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
  1870. NdisMoveMemory(pNetworkAddr, &pIpAddr->in_addr, sizeof(pIpAddr->in_addr));
  1871. DBGP((3, "%d Set network layer addr: length %d\n", pElan->ElanNumber, pAddr->AddressLength));
  1872. #if DBG
  1873. if (pAddr->AddressLength >= 4)
  1874. {
  1875. DBGP((1, "Network layer addr: %d.%d.%d.%d\n",
  1876. pNetworkAddr[0],
  1877. pNetworkAddr[1],
  1878. pNetworkAddr[2],
  1879. pNetworkAddr[3]));
  1880. }
  1881. #endif // DBG
  1882. //
  1883. // Send off the request.
  1884. //
  1885. Status = AtmLaneSendNdisCoRequest(
  1886. NdisAdapterHandle,
  1887. NdisAfHandle,
  1888. pNdisRequest,
  1889. NdisRequestSetInformation,
  1890. OID_ATM_MY_IP_NM_ADDRESS,
  1891. pNetworkAddr,
  1892. sizeof(pIpAddr->in_addr)
  1893. );
  1894. if (Status == NDIS_STATUS_PENDING)
  1895. {
  1896. Status = NDIS_STATUS_SUCCESS;
  1897. }
  1898. break;
  1899. }
  1900. while (FALSE);
  1901. return (Status);
  1902. }