Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
13 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Driver - initialization implementation
  8. Author:
  9. kyrilf
  10. --*/
  11. #define NDIS51_MINIPORT 1
  12. #define NDIS_MINIPORT_DRIVER 1
  13. #define NDIS50 1
  14. #define NDIS51 1
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <ndis.h>
  18. #include "main.h"
  19. #include "init.h"
  20. #include "prot.h"
  21. #include "nic.h"
  22. #include "univ.h"
  23. #include "wlbsparm.h"
  24. #include "log.h"
  25. #include "trace.h" // For wmi event tracing
  26. static ULONG log_module_id = LOG_MODULE_INIT;
  27. /* Added for NDIS51. */
  28. extern VOID Nic_pnpevent_notify (
  29. NDIS_HANDLE adapter_handle,
  30. NDIS_DEVICE_PNP_EVENT pnp_event,
  31. PVOID info_buf,
  32. ULONG info_len);
  33. /* Mark code that is used only during initialization. */
  34. #pragma alloc_text (INIT, DriverEntry)
  35. NDIS_STATUS DriverEntry (
  36. PVOID driver_obj,
  37. PVOID registry_path)
  38. {
  39. NDIS_PROTOCOL_CHARACTERISTICS prot_char;
  40. NDIS_MINIPORT_CHARACTERISTICS nic_char;
  41. NDIS_STRING prot_name = UNIV_NDIS_PROTOCOL_NAME;
  42. NTSTATUS status;
  43. PUNICODE_STRING reg_path = (PUNICODE_STRING) registry_path;
  44. WCHAR params [] = L"\\Parameters\\Interface\\";
  45. ULONG i;
  46. /* Register Convoy protocol with NDIS. */
  47. UNIV_PRINT (("DriverEntry: Loading the driver %x", driver_obj));
  48. univ_driver_ptr = driver_obj;
  49. /* Initialize the array of bindings. */
  50. univ_adapters_count = 0;
  51. for (i = 0 ; i < CVY_MAX_ADAPTERS; i++)
  52. {
  53. univ_adapters [i] . code = MAIN_ADAPTER_CODE;
  54. univ_adapters [i] . announced = FALSE;
  55. univ_adapters [i] . inited = FALSE;
  56. univ_adapters [i] . bound = FALSE;
  57. univ_adapters [i] . used = FALSE;
  58. univ_adapters [i] . ctxtp = NULL;
  59. univ_adapters [i] . device_name_len = 0;
  60. univ_adapters [i] . device_name = NULL;
  61. }
  62. /* create UNICODE name for the protocol */
  63. univ_reg_path_len = reg_path -> Length + wcslen (params) * sizeof (WCHAR) + sizeof (WCHAR);
  64. status = NdisAllocateMemoryWithTag (& univ_reg_path, univ_reg_path_len, UNIV_POOL_TAG);
  65. if (status != NDIS_STATUS_SUCCESS)
  66. {
  67. UNIV_PRINT (("Error allocating memory %x", status));
  68. __LOG_MSG1 (MSG_ERROR_MEMORY, MSG_NONE, status);
  69. return STATUS_INSUFFICIENT_RESOURCES;
  70. }
  71. RtlZeroMemory (univ_reg_path, reg_path -> Length + wcslen (params) * sizeof (WCHAR) + sizeof (WCHAR));
  72. RtlCopyMemory (univ_reg_path, reg_path -> Buffer, reg_path -> Length);
  73. RtlCopyMemory (((PCHAR) univ_reg_path) + reg_path -> Length, params, wcslen (params) * sizeof (WCHAR));
  74. /* Initialize miniport wrapper. */
  75. NdisMInitializeWrapper (& univ_wrapper_handle, driver_obj, registry_path, NULL);
  76. /* Initialize miniport characteristics. */
  77. RtlZeroMemory (& nic_char, sizeof (nic_char));
  78. nic_char . MajorNdisVersion = UNIV_NDIS_MAJOR_VERSION;
  79. nic_char . MinorNdisVersion = UNIV_NDIS_MINOR_VERSION;
  80. nic_char . HaltHandler = Nic_halt;
  81. nic_char . InitializeHandler = Nic_init;
  82. nic_char . QueryInformationHandler = Nic_info_query;
  83. nic_char . SetInformationHandler = Nic_info_set;
  84. nic_char . ResetHandler = Nic_reset;
  85. nic_char . ReturnPacketHandler = Nic_return;
  86. nic_char . SendPacketsHandler = Nic_packets_send;
  87. nic_char . TransferDataHandler = Nic_transfer;
  88. /* For NDIS51, define 3 new handlers. These handlers do nothing for now, but stuff will be added later. */
  89. nic_char . CancelSendPacketsHandler = Nic_cancel_send_packets;
  90. nic_char . PnPEventNotifyHandler = Nic_pnpevent_notify;
  91. nic_char . AdapterShutdownHandler = Nic_adapter_shutdown;
  92. UNIV_PRINT (("DriverEntry: Registering miniport"));
  93. status = NdisIMRegisterLayeredMiniport (univ_wrapper_handle, & nic_char, sizeof (nic_char), & univ_driver_handle);
  94. if (status != NDIS_STATUS_SUCCESS)
  95. {
  96. UNIV_PRINT (("error registering layered miniport with NDIS %x", status));
  97. __LOG_MSG1 (MSG_ERROR_REGISTERING, MSG_NONE, status);
  98. NdisTerminateWrapper (univ_wrapper_handle, NULL);
  99. NdisFreeMemory(univ_reg_path, univ_reg_path_len, 0);
  100. goto error;
  101. }
  102. /* Initialize protocol characteristics. */
  103. RtlZeroMemory (& prot_char, sizeof (prot_char));
  104. /* This value needs to be 0, otherwise error registering protocol */
  105. prot_char . MinorNdisVersion = 0;
  106. prot_char . MajorNdisVersion = UNIV_NDIS_MAJOR_VERSION;
  107. prot_char . BindAdapterHandler = Prot_bind;
  108. prot_char . UnbindAdapterHandler = Prot_unbind;
  109. prot_char . OpenAdapterCompleteHandler = Prot_open_complete;
  110. prot_char . CloseAdapterCompleteHandler = Prot_close_complete;
  111. prot_char . StatusHandler = Prot_status;
  112. prot_char . StatusCompleteHandler = Prot_status_complete;
  113. prot_char . ResetCompleteHandler = Prot_reset_complete;
  114. prot_char . RequestCompleteHandler = Prot_request_complete;
  115. prot_char . SendCompleteHandler = Prot_send_complete;
  116. prot_char . TransferDataCompleteHandler = Prot_transfer_complete;
  117. prot_char . ReceiveHandler = Prot_recv_indicate;
  118. prot_char . ReceiveCompleteHandler = Prot_recv_complete;
  119. prot_char . ReceivePacketHandler = Prot_packet_recv;
  120. prot_char . PnPEventHandler = Prot_PNP_handle;
  121. prot_char . Name = prot_name;
  122. UNIV_PRINT (("DriverEntry: Registering protocol"));
  123. NdisRegisterProtocol(& status, & univ_prot_handle, & prot_char, sizeof (prot_char));
  124. if (status != NDIS_STATUS_SUCCESS)
  125. {
  126. UNIV_PRINT (("error registering protocol with NDIS %x", status));
  127. __LOG_MSG1 (MSG_ERROR_REGISTERING, MSG_NONE, status);
  128. NdisTerminateWrapper (univ_wrapper_handle, NULL);
  129. NdisFreeMemory(univ_reg_path, univ_reg_path_len, 0);
  130. goto error;
  131. }
  132. NdisIMAssociateMiniport (univ_driver_handle, univ_prot_handle);
  133. NdisMRegisterUnloadHandler (univ_wrapper_handle, Init_unload);
  134. NdisAllocateSpinLock (& univ_bind_lock);
  135. /* Allocate the global spin lock to protect the list of bi-directional affinity teams. */
  136. NdisAllocateSpinLock(&univ_bda_teaming_lock);
  137. UNIV_PRINT (("DriverEntry: completed OK"));
  138. //
  139. // Initialize WMI event tracing
  140. //
  141. Trace_Initialize( driver_obj, registry_path );
  142. return NDIS_STATUS_SUCCESS;
  143. error:
  144. return status;
  145. } /* end DriverEntry */
  146. VOID Init_unload (
  147. PVOID driver_obj)
  148. {
  149. NDIS_STATUS status;
  150. ULONG i;
  151. UNIV_PRINT (("Init_unload: Unloading the driver %x", driver_obj));
  152. /* If we failed to deallocate the context during unbind (both halt and unbind
  153. were not called for example) - do it now before unloading the driver. */
  154. for (i = 0 ; i < CVY_MAX_ADAPTERS; i++)
  155. {
  156. NdisAcquireSpinLock(& univ_bind_lock);
  157. if (univ_adapters [i] . inited && univ_adapters [i] . ctxtp != NULL)
  158. {
  159. univ_adapters [i] . used = FALSE;
  160. univ_adapters [i] . inited = FALSE;
  161. univ_adapters [i] . announced = FALSE;
  162. univ_adapters [i] . bound = FALSE;
  163. NdisReleaseSpinLock(& univ_bind_lock);
  164. Main_cleanup (univ_adapters [i] . ctxtp);
  165. NdisFreeMemory (univ_adapters [i] . ctxtp, sizeof (MAIN_CTXT), 0);
  166. univ_adapters [i] . ctxtp = NULL;
  167. NdisFreeMemory (univ_adapters [i] . device_name, univ_adapters [i] . device_name_len, 0);
  168. univ_adapters [i] . device_name = NULL;
  169. univ_adapters [i] . device_name_len = 0;
  170. }
  171. else
  172. {
  173. NdisReleaseSpinLock(& univ_bind_lock);
  174. }
  175. }
  176. /* Free the global spin lock to protect the list of bi-directional affinity teams. */
  177. NdisFreeSpinLock(&univ_bda_teaming_lock);
  178. NdisFreeSpinLock (& univ_bind_lock);
  179. if (univ_prot_handle == NULL)
  180. status = NDIS_STATUS_FAILURE;
  181. else
  182. NdisDeregisterProtocol (& status, univ_prot_handle);
  183. UNIV_PRINT (("Init_unload: Deregistered protocol %x", univ_prot_handle, status));
  184. //
  185. // Deinitialize WMI event tracing
  186. //
  187. Trace_Deinitialize();
  188. NdisFreeMemory(univ_reg_path, univ_reg_path_len, 0);
  189. UNIV_PRINT (("Init_unload: Completed OK"));
  190. } /* end Init_unload */
  191. ULONG NLBMiniportCount = 0;
  192. enum _DEVICE_STATE {
  193. PS_DEVICE_STATE_READY = 0, // ready for create/delete
  194. PS_DEVICE_STATE_CREATING, // create operation in progress
  195. PS_DEVICE_STATE_DELETING // delete operation in progress
  196. } NLBControlDeviceState = PS_DEVICE_STATE_READY;
  197. /*
  198. * Function:
  199. * Purpose: This function is called by MiniportInitialize and registers the IOCTL interface for WLBS.
  200. * The device is registered only for the first miniport instantiation.
  201. * Author: shouse, 3.1.01 - Copied largely from the sample IM driver net\ndis\samples\im\
  202. */
  203. NDIS_STATUS Init_register_device (VOID) {
  204. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  205. UNICODE_STRING DeviceName;
  206. UNICODE_STRING DeviceLinkUnicodeString;
  207. PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION];
  208. UINT i;
  209. UNIV_PRINT(("Init_register_device: Entering, NLBMiniportCount=%u", NLBMiniportCount));
  210. NdisAcquireSpinLock(&univ_bind_lock);
  211. ++NLBMiniportCount;
  212. if (1 == NLBMiniportCount)
  213. {
  214. ASSERT(NLBControlDeviceState != PS_DEVICE_STATE_CREATING);
  215. UNIV_PRINT((" ** Registering IOCTL interface"));
  216. /* Another thread could be running PtDeregisterDevice on behalf
  217. of another miniport instance. If so, wait for it to exit. */
  218. while (NLBControlDeviceState != PS_DEVICE_STATE_READY)
  219. {
  220. NdisReleaseSpinLock(&univ_bind_lock);
  221. NdisMSleep(1);
  222. NdisAcquireSpinLock(&univ_bind_lock);
  223. }
  224. NLBControlDeviceState = PS_DEVICE_STATE_CREATING;
  225. NdisReleaseSpinLock(&univ_bind_lock);
  226. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
  227. DispatchTable[i] = Main_dispatch;
  228. NdisInitUnicodeString(&DeviceName, CVY_DEVICE_NAME);
  229. NdisInitUnicodeString(&DeviceLinkUnicodeString, CVY_DOSDEVICE_NAME);
  230. /* Create a device object and register our dispatch handlers. */
  231. Status = NdisMRegisterDevice(univ_wrapper_handle, &DeviceName, &DeviceLinkUnicodeString,
  232. &DispatchTable[0], &univ_device_object, &univ_device_handle);
  233. if (Status != NDIS_STATUS_SUCCESS || univ_device_handle == NULL)
  234. {
  235. UNIV_PRINT((" ** Error registering device with NDIS %x", Status));
  236. __LOG_MSG1(MSG_ERROR_REGISTERING, MSG_NONE, Status);
  237. univ_device_handle = NULL;
  238. }
  239. NdisAcquireSpinLock(&univ_bind_lock);
  240. NLBControlDeviceState = PS_DEVICE_STATE_READY;
  241. }
  242. NdisReleaseSpinLock(&univ_bind_lock);
  243. UNIV_PRINT(("Init_register_device: Exiting, Status=%x", Status));
  244. return (Status);
  245. }
  246. /*
  247. * Function:
  248. * Purpose: This function is called by MiniportHalt and deregisters the IOCTL interface for WLBS.
  249. * The device is deregistered only wnen the last miniport halts.
  250. * Author: shouse, 3.1.01 - Copied largely from the sample IM driver net\ndis\samples\im\
  251. */
  252. NDIS_STATUS Init_deregister_device (VOID) {
  253. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  254. UNIV_PRINT(("Init_deregister_device: Entering, NLBMiniportCount=%u", NLBMiniportCount));
  255. NdisAcquireSpinLock(&univ_bind_lock);
  256. ASSERT(NLBMiniportCount > 0);
  257. --NLBMiniportCount;
  258. if (0 == NLBMiniportCount)
  259. {
  260. /* All miniport instances have been halted. Deregister the control device. */
  261. ASSERT(NLBControlDeviceState == PS_DEVICE_STATE_READY);
  262. UNIV_PRINT((" ** Deleting IOCTL interface"));
  263. /* Block PtRegisterDevice() while we release the control
  264. device lock and deregister the device. */
  265. NLBControlDeviceState = PS_DEVICE_STATE_DELETING;
  266. NdisReleaseSpinLock(&univ_bind_lock);
  267. if (univ_device_handle != NULL)
  268. {
  269. Status = NdisMDeregisterDevice(univ_device_handle);
  270. univ_device_handle = NULL;
  271. }
  272. NdisAcquireSpinLock(&univ_bind_lock);
  273. NLBControlDeviceState = PS_DEVICE_STATE_READY;
  274. }
  275. NdisReleaseSpinLock(&univ_bind_lock);
  276. UNIV_PRINT(("Init_deregister_Device: Exiting, Status=%x", Status));
  277. return Status;
  278. }