Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

571 lines
16 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. PURPOSE.
  7. Module Name:
  8. INIT.C
  9. Abstract:
  10. This module contains initialization helper routines called during
  11. MiniportInitialize.
  12. Revision History:
  13. Notes:
  14. --*/
  15. #include "miniport.h"
  16. #pragma NDIS_PAGEABLE_FUNCTION(NICAllocAdapter)
  17. #pragma NDIS_PAGEABLE_FUNCTION(NICFreeAdapter)
  18. #pragma NDIS_PAGEABLE_FUNCTION(NICInitializeAdapter)
  19. #pragma NDIS_PAGEABLE_FUNCTION(NICReadRegParameters)
  20. NDIS_STATUS NICAllocAdapter(
  21. PMP_ADAPTER *pAdapter)
  22. {
  23. PMP_ADAPTER Adapter = NULL;
  24. PNDIS_PACKET Packet;
  25. PNDIS_BUFFER Buffer;
  26. PUCHAR pTCBMem;
  27. PTCB pTCB;
  28. NDIS_STATUS Status;
  29. LONG index;
  30. DEBUGP(MP_TRACE, ("--> NICAllocAdapter\n"));
  31. *pAdapter = NULL;
  32. do
  33. {
  34. //
  35. // Allocate memory for adapter context
  36. //
  37. Status = NdisAllocateMemoryWithTag(
  38. &Adapter,
  39. sizeof(MP_ADAPTER),
  40. NIC_TAG);
  41. if(Status != NDIS_STATUS_SUCCESS)
  42. {
  43. DEBUGP(MP_ERROR, ("Failed to allocate memory for adapter context\n"));
  44. break;
  45. }
  46. //
  47. // Zero the memory block
  48. //
  49. NdisZeroMemory(Adapter, sizeof(MP_ADAPTER));
  50. NdisInitializeListHead(&Adapter->List);
  51. //
  52. // Initialize Send & Recv listheads and corresponding
  53. // spinlocks.
  54. //
  55. NdisInitializeListHead(&Adapter->RecvWaitList);
  56. NdisInitializeListHead(&Adapter->SendWaitList);
  57. NdisInitializeListHead(&Adapter->SendFreeList);
  58. NdisAllocateSpinLock(&Adapter->SendLock);
  59. NdisInitializeListHead(&Adapter->RecvFreeList);
  60. NdisAllocateSpinLock(&Adapter->RecvLock);
  61. //
  62. // Allocate lookside list for Receive Control blocks.
  63. //
  64. NdisInitializeNPagedLookasideList(
  65. &Adapter->RecvLookaside,
  66. NULL, // No Allocate function
  67. NULL, // No Free function
  68. 0, // Reserved for system use
  69. sizeof(RCB),
  70. NIC_TAG,
  71. 0); // Reserved for system use
  72. MP_SET_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE);
  73. //
  74. // Allocate packet pool for receive indications
  75. //
  76. NdisAllocatePacketPool(
  77. &Status,
  78. &Adapter->RecvPacketPoolHandle,
  79. NIC_MAX_BUSY_RECVS,
  80. PROTOCOL_RESERVED_SIZE_IN_PACKET);
  81. if(Status != NDIS_STATUS_SUCCESS)
  82. {
  83. DEBUGP(MP_ERROR, ("NdisAllocatePacketPool failed\n"));
  84. break;
  85. }
  86. //
  87. // Initialize receive packets
  88. //
  89. for(index=0; index < NIC_MAX_BUSY_RECVS; index++)
  90. {
  91. //
  92. // Allocate a packet descriptor for receive packets
  93. // from a preallocated pool.
  94. //
  95. NdisAllocatePacket(
  96. &Status,
  97. &Packet,
  98. Adapter->RecvPacketPoolHandle);
  99. if(Status != NDIS_STATUS_SUCCESS)
  100. {
  101. DEBUGP(MP_ERROR, ("NdisAllocatePacket failed\n"));
  102. break;
  103. }
  104. NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE);
  105. //
  106. // Insert it into the list of free receive packets.
  107. //
  108. NdisInterlockedInsertTailList(
  109. &Adapter->RecvFreeList,
  110. (PLIST_ENTRY)&Packet->MiniportReserved[0],
  111. &Adapter->RecvLock);
  112. }
  113. //
  114. // Allocate a huge block of memory for all TCB's
  115. //
  116. Status = NdisAllocateMemoryWithTag(
  117. &pTCBMem,
  118. sizeof(TCB) * NIC_MAX_BUSY_SENDS,
  119. NIC_TAG);
  120. if(Status != NDIS_STATUS_SUCCESS)
  121. {
  122. DEBUGP(MP_ERROR, ("Failed to allocate memory for TCB's\n"));
  123. break;
  124. }
  125. NdisZeroMemory(pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS);
  126. Adapter->TCBMem = pTCBMem;
  127. //
  128. // Allocate a buffer pool for send buffers.
  129. //
  130. NdisAllocateBufferPool(
  131. &Status,
  132. &Adapter->SendBufferPoolHandle,
  133. NIC_MAX_BUSY_SENDS);
  134. if(Status != NDIS_STATUS_SUCCESS)
  135. {
  136. DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for send buffer failed\n"));
  137. break;
  138. }
  139. //
  140. // Divide the TCBMem blob into TCBs and create a buffer
  141. // descriptor for the Data portion of the TCBs.
  142. //
  143. for(index=0; index < NIC_MAX_BUSY_SENDS; index++)
  144. {
  145. pTCB = (PTCB) pTCBMem;
  146. //
  147. // Create a buffer descriptor for the Data portion of the TCBs.
  148. // Buffer descriptors are nothing but MDLs on NT systems.
  149. //
  150. NdisAllocateBuffer(
  151. &Status,
  152. &Buffer,
  153. Adapter->SendBufferPoolHandle,
  154. (PVOID)&pTCB->Data[0],
  155. NIC_BUFFER_SIZE);
  156. if(Status != NDIS_STATUS_SUCCESS)
  157. {
  158. DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n"));
  159. break;
  160. }
  161. //
  162. // Initialize the TCB structure.
  163. //
  164. pTCB->Buffer = Buffer;
  165. pTCB->pData = (PUCHAR) &pTCB->Data[0];
  166. pTCB->Adapter = Adapter;
  167. NdisInterlockedInsertTailList(
  168. &Adapter->SendFreeList,
  169. &pTCB->List,
  170. &Adapter->SendLock);
  171. pTCBMem = pTCBMem + sizeof(TCB);
  172. }
  173. } while(FALSE);
  174. *pAdapter = Adapter;
  175. //
  176. // In the failure case, the caller of this routine will end up
  177. // calling NICFreeAdapter to free all the successfully allocated
  178. // resources.
  179. //
  180. DEBUGP(MP_TRACE, ("<-- NICAllocAdapter\n"));
  181. return(Status);
  182. }
  183. void NICFreeAdapter(
  184. PMP_ADAPTER Adapter)
  185. {
  186. NDIS_STATUS Status;
  187. PNDIS_PACKET Packet;
  188. PNDIS_BUFFER Buffer;
  189. PUCHAR pMem;
  190. PTCB pTCB;
  191. PLIST_ENTRY pEntry;
  192. DEBUGP(MP_TRACE, ("--> NICFreeAdapter\n"));
  193. ASSERT(Adapter);
  194. ASSERT(!Adapter->RefCount);
  195. //
  196. // Free all the resources we allocated for send.
  197. //
  198. while(!IsListEmpty(&Adapter->SendFreeList))
  199. {
  200. pTCB = (PTCB) NdisInterlockedRemoveHeadList(
  201. &Adapter->SendFreeList,
  202. &Adapter->SendLock);
  203. if(!pTCB)
  204. {
  205. break;
  206. }
  207. if(pTCB->Buffer)
  208. {
  209. NdisFreeBuffer(pTCB->Buffer);
  210. }
  211. }
  212. if(Adapter->SendBufferPoolHandle)
  213. {
  214. NdisFreeBufferPool(Adapter->SendBufferPoolHandle);
  215. }
  216. NdisFreeMemory(Adapter->TCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS, 0);
  217. ASSERT(IsListEmpty(&Adapter->SendFreeList));
  218. ASSERT(IsListEmpty(&Adapter->RecvWaitList));
  219. ASSERT(IsListEmpty(&Adapter->SendWaitList));
  220. NdisFreeSpinLock(&Adapter->SendLock);
  221. //
  222. // Free all the resources we allocated for receive.
  223. //
  224. if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE))
  225. {
  226. NdisDeleteNPagedLookasideList(&Adapter->RecvLookaside);
  227. MP_CLEAR_FLAG(Adapter, fMP_ADAPTER_RECV_LOOKASIDE);
  228. }
  229. while(!IsListEmpty(&Adapter->RecvFreeList))
  230. {
  231. pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  232. &Adapter->RecvFreeList,
  233. &Adapter->RecvLock);
  234. if(pEntry)
  235. {
  236. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  237. NdisFreePacket(Packet);
  238. }
  239. }
  240. if(Adapter->RecvPacketPoolHandle)
  241. {
  242. NdisFreePacketPool(Adapter->RecvPacketPoolHandle);
  243. }
  244. ASSERT(IsListEmpty(&Adapter->RecvFreeList));
  245. NdisFreeSpinLock(&Adapter->RecvLock);
  246. //
  247. // Finally free the memory for adapter context.
  248. //
  249. NdisFreeMemory(Adapter, sizeof(MP_ADAPTER), 0);
  250. DEBUGP(MP_TRACE, ("<-- NICFreeAdapter\n"));
  251. }
  252. void NICAttachAdapter(PMP_ADAPTER Adapter)
  253. {
  254. DEBUGP(MP_TRACE, ("--> NICAttachAdapter\n"));
  255. NdisInterlockedInsertTailList(
  256. &GlobalData.AdapterList,
  257. &Adapter->List,
  258. &GlobalData.Lock);
  259. DEBUGP(MP_TRACE, ("<-- NICAttachAdapter\n"));
  260. }
  261. void NICDetachAdapter(PMP_ADAPTER Adapter)
  262. {
  263. DEBUGP(MP_TRACE, ("--> NICDetachAdapter\n"));
  264. NdisAcquireSpinLock(&GlobalData.Lock);
  265. RemoveEntryList(&Adapter->List);
  266. NdisReleaseSpinLock(&GlobalData.Lock);
  267. DEBUGP(MP_TRACE, ("<-- NICDetachAdapter\n"));
  268. }
  269. NDIS_STATUS
  270. NICReadRegParameters(
  271. PMP_ADAPTER Adapter,
  272. NDIS_HANDLE WrapperConfigurationContext)
  273. /*++
  274. Routine Description:
  275. Read device configuration parameters from the registry
  276. Arguments:
  277. Adapter Pointer to our adapter
  278. WrapperConfigurationContext For use by NdisOpenConfiguration
  279. Should be called at IRQL = PASSIVE_LEVEL.
  280. Return Value:
  281. NDIS_STATUS_SUCCESS
  282. NDIS_STATUS_FAILURE
  283. NDIS_STATUS_RESOURCES
  284. --*/
  285. {
  286. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  287. NDIS_HANDLE ConfigurationHandle;
  288. PUCHAR NetworkAddress;
  289. UINT Length;
  290. PUCHAR pAddr;
  291. static ULONG g_ulAddress = 0;
  292. DEBUGP(MP_TRACE, ("--> NICReadRegParameters\n"));
  293. //
  294. // Open the registry for this adapter to read advanced
  295. // configuration parameters stored by the INF file.
  296. //
  297. NdisOpenConfiguration(
  298. &Status,
  299. &ConfigurationHandle,
  300. WrapperConfigurationContext);
  301. if(Status != NDIS_STATUS_SUCCESS)
  302. {
  303. DEBUGP(MP_ERROR, ("NdisOpenConfiguration failed\n"));
  304. return NDIS_STATUS_FAILURE;
  305. }
  306. //
  307. // Read all of our configuration parameters using NdisReadConfiguration
  308. // and parse the value.
  309. //
  310. //
  311. // Just for testing purposes, let us make up a dummy mac address.
  312. // In order to avoid conflicts with MAC addresses, it is usually a good
  313. // idea to check the IEEE OUI list (e.g. at
  314. // http://standards.ieee.org/regauth/oui/oui.txt). According to that
  315. // list 00-50-F2 is owned by Microsoft.
  316. //
  317. // An important rule to "generating" MAC addresses is to have the
  318. // "locally administered bit" set in the address, which is bit 0x02 for
  319. // LSB-type networks like Ethernet. Also make sure to never set the
  320. // multicast bit in any MAC address: bit 0x01 in LSB networks.
  321. //
  322. pAddr = (PUCHAR) &g_ulAddress;
  323. ++g_ulAddress;
  324. Adapter->PermanentAddress[0] = 0x02;
  325. Adapter->PermanentAddress[1] = 0x50;
  326. Adapter->PermanentAddress[2] = 0xF2;
  327. Adapter->PermanentAddress[3] = 0x00;
  328. Adapter->PermanentAddress[4] = 0x00;
  329. Adapter->PermanentAddress[5] = pAddr[0];
  330. //
  331. // Read NetworkAddress registry value and use it as the current address
  332. // if there is a software configurable NetworkAddress specified in
  333. // the registry.
  334. //
  335. NdisReadNetworkAddress(
  336. &Status,
  337. &NetworkAddress,
  338. &Length,
  339. ConfigurationHandle);
  340. if((Status == NDIS_STATUS_SUCCESS) && (Length == ETH_LENGTH_OF_ADDRESS))
  341. {
  342. ETH_COPY_NETWORK_ADDRESS(
  343. Adapter->CurrentAddress,
  344. NetworkAddress);
  345. } else {
  346. ETH_COPY_NETWORK_ADDRESS(
  347. Adapter->CurrentAddress,
  348. Adapter->PermanentAddress);
  349. }
  350. DEBUGP(MP_LOUD, ("Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
  351. Adapter->PermanentAddress[0],
  352. Adapter->PermanentAddress[1],
  353. Adapter->PermanentAddress[2],
  354. Adapter->PermanentAddress[3],
  355. Adapter->PermanentAddress[4],
  356. Adapter->PermanentAddress[5]));
  357. DEBUGP(MP_LOUD, ("Current Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
  358. Adapter->CurrentAddress[0],
  359. Adapter->CurrentAddress[1],
  360. Adapter->CurrentAddress[2],
  361. Adapter->CurrentAddress[3],
  362. Adapter->CurrentAddress[4],
  363. Adapter->CurrentAddress[5]));
  364. Adapter->ulLinkSpeed = NIC_LINK_SPEED;
  365. //
  366. // Close the configuration registry
  367. //
  368. NdisCloseConfiguration(ConfigurationHandle);
  369. DEBUGP(MP_TRACE, ("<-- NICReadRegParameters\n"));
  370. return NDIS_STATUS_SUCCESS;
  371. }
  372. NDIS_STATUS NICInitializeAdapter(
  373. IN PMP_ADAPTER Adapter,
  374. IN NDIS_HANDLE WrapperConfigurationContext
  375. )
  376. /*++
  377. Routine Description:
  378. Query assigned resources and initialize the adapter.
  379. Arguments:
  380. Adapter Pointer to our adapter
  381. Return Value:
  382. NDIS_STATUS_SUCCESS
  383. NDIS_STATUS_ADAPTER_NOT_FOUND
  384. --*/
  385. {
  386. NDIS_STATUS Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  387. UCHAR resBuf[NIC_RESOURCE_BUF_SIZE];
  388. PNDIS_RESOURCE_LIST resList = (PNDIS_RESOURCE_LIST)resBuf;
  389. UINT bufSize = NIC_RESOURCE_BUF_SIZE;
  390. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc;
  391. ULONG index;
  392. DEBUGP(MP_TRACE, ("---> InitializeAdapter\n"));
  393. do
  394. {
  395. //
  396. // Get the resources assigned by the PNP manager. NDIS gets
  397. // these resources in IRP_MN_START_DEVICE request.
  398. //
  399. NdisMQueryAdapterResources(
  400. &Status,
  401. WrapperConfigurationContext,
  402. resList,
  403. &bufSize);
  404. if (Status == NDIS_STATUS_SUCCESS)
  405. {
  406. for (index=0; index < resList->Count; index++)
  407. {
  408. pResDesc = &resList->PartialDescriptors[index];
  409. switch(pResDesc->Type)
  410. {
  411. case CmResourceTypePort:
  412. DEBUGP(MP_INFO, ("IoBaseAddress = 0x%x\n",
  413. NdisGetPhysicalAddressLow(pResDesc->u.Port.Start)));
  414. DEBUGP(MP_INFO, ("IoRange = x%x\n",
  415. pResDesc->u.Port.Length));
  416. break;
  417. case CmResourceTypeInterrupt:
  418. DEBUGP(MP_INFO, ("InterruptLevel = x%x\n",
  419. pResDesc->u.Interrupt.Level));
  420. break;
  421. case CmResourceTypeMemory:
  422. DEBUGP(MP_INFO, ("MemPhysAddress(Low) = 0x%0x\n",
  423. NdisGetPhysicalAddressLow(pResDesc->u.Memory.Start)));
  424. DEBUGP(MP_INFO, ("MemPhysAddress(High) = 0x%0x\n",
  425. NdisGetPhysicalAddressHigh(pResDesc->u.Memory.Start)));
  426. break;
  427. }
  428. }
  429. }
  430. Status = NDIS_STATUS_SUCCESS;
  431. //
  432. // Map bus-relative IO range to system IO space using
  433. // NdisMRegisterIoPortRange
  434. //
  435. //
  436. // Map bus-relative registers to virtual system-space
  437. // using NdisMMapIoSpace
  438. //
  439. //
  440. // Disable interrupts here as soon as possible
  441. //
  442. //
  443. // Register the interrupt using NdisMRegisterInterrupt
  444. //
  445. //
  446. // Initialize the hardware with mapped resources
  447. //
  448. #ifdef NDIS50_MINIPORT
  449. //
  450. // Register a shutdown handler for NDIS50 or earlier miniports
  451. // For NDIS51 miniports, set AdapterShutdownHandler.
  452. //
  453. NdisMRegisterAdapterShutdownHandler(
  454. Adapter->AdapterHandle,
  455. (PVOID) Adapter,
  456. (ADAPTER_SHUTDOWN_HANDLER) MPShutdown);
  457. #endif
  458. //
  459. // Enable the interrupt
  460. //
  461. } while (FALSE);
  462. DEBUGP(MP_TRACE, ("<--- InitializeAdapter, Status=%x\n", Status));
  463. return Status;
  464. }