Windows NT 4.0 source code leak
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.

2085 lines
42 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. lslmlid.c
  5. Abstract:
  6. This file contains all the MLID interface routines to the LSL
  7. Author:
  8. Sean Selitrennikoff (SeanSe) 3-8-93
  9. Environment:
  10. Kernel Mode.
  11. Revision History:
  12. --*/
  13. #include <ndis.h>
  14. #include "lsl.h"
  15. #include "frames.h"
  16. #include "lslmlid.h"
  17. #include "mlid.h"
  18. //
  19. // A global which has pointers to the functions in this file. Used for registering
  20. // with the LSL.
  21. //
  22. INFO_BLOCK
  23. NdisMlidInfoBlock = {
  24. 0xE,
  25. {
  26. GetMLIDConfiguration,
  27. GetMLIDStatistics,
  28. AddMulticastAddress,
  29. DeleteMulticastAddress,
  30. NULL,
  31. MLIDShutdown,
  32. MLIDReset,
  33. NULL,
  34. NULL,
  35. SetLookAheadSize,
  36. PromiscuousChange,
  37. NULL,
  38. NULL,
  39. MLIDManagement
  40. }
  41. };
  42. MLID_Reg
  43. NdisMlidHandlerInfo = {
  44. MLIDSendHandler,
  45. &NdisMlidInfoBlock
  46. };
  47. UINT32
  48. BuildNewMulticastList(
  49. PMLID_STRUCT Mlid,
  50. PUINT8 AddMulticastAddr
  51. );
  52. UINT32
  53. BuildNewFunctionalAddr(
  54. PMLID_STRUCT Mlid,
  55. PUINT8 AddFunctionalAddr
  56. );
  57. UINT32
  58. RemoveFromMulticastList(
  59. PMLID_STRUCT Mlid,
  60. PUINT8 DelMulticastAddr
  61. );
  62. UINT32
  63. RemoveFromFunctionalAddr(
  64. PMLID_STRUCT Mlid,
  65. PUINT8 DelFunctionalAddr
  66. );
  67. PMLID_ConfigTable
  68. GetMLIDConfiguration(
  69. UINT32 BoardNumber
  70. )
  71. /*++
  72. Routine Description:
  73. Returns a pointer to the MLIDs configuration table for the specified logical
  74. board. This commnand is supported by all MLIDs. A separate configuration
  75. table is maintained by the MLID for each adapter/frame-type combination.
  76. Arguments:
  77. BoardNumber - The board number.
  78. Return Value:
  79. PMLID_ConfigTable - A pointer to tyhe MLIDs configuration table.
  80. NULL - Reports the BAD_PARAMETER condition, MLID does not exist.
  81. --*/
  82. {
  83. UINT32 i;
  84. PMLID_ConfigTable ConfigTable;
  85. NdisAcquireSpinLock(&NdisMlidSpinLock);
  86. //
  87. // Verify that BoardNumber is in valid range
  88. //
  89. for (i =0 ; i < AllocatedMlidBoards; i++) {
  90. if (MlidBoards[i].BoardNumber == BoardNumber) {
  91. break;
  92. }
  93. }
  94. if (i == AllocatedMlidBoards) {
  95. NdisReleaseSpinLock(&NdisMlidSpinLock);
  96. return(NULL);
  97. }
  98. //
  99. // If BoardNumber is not open, fail.
  100. //
  101. if (MlidBoards[i].Mlid == NULL) {
  102. NdisReleaseSpinLock(&NdisMlidSpinLock);
  103. return(NULL);
  104. }
  105. //
  106. // If Board is unloading - fail
  107. //
  108. if (MlidBoards[i].Mlid->Unloading) {
  109. NdisReleaseSpinLock(&NdisMlidSpinLock);
  110. return(NULL);
  111. }
  112. //
  113. // return pointer to configuration table.
  114. //
  115. ConfigTable = &(MlidBoards[i].Mlid->ConfigTable);
  116. NdisReleaseSpinLock(&NdisMlidSpinLock);
  117. return(ConfigTable);
  118. }
  119. PMLID_StatsTable
  120. GetMLIDStatistics(
  121. UINT32 BoardNumber
  122. )
  123. /*++
  124. Routine Description:
  125. Returns a pointer to the MLIDs statistics table for the specified board. All
  126. MLIDs support this command. The MLID maintains one statistics table for each
  127. physical adapter. Each frame-type (or logical board) present for that physical
  128. adapter uses the same table. The board number can be any of the logical
  129. board values present for the physical adapter. Regardless of the logical
  130. board number, GetMLIDStatistics will return the same table.
  131. Arguments:
  132. BoardNumber - The board number.
  133. Return Value:
  134. PMLID_Statistics - A pointer to the MLIDs Statistics Table.
  135. NULL - Reports the BAD_PARAMETER condition.
  136. --*/
  137. {
  138. UINT32 i;
  139. PMLID_StatsTable StatsTable;
  140. NdisAcquireSpinLock(&NdisMlidSpinLock);
  141. //
  142. // Verify that BoardNumber is in valid range
  143. //
  144. for (i =0 ; i < AllocatedMlidBoards; i++) {
  145. if (MlidBoards[i].BoardNumber == BoardNumber) {
  146. break;
  147. }
  148. }
  149. if (i == AllocatedMlidBoards) {
  150. NdisReleaseSpinLock(&NdisMlidSpinLock);
  151. return(NULL);
  152. }
  153. //
  154. // If BoardNumber is not open, fail.
  155. //
  156. if (MlidBoards[i].Mlid == NULL) {
  157. NdisReleaseSpinLock(&NdisMlidSpinLock);
  158. return(NULL);
  159. }
  160. //
  161. // If Board is unloading - fail
  162. //
  163. if (MlidBoards[i].Mlid->Unloading) {
  164. NdisReleaseSpinLock(&NdisMlidSpinLock);
  165. return(NULL);
  166. }
  167. //
  168. // return pointer to statistics table.
  169. //
  170. StatsTable = &(MlidBoards[i].Mlid->StatsTable->StatsTable);
  171. NdisReleaseSpinLock(&NdisMlidSpinLock);
  172. return(StatsTable);
  173. }
  174. UINT32
  175. AddMulticastAddress(
  176. UINT32 BoardNumber,
  177. PUINT8 AddMulticastAddr
  178. )
  179. /*++
  180. Routine Description:
  181. The MLID manages enabled multicast addresses according to the physical adapter.
  182. The format of the multicast address is LAN medium dependent. This routine
  183. allows a protocol to add a single multicast address.
  184. Arguments:
  185. BoardNumber - The board number.
  186. AddMulticastAddr - A pointer to the multicast address to add.
  187. Return Value:
  188. SUCCESSFUL - Success.
  189. OUT_OF_RESOURCES - The MLID has insufficient resources to enable the address.
  190. BAD_PARAMETER - The address is not valid for the MLIDs media type.
  191. BAD_COMMAND - Multicast addressing is not supported by the MLID.
  192. --*/
  193. {
  194. PMLID_STRUCT Mlid;
  195. UINT32 i;
  196. UINT32 Status;
  197. NDIS_STATUS NdisStatus;
  198. PNDIS_REQUEST NdisMlidRequest;
  199. NdisAcquireSpinLock(&NdisMlidSpinLock);
  200. //
  201. // Verify that BoardNumber is in valid range
  202. //
  203. for (i =0 ; i < AllocatedMlidBoards; i++) {
  204. if (MlidBoards[i].BoardNumber == BoardNumber) {
  205. break;
  206. }
  207. }
  208. if (i == AllocatedMlidBoards) {
  209. NdisReleaseSpinLock(&NdisMlidSpinLock);
  210. return(BAD_PARAMETER);
  211. }
  212. //
  213. // If BoardNumber is not open, fail.
  214. //
  215. if (MlidBoards[i].Mlid == NULL) {
  216. NdisReleaseSpinLock(&NdisMlidSpinLock);
  217. return(BAD_PARAMETER);
  218. }
  219. //
  220. // If Board is unloading - fail
  221. //
  222. if (MlidBoards[i].Mlid->Unloading) {
  223. NdisReleaseSpinLock(&NdisMlidSpinLock);
  224. return(BAD_PARAMETER);
  225. }
  226. Mlid = MlidBoards[i].Mlid;
  227. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  228. NdisReleaseSpinLock(&NdisMlidSpinLock);
  229. switch (Mlid->NdisMlidMedium) {
  230. case NdisMedium802_3:
  231. Status = BuildNewMulticastList(Mlid, AddMulticastAddr);
  232. break;
  233. case NdisMedium802_5:
  234. Status = BuildNewFunctionalAddr(Mlid, AddMulticastAddr);
  235. break;
  236. case NdisMediumFddi:
  237. Status = BuildNewMulticastList(Mlid, AddMulticastAddr);
  238. break;
  239. }
  240. if (Status == DUPLICATE_ENTRY) {
  241. //
  242. // The address already existed, return success
  243. //
  244. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  245. return(SUCCESSFUL);
  246. }
  247. if (Status != SUCCESSFUL) {
  248. //
  249. // return error message -- most likely, OUT_OF_RESOURCES
  250. //
  251. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  252. return(Status);
  253. }
  254. //
  255. // Allocate NDIS_REQUEST
  256. //
  257. NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
  258. if (NdisMlidRequest == NULL) {
  259. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  260. return(OUT_OF_RESOURCES);
  261. }
  262. //
  263. // Build an NDIS request
  264. //
  265. NdisMlidRequest->RequestType = NdisRequestSetInformation;
  266. switch (Mlid->NdisMlidMedium) {
  267. case NdisMedium802_3:
  268. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
  269. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
  270. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
  271. Mlid->MulticastAddresses.MACount * 6;
  272. break;
  273. case NdisMedium802_5:
  274. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
  275. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->MulticastAddresses.FunctionalAddr);
  276. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = 4;
  277. break;
  278. case NdisMediumFddi:
  279. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
  280. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
  281. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
  282. Mlid->MulticastAddresses.MACount * 6;
  283. break;
  284. }
  285. NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
  286. NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  287. Mlid->RequestStatus = NDIS_STATUS_PENDING;
  288. //
  289. // Release spin lock
  290. //
  291. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  292. //
  293. // Submit NDIS request
  294. //
  295. NdisRequest(
  296. &NdisStatus,
  297. Mlid->NdisBindingHandle,
  298. NdisMlidRequest
  299. );
  300. //
  301. // If it pended, see if it completed already.
  302. //
  303. if (NdisStatus == NDIS_STATUS_PENDING) {
  304. if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
  305. //
  306. // Assume it will complete successfully
  307. //
  308. NdisStatus = NDIS_STATUS_SUCCESS;
  309. } else {
  310. NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
  311. }
  312. } else {
  313. //
  314. // Free NDIS_REQUEST
  315. //
  316. ExFreePool(NdisMlidRequest);
  317. }
  318. //
  319. // return status
  320. //
  321. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  322. return(SUCCESSFUL);
  323. }
  324. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  325. //
  326. // Remove the address - error
  327. //
  328. switch (Mlid->NdisMlidMedium) {
  329. case NdisMedium802_3:
  330. Status = RemoveFromMulticastList(Mlid, AddMulticastAddr);
  331. break;
  332. case NdisMedium802_5:
  333. Status = RemoveFromFunctionalAddr(Mlid, AddMulticastAddr);
  334. break;
  335. case NdisMediumFddi:
  336. Status = RemoveFromMulticastList(Mlid, AddMulticastAddr);
  337. break;
  338. }
  339. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  340. if (NdisStatus == NDIS_STATUS_RESOURCES) {
  341. return(OUT_OF_RESOURCES);
  342. }
  343. return(BAD_PARAMETER);
  344. }
  345. UINT32
  346. DeleteMulticastAddress(
  347. UINT32 BoardNumber,
  348. PUINT8 DelMulticastAddr
  349. )
  350. /*++
  351. Routine Description:
  352. Disables the reception of a previously enabled multicast address.
  353. Arguments:
  354. BoardNumber - The board number.
  355. DelMulticastAddr - The address to remove/disable.
  356. Return Value:
  357. SUCCESSFUL - Success.
  358. ITEM_NOT_PRESENT - The specified address is not enabled for the MLID.
  359. BAD_PARAMETER - The address is not valid for the MLIDs media type.
  360. BAD_COMMAND - Multicast addressing is not supported by the MLID.
  361. --*/
  362. {
  363. PMLID_STRUCT Mlid;
  364. UINT32 i;
  365. UINT32 Status;
  366. NDIS_STATUS NdisStatus;
  367. PNDIS_REQUEST NdisMlidRequest;
  368. NdisAcquireSpinLock(&NdisMlidSpinLock);
  369. //
  370. // Verify that BoardNumber is in valid range
  371. //
  372. for (i =0 ; i < AllocatedMlidBoards; i++) {
  373. if (MlidBoards[i].BoardNumber == BoardNumber) {
  374. break;
  375. }
  376. }
  377. if (i == AllocatedMlidBoards) {
  378. NdisReleaseSpinLock(&NdisMlidSpinLock);
  379. return(BAD_PARAMETER);
  380. }
  381. //
  382. // If BoardNumber is not open, fail.
  383. //
  384. if (MlidBoards[i].Mlid == NULL) {
  385. NdisReleaseSpinLock(&NdisMlidSpinLock);
  386. return(BAD_PARAMETER);
  387. }
  388. //
  389. // If Board is unloading - fail
  390. //
  391. if (MlidBoards[i].Mlid->Unloading) {
  392. NdisReleaseSpinLock(&NdisMlidSpinLock);
  393. return(BAD_PARAMETER);
  394. }
  395. Mlid = MlidBoards[i].Mlid;
  396. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  397. NdisReleaseSpinLock(&NdisMlidSpinLock);
  398. switch (Mlid->NdisMlidMedium) {
  399. case NdisMedium802_3:
  400. Status = RemoveFromMulticastList(Mlid, DelMulticastAddr);
  401. break;
  402. case NdisMedium802_5:
  403. Status = RemoveFromFunctionalAddr(Mlid, DelMulticastAddr);
  404. break;
  405. case NdisMediumFddi:
  406. Status = RemoveFromMulticastList(Mlid, DelMulticastAddr);
  407. break;
  408. }
  409. if (Status == DUPLICATE_ENTRY) {
  410. //
  411. // The address still exists, return success
  412. //
  413. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  414. return(SUCCESSFUL);
  415. }
  416. if (Status != SUCCESSFUL) {
  417. //
  418. // return error message -- most likely, ITEM_NOT_PRESENT
  419. //
  420. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  421. return(Status);
  422. }
  423. //
  424. // Allocate NDIS_REQUEST
  425. //
  426. NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
  427. if (NdisMlidRequest == NULL) {
  428. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  429. return(OUT_OF_RESOURCES);
  430. }
  431. //
  432. // Build an NDIS request
  433. //
  434. NdisMlidRequest->RequestType = NdisRequestSetInformation;
  435. switch (Mlid->NdisMlidMedium) {
  436. case NdisMedium802_3:
  437. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_3_MULTICAST_LIST;
  438. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
  439. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
  440. Mlid->MulticastAddresses.MACount * 6;
  441. break;
  442. case NdisMedium802_5:
  443. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_802_5_CURRENT_FUNCTIONAL;
  444. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->MulticastAddresses.FunctionalAddr);
  445. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = 4;
  446. break;
  447. case NdisMediumFddi:
  448. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_FDDI_LONG_MULTICAST_LIST;
  449. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)(Mlid->MulticastAddresses.Addresses);
  450. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength =
  451. Mlid->MulticastAddresses.MACount * 6;
  452. break;
  453. }
  454. NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
  455. NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  456. Mlid->RequestStatus = NDIS_STATUS_PENDING;
  457. //
  458. // Release spin lock
  459. //
  460. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  461. //
  462. // Submit NDIS request
  463. //
  464. NdisRequest(
  465. &NdisStatus,
  466. Mlid->NdisBindingHandle,
  467. NdisMlidRequest
  468. );
  469. //
  470. // If it pended, see if it completed already.
  471. //
  472. if (NdisStatus == NDIS_STATUS_PENDING) {
  473. if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
  474. //
  475. // Assume it will complete successfully
  476. //
  477. NdisStatus = NDIS_STATUS_SUCCESS;
  478. } else {
  479. NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
  480. }
  481. } else {
  482. //
  483. // Free NDIS_REQUEST
  484. //
  485. ExFreePool(NdisMlidRequest);
  486. }
  487. //
  488. // return status
  489. //
  490. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  491. return(SUCCESSFUL);
  492. }
  493. //
  494. // Put the address back -- error
  495. //
  496. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  497. switch (Mlid->NdisMlidMedium) {
  498. case NdisMedium802_3:
  499. Status = BuildNewMulticastList(Mlid, DelMulticastAddr);
  500. break;
  501. case NdisMedium802_5:
  502. Status = BuildNewFunctionalAddr(Mlid, DelMulticastAddr);
  503. break;
  504. case NdisMediumFddi:
  505. Status = BuildNewMulticastList(Mlid, DelMulticastAddr);
  506. break;
  507. }
  508. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  509. return(BAD_PARAMETER);
  510. }
  511. UINT32
  512. MLIDShutdown(
  513. UINT32 BoardNumber,
  514. UINT32 ShutDownType
  515. )
  516. /*++
  517. Routine Description:
  518. Allows an application to shut down a physical adapter.
  519. Arguments:
  520. BoardNumber - The board number.
  521. ShutDownType - Form of shutdown desired: 0 == shutdown hardware and deregister
  522. from LSL, 0 != shutdown hardware only.
  523. Return Value:
  524. SUCCESSFUL - Success.
  525. FAIL - Could not shutdown hardware.
  526. BAD_COMMAND - The MLID does not support this command.
  527. --*/
  528. {
  529. //
  530. // Always return BAD_COMMAND. First, because it is easy. Second because
  531. // we cannot guarantee that the we know of all accesses to the NDIS MAC.
  532. //
  533. return(BAD_COMMAND);
  534. }
  535. UINT32
  536. MLIDReset(
  537. UINT32 BoardNumber
  538. )
  539. /*++
  540. Routine Description:
  541. Causes the MLID to totally re-initialize the physical adapter. Leaves any
  542. multicast addresses that were previously enabled.
  543. Arguments:
  544. BoardNumber - The board number.
  545. Return Value:
  546. SUCCESSFUL - Success.
  547. FAIL - The MLID was unable to reset its hardware.
  548. BAD_COMMAND - The MLID does not support this command.
  549. --*/
  550. {
  551. PMLID_STRUCT Mlid;
  552. UINT32 i;
  553. NDIS_STATUS NdisStatus;
  554. NdisAcquireSpinLock(&NdisMlidSpinLock);
  555. //
  556. // Verify that BoardNumber is in valid range
  557. //
  558. for (i =0 ; i < AllocatedMlidBoards; i++) {
  559. if (MlidBoards[i].BoardNumber == BoardNumber) {
  560. break;
  561. }
  562. }
  563. if (i == AllocatedMlidBoards) {
  564. NdisReleaseSpinLock(&NdisMlidSpinLock);
  565. return(FAIL);
  566. }
  567. //
  568. // If BoardNumber is not open, fail.
  569. //
  570. if (MlidBoards[i].Mlid == NULL) {
  571. NdisReleaseSpinLock(&NdisMlidSpinLock);
  572. return(FAIL);
  573. }
  574. //
  575. // If Board is unloading - fail
  576. //
  577. if (MlidBoards[i].Mlid->Unloading) {
  578. NdisReleaseSpinLock(&NdisMlidSpinLock);
  579. return(FAIL);
  580. }
  581. Mlid = MlidBoards[i].Mlid;
  582. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  583. NdisReleaseSpinLock(&NdisMlidSpinLock);
  584. //
  585. // Hack so that we will cancel all requests until the reset completes
  586. //
  587. Mlid->Unloading = TRUE;
  588. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[12].StatCounter)))++; // MAdapterResetCount
  589. //
  590. // Time stamp the sucker
  591. //
  592. {
  593. LARGE_INTEGER TimeStamp;
  594. KeQuerySystemTime(&TimeStamp);
  595. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[13].StatCounter))) = // MAdapterOprTimeStamp
  596. TimeStamp.LowPart;
  597. }
  598. //
  599. // Release spin lock
  600. //
  601. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  602. //
  603. // Call NdisReset
  604. //
  605. NdisReset(
  606. &NdisStatus,
  607. Mlid->NdisBindingHandle
  608. );
  609. //
  610. // If it pended, see if it completed already.
  611. //
  612. if (NdisStatus == NDIS_STATUS_PENDING) {
  613. if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
  614. //
  615. // Assume it will complete successfully
  616. //
  617. NdisStatus = NDIS_STATUS_SUCCESS;
  618. } else {
  619. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  620. Mlid->Unloading = FALSE;
  621. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  622. NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
  623. }
  624. } else {
  625. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  626. Mlid->Unloading = FALSE;
  627. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  628. }
  629. //
  630. // return status
  631. //
  632. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  633. return(SUCCESSFUL);
  634. }
  635. return(FAIL);
  636. }
  637. UINT32
  638. SetLookAheadSize(
  639. UINT32 BoardNumber,
  640. UINT32 RequestSize
  641. )
  642. /*++
  643. Routine Description:
  644. Tells the MLID the amount of look ahead data that is needed by the caller
  645. to properly process received packets.
  646. Arguments:
  647. BoardNumber - The board number.
  648. RequestedSize - Requested look ahead size in bytes.
  649. Return Value:
  650. SUCCESSFUL - Success.
  651. BAD_PARAMETER - Requested look ahead size exceed bounds.
  652. --*/
  653. {
  654. PMLID_STRUCT Mlid;
  655. UINT32 i;
  656. UINT32 OldSize;
  657. NDIS_STATUS NdisStatus;
  658. PNDIS_REQUEST NdisMlidRequest;
  659. //
  660. // Verify that the size is ok
  661. //
  662. if (RequestSize > (256 - 40)) { // 40 is largest Media header size (TR SNAP w/ SR)
  663. return(BAD_PARAMETER);
  664. }
  665. RequestSize += 40;
  666. NdisAcquireSpinLock(&NdisMlidSpinLock);
  667. //
  668. // Verify that BoardNumber is in valid range
  669. //
  670. for (i =0 ; i < AllocatedMlidBoards; i++) {
  671. if (MlidBoards[i].BoardNumber == BoardNumber) {
  672. break;
  673. }
  674. }
  675. if (i == AllocatedMlidBoards) {
  676. NdisReleaseSpinLock(&NdisMlidSpinLock);
  677. return(BAD_PARAMETER);
  678. }
  679. //
  680. // If BoardNumber is not open, fail.
  681. //
  682. if (MlidBoards[i].Mlid == NULL) {
  683. NdisReleaseSpinLock(&NdisMlidSpinLock);
  684. return(BAD_PARAMETER);
  685. }
  686. //
  687. // If Board is unloading - fail
  688. //
  689. if (MlidBoards[i].Mlid->Unloading) {
  690. NdisReleaseSpinLock(&NdisMlidSpinLock);
  691. return(BAD_PARAMETER);
  692. }
  693. Mlid = MlidBoards[i].Mlid;
  694. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  695. NdisReleaseSpinLock(&NdisMlidSpinLock);
  696. //
  697. // Allocate NDIS_REQUEST
  698. //
  699. NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
  700. if (NdisMlidRequest == NULL) {
  701. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  702. return(OUT_OF_RESOURCES);
  703. }
  704. //
  705. // Store lookahead size
  706. //
  707. OldSize = Mlid->ConfigTable.MLIDCFG_LookAheadSize;
  708. Mlid->ConfigTable.MLIDCFG_LookAheadSize = RequestSize;
  709. //
  710. // Build an NDIS request
  711. //
  712. NdisMlidRequest->RequestType = NdisRequestSetInformation;
  713. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_GEN_MAXIMUM_LOOKAHEAD;
  714. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->ConfigTable.MLIDCFG_LookAheadSize);
  715. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT32);
  716. NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
  717. NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  718. Mlid->RequestStatus = NDIS_STATUS_PENDING;
  719. //
  720. // Release spin lock
  721. //
  722. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  723. //
  724. // Submit NDIS request
  725. //
  726. NdisRequest(
  727. &NdisStatus,
  728. Mlid->NdisBindingHandle,
  729. NdisMlidRequest
  730. );
  731. //
  732. // If it pended, see if it completed already.
  733. //
  734. if (NdisStatus == NDIS_STATUS_PENDING) {
  735. if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
  736. //
  737. // Assume it will complete successfully
  738. //
  739. NdisStatus = NDIS_STATUS_SUCCESS;
  740. } else {
  741. NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
  742. }
  743. } else {
  744. //
  745. // Free NDIS_REQUEST
  746. //
  747. ExFreePool(NdisMlidRequest);
  748. }
  749. //
  750. // return status
  751. //
  752. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  753. return(SUCCESSFUL);
  754. }
  755. //
  756. // Restore old size
  757. //
  758. Mlid->ConfigTable.MLIDCFG_LookAheadSize = OldSize;
  759. return(BAD_PARAMETER);
  760. }
  761. UINT32
  762. PromiscuousChange(
  763. UINT32 BoardNumber,
  764. UINT32 PromiscuousState,
  765. UINT32 PromiscuousMode
  766. )
  767. /*++
  768. Routine Description:
  769. Used to enable and disable promiscuous mode on the MLIDs adapter. A protocol
  770. stack can enable promiscuous mode multiple times without error; however, only
  771. the current call is in effect. If the LAN medium or adapter doees not distinquish
  772. between MAC and non-MAC frames, both frames are assumed for the PromiscuousMode
  773. mask.
  774. The MLID keeps a counter for each promiscuous mode and disables only when the
  775. count reaches zero.
  776. Arguments:
  777. BoardNumber - The board number.
  778. PromiscuousState - If 0, then disables promiscuous mode, else enables promiscuous mode.
  779. PromiscuousMode - Has the mask for what type of frames the MLID is to
  780. promiscuously receive. 0x1 - MAC Frames, 0x2 - Non-MAC Frames, 0x3 - Both.
  781. Return Value:
  782. SUCCESSFUL - Success.
  783. BAD_COMMAND - Promiscuous mode is not supported by the MLID.
  784. --*/
  785. {
  786. PMLID_STRUCT Mlid;
  787. UINT32 i;
  788. UINT32 OldFilterValue;
  789. UINT32 OldCount;
  790. NDIS_STATUS NdisStatus;
  791. PNDIS_REQUEST NdisMlidRequest;
  792. NdisAcquireSpinLock(&NdisMlidSpinLock);
  793. //
  794. // Verify that BoardNumber is in valid range
  795. //
  796. for (i =0 ; i < AllocatedMlidBoards; i++) {
  797. if (MlidBoards[i].BoardNumber == BoardNumber) {
  798. break;
  799. }
  800. }
  801. if (i == AllocatedMlidBoards) {
  802. NdisReleaseSpinLock(&NdisMlidSpinLock);
  803. return(BAD_PARAMETER);
  804. }
  805. //
  806. // If BoardNumber is not open, fail.
  807. //
  808. if (MlidBoards[i].Mlid == NULL) {
  809. NdisReleaseSpinLock(&NdisMlidSpinLock);
  810. return(BAD_PARAMETER);
  811. }
  812. //
  813. // If Board is unloading - fail
  814. //
  815. if (MlidBoards[i].Mlid->Unloading) {
  816. NdisReleaseSpinLock(&NdisMlidSpinLock);
  817. return(BAD_PARAMETER);
  818. }
  819. Mlid = MlidBoards[i].Mlid;
  820. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  821. NdisReleaseSpinLock(&NdisMlidSpinLock);
  822. //
  823. // If already enabled and we are to enable it, then increment counter and exit
  824. //
  825. if ((PromiscuousState != 0) &&
  826. (Mlid->PromiscuousModeEnables != 0)) {
  827. Mlid->PromiscuousModeEnables++;
  828. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  829. return(SUCCESSFUL);
  830. }
  831. //
  832. // If we are to disable it and count > 1 then decrement counter and exit
  833. //
  834. if ((PromiscuousState == 0) &&
  835. (Mlid->PromiscuousModeEnables > 1)) {
  836. Mlid->PromiscuousModeEnables--;
  837. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  838. return(SUCCESSFUL);
  839. }
  840. //
  841. // Allocate NDIS_REQUEST
  842. //
  843. NdisMlidRequest = (PNDIS_REQUEST)ExAllocatePool(NonPagedPool, sizeof(NDIS_REQUEST));
  844. if (NdisMlidRequest == NULL) {
  845. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  846. return(OUT_OF_RESOURCES);
  847. }
  848. //
  849. // Save old value
  850. //
  851. OldFilterValue = Mlid->NdisPacketFilterValue;
  852. OldCount = Mlid->PromiscuousModeEnables;
  853. if (PromiscuousState == 0) {
  854. Mlid->PromiscuousModeEnables = 0;
  855. Mlid->NdisPacketFilterValue &= ~(NDIS_PACKET_TYPE_PROMISCUOUS);
  856. } else {
  857. Mlid->PromiscuousModeEnables = 1;
  858. Mlid->NdisPacketFilterValue |= NDIS_PACKET_TYPE_PROMISCUOUS;
  859. }
  860. //
  861. // Build an NDIS request
  862. //
  863. NdisMlidRequest->RequestType = NdisRequestSetInformation;
  864. NdisMlidRequest->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  865. NdisMlidRequest->DATA.SET_INFORMATION.InformationBuffer = (PVOID)&(Mlid->NdisPacketFilterValue);
  866. NdisMlidRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof(UINT32);
  867. NdisMlidRequest->DATA.SET_INFORMATION.BytesRead = 0;
  868. NdisMlidRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  869. Mlid->RequestStatus = NDIS_STATUS_PENDING;
  870. //
  871. // Release spin lock
  872. //
  873. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  874. //
  875. // Submit NDIS request
  876. //
  877. NdisRequest(
  878. &NdisStatus,
  879. Mlid->NdisBindingHandle,
  880. NdisMlidRequest
  881. );
  882. //
  883. // If it pended, see if it completed already.
  884. //
  885. if (NdisStatus == NDIS_STATUS_PENDING) {
  886. if ((NDIS_STATUS)Mlid->RequestStatus == NDIS_STATUS_PENDING) {
  887. //
  888. // Assume it will complete successfully
  889. //
  890. NdisStatus = NDIS_STATUS_SUCCESS;
  891. } else {
  892. NdisStatus = (NDIS_STATUS)Mlid->RequestStatus;
  893. }
  894. } else {
  895. //
  896. // Free NDIS_REQUEST
  897. //
  898. ExFreePool(NdisMlidRequest);
  899. }
  900. //
  901. // return status
  902. //
  903. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  904. return(SUCCESSFUL);
  905. }
  906. //
  907. // restore state
  908. //
  909. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  910. Mlid->NdisPacketFilterValue = OldFilterValue;
  911. Mlid->PromiscuousModeEnables = OldCount;
  912. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  913. return(BAD_COMMAND);
  914. }
  915. UINT32
  916. MLIDManagement(
  917. UINT32 BoardNumber,
  918. PECB ManagementECB
  919. )
  920. /*++
  921. Routine Description:
  922. Allows a management entity to access management information from/and control
  923. an MLID.
  924. Arguments:
  925. BoardNumber - The board number.
  926. ManagementECB - A pointer to an ECB containing the management information.
  927. Return Value:
  928. SUCCESSFUL - Success.
  929. RESPONSE_DELAYED - Command will complete asyncronously.
  930. BAD_COMMAND - Not supported.
  931. BAD_PARAMETER - The Protocol ID field is invalid.
  932. NO_SUCH_HANDLER - Management entity for the Management Handle in teh ECB does
  933. not exist
  934. --*/
  935. {
  936. //
  937. // Always return BAD_COMMAND.
  938. //
  939. return(BAD_COMMAND);
  940. }
  941. VOID
  942. MLIDSendHandler(
  943. PECB SendECB
  944. )
  945. /*++
  946. Routine Description:
  947. This routine takes an ECB, assembles a packet based on the frame-type and
  948. sends it on the wire.
  949. Arguments:
  950. SendECB - A pointer to the ECB discribing the data and destination address for
  951. the packet.
  952. Return Value:
  953. None.
  954. --*/
  955. {
  956. PMLID_STRUCT Mlid;
  957. UINT32 i;
  958. BOOLEAN Result;
  959. NdisAcquireSpinLock(&NdisMlidSpinLock);
  960. //
  961. // Verify that BoardNumber is in valid range
  962. //
  963. for (i =0 ; i < AllocatedMlidBoards; i++) {
  964. if (MlidBoards[i].BoardNumber == SendECB->ECB_BoardNumber) {
  965. break;
  966. }
  967. }
  968. if (i == AllocatedMlidBoards) {
  969. //
  970. // Cancel the ECB
  971. //
  972. SendECB->ECB_Status = (UINT16)CANCELED;
  973. NdisReleaseSpinLock(&NdisMlidSpinLock);
  974. //
  975. // We could try to find a board number with a link to the LSL, but
  976. // in any case we might fail. The transport and/or LSL has hosed us,
  977. // so we will just let it sit.
  978. //
  979. return;
  980. }
  981. //
  982. // If BoardNumber is not open, fail.
  983. //
  984. if (MlidBoards[i].Mlid == NULL) {
  985. //
  986. // Cancel the ECB
  987. //
  988. SendECB->ECB_Status = (UINT16)CANCELED;
  989. NdisReleaseSpinLock(&NdisMlidSpinLock);
  990. //
  991. // We could try to find a board number with a link to the LSL, but
  992. // in any case we might fail. The transport and/or LSL has hosed us,
  993. // so we will just let it sit.
  994. //
  995. return;
  996. }
  997. //
  998. // If Board is unloading - fail
  999. //
  1000. if (MlidBoards[i].Mlid->Unloading) {
  1001. //
  1002. // Cancel the ECB
  1003. //
  1004. SendECB->ECB_Status = (UINT16)CANCELED;
  1005. NdisReleaseSpinLock(&NdisMlidSpinLock);
  1006. //
  1007. // We could try to find a board number with a link to the LSL, but
  1008. // in any case we might fail. The transport and/or LSL has hosed us,
  1009. // so we will just let it sit.
  1010. //
  1011. return;
  1012. }
  1013. Mlid = MlidBoards[i].Mlid;
  1014. NdisAcquireSpinLock(&(Mlid->MlidSpinLock));
  1015. NdisReleaseSpinLock(&NdisMlidSpinLock);
  1016. //
  1017. // Update MTotalGroupAddrTxCount
  1018. //
  1019. switch (Mlid->NdisMlidMedium) {
  1020. case NdisMediumFddi:
  1021. case NdisMedium802_3:
  1022. if (ETH_IS_BROADCAST(SendECB->ECB_ImmediateAddress)) {
  1023. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1024. break;
  1025. }
  1026. if (ETH_IS_MULTICAST(SendECB->ECB_ImmediateAddress)) {
  1027. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1028. break;
  1029. }
  1030. if (ETH_IS_MULTICAST(SendECB->ECB_ImmediateAddress)) {
  1031. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1032. break;
  1033. }
  1034. break;
  1035. case NdisMedium802_5:
  1036. TR_IS_BROADCAST(SendECB->ECB_ImmediateAddress, &Result);
  1037. if (Result == TRUE) {
  1038. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1039. break;
  1040. }
  1041. TR_IS_GROUP(SendECB->ECB_ImmediateAddress, &Result);
  1042. if (Result == TRUE) {
  1043. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1044. break;
  1045. }
  1046. TR_IS_FUNCTIONAL(SendECB->ECB_ImmediateAddress, &Result);
  1047. if (Result == TRUE) {
  1048. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[10].StatCounter)))++;
  1049. break;
  1050. }
  1051. break;
  1052. }
  1053. (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MGenericCountsPtr))[14].StatCounter)))++; // MQDepth
  1054. //
  1055. // Put ECB on send queue
  1056. //
  1057. if (Mlid->FirstPendingSend == NULL) {
  1058. Mlid->FirstPendingSend = SendECB;
  1059. Mlid->LastPendingSend = SendECB;
  1060. SendECB->ECB_NextLink = NULL;
  1061. SendECB->ECB_PreviousLink = NULL;
  1062. } else {
  1063. Mlid->LastPendingSend->ECB_NextLink = SendECB;
  1064. SendECB->ECB_PreviousLink = Mlid->LastPendingSend;
  1065. SendECB->ECB_NextLink = NULL;
  1066. Mlid->LastPendingSend = SendECB;
  1067. }
  1068. //
  1069. // Send all packets possible
  1070. //
  1071. if (Mlid->StageOpen && !Mlid->InSendPacket) {
  1072. SendPackets(Mlid);
  1073. }
  1074. NdisReleaseSpinLock(&(Mlid->MlidSpinLock));
  1075. }
  1076. UINT32
  1077. BuildNewMulticastList(
  1078. PMLID_STRUCT Mlid,
  1079. PUINT8 AddMulticastAddr
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. This routine takes a multicast addresses for either Ethernet or FDDI and
  1084. adds it to the Mlids database if it does not exist, otherwise it increments
  1085. the reference count on the address if it does exist.
  1086. Arguments:
  1087. Mlid - Pointer to the MLID.
  1088. AddMulticastAddr - The multicast address to add.
  1089. Return Value:
  1090. SUCCESSFUL - Success.
  1091. DUPLICATE_ENTRY - The address already existed in the database.
  1092. OUT_OF_RESOURCES - No memory avaiable to grow database.
  1093. --*/
  1094. {
  1095. UINT32 i;
  1096. //
  1097. // If address already exists, increment counter.
  1098. //
  1099. for (i = 0; i < Mlid->MulticastAddresses.MACount; i++) {
  1100. if (RtlCompareMemory(Mlid->MulticastAddresses.Addresses + i * 6,
  1101. AddMulticastAddr,
  1102. 6
  1103. ) == 0) {
  1104. //
  1105. // Increment count and exit
  1106. //
  1107. Mlid->MulticastAddresses.EnableCounts[i]++;
  1108. return(DUPLICATE_ENTRY);
  1109. }
  1110. }
  1111. //
  1112. // Allocate space for new array, if necessary
  1113. //
  1114. if (Mlid->MulticastAddresses.MACount == Mlid->MulticastAddresses.MAAllocated) {
  1115. PUINT8 TmpAddressArray;
  1116. PUINT32 TmpCountArray;
  1117. //
  1118. // Allocate memory for new array
  1119. //
  1120. TmpAddressArray = (PUINT8)ExAllocatePool(NonPagedPool,
  1121. 6 * (Mlid->MulticastAddresses.MACount + 2)
  1122. );
  1123. if (TmpAddressArray == NULL) {
  1124. return(OUT_OF_RESOURCES);
  1125. }
  1126. TmpCountArray = (PUINT32)ExAllocatePool(NonPagedPool,
  1127. sizeof(UINT32) *
  1128. (Mlid->MulticastAddresses.MACount + 2)
  1129. );
  1130. if (TmpCountArray == NULL) {
  1131. return(OUT_OF_RESOURCES);
  1132. }
  1133. //
  1134. // Copy over old addresses
  1135. //
  1136. RtlCopyMemory(TmpAddressArray,
  1137. Mlid->MulticastAddresses.Addresses,
  1138. 6 * Mlid->MulticastAddresses.MACount
  1139. );
  1140. //
  1141. // Copy over old counts
  1142. //
  1143. RtlCopyMemory(TmpCountArray,
  1144. Mlid->MulticastAddresses.EnableCounts,
  1145. sizeof(UINT32) * Mlid->MulticastAddresses.MACount
  1146. );
  1147. //
  1148. // Free old resources
  1149. //
  1150. ExFreePool(Mlid->MulticastAddresses.Addresses);
  1151. ExFreePool(Mlid->MulticastAddresses.EnableCounts);
  1152. //
  1153. // Save new space
  1154. //
  1155. Mlid->MulticastAddresses.Addresses = TmpAddressArray;
  1156. Mlid->MulticastAddresses.EnableCounts = TmpCountArray;
  1157. //
  1158. // Increment allocated count
  1159. //
  1160. Mlid->MulticastAddresses.MAAllocated += 2;
  1161. }
  1162. //
  1163. // Put address in new slot
  1164. //
  1165. RtlCopyMemory(Mlid->MulticastAddresses.Addresses +
  1166. Mlid->MulticastAddresses.MACount * 6,
  1167. AddMulticastAddr,
  1168. 6
  1169. );
  1170. //
  1171. // Set reference count
  1172. //
  1173. Mlid->MulticastAddresses.EnableCounts[Mlid->MulticastAddresses.MACount] = 1;
  1174. Mlid->MulticastAddresses.MACount++;
  1175. return(SUCCESSFUL);
  1176. }
  1177. UINT32
  1178. BuildNewFunctionalAddr(
  1179. PMLID_STRUCT Mlid,
  1180. PUINT8 AddFunctionalAddr
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. This routine takes a functional address(es) for token ring and
  1185. adds it to the Mlid functional address if it does not exist, otherwise
  1186. it increments the reference count on the address(es) if it does exist.
  1187. Arguments:
  1188. Mlid - Pointer to the MLID.
  1189. AddFunctionalAddr - The functional address to add.
  1190. Return Value:
  1191. SUCCESSFUL - Success.
  1192. DUPLICATE_ENTRY - The address already existed in the database.
  1193. OUT_OF_RESOURCES - No memory avaiable to grow database.
  1194. --*/
  1195. {
  1196. UINT32 i;
  1197. UINT32 ShortenedFunctionalAddr;
  1198. UNALIGNED UINT32 *PAddr;
  1199. UINT32 NewAddressBits;
  1200. UINT32 OldAddressBits;
  1201. if (Mlid->MulticastAddresses.MAAllocated == 0) {
  1202. //
  1203. // Get memory for the counts
  1204. //
  1205. Mlid->MulticastAddresses.EnableCounts = (PUINT32)ExAllocatePool(NonPagedPool,
  1206. sizeof(UINT32) * 32
  1207. );
  1208. if (Mlid->MulticastAddresses.EnableCounts == NULL) {
  1209. return(OUT_OF_RESOURCES);
  1210. }
  1211. RtlZeroMemory(Mlid->MulticastAddresses.EnableCounts, sizeof(UINT32) * 32);
  1212. Mlid->MulticastAddresses.MAAllocated = 32;
  1213. }
  1214. //
  1215. // Get low four bytes of address
  1216. //
  1217. PAddr = (UNALIGNED UINT32 *)(AddFunctionalAddr + 2);
  1218. ShortenedFunctionalAddr = *PAddr;
  1219. //
  1220. // Get new bits and old bits
  1221. //
  1222. OldAddressBits = Mlid->MulticastAddresses.FunctionalAddr & ShortenedFunctionalAddr;
  1223. NewAddressBits = ShortenedFunctionalAddr ^ OldAddressBits;
  1224. //
  1225. // Increment count of each bit that exists in current functional address
  1226. //
  1227. i = 0;
  1228. while (OldAddressBits != 0) {
  1229. if (OldAddressBits & 1) {
  1230. Mlid->MulticastAddresses.EnableCounts[i]++;
  1231. }
  1232. OldAddressBits >>= 1;
  1233. i++;
  1234. }
  1235. if (NewAddressBits == 0) {
  1236. return(DUPLICATE_ENTRY);
  1237. }
  1238. //
  1239. // Store new bits
  1240. //
  1241. Mlid->MulticastAddresses.FunctionalAddr |= NewAddressBits;
  1242. //
  1243. // Set counts of each new address bit
  1244. //
  1245. i = 0;
  1246. while (NewAddressBits != 0) {
  1247. if (NewAddressBits & 1) {
  1248. Mlid->MulticastAddresses.EnableCounts[i] = 1;
  1249. }
  1250. NewAddressBits >>= 1;
  1251. i++;
  1252. }
  1253. return(SUCCESSFUL);
  1254. }
  1255. UINT32
  1256. RemoveFromMulticastList(
  1257. PMLID_STRUCT Mlid,
  1258. PUINT8 DelMulticastAddr
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. This routine takes a multicast addresses for either Ethernet or FDDI and
  1263. removes it from the Mlids database if the reference count is one, otherwise
  1264. it decrements the reference count on the address.
  1265. Arguments:
  1266. Mlid - Pointer to the MLID.
  1267. DelMulticastAddr - The multicast address to add.
  1268. Return Value:
  1269. SUCCESSFUL - Success and address is removed.
  1270. ITEM_NOT_PRESENT - The address does not exist in the database.
  1271. DUPLICATE_ENTRY - Success and address still exists.
  1272. --*/
  1273. {
  1274. UINT32 i;
  1275. //
  1276. // If address already exists, decrement counter.
  1277. //
  1278. for (i = 0; i < Mlid->MulticastAddresses.MACount; i++) {
  1279. if (RtlCompareMemory(Mlid->MulticastAddresses.Addresses + i * 6,
  1280. DelMulticastAddr,
  1281. 6
  1282. ) == 0) {
  1283. //
  1284. // Increment count and exit
  1285. //
  1286. Mlid->MulticastAddresses.EnableCounts[i]--;
  1287. //
  1288. // If this is not the last reference we can exit now
  1289. //
  1290. if (Mlid->MulticastAddresses.EnableCounts[i] != 0) {
  1291. return(DUPLICATE_ENTRY);
  1292. }
  1293. //
  1294. // Now we need to adjust the address array and counts array
  1295. //
  1296. RtlMoveMemory(
  1297. Mlid->MulticastAddresses.Addresses + i * 6,
  1298. Mlid->MulticastAddresses.Addresses + (i + 1) * 6,
  1299. 6 * (Mlid->MulticastAddresses.MACount - (i + 1))
  1300. );
  1301. RtlMoveMemory(
  1302. Mlid->MulticastAddresses.EnableCounts + i,
  1303. Mlid->MulticastAddresses.EnableCounts + (i + 1),
  1304. sizeof(UINT32) * (Mlid->MulticastAddresses.MACount - (i + 1))
  1305. );
  1306. Mlid->MulticastAddresses.MACount--;
  1307. return(SUCCESSFUL);
  1308. }
  1309. }
  1310. return(ITEM_NOT_PRESENT);
  1311. }
  1312. UINT32
  1313. RemoveFromFunctionalAddr(
  1314. PMLID_STRUCT Mlid,
  1315. PUINT8 DelFunctionalAddr
  1316. )
  1317. /*++
  1318. Routine Description:
  1319. This routine takes functional address(es) for token ring and
  1320. removes it/them from the Mlids database if the reference count i/ares one,
  1321. otherwise it decrements the reference count on the address(es).
  1322. Arguments:
  1323. Mlid - Pointer to the MLID.
  1324. DelFunctionalAddr - The functional address to remove.
  1325. Return Value:
  1326. SUCCESSFUL - Success and address is changed.
  1327. ITEM_NOT_PRESENT - The address does not exist in the database.
  1328. DUPLICATE_ENTRY - Success and address is unchanged.
  1329. --*/
  1330. {
  1331. UINT32 i;
  1332. UINT32 ShortenedFunctionalAddr;
  1333. UNALIGNED UINT32 *PAddr;
  1334. UINT32 OldAddressBits;
  1335. UINT32 Status = DUPLICATE_ENTRY;
  1336. if (Mlid->MulticastAddresses.MAAllocated == 0) {
  1337. return(ITEM_NOT_PRESENT);
  1338. }
  1339. //
  1340. // Get low four bytes of address
  1341. //
  1342. PAddr = (UNALIGNED UINT32 *)(DelFunctionalAddr + 2);
  1343. ShortenedFunctionalAddr = *PAddr;
  1344. //
  1345. // Get new bits and old bits
  1346. //
  1347. OldAddressBits = Mlid->MulticastAddresses.FunctionalAddr & ShortenedFunctionalAddr;
  1348. if (OldAddressBits != ShortenedFunctionalAddr) {
  1349. return(ITEM_NOT_PRESENT);
  1350. }
  1351. //
  1352. // Increment count of each bit that exists in current functional address
  1353. //
  1354. i = 0;
  1355. while (OldAddressBits != 0) {
  1356. if (OldAddressBits & 1) {
  1357. Mlid->MulticastAddresses.EnableCounts[i]--;
  1358. if (Mlid->MulticastAddresses.EnableCounts[i] == 0) {
  1359. //
  1360. // Remove this bit
  1361. //
  1362. Mlid->MulticastAddresses.FunctionalAddr &= ~(1 << i);
  1363. Status = SUCCESSFUL;
  1364. }
  1365. }
  1366. OldAddressBits >>= 1;
  1367. i++;
  1368. }
  1369. return(Status);
  1370. }