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.

2071 lines
47 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Elnk.c
  5. Abstract:
  6. This is the main file for the 3Com Etherlink/MC and Etherlink 16
  7. Ethernet adapters. This driver conforms to the NDIS 3.0 interface.
  8. Author:
  9. Johnson R. Apacible (JohnsonA) 10-June-1991
  10. Environment:
  11. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  12. Revision History:
  13. --*/
  14. #include <ndis.h>
  15. //
  16. // So we can trace things...
  17. //
  18. #define STATIC
  19. #include <efilter.h>
  20. #include <elnkhw.h>
  21. #include <elnksw.h>
  22. #include "keywords.h"
  23. //
  24. // Globals
  25. //
  26. NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
  27. NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  28. NDIS_HANDLE ElnkMacHandle;
  29. LIST_ENTRY ElnkAdapterList;
  30. NDIS_SPIN_LOCK ElnkAdapterListLock;
  31. NDIS_HANDLE ElnkNdisWrapperHandle;
  32. PDRIVER_OBJECT ElnkDriverObject;
  33. STATIC
  34. BOOLEAN
  35. ElnkInitialInit(
  36. IN PELNK_ADAPTER Adapter,
  37. IN UINT ElnkInterruptVector
  38. );
  39. STATIC
  40. NDIS_STATUS
  41. ElnkOpenAdapter(
  42. OUT PNDIS_STATUS OpenErrorStatus,
  43. OUT NDIS_HANDLE *MacBindingHandle,
  44. OUT PUINT SelectedMediumIndex,
  45. IN PNDIS_MEDIUM MediumArray,
  46. IN UINT MediumArraySize,
  47. IN NDIS_HANDLE NdisBindingContext,
  48. IN NDIS_HANDLE MacAdapterContext,
  49. IN UINT OpenOptions,
  50. IN PSTRING AddressingInformation OPTIONAL
  51. );
  52. VOID
  53. Elnk16GenerateIdPattern(
  54. IN PELNK_ADAPTER Adapter
  55. );
  56. STATIC
  57. NDIS_STATUS
  58. ElnkCloseAdapter(
  59. IN NDIS_HANDLE MacBindingHandle
  60. );
  61. extern
  62. VOID
  63. ElnkQueueRequest(
  64. IN PELNK_ADAPTER Adapter,
  65. IN PNDIS_REQUEST NdisRequest
  66. );
  67. STATIC
  68. NDIS_STATUS
  69. ElnkReset(
  70. IN NDIS_HANDLE MacBindingHandle
  71. );
  72. VOID
  73. ElnkUnloadMac(
  74. IN NDIS_HANDLE MacMacContext
  75. );
  76. VOID
  77. ElnkRemoveAdapter(
  78. IN NDIS_HANDLE MacAdapterContext
  79. );
  80. NDIS_STATUS
  81. ElnkAddAdapter(
  82. IN NDIS_HANDLE MacMacContext,
  83. IN NDIS_HANDLE ConfigurationHandle,
  84. IN PNDIS_STRING DeviceName
  85. );
  86. STATIC
  87. VOID
  88. ElnkCloseAction(
  89. IN NDIS_HANDLE MacBindingHandle
  90. );
  91. VOID
  92. InitializeAdapterVariables(
  93. IN PELNK_ADAPTER Adapter
  94. );
  95. VOID
  96. ResetAdapterVariables(
  97. IN PELNK_ADAPTER Adapter
  98. );
  99. VOID
  100. ElnkDeleteAdapterMemory(
  101. IN PELNK_ADAPTER Adapter
  102. );
  103. BOOLEAN
  104. ElnkAllocateAdapterMemory(
  105. IN PELNK_ADAPTER Adapter
  106. );
  107. NTSTATUS
  108. DriverEntry(
  109. IN PDRIVER_OBJECT DriverObject,
  110. IN PUNICODE_STRING RegistryPath
  111. );
  112. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  113. NTSTATUS
  114. DriverEntry(
  115. IN PDRIVER_OBJECT DriverObject,
  116. IN PUNICODE_STRING RegistryPath
  117. )
  118. /*++
  119. Routine Description:
  120. This is the primary initialization routine for the Elnk driver.
  121. It is simply responsible for the intializing the wrapper and registering
  122. the MAC. It then calls a system and architecture specific routine that
  123. will initialize and register each adapter.
  124. Arguments:
  125. DriverObject - Pointer to driver object created by the system.
  126. Return Value:
  127. The status of the operation.
  128. --*/
  129. {
  130. //
  131. // Receives the status of the NdisRegisterMac operation.
  132. //
  133. NDIS_STATUS Status;
  134. NDIS_HANDLE NdisWrapperHandle;
  135. #if ELNKMC
  136. static NDIS_STRING MacName = NDIS_STRING_CONST("ELNKMC");
  137. #if NDIS_WIN
  138. UCHAR pIds[sizeof (EISA_MCA_ADAPTER_IDS) + sizeof (USHORT)];
  139. #endif
  140. #else
  141. static NDIS_STRING MacName = NDIS_STRING_CONST("ELNK16");
  142. #endif
  143. char Tmp[sizeof(NDIS_MAC_CHARACTERISTICS)];
  144. PNDIS_MAC_CHARACTERISTICS ElnkChar = (PNDIS_MAC_CHARACTERISTICS)Tmp;
  145. #if NDIS_WIN
  146. #if ELNKMC
  147. ((PEISA_MCA_ADAPTER_IDS)pIds)->nEisaAdapters=0;
  148. ((PEISA_MCA_ADAPTER_IDS)pIds)->nMcaAdapters=1;
  149. *(PUSHORT)(((PEISA_MCA_ADAPTER_IDS)pIds)->IdArray)=ELNKMC_ADAPTER_ID;
  150. (PVOID) DriverObject = (PVOID) pIds;
  151. #endif
  152. #endif
  153. //
  154. // Initialize the wrapper.
  155. //
  156. NdisInitializeWrapper(
  157. &NdisWrapperHandle,
  158. DriverObject,
  159. RegistryPath,
  160. NULL
  161. );
  162. ElnkDriverObject = DriverObject;
  163. ElnkNdisWrapperHandle = NdisWrapperHandle;
  164. //
  165. // Initialize the MAC characteristics for the call to
  166. // NdisRegisterMac.
  167. //
  168. ElnkChar->MajorNdisVersion = ELNK_NDIS_MAJOR_VERSION;
  169. ElnkChar->MinorNdisVersion = ELNK_NDIS_MINOR_VERSION;
  170. ElnkChar->OpenAdapterHandler = ElnkOpenAdapter;
  171. ElnkChar->CloseAdapterHandler = ElnkCloseAdapter;
  172. ElnkChar->RequestHandler = ElnkRequest;
  173. ElnkChar->SendHandler = ElnkSend;
  174. ElnkChar->TransferDataHandler = ElnkTransferData;
  175. ElnkChar->ResetHandler = ElnkReset;
  176. ElnkChar->QueryGlobalStatisticsHandler = ElnkQueryGlobalStatistics;
  177. ElnkChar->UnloadMacHandler = ElnkUnloadMac;
  178. ElnkChar->AddAdapterHandler = ElnkAddAdapter;
  179. ElnkChar->RemoveAdapterHandler = ElnkRemoveAdapter;
  180. ElnkChar->Name = MacName;
  181. //
  182. // Initialize Globals
  183. //
  184. InitializeListHead(&ElnkAdapterList);
  185. NdisAllocateSpinLock(&ElnkAdapterListLock);
  186. NdisRegisterMac(
  187. &Status,
  188. &ElnkMacHandle,
  189. NdisWrapperHandle,
  190. NULL,
  191. ElnkChar,
  192. sizeof(*ElnkChar)
  193. );
  194. if (Status != NDIS_STATUS_SUCCESS) {
  195. if ELNKDEBUG DPrint1("Elnk: NdisRegisterMac failed\n");
  196. NdisFreeSpinLock(&ElnkAdapterListLock);
  197. NdisTerminateWrapper(NdisWrapperHandle, NULL);
  198. return NDIS_STATUS_FAILURE;
  199. }
  200. return(NDIS_STATUS_SUCCESS);
  201. }
  202. #if ELNKMC
  203. #pragma NDIS_INIT_FUNCTION(ElnkmcRegisterAdapter)
  204. NDIS_STATUS
  205. ElnkmcRegisterAdapter(
  206. IN NDIS_HANDLE NdisMacHandle,
  207. IN NDIS_HANDLE ConfigurationHandle,
  208. IN PNDIS_STRING DeviceName,
  209. IN UINT ElnkInterruptVector,
  210. IN NDIS_PHYSICAL_ADDRESS ElnkSharedRam,
  211. IN USHORT ElnkIOBase,
  212. IN PUCHAR CurrentAddress,
  213. IN UINT MaximumMulticastAddresses,
  214. IN UINT MaximumOpenAdapters,
  215. IN BOOLEAN ConfigError,
  216. IN NDIS_STATUS ConfigErrorCode
  217. )
  218. /*++
  219. Routine Description:
  220. This routine (and its interface) are not portable. They are
  221. defined by the OS and the architecture.
  222. This routine is responsible for the allocation of the datastructures
  223. for the driver as well as any hardware specific details necessary
  224. to talk with the device.
  225. Arguments:
  226. NdisMacHandle - The handle given back to the mac from ndis when
  227. the mac registered itself.
  228. ConfigurationHandle - Handle passed to MacAddAdapter.
  229. DeviceName - The string containing the name to give to the device
  230. adapter. This name is preallocated by the caller and cannot be
  231. reused until the adapter is unloaded.
  232. ElnkInterruptVector - The interrupt vector to used for the adapter.
  233. ElnkSharedRam - address of the card RAM to be mapped.
  234. ElnkIOBase - base address of the card port I/O addresses.
  235. CurrentAddress - the alternative address to be used by the card. If NULL,
  236. the BIA is used.
  237. MaximumMulticastAddresses - The maximum number of multicast
  238. addresses to filter at any one time.
  239. MaximumOpenAdapters - The maximum number of opens at any one time.
  240. ConfigError - Was there a configuration error
  241. ConfigErrorCode - The NDIS_ERROR_CODE to log as the error.
  242. Return Value:
  243. Returns false if anything occurred that prevents the initialization
  244. of the adapter.
  245. --*/
  246. {
  247. //
  248. // Pointer for the adapter root.
  249. //
  250. PELNK_ADAPTER Adapter;
  251. //
  252. // status of various calls
  253. //
  254. NDIS_STATUS Status;
  255. //
  256. // adapter information
  257. //
  258. NDIS_ADAPTER_INFORMATION AdapterInformation;
  259. //
  260. // Allocate the Adapter block.
  261. //
  262. Status = ELNK_ALLOC_PHYS(&Adapter, sizeof(ELNK_ADAPTER));
  263. if ( Status == NDIS_STATUS_SUCCESS ) {
  264. NdisZeroMemory(
  265. Adapter,
  266. sizeof(ELNK_ADAPTER)
  267. );
  268. Adapter->NdisMacHandle = NdisMacHandle;
  269. //
  270. // Should an alternative address be used?
  271. //
  272. if (CurrentAddress != NULL) {
  273. Adapter->AddressChanged = TRUE;
  274. ETH_COPY_NETWORK_ADDRESS(
  275. Adapter->CurrentAddress,
  276. CurrentAddress
  277. );
  278. } else {
  279. Adapter->AddressChanged = FALSE;
  280. }
  281. //
  282. // Set the port addresses.
  283. //
  284. Adapter->IoBase = ElnkIOBase;
  285. Adapter->CurrentCsr = CSR_DEFAULT;
  286. Adapter->IsExternal = TRUE;
  287. Adapter->CardOffset = 0xC000;
  288. Adapter->SharedRamSize = 16;
  289. Adapter->SharedRamPhys = NdisGetPhysicalAddressLow(ElnkSharedRam);
  290. Adapter->InterruptVector = ElnkInterruptVector;
  291. Adapter->NumberOfTransmitBuffers =
  292. ELNKMC_NUMBER_OF_TRANSMIT_BUFFERS;
  293. Adapter->NumberOfReceiveBuffers =
  294. ELNKMC_NUMBER_OF_RECEIVE_BUFFERS;
  295. Adapter->MemoryIsMapped = FALSE;
  296. //
  297. // Initialize the interrupt.
  298. //
  299. InitializeListHead(&Adapter->OpenBindings);
  300. InitializeListHead(&Adapter->CloseList);
  301. Adapter->IsrLevel = (KIRQL)(HIGH_LEVEL - ElnkInterruptVector);
  302. InitializeAdapterVariables(Adapter);
  303. ResetAdapterVariables(Adapter);
  304. //
  305. // We can start the chip. We may not
  306. // have any bindings to indicate to but this
  307. // is unimportant.
  308. //
  309. NdisZeroMemory(&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
  310. AdapterInformation.DmaChannel = 0;
  311. AdapterInformation.Master = FALSE;
  312. AdapterInformation.AdapterType = NdisInterfaceMca;
  313. AdapterInformation.PhysicalMapRegistersNeeded = 0;
  314. AdapterInformation.MaximumPhysicalMapping = 0;
  315. AdapterInformation.NumberOfPortDescriptors = 1;
  316. AdapterInformation.PortDescriptors[0].InitialPort = (ULONG)(Adapter->IoBase);
  317. AdapterInformation.PortDescriptors[0].NumberOfPorts = 0x10;
  318. AdapterInformation.PortDescriptors[0].PortOffset = NULL;
  319. if (NdisRegisterAdapter(
  320. &Adapter->NdisAdapterHandle,
  321. Adapter->NdisMacHandle,
  322. Adapter,
  323. ConfigurationHandle,
  324. DeviceName,
  325. &AdapterInformation
  326. ) != NDIS_STATUS_SUCCESS) {
  327. ElnkLogError(
  328. Adapter,
  329. registerAdapter,
  330. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  331. 0
  332. );
  333. if ELNKDEBUG DPrint1("ElnkmcRegisterAdapter: NdisRegisterAdapter failed\n");
  334. ELNK_FREE_PHYS(Adapter);
  335. return NDIS_STATUS_FAILURE;
  336. }
  337. if (ConfigError) {
  338. ElnkLogError(
  339. Adapter,
  340. registerAdapter,
  341. ConfigErrorCode,
  342. 0
  343. );
  344. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  345. ELNK_FREE_PHYS(Adapter);
  346. return(NDIS_STATUS_FAILURE);
  347. }
  348. //
  349. // Allocate adapter structures
  350. //
  351. if (!ElnkAllocateAdapterMemory(Adapter)) {
  352. ElnkLogError(
  353. Adapter,
  354. registerAdapter,
  355. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  356. 0
  357. );
  358. if ELNKDEBUG DPrint1("ElnkRegisterAdapter - unsuccessful memory allocation\n");
  359. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  360. ELNK_FREE_PHYS(Adapter);
  361. return(NDIS_STATUS_RESOURCES);
  362. }
  363. NdisInitializeTimer(
  364. &Adapter->DeadmanTimer,
  365. (PVOID) ElnkDeadmanDpc,
  366. (PVOID) Adapter
  367. );
  368. NdisInitializeTimer(
  369. &Adapter->DeferredTimer,
  370. (PVOID) ElnkStandardInterruptDpc,
  371. (PVOID) Adapter
  372. );
  373. NdisAllocateSpinLock(&Adapter->Lock);
  374. //
  375. // Get station address
  376. //
  377. ElnkGetStationAddress(Adapter);
  378. //
  379. // Check for validity of the address
  380. //
  381. if (((Adapter->NetworkAddress[0] == 0xFF) &&
  382. (Adapter->NetworkAddress[1] == 0xFF) &&
  383. (Adapter->NetworkAddress[2] == 0xFF) &&
  384. (Adapter->NetworkAddress[3] == 0xFF) &&
  385. (Adapter->NetworkAddress[4] == 0xFF) &&
  386. (Adapter->NetworkAddress[5] == 0xFF)) ||
  387. ((Adapter->NetworkAddress[0] == 0x00) &&
  388. (Adapter->NetworkAddress[1] == 0x00) &&
  389. (Adapter->NetworkAddress[2] == 0x00) &&
  390. (Adapter->NetworkAddress[3] == 0x00) &&
  391. (Adapter->NetworkAddress[4] == 0x00) &&
  392. (Adapter->NetworkAddress[5] == 0x00)))
  393. {
  394. ElnkLogError(
  395. Adapter,
  396. startChip,
  397. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  398. 0);
  399. return(NDIS_STATUS_FAILURE);
  400. }
  401. //
  402. // Do the initial init first so we can get the adapter's address
  403. // before creating the filter DB.
  404. //
  405. Adapter->FilterDB = NULL;
  406. if (!EthCreateFilter(
  407. MaximumMulticastAddresses,
  408. ElnkChangeAddresses,
  409. ElnkChangeClass,
  410. ElnkCloseAction,
  411. Adapter->CurrentAddress,
  412. &Adapter->Lock,
  413. &Adapter->FilterDB
  414. )) {
  415. ElnkLogError(
  416. Adapter,
  417. registerAdapter,
  418. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  419. 0
  420. );
  421. if ELNKDEBUG
  422. DPrint1("ElnkRegisterAdapter - unsuccessful filter create.\n");
  423. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  424. NdisFreeSpinLock(&Adapter->Lock);
  425. ELNK_FREE_PHYS(Adapter);
  426. return NDIS_STATUS_RESOURCES;
  427. }
  428. if (!ElnkInitialInit(Adapter, ElnkInterruptVector))
  429. {
  430. EthDeleteFilter(Adapter->FilterDB);
  431. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  432. NdisFreeSpinLock(&Adapter->Lock);
  433. ELNK_FREE_PHYS(Adapter);
  434. return NDIS_STATUS_FAILURE;
  435. }
  436. else
  437. {
  438. //
  439. // Record it in the global adapter list.
  440. //
  441. NdisInterlockedInsertTailList(&ElnkAdapterList,
  442. &Adapter->AdapterList,
  443. &ElnkAdapterListLock
  444. );
  445. return NDIS_STATUS_SUCCESS;
  446. }
  447. } else {
  448. if ELNKDEBUG DPrint1("ElnkRegisterAdapter - failed allocation of adapter block.\n");
  449. return NDIS_STATUS_RESOURCES;
  450. }
  451. }
  452. #else
  453. #pragma NDIS_INIT_FUNCTION(Elnk16RegisterAdapter)
  454. NDIS_STATUS
  455. Elnk16RegisterAdapter(
  456. IN NDIS_HANDLE NdisMacHandle,
  457. IN NDIS_HANDLE ConfigurationHandle,
  458. IN PNDIS_STRING DeviceName,
  459. IN UINT InterruptVector,
  460. IN NDIS_PHYSICAL_ADDRESS WinBase,
  461. IN UINT WindowSize,
  462. IN USHORT IoBase,
  463. IN BOOLEAN IsExternal,
  464. IN BOOLEAN ZwsEnabled,
  465. IN PUCHAR CurrentAddress,
  466. IN UINT MaximumMulticastAddresses,
  467. IN UINT MaximumOpenAdapters,
  468. IN BOOLEAN ConfigError,
  469. IN NDIS_STATUS ConfigErrorCode
  470. )
  471. /*++
  472. Routine Description:
  473. This routine (and its interface) are not portable. They are
  474. defined by the OS and the architecture.
  475. This routine is responsible for the allocation of the datastructures
  476. for the driver as well as any hardware specific details necessary
  477. to talk with the device.
  478. Arguments:
  479. NdisMacHandle - The handle given back to the mac from ndis when
  480. the mac registered itself.
  481. ConfigurationHandle - Handle passed to MacAddAdapter.
  482. DeviceName - The string containing the name to give to the device
  483. adapter. This name is preallocated by the caller and cannot be
  484. reused until the adapter is unloaded.
  485. InterruptVector - The interrupt vector to used for the adapter.
  486. WinBase - Base address of card window.
  487. WindowSize - Size of card window.
  488. IoBase - address of I/O base register.
  489. IsExternal - are we using the external transceiver?
  490. ZwsEnable - should Zero Wait Status be enabled
  491. CurrentAddress - the alternative address to be used by the card. If NULL,
  492. the BIA is used.
  493. MaximumMulticastAddresses - The maximum number of multicast
  494. addresses to filter at any one time.
  495. MaximumOpenAdapters - The maximum number of opens at any one time.
  496. ConfigError - Was there a configuration error
  497. ConfigErrorCode - The NDIS_ERROR_CODE to log as the error.
  498. Return Value:
  499. Returns NDIS_STATUS_FAILURE if anything occurred that prevents the initialization
  500. of the adapter.
  501. --*/
  502. {
  503. //
  504. // Pointer for the adapter root.
  505. //
  506. PELNK_ADAPTER Adapter;
  507. //
  508. // status of various calls
  509. //
  510. NDIS_STATUS Status;
  511. //
  512. // adapter information
  513. //
  514. NDIS_ADAPTER_INFORMATION AdapterInformation;
  515. //
  516. // Allocate the Adapter block.
  517. //
  518. Status = ELNK_ALLOC_PHYS(&Adapter, sizeof(ELNK_ADAPTER));
  519. if ( Status == NDIS_STATUS_SUCCESS ) {
  520. NdisZeroMemory(
  521. Adapter,
  522. sizeof(ELNK_ADAPTER)
  523. );
  524. Adapter->NdisMacHandle = NdisMacHandle;
  525. //
  526. // Should an alternative address be used?
  527. //
  528. if (CurrentAddress != NULL) {
  529. Adapter->AddressChanged = TRUE;
  530. ETH_COPY_NETWORK_ADDRESS(
  531. Adapter->CurrentAddress,
  532. CurrentAddress
  533. );
  534. } else {
  535. Adapter->AddressChanged = FALSE;
  536. }
  537. //
  538. // Set the port addresses.
  539. //
  540. Adapter->IoBase = IoBase;
  541. Adapter->CurrentCsr = CSR_DEFAULT;
  542. Adapter->SharedRamPhys = NdisGetPhysicalAddressLow(WinBase);
  543. Adapter->SharedRamSize = WindowSize;
  544. //
  545. // Allocate memory for all of the adapter structures.
  546. //
  547. Adapter->MemoryIsMapped = FALSE;
  548. //
  549. // Initialize the interrupt.
  550. //
  551. InitializeListHead(&Adapter->OpenBindings);
  552. InitializeListHead(&Adapter->CloseList);
  553. Adapter->IsrLevel = (KIRQL)(HIGH_LEVEL - InterruptVector);
  554. Adapter->InterruptVector = (UINT) InterruptVector;
  555. //
  556. // We can start the chip. We may not
  557. // have any bindings to indicate to but this
  558. // is unimportant.
  559. //
  560. NdisZeroMemory(&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
  561. AdapterInformation.DmaChannel = 0;
  562. AdapterInformation.Master = FALSE;
  563. AdapterInformation.AdapterType = NdisInterfaceIsa;
  564. AdapterInformation.PhysicalMapRegistersNeeded = 0;
  565. AdapterInformation.MaximumPhysicalMapping = 0;
  566. AdapterInformation.NumberOfPortDescriptors = 1;
  567. AdapterInformation.PortDescriptors[0].InitialPort = (ULONG)(Adapter->IoBase);
  568. AdapterInformation.PortDescriptors[0].NumberOfPorts = 0x10;
  569. AdapterInformation.PortDescriptors[0].PortOffset = NULL;
  570. if (NdisRegisterAdapter(
  571. &Adapter->NdisAdapterHandle,
  572. Adapter->NdisMacHandle,
  573. Adapter,
  574. ConfigurationHandle,
  575. DeviceName,
  576. &AdapterInformation
  577. ) != NDIS_STATUS_SUCCESS) {
  578. ElnkLogError(
  579. Adapter,
  580. registerAdapter,
  581. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  582. 0
  583. );
  584. if ELNKDEBUG DPrint1("Elnk16RegisterAdapter: NdisRegisterAdapter failed\n");
  585. ELNK_FREE_PHYS(Adapter);
  586. return NDIS_STATUS_FAILURE;
  587. }
  588. if (ConfigError) {
  589. ElnkLogError(
  590. Adapter,
  591. registerAdapter,
  592. ConfigErrorCode,
  593. 0
  594. );
  595. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  596. ELNK_FREE_PHYS(Adapter);
  597. return(NDIS_STATUS_FAILURE);
  598. }
  599. //
  600. // Verify the Configuration of the hardware
  601. //
  602. if (!Elnk16ConfigureAdapter(
  603. Adapter,
  604. IsExternal,
  605. ZwsEnabled
  606. )) {
  607. ElnkLogError(
  608. Adapter,
  609. registerAdapter,
  610. NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
  611. 0
  612. );
  613. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  614. ELNK_FREE_PHYS(Adapter);
  615. return(NDIS_STATUS_FAILURE);
  616. }
  617. //
  618. // Allocate adapter structures
  619. //
  620. if (!ElnkAllocateAdapterMemory(Adapter)) {
  621. ElnkLogError(
  622. Adapter,
  623. registerAdapter,
  624. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  625. 0
  626. );
  627. if ELNKDEBUG DPrint1("ElnkRegisterAdapter - unsuccessful memory allocation\n");
  628. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  629. ELNK_FREE_PHYS(Adapter);
  630. return(NDIS_STATUS_FAILURE);
  631. }
  632. InitializeAdapterVariables(Adapter);
  633. ResetAdapterVariables(Adapter);
  634. NdisInitializeTimer(
  635. &Adapter->DeadmanTimer,
  636. (PVOID) ElnkDeadmanDpc,
  637. (PVOID) Adapter
  638. );
  639. NdisInitializeTimer(
  640. &Adapter->DeferredTimer,
  641. (PVOID) ElnkStandardInterruptDpc,
  642. (PVOID) Adapter
  643. );
  644. NdisAllocateSpinLock(&Adapter->Lock);
  645. //
  646. // Get station address
  647. //
  648. ElnkGetStationAddress(Adapter);
  649. //
  650. // Check for validity of the address
  651. //
  652. if (((Adapter->NetworkAddress[0] == 0xFF) &&
  653. (Adapter->NetworkAddress[1] == 0xFF) &&
  654. (Adapter->NetworkAddress[2] == 0xFF) &&
  655. (Adapter->NetworkAddress[3] == 0xFF) &&
  656. (Adapter->NetworkAddress[4] == 0xFF) &&
  657. (Adapter->NetworkAddress[5] == 0xFF)) ||
  658. ((Adapter->NetworkAddress[0] == 0x00) &&
  659. (Adapter->NetworkAddress[1] == 0x00) &&
  660. (Adapter->NetworkAddress[2] == 0x00) &&
  661. (Adapter->NetworkAddress[3] == 0x00) &&
  662. (Adapter->NetworkAddress[4] == 0x00) &&
  663. (Adapter->NetworkAddress[5] == 0x00)))
  664. {
  665. ElnkLogError(
  666. Adapter,
  667. startChip,
  668. NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
  669. 0);
  670. return(NDIS_STATUS_FAILURE);
  671. }
  672. if (!EthCreateFilter(
  673. MaximumMulticastAddresses,
  674. ElnkChangeAddresses,
  675. ElnkChangeClass,
  676. ElnkCloseAction,
  677. Adapter->CurrentAddress,
  678. &Adapter->Lock,
  679. &Adapter->FilterDB
  680. )) {
  681. ElnkLogError(
  682. Adapter,
  683. registerAdapter,
  684. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  685. 0
  686. );
  687. if ELNKDEBUG
  688. DPrint1("ElnkRegisterAdapter - unsuccessful filter create.\n");
  689. ElnkDeleteAdapterMemory(Adapter);
  690. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  691. NdisFreeSpinLock(&Adapter->Lock);
  692. ELNK_FREE_PHYS(Adapter);
  693. return NDIS_STATUS_FAILURE;
  694. }
  695. if (!ElnkInitialInit(
  696. Adapter,
  697. Adapter->InterruptVector
  698. )) {
  699. EthDeleteFilter(Adapter->FilterDB);
  700. ElnkDeleteAdapterMemory(Adapter);
  701. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  702. NdisFreeSpinLock(&Adapter->Lock);
  703. ELNK_FREE_PHYS(Adapter);
  704. return NDIS_STATUS_FAILURE;
  705. }
  706. //
  707. // Record it in the global adapter list.
  708. //
  709. NdisInterlockedInsertTailList(&ElnkAdapterList,
  710. &Adapter->AdapterList,
  711. &ElnkAdapterListLock
  712. );
  713. return NDIS_STATUS_SUCCESS;
  714. } else {
  715. if ELNKDEBUG DPrint1("ElnkRegisterAdapter - unsuccessful allocation of adapter block.\n");
  716. return NDIS_STATUS_FAILURE;
  717. }
  718. }
  719. #endif
  720. #pragma NDIS_INIT_FUNCTION(ElnkAllocateAdapterMemory)
  721. BOOLEAN
  722. ElnkAllocateAdapterMemory(
  723. IN PELNK_ADAPTER Adapter
  724. )
  725. /*++
  726. Routine Description:
  727. This routine is responsible for the allocation of the datastructures
  728. for the Adapter structure.
  729. Arguments:
  730. Adapter - the adapter structure to allocate for.
  731. Return Value:
  732. Returns false if we cannot allocate memory.
  733. --*/
  734. {
  735. NDIS_STATUS Status;
  736. //
  737. // add 1 for multicast block
  738. //
  739. Status = ELNK_ALLOC_PHYS(
  740. &Adapter->TransmitInfo,
  741. sizeof(ELNK_TRANSMIT_INFO) *
  742. (Adapter->NumberOfTransmitBuffers + 1)
  743. );
  744. if (Status != NDIS_STATUS_SUCCESS) {
  745. ElnkLogError(
  746. Adapter,
  747. allocateAdapterMemory,
  748. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  749. 0
  750. );
  751. ElnkDeleteAdapterMemory(Adapter);
  752. return(FALSE);
  753. }
  754. Status = ELNK_ALLOC_PHYS(
  755. &Adapter->ReceiveInfo,
  756. sizeof(ELNK_RECEIVE_INFO) *
  757. Adapter->NumberOfReceiveBuffers
  758. );
  759. if (Status != NDIS_STATUS_SUCCESS) {
  760. ElnkLogError(
  761. Adapter,
  762. allocateAdapterMemory,
  763. NDIS_ERROR_CODE_OUT_OF_RESOURCES,
  764. 1
  765. );
  766. ElnkDeleteAdapterMemory(Adapter);
  767. return(FALSE);
  768. }
  769. return(TRUE);
  770. }
  771. VOID
  772. ElnkDeleteAdapterMemory(
  773. IN PELNK_ADAPTER Adapter
  774. )
  775. /*++
  776. Routine Description:
  777. This routine is responsible for the deallocation of the datastructures
  778. for the Adapter structure.
  779. Arguments:
  780. Adapter - the adapter structure to deallocate for.
  781. Return Value:
  782. None.
  783. --*/
  784. {
  785. if (Adapter->TransmitInfo != NULL) {
  786. ELNK_FREE_PHYS(Adapter->TransmitInfo);
  787. }
  788. if (Adapter->ReceiveInfo != NULL) {
  789. ELNK_FREE_PHYS(Adapter->ReceiveInfo);
  790. }
  791. }
  792. #pragma NDIS_INIT_FUNCTION(InitializeAdapterVariables)
  793. VOID
  794. InitializeAdapterVariables(
  795. IN PELNK_ADAPTER Adapter
  796. )
  797. /*++
  798. Routine Description:
  799. This routine is initializes the adapter variables.
  800. Arguments:
  801. Adapter - the adapter structure to initialize
  802. Return Value:
  803. None.
  804. --*/
  805. {
  806. //
  807. // No long necessary -- we zero structure out and this routine is
  808. // only called at initialinit time.
  809. //
  810. // Adapter->OpenCount = 0;
  811. //
  812. Adapter->References = 1;
  813. Adapter->ResetInProgress = FALSE;
  814. Adapter->ResettingOpen = NULL;
  815. Adapter->OldParameterField = DEFAULT_PARM5;
  816. Adapter->FirstOpen = TRUE;
  817. Adapter->FirstReset = TRUE;
  818. Adapter->DoingProcessing = FALSE;
  819. Adapter->ProcessingRequests = FALSE;
  820. Adapter->StatisticsField = 0x12345678;
  821. //
  822. // Packet counts
  823. //
  824. // No long necessary -- we zero structure out and this routine is
  825. // only called at initialinit time.
  826. //
  827. // Adapter->GoodTransmits = 0;
  828. // Adapter->GoodReceives = 0;
  829. //
  830. // Count of transmit errors
  831. //
  832. // No long necessary -- we zero structure out and this routine is
  833. // only called at initialinit time.
  834. //
  835. // Adapter->RetryFailure = 0;
  836. // Adapter->LostCarrier = 0;
  837. // Adapter->UnderFlow = 0;
  838. // Adapter->NoClearToSend = 0;
  839. // Adapter->Deferred = 0;
  840. // Adapter->OneRetry = 0;
  841. // Adapter->MoreThanOneRetry = 0;
  842. //
  843. // Count of receive errors
  844. //
  845. // No long necessary -- we zero structure out and this routine is
  846. // only called at initialinit time.
  847. //
  848. // Adapter->FrameTooShort = 0;
  849. // Adapter->NoEofDetected = 0;
  850. }
  851. VOID
  852. ResetAdapterVariables(
  853. IN PELNK_ADAPTER Adapter
  854. )
  855. /*++
  856. Routine Description:
  857. This routine resets the adapter variables to their post reset value
  858. Arguments:
  859. Adapter - the adapter structure whose elements are to be reset
  860. Return Value:
  861. None.
  862. --*/
  863. {
  864. Adapter->TransmitsQueued = 0;
  865. Adapter->FirstRequest = NULL;
  866. Adapter->LastRequest = NULL;
  867. Adapter->FirstPendingCommand = ELNK_EMPTY;
  868. Adapter->LastPendingCommand = ELNK_EMPTY;
  869. Adapter->NextCommandBlock = 0;
  870. Adapter->NumberOfAvailableCommandBlocks =
  871. Adapter->NumberOfTransmitBuffers;
  872. Adapter->FirstLoopBack = NULL;
  873. Adapter->LastLoopBack = NULL;
  874. Adapter->FirstFinishTransmit = NULL;
  875. Adapter->LastFinishTransmit = NULL;
  876. Adapter->StageOpen = TRUE;
  877. Adapter->AlreadyProcessingStage = FALSE;
  878. Adapter->FirstStagePacket = NULL;
  879. Adapter->LastStagePacket = NULL;
  880. }
  881. STATIC
  882. NDIS_STATUS
  883. ElnkOpenAdapter(
  884. OUT PNDIS_STATUS OpenErrorStatus,
  885. OUT NDIS_HANDLE *MacBindingHandle,
  886. OUT PUINT SelectedMediumIndex,
  887. IN PNDIS_MEDIUM MediumArray,
  888. IN UINT MediumArraySize,
  889. IN NDIS_HANDLE NdisBindingContext,
  890. IN NDIS_HANDLE MacAdapterContext,
  891. IN UINT OpenOptions,
  892. IN PSTRING AddressingInformation OPTIONAL
  893. )
  894. /*++
  895. Routine Description:
  896. This routine is used to create an open instance of an adapter, in effect
  897. creating a binding between an upper-level module and the MAC module over
  898. the adapter.
  899. Arguments:
  900. MacBindingHandle - A pointer to a location in which the MAC stores
  901. a context value that it uses to represent this binding.
  902. SelectedMediumIndex - Index in MediumArray of the medium type that
  903. the MAC wishes to be viewed as.
  904. MediumArray - Array of medium types which a protocol supports.
  905. MediumArraySize - Number of elements in MediumArray.
  906. NdisBindingContext - A value to be recorded by the MAC and passed as
  907. context whenever an indication is delivered by the MAC for this binding.
  908. MacAdapterContext - The value associated with the adapter that is being
  909. opened when the MAC registered the adapter with NdisRegisterAdapter.
  910. OpenOptions - bit mask.
  911. AddressingInformation - An optional pointer to a variable length string
  912. containing hardware-specific information that can be used to program the
  913. device. (This is not used by this MAC.)
  914. Return Value:
  915. The function value is the status of the operation. If the MAC does not
  916. complete this request synchronously, the value would be
  917. NDIS_STATUS_PENDING.
  918. --*/
  919. {
  920. //
  921. // The ELNK_ADAPTER that this open binding should belong too.
  922. //
  923. PELNK_ADAPTER Adapter;
  924. //
  925. // for index
  926. //
  927. UINT i;
  928. //
  929. // return status
  930. //
  931. NDIS_STATUS Status;
  932. //
  933. // Pointer to the space allocated for the binding.
  934. //
  935. PELNK_OPEN NewOpen;
  936. //
  937. // Pointer to the reserved portion of ndisrequest
  938. //
  939. PELNK_REQUEST_RESERVED Reserved;
  940. //
  941. // Holds the status that should be returned to the caller.
  942. //
  943. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  944. OpenErrorStatus; AddressingInformation; OpenOptions;
  945. //
  946. // If we are being removed, don't allow new opens.
  947. //
  948. Adapter = PELNK_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
  949. NdisInterlockedAddUlong(&Adapter->References, 1, &Adapter->Lock);
  950. //
  951. // Search for the medium type (802.3)
  952. //
  953. for (i = 0; i < MediumArraySize; i++){
  954. if (MediumArray[i] == NdisMedium802_3){
  955. break;
  956. }
  957. }
  958. if (i == MediumArraySize){
  959. NdisAcquireSpinLock(&Adapter->Lock);
  960. StatusToReturn = NDIS_STATUS_UNSUPPORTED_MEDIA;
  961. goto OpenDoDeferred;
  962. }
  963. *SelectedMediumIndex = i;
  964. //
  965. // Allocate the space for the open binding. Fill in the fields.
  966. //
  967. Status = ELNK_ALLOC_PHYS(&NewOpen, sizeof(ELNK_OPEN));
  968. if (Status != NDIS_STATUS_SUCCESS) {
  969. NdisAcquireSpinLock(&Adapter->Lock);
  970. StatusToReturn = NDIS_STATUS_RESOURCES;
  971. goto OpenDoDeferred;
  972. }
  973. *MacBindingHandle = BINDING_HANDLE_FROM_PELNK_OPEN(NewOpen);
  974. InitializeListHead(&NewOpen->OpenList);
  975. NewOpen->NdisBindingContext = NdisBindingContext;
  976. NewOpen->References = 1;
  977. NewOpen->BindingShuttingDown = FALSE;
  978. NewOpen->OwningAdapter = Adapter;
  979. NewOpen->ProtOptionFlags = 0;
  980. NewOpen->OpenCloseRequest.RequestType = NdisRequestOpen;
  981. Reserved = PELNK_RESERVED_FROM_REQUEST(&NewOpen->OpenCloseRequest);
  982. Reserved->OpenBlock = NewOpen;
  983. Reserved->Next = (PNDIS_REQUEST)NULL;
  984. NdisAcquireSpinLock(&Adapter->Lock);
  985. ElnkQueueRequest(Adapter, &NewOpen->OpenCloseRequest);
  986. StatusToReturn = NDIS_STATUS_PENDING;
  987. //
  988. // Fire off the timer for the next state.
  989. //
  990. if (Adapter->FirstOpen) {
  991. Adapter->FirstOpen = FALSE;
  992. NdisSetTimer(
  993. &Adapter->DeadmanTimer,
  994. 2000
  995. );
  996. }
  997. OpenDoDeferred:
  998. ELNK_DO_DEFERRED(Adapter);
  999. return StatusToReturn;
  1000. }
  1001. STATIC
  1002. NDIS_STATUS
  1003. ElnkCloseAdapter(
  1004. IN NDIS_HANDLE MacBindingHandle
  1005. )
  1006. /*++
  1007. Routine Description:
  1008. This routine causes the MAC to close an open handle (binding).
  1009. Arguments:
  1010. MacBindingHandle - The context value returned by the MAC when the
  1011. adapter was opened. In reality it is a PELNK_OPEN.
  1012. Return Value:
  1013. The function value is the status of the operation.
  1014. --*/
  1015. {
  1016. //
  1017. // Elnk Adapter this open belongs to
  1018. //
  1019. PELNK_ADAPTER Adapter;
  1020. //
  1021. // Pointer to the space allocated for the binding
  1022. //
  1023. PELNK_OPEN Open;
  1024. //
  1025. // Status to return to the caller
  1026. //
  1027. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1028. Adapter = PELNK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1029. //
  1030. // Hold the lock while we update the reference counts for the
  1031. // adapter and the open.
  1032. //
  1033. Open = PELNK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1034. NdisAcquireSpinLock(&Adapter->Lock);
  1035. Adapter->References++;
  1036. //
  1037. // Don't do anything if it's closing
  1038. //
  1039. if (!Open->BindingShuttingDown) {
  1040. PELNK_REQUEST_RESERVED Reserved = PELNK_RESERVED_FROM_REQUEST(&Open->OpenCloseRequest);
  1041. Open->OpenCloseRequest.RequestType = NdisRequestClose;
  1042. Reserved->OpenBlock = Open;
  1043. Reserved->Next = (PNDIS_REQUEST)NULL;
  1044. Open->References++;
  1045. ElnkQueueRequest(Adapter, &Open->OpenCloseRequest);
  1046. //
  1047. // Remove the creation reference.
  1048. //
  1049. Open->References--;
  1050. StatusToReturn = NDIS_STATUS_PENDING;
  1051. } else {
  1052. StatusToReturn = NDIS_STATUS_CLOSING;
  1053. }
  1054. //
  1055. // This macro assumes it is called with the lock held,
  1056. // and releases it.
  1057. //
  1058. ELNK_DO_DEFERRED(Adapter);
  1059. return StatusToReturn;
  1060. }
  1061. extern
  1062. VOID
  1063. ElnkUnloadMac(
  1064. IN NDIS_HANDLE MacMacContext
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. ElnkUnload is called when the MAC is to unload itself.
  1069. Arguments:
  1070. Return Value:
  1071. None.
  1072. --*/
  1073. {
  1074. NDIS_STATUS InitStatus;
  1075. //
  1076. // If the list is empty, or we just emptied it,
  1077. // then unload ourselves.
  1078. //
  1079. ASSERT(IsListEmpty(&ElnkAdapterList));
  1080. NdisFreeSpinLock(&ElnkAdapterListLock);
  1081. NdisDeregisterMac(
  1082. &InitStatus,
  1083. ElnkMacHandle
  1084. );
  1085. NdisTerminateWrapper(
  1086. ElnkNdisWrapperHandle,
  1087. NULL
  1088. );
  1089. return;
  1090. }
  1091. #pragma NDIS_INIT_FUNCTION(ElnkAddAdapter)
  1092. #if ELNKMC
  1093. extern
  1094. NDIS_STATUS
  1095. ElnkAddAdapter(
  1096. IN NDIS_HANDLE MacMacContext,
  1097. IN NDIS_HANDLE ConfigurationHandle,
  1098. IN PNDIS_STRING AdapterName
  1099. )
  1100. /*++
  1101. Routine Description:
  1102. ElnkAddAdapter adds an adapter to the list supported
  1103. by this MAC.
  1104. Arguments:
  1105. Return Value:
  1106. NDIS_STATUS_SUCCESS
  1107. NDIS_STATUS_PENDING
  1108. --*/
  1109. {
  1110. NDIS_HANDLE ConfigHandle;
  1111. NDIS_STATUS Status;
  1112. NDIS_STRING NetAddrStr = NETWORK_ADDRESS;
  1113. UINT ChannelNumber = 0;
  1114. UINT InterruptLevel;
  1115. USHORT IoBase;
  1116. ULONG RamBase;
  1117. NDIS_PHYSICAL_ADDRESS PhysicalAddress;
  1118. NDIS_MCA_POS_DATA McaData;
  1119. UCHAR NetworkAddress[ETH_LENGTH_OF_ADDRESS];
  1120. PUCHAR CurrentAddress = NULL;
  1121. ULONG Length;
  1122. PVOID NetAddress;
  1123. BOOLEAN ConfigError = FALSE;
  1124. NDIS_STATUS ConfigErrorCode;
  1125. NdisOpenConfiguration(
  1126. &Status,
  1127. &ConfigHandle,
  1128. ConfigurationHandle
  1129. );
  1130. if (Status != NDIS_STATUS_SUCCESS) {
  1131. return NDIS_STATUS_FAILURE;
  1132. }
  1133. NdisReadMcaPosInformation(
  1134. &Status,
  1135. ConfigurationHandle,
  1136. &ChannelNumber,
  1137. &McaData
  1138. );
  1139. if (Status != NDIS_STATUS_SUCCESS) {
  1140. ConfigError = TRUE;
  1141. ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  1142. goto RegisterAdapter;
  1143. }
  1144. //
  1145. // Interpret POS data
  1146. //
  1147. switch ((McaData.PosData1 & REG1_IO_BASE_MASK)>>1) {
  1148. case 0x00:
  1149. IoBase = 0x0300;
  1150. break;
  1151. case 0x01:
  1152. IoBase = 0x1300;
  1153. break;
  1154. case 0x02:
  1155. IoBase = 0x2300;
  1156. break;
  1157. case 0x03:
  1158. IoBase = 0x3300;
  1159. break;
  1160. }
  1161. switch ((McaData.PosData1 & REG1_RAM_BASE_MASK)>>3) {
  1162. case 0x00:
  1163. RamBase = 0x0C0000;
  1164. break;
  1165. case 0x01:
  1166. RamBase = 0x0C8000;
  1167. break;
  1168. case 0x02:
  1169. RamBase = 0x0D0000;
  1170. break;
  1171. case 0x03:
  1172. RamBase = 0x0D8000;
  1173. break;
  1174. }
  1175. switch ((McaData.PosData1 & REG1_INTERRUPT_LEVEL_MASK)>>6) {
  1176. case 0x00:
  1177. InterruptLevel = 12;
  1178. break;
  1179. case 0x01:
  1180. InterruptLevel = 7;
  1181. break;
  1182. case 0x02:
  1183. InterruptLevel = 3;
  1184. break;
  1185. case 0x03:
  1186. InterruptLevel = 9;
  1187. break;
  1188. }
  1189. //
  1190. // Read net address
  1191. //
  1192. NdisReadNetworkAddress(
  1193. &Status,
  1194. &NetAddress,
  1195. &Length,
  1196. ConfigHandle
  1197. );
  1198. if ((Length == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
  1199. ETH_COPY_NETWORK_ADDRESS(
  1200. NetworkAddress,
  1201. NetAddress
  1202. );
  1203. CurrentAddress = NetworkAddress;
  1204. }
  1205. RegisterAdapter:
  1206. NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
  1207. NdisSetPhysicalAddressLow(PhysicalAddress, RamBase);
  1208. Status = ElnkmcRegisterAdapter(
  1209. ElnkMacHandle,
  1210. ConfigurationHandle,
  1211. AdapterName,
  1212. InterruptLevel,
  1213. PhysicalAddress,
  1214. IoBase,
  1215. CurrentAddress,
  1216. ELNK_MAXIMUM_MULTICAST,
  1217. 32,
  1218. ConfigError,
  1219. ConfigErrorCode
  1220. );
  1221. NdisCloseConfiguration(ConfigHandle);
  1222. return Status;
  1223. }
  1224. #else
  1225. extern
  1226. NDIS_STATUS
  1227. ElnkAddAdapter(
  1228. IN NDIS_HANDLE MacMacContext,
  1229. IN NDIS_HANDLE ConfigurationHandle,
  1230. IN PNDIS_STRING AdapterName
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. ElnkAddAdapter adds an adapter to the list supported
  1235. by this MAC.
  1236. Arguments:
  1237. Return Value:
  1238. NDIS_STATUS_SUCCESS
  1239. NDIS_STATUS_PENDING
  1240. --*/
  1241. {
  1242. NDIS_HANDLE ConfigHandle;
  1243. NDIS_STATUS Status;
  1244. PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
  1245. NDIS_STRING NetAddrStr = NETWORK_ADDRESS;
  1246. NDIS_STRING TransStr = NDIS_STRING_CONST("Transceiver");
  1247. NDIS_STRING InterruptStr = NDIS_STRING_CONST("InterruptNumber");
  1248. NDIS_STRING IoPortStr = IOBASE;
  1249. NDIS_STRING RamBaseStr = NDIS_STRING_CONST("MemoryMappedBaseAddress");
  1250. NDIS_STRING ZWStr = NDIS_STRING_CONST("ZeroWaitState");
  1251. NDIS_STRING RamSizeStr = NDIS_STRING_CONST("MemoryMappedSize");
  1252. USHORT IoBase;
  1253. UINT InterruptVector;
  1254. BOOLEAN IsExternal;
  1255. BOOLEAN ZwsEnabled;
  1256. ULONG WindowBase;
  1257. NDIS_PHYSICAL_ADDRESS PhysicalAddress;
  1258. UINT WindowSize;
  1259. UCHAR NetworkAddress[ETH_LENGTH_OF_ADDRESS];
  1260. PUCHAR CurrentAddress = NULL;
  1261. ULONG Length;
  1262. PVOID NetAddress;
  1263. BOOLEAN ConfigError = FALSE;
  1264. NDIS_STATUS ConfigErrorCode;
  1265. NdisOpenConfiguration(
  1266. &Status,
  1267. &ConfigHandle,
  1268. ConfigurationHandle
  1269. );
  1270. if (Status != NDIS_STATUS_SUCCESS) {
  1271. return NDIS_STATUS_FAILURE;
  1272. }
  1273. //
  1274. // Read net address
  1275. //
  1276. NdisReadNetworkAddress(
  1277. &Status,
  1278. &NetAddress,
  1279. &Length,
  1280. ConfigHandle
  1281. );
  1282. if ((Length == ETH_LENGTH_OF_ADDRESS) && (Status == NDIS_STATUS_SUCCESS)) {
  1283. ETH_COPY_NETWORK_ADDRESS(
  1284. NetworkAddress,
  1285. NetAddress
  1286. );
  1287. CurrentAddress = NetworkAddress;
  1288. }
  1289. #if NDIS_NT
  1290. //
  1291. // Let's get the interrupt number
  1292. //
  1293. NdisReadConfiguration(
  1294. &Status,
  1295. &ReturnedValue,
  1296. ConfigHandle,
  1297. &InterruptStr,
  1298. NdisParameterInteger
  1299. );
  1300. if (Status == NDIS_STATUS_SUCCESS) {
  1301. InterruptVector = ReturnedValue->ParameterData.IntegerData;
  1302. } else {
  1303. InterruptVector = ELNK16_DEFAULT_INTERRUPT_VECTOR;
  1304. }
  1305. {
  1306. UCHAR i;
  1307. static UINT Interrupts[] = {3,5,7,9,10,11,12,15};
  1308. for (i=0; i < 8; i++) {
  1309. if (Interrupts[i] == InterruptVector) {
  1310. break;
  1311. }
  1312. }
  1313. if (i == 8) {
  1314. ConfigError = TRUE;
  1315. ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  1316. goto RegisterAdapter;
  1317. }
  1318. }
  1319. #endif // NDIS_NT
  1320. //
  1321. // Get the Io Port
  1322. //
  1323. NdisReadConfiguration(
  1324. &Status,
  1325. &ReturnedValue,
  1326. ConfigHandle,
  1327. &IoPortStr,
  1328. NdisParameterHexInteger
  1329. );
  1330. if (Status == NDIS_STATUS_SUCCESS) {
  1331. IoBase = (USHORT) ReturnedValue->ParameterData.IntegerData;
  1332. } else {
  1333. IoBase = ELNK16_DEFAULT_IOBASE;
  1334. }
  1335. {
  1336. UINT i;
  1337. for (i=0x200; i < 0x3f0; i += 0x10) {
  1338. if ((i == 0x270) ||
  1339. // (i == 0x290) ||
  1340. (i == 0x2f0) ||
  1341. (i == 0x370) ||
  1342. (i == 0x3b0) ||
  1343. (i == 0x3c0) ||
  1344. (i == 0x3d0)) {
  1345. continue;
  1346. }
  1347. if (i == IoBase) {
  1348. break;
  1349. }
  1350. }
  1351. if (i != IoBase) {
  1352. ConfigError = TRUE;
  1353. ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  1354. goto RegisterAdapter;
  1355. }
  1356. }
  1357. #if NDIS_NT
  1358. //
  1359. // Get the RamBase
  1360. //
  1361. NdisReadConfiguration(
  1362. &Status,
  1363. &ReturnedValue,
  1364. ConfigHandle,
  1365. &RamBaseStr,
  1366. NdisParameterHexInteger
  1367. );
  1368. if (Status == NDIS_STATUS_SUCCESS) {
  1369. WindowBase = ReturnedValue->ParameterData.IntegerData;
  1370. } else {
  1371. WindowBase = ELNK16_DEFAULT_WINBASE;
  1372. }
  1373. if ((WindowBase < 0xC0000) ||
  1374. (WindowBase > 0xDFFFF) ||
  1375. ((WindowBase & 0x3FFF) != 0x0)) {
  1376. ConfigError = TRUE;
  1377. ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  1378. goto RegisterAdapter;
  1379. }
  1380. //
  1381. // Let's get the size of the Window
  1382. //
  1383. NdisReadConfiguration(
  1384. &Status,
  1385. &ReturnedValue,
  1386. ConfigHandle,
  1387. &RamSizeStr,
  1388. NdisParameterHexInteger
  1389. );
  1390. if (Status == NDIS_STATUS_SUCCESS) {
  1391. WindowSize = ReturnedValue->ParameterData.IntegerData;
  1392. } else {
  1393. WindowSize = ELNK16_DEFAULT_WINDOW_SIZE;
  1394. }
  1395. //
  1396. // Convert to local method
  1397. //
  1398. WindowSize = WindowSize >> 10;
  1399. if ((WindowSize != 16) &&
  1400. (WindowSize != 32) &&
  1401. (WindowSize != 48) &&
  1402. (WindowSize != 64)) {
  1403. ConfigError = TRUE;
  1404. ConfigErrorCode = NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION;
  1405. goto RegisterAdapter;
  1406. }
  1407. //
  1408. // Are we using External Transceiver?
  1409. //
  1410. NdisReadConfiguration(
  1411. &Status,
  1412. &ReturnedValue,
  1413. ConfigHandle,
  1414. &TransStr,
  1415. NdisParameterInteger
  1416. );
  1417. if (Status == NDIS_STATUS_SUCCESS) {
  1418. IsExternal = (ReturnedValue->ParameterData.IntegerData == 1)?TRUE:FALSE;
  1419. } else {
  1420. IsExternal = TRUE;
  1421. }
  1422. //
  1423. // Do we want to enable Zero wait state
  1424. //
  1425. NdisReadConfiguration(
  1426. &Status,
  1427. &ReturnedValue,
  1428. ConfigHandle,
  1429. &ZWStr,
  1430. NdisParameterInteger
  1431. );
  1432. if (Status == NDIS_STATUS_SUCCESS) {
  1433. ZwsEnabled = (ReturnedValue->ParameterData.IntegerData == 1)?TRUE:FALSE;
  1434. } else {
  1435. ZwsEnabled = TRUE;
  1436. }
  1437. #endif // NDIS_NT
  1438. #if NDIS_WIN
  1439. // use defaults for now. We will read these values from eeprom.
  1440. InterruptVector = ELNK16_DEFAULT_INTERRUPT_VECTOR;
  1441. WindowBase = ELNK16_DEFAULT_WINBASE;
  1442. WindowSize = ELNK16_DEFAULT_WINDOW_SIZE;
  1443. IsExternal = TRUE;
  1444. ZwsEnabled = TRUE;
  1445. #endif // NDIS_WIN
  1446. RegisterAdapter:
  1447. NdisSetPhysicalAddressHigh(PhysicalAddress, 0);
  1448. NdisSetPhysicalAddressLow(PhysicalAddress, WindowBase);
  1449. Status = Elnk16RegisterAdapter(
  1450. ElnkMacHandle,
  1451. ConfigurationHandle,
  1452. AdapterName,
  1453. InterruptVector,
  1454. PhysicalAddress,
  1455. WindowSize,
  1456. IoBase,
  1457. IsExternal,
  1458. ZwsEnabled,
  1459. CurrentAddress,
  1460. ELNK_MAXIMUM_MULTICAST,
  1461. 32,
  1462. ConfigError,
  1463. ConfigErrorCode
  1464. );
  1465. if (Status != NDIS_STATUS_SUCCESS) {
  1466. if ELNKDEBUG DPrint1("Elnk16AddAdapter: Elnk16RegisterAdapter failed\n");
  1467. }
  1468. NdisCloseConfiguration(ConfigHandle);
  1469. return Status;
  1470. }
  1471. #endif
  1472. extern
  1473. VOID
  1474. ElnkRemoveAdapter(
  1475. IN NDIS_HANDLE MacAdapterContext
  1476. )
  1477. /*++
  1478. Routine Description:
  1479. ElnkRemoveAdapter removes an adapter previously registered
  1480. with NdisRegisterAdapter.
  1481. Arguments:
  1482. MacAdapterContext - The context value that the MAC passed
  1483. to NdisRegisterAdapter; actually as pointer to a
  1484. ELNK_ADAPTER.
  1485. Return Value:
  1486. None.
  1487. --*/
  1488. {
  1489. PELNK_ADAPTER Adapter;
  1490. BOOLEAN Cancelled;
  1491. Adapter = PELNK_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
  1492. ASSERT(Adapter->OpenCount == 0);
  1493. //
  1494. // There are no opens left, so remove ourselves.
  1495. //
  1496. NdisCancelTimer(&Adapter->DeadmanTimer,&Cancelled);
  1497. NdisRemoveInterrupt(&Adapter->Interrupt);
  1498. EthDeleteFilter(Adapter->FilterDB);
  1499. NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
  1500. NdisFreeSpinLock(&Adapter->Lock);
  1501. NdisAcquireSpinLock(&ElnkAdapterListLock);
  1502. RemoveEntryList(&Adapter->AdapterList);
  1503. NdisReleaseSpinLock(&ElnkAdapterListLock);
  1504. ELNK_FREE_PHYS(Adapter);
  1505. #if !ELNKMC
  1506. //
  1507. // Put the card in START state. This leaves the
  1508. // card in the same state as a hardware powerup.
  1509. // This guarantees that the card is in a known workable
  1510. // state if an additional AddAdapter is issued before the
  1511. // power has been cycled. Otherwise, the AddAdapter fails.
  1512. //
  1513. // Go to Run state
  1514. NdisRawWritePortUchar(ELNK16_ID_PORT,0x00);
  1515. Elnk16GenerateIdPattern(Adapter);
  1516. NdisRawWritePortUchar(ELNK16_ID_PORT,0x00);
  1517. // Go to Reset state
  1518. Elnk16GenerateIdPattern(Adapter);
  1519. // Go to IoLoad state
  1520. Elnk16GenerateIdPattern(Adapter);
  1521. // Go to Config state
  1522. NdisRawWritePortUchar(ELNK16_ID_PORT,(UCHAR)0xFF);
  1523. // Reset the card, which leaves the card in Start state
  1524. NdisRawWritePortUchar(ELNK16_ICR,ICR_RESET);
  1525. #endif
  1526. return;
  1527. }