Source code of Windows XP (NT5)
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.

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