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.

2011 lines
67 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. prot.c
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Driver - lower-level (protocol) layer of intermediate miniport
  8. Author:
  9. kyrilf
  10. --*/
  11. #define NDIS50 1
  12. #define NDIS51 1
  13. #include <ndis.h>
  14. #include <strsafe.h>
  15. #include "prot.h"
  16. #include "nic.h"
  17. #include "main.h"
  18. #include "util.h"
  19. #include "univ.h"
  20. #include "log.h"
  21. #include "nlbwmi.h"
  22. #include "init.h"
  23. #include "prot.tmh"
  24. /* GLOBALS */
  25. NTHALAPI KIRQL KeGetCurrentIrql();
  26. static ULONG log_module_id = LOG_MODULE_PROT;
  27. /* PROCEDURES */
  28. VOID Prot_bind ( /* PASSIVE_IRQL */
  29. PNDIS_STATUS statusp,
  30. NDIS_HANDLE bind_handle,
  31. PNDIS_STRING device_name,
  32. PVOID reg_path,
  33. PVOID reserved)
  34. {
  35. NDIS_STATUS status;
  36. NDIS_STATUS error_status;
  37. PMAIN_CTXT ctxtp;
  38. ULONG ret;
  39. UINT medium_index;
  40. ULONG i;
  41. ULONG peek_size;
  42. ULONG tmp;
  43. ULONG xferred;
  44. ULONG needed;
  45. ULONG result;
  46. PNDIS_REQUEST request;
  47. MAIN_ACTION act;
  48. INT adapter_index;
  49. PMAIN_ADAPTER adapterp = NULL;
  50. NDIS_HANDLE ctxt_handle;
  51. NDIS_HANDLE config_handle;
  52. PNDIS_CONFIGURATION_PARAMETER param;
  53. NDIS_STRING device_str = NDIS_STRING_CONST ("UpperBindings");
  54. BOOL bFirstMiniport = FALSE;
  55. /* make sure we are not attempting to bind to ourselves */
  56. /* PASSIVE_LEVEL - %ls is OK. */
  57. UNIV_PRINT_INFO(("Prot_bind: Binding to %ls", device_name -> Buffer));
  58. adapter_index = Main_adapter_get (device_name -> Buffer);
  59. if (adapter_index != MAIN_ADAPTER_NOT_FOUND)
  60. {
  61. UNIV_PRINT_CRIT(("Prot_bind: Already bound to this device 0x%x", adapter_index));
  62. TRACE_CRIT("%!FUNC! Already bound to this device 0x%x", adapter_index);
  63. *statusp = NDIS_STATUS_FAILURE;
  64. UNIV_PRINT_INFO(("Prot_bind: return=NDIS_STATUS_FAILURE"));
  65. TRACE_INFO("%!FUNC! return=NDIS_STATUS_FAILURE");
  66. return;
  67. }
  68. adapter_index = Main_adapter_selfbind (device_name -> Buffer);
  69. if (adapter_index != MAIN_ADAPTER_NOT_FOUND)
  70. {
  71. UNIV_PRINT_CRIT(("Prot_bind: Attempting to bind to ourselves 0x%x", adapter_index));
  72. TRACE_CRIT("%!FUNC! Attempting to bind to ourselves 0x%x", adapter_index);
  73. *statusp = NDIS_STATUS_FAILURE;
  74. UNIV_PRINT_INFO(("Prot_bind: return=NDIS_STATUS_FAILURE"));
  75. TRACE_INFO("%!FUNC! return=NDIS_STATUS_FAILURE");
  76. return;
  77. }
  78. adapter_index = Main_adapter_alloc (device_name);
  79. if (adapter_index == MAIN_ADAPTER_NOT_FOUND)
  80. {
  81. UNIV_PRINT_CRIT(("Prot_bind: Unable to allocate memory for adapter 0x%x", univ_adapters_count));
  82. TRACE_CRIT("%!FUNC! Unable to allocate memory for adapter 0x%x", univ_adapters_count);
  83. *statusp = NDIS_STATUS_FAILURE;
  84. UNIV_PRINT_INFO(("Prot_bind: return=NDIS_STATUS_FAILURE"));
  85. TRACE_INFO("%!FUNC! return=NDIS_STATUS_FAILURE");
  86. return;
  87. }
  88. adapterp = &(univ_adapters [adapter_index]);
  89. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  90. NdisAcquireSpinLock(& univ_bind_lock);
  91. adapterp -> bound = TRUE;
  92. NdisReleaseSpinLock(& univ_bind_lock);
  93. UNIV_PRINT_VERB(("Prot_bind: Devicename length %d max length %d",
  94. device_name -> Length, device_name -> MaximumLength));
  95. TRACE_VERB("%!FUNC! Devicename length %d max length %d",
  96. device_name -> Length, device_name -> MaximumLength);
  97. /* This memory is allocated by Main_adapter_alloc(). */
  98. UNIV_ASSERT(adapterp->device_name);
  99. NdisMoveMemory (adapterp -> device_name,
  100. device_name -> Buffer,
  101. device_name -> Length);
  102. adapterp -> device_name_len = device_name -> MaximumLength;
  103. adapterp -> device_name [(device_name -> Length)/sizeof (WCHAR)] = UNICODE_NULL;
  104. /* This memory is allocated by Main_adapter_alloc(). */
  105. UNIV_ASSERT(adapterp->ctxtp);
  106. /* initialize context */
  107. ctxtp = adapterp -> ctxtp;
  108. NdisZeroMemory (ctxtp, sizeof (MAIN_CTXT));
  109. NdisAcquireSpinLock (& univ_bind_lock);
  110. ctxtp -> code = MAIN_CTXT_CODE;
  111. ctxtp -> bind_handle = bind_handle;
  112. ctxtp -> adapter_id = adapter_index;
  113. ctxtp -> requests_pending = 0;
  114. NdisReleaseSpinLock (& univ_bind_lock);
  115. /* karthicn, 11.28.01 - If it is the first nic that we are binding to, Create the IOCTL interface.
  116. This was previously done in Nic_init. It is moved here just to maintain consistency with the
  117. removal of the IOCTL interface. The IOCTL interface is now removed from Prot_unbind (used
  118. to be in Nic_halt).
  119. DO NOT call this function with the univ_bind_lock acquired. */
  120. Init_register_device(&bFirstMiniport);
  121. NdisInitializeEvent (& ctxtp -> completion_event);
  122. NdisResetEvent (& ctxtp -> completion_event);
  123. /* bind to specified adapter */
  124. ctxt_handle = (NDIS_HANDLE) ctxtp;
  125. NdisOpenAdapter (& status, & error_status, & ctxtp -> mac_handle,
  126. & medium_index, univ_medium_array, UNIV_NUM_MEDIUMS,
  127. univ_prot_handle, ctxtp, device_name, 0, NULL);
  128. /* if pending - wait for Prot_open_complete to set the completion event */
  129. if (status == NDIS_STATUS_PENDING)
  130. {
  131. /* We can't wait at DISPATCH_LEVEL. */
  132. UNIV_ASSERT(KeGetCurrentIrql() <= PASSIVE_LEVEL);
  133. ret = NdisWaitEvent(& ctxtp -> completion_event, UNIV_WAIT_TIME);
  134. if (! ret)
  135. {
  136. UNIV_PRINT_CRIT(("Prot_bind: Error waiting for event"));
  137. TRACE_CRIT("%!FUNC! Error waiting for event");
  138. __LOG_MSG1 (MSG_ERROR_INTERNAL, MSG_NONE, status);
  139. * statusp = status;
  140. NdisAcquireSpinLock(& univ_bind_lock);
  141. adapterp -> bound = FALSE;
  142. NdisReleaseSpinLock(& univ_bind_lock);
  143. Main_adapter_put (adapterp);
  144. UNIV_PRINT_INFO(("Prot_bind: return=0x%x", status));
  145. TRACE_INFO("%!FUNC! return=0x%x", status);
  146. return;
  147. }
  148. status = ctxtp -> completion_status;
  149. }
  150. /* check binding status */
  151. if (status != NDIS_STATUS_SUCCESS)
  152. {
  153. UNIV_PRINT_CRIT(("Prot_bind: Error openning adapter %x", status));
  154. TRACE_CRIT("%!FUNC! Error openning adapter 0x%x", status);
  155. __LOG_MSG1 (MSG_ERROR_OPEN, device_name -> Buffer + (wcslen(L"\\DEVICE\\") * sizeof(WCHAR)), status);
  156. /* If the failure was because the medium was not supported, log this. */
  157. if (status == NDIS_STATUS_UNSUPPORTED_MEDIA) {
  158. UNIV_PRINT_CRIT(("Prot_bind: Unsupported medium"));
  159. TRACE_CRIT("%!FUNC! Unsupported medium");
  160. __LOG_MSG (MSG_ERROR_MEDIA, MSG_NONE);
  161. }
  162. * statusp = status;
  163. NdisAcquireSpinLock(& univ_bind_lock);
  164. adapterp -> bound = FALSE;
  165. NdisReleaseSpinLock(& univ_bind_lock);
  166. Main_adapter_put (adapterp);
  167. UNIV_PRINT_INFO(("Prot_bind: return=0x%x", status));
  168. TRACE_INFO("%!FUNC! return=0x%x", status);
  169. return;
  170. }
  171. ctxtp -> medium = univ_medium_array [medium_index];
  172. /* V1.3.1b make sure that underlying adapter is of the supported medium */
  173. if (ctxtp -> medium != NdisMedium802_3)
  174. {
  175. /* This should never happen because this error should be caught earlier
  176. by NdisOpenAdapter, but we'll put another check here just in case. */
  177. UNIV_PRINT_CRIT(("Prot_bind: Unsupported medium %d", ctxtp -> medium));
  178. TRACE_CRIT("%!FUNC! Unsupported medium %d", ctxtp -> medium);
  179. __LOG_MSG1 (MSG_ERROR_MEDIA, MSG_NONE, ctxtp -> medium);
  180. goto error;
  181. }
  182. /* V1.3.0b extract current MAC address from the NIC - note that main is not
  183. inited yet so we have to create a local action */
  184. act.code = MAIN_ACTION_CODE;
  185. act.ctxtp = ctxtp;
  186. act.op.request.xferred = &xferred;
  187. act.op.request.needed = &needed;
  188. act.op.request.external = FALSE;
  189. act.op.request.buffer_len = 0;
  190. act.op.request.buffer = NULL;
  191. NdisInitializeEvent(&act.op.request.event);
  192. NdisResetEvent(&act.op.request.event);
  193. NdisZeroMemory(&act.op.request.req, sizeof(NDIS_REQUEST));
  194. request = &act.op.request.req;
  195. request -> RequestType = NdisRequestQueryInformation;
  196. request -> DATA . QUERY_INFORMATION . Oid = OID_802_3_CURRENT_ADDRESS;
  197. request -> DATA . QUERY_INFORMATION . InformationBuffer = & ctxtp -> ded_mac_addr;
  198. request -> DATA . QUERY_INFORMATION . InformationBufferLength = sizeof (CVY_MAC_ADR);
  199. act.status = NDIS_STATUS_FAILURE;
  200. status = Prot_request (ctxtp, & act, FALSE);
  201. if (status != NDIS_STATUS_SUCCESS)
  202. {
  203. UNIV_PRINT_CRIT(("Prot_bind: Error %x requesting station address %d %d", status, xferred, needed));
  204. TRACE_CRIT("%!FUNC! Error 0x%x requesting station address %d %d", status, xferred, needed);
  205. goto error;
  206. }
  207. /* V1.3.1b get MAC options */
  208. request -> RequestType = NdisRequestQueryInformation;
  209. request -> DATA . QUERY_INFORMATION . Oid = OID_GEN_MAC_OPTIONS;
  210. request -> DATA . QUERY_INFORMATION . InformationBuffer = & result;
  211. request -> DATA . QUERY_INFORMATION . InformationBufferLength = sizeof (ULONG);
  212. act.status = NDIS_STATUS_FAILURE;
  213. status = Prot_request (ctxtp, & act, FALSE);
  214. if (status != NDIS_STATUS_SUCCESS)
  215. {
  216. UNIV_PRINT_CRIT(("Prot_bind: Error %x requesting MAC options %d %d", status, xferred, needed));
  217. TRACE_CRIT("%!FUNC! Error 0x%x requesting MAC options %d %d", status, xferred, needed);
  218. goto error;
  219. }
  220. ctxtp -> mac_options = result;
  221. /* Make sure the 802.3 adapter supports dynamically changing the MAC address of the NIC. */
  222. if (!(ctxtp -> mac_options & NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)) {
  223. UNIV_PRINT_CRIT(("Prot_bind: Unsupported network adapter MAC options %x", ctxtp -> mac_options));
  224. __LOG_MSG (MSG_ERROR_DYNAMIC_MAC, MSG_NONE);
  225. TRACE_CRIT("%!FUNC! Unsupported network adapter MAC options 0x%x", ctxtp -> mac_options);
  226. goto error;
  227. }
  228. status = Params_init (ctxtp, univ_reg_path, adapterp -> device_name + 8, & (ctxtp -> params));
  229. if (status != NDIS_STATUS_SUCCESS)
  230. {
  231. UNIV_PRINT_CRIT(("Prot_bind: Error retrieving registry parameters %x", status));
  232. TRACE_CRIT("%!FUNC! Error retrieving registry parameters 0x%x", status);
  233. ctxtp -> convoy_enabled = ctxtp -> params_valid = FALSE;
  234. }
  235. else
  236. {
  237. ctxtp -> convoy_enabled = ctxtp -> params_valid = TRUE;
  238. }
  239. /* Now, cat the cluster IP address onto the log message string to complete it. */
  240. status = StringCbCat(ctxtp->log_msg_str, sizeof(ctxtp->log_msg_str), (PWSTR)ctxtp->params.cl_ip_addr);
  241. if (FAILED(status)) {
  242. UNIV_PRINT_INFO(("Prot_bind: Error 0x%08x -> Unable to cat the cluster IP address onto the log message string...", status));
  243. TRACE_INFO("%!FUNC! Error 0x%08x -> Unable to cat the cluster IP address onto the log message string...", status);
  244. }
  245. /* Reset status, regardless of whether or not concatenating the string succeeded or failed. */
  246. status = NDIS_STATUS_SUCCESS;
  247. /* V1.3.2b figure out MTU of the medium */
  248. request -> RequestType = NdisRequestQueryInformation;
  249. request -> DATA . QUERY_INFORMATION . Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
  250. request -> DATA . QUERY_INFORMATION . InformationBuffer = & result;
  251. request -> DATA . QUERY_INFORMATION . InformationBufferLength = sizeof (ULONG);
  252. act.status = NDIS_STATUS_FAILURE;
  253. status = Prot_request (ctxtp, & act, FALSE);
  254. if (status != NDIS_STATUS_SUCCESS)
  255. {
  256. UNIV_PRINT_CRIT(("Prot_bind: Error %x requesting max frame size %d %d", status, xferred, needed));
  257. TRACE_CRIT("%!FUNC! Error 0x%x requesting max frame size %d %d", status, xferred, needed);
  258. ctxtp -> max_frame_size = CVY_MAX_FRAME_SIZE;
  259. }
  260. else
  261. {
  262. ctxtp -> max_frame_size = result;
  263. }
  264. /* figure out maximum multicast list size */
  265. request -> RequestType = NdisRequestQueryInformation;
  266. request -> DATA . QUERY_INFORMATION . Oid = OID_802_3_MAXIMUM_LIST_SIZE;
  267. request -> DATA . QUERY_INFORMATION . InformationBufferLength = sizeof (ULONG);
  268. request -> DATA . QUERY_INFORMATION . InformationBuffer = & ctxtp->max_mcast_list_size;
  269. act.status = NDIS_STATUS_FAILURE;
  270. status = Prot_request (ctxtp, & act, FALSE);
  271. if (status != NDIS_STATUS_SUCCESS)
  272. {
  273. UNIV_PRINT_CRIT(("Prot_bind: Error %x setting multicast address %d %d", status, xferred, needed));
  274. TRACE_CRIT("%!FUNC! Error 0x%x setting multicast address %d %d", status, xferred, needed);
  275. goto error;
  276. }
  277. /* initialize main context now */
  278. status = Main_init (ctxtp);
  279. /* Note: if Main_init fails, it calls Main_cleanup itself in order to un-do
  280. any allocation it had successfully completed before the failure. */
  281. if (status != NDIS_STATUS_SUCCESS)
  282. {
  283. UNIV_PRINT_CRIT(("Prot_bind: Error initializing main module %x", status));
  284. TRACE_CRIT("%!FUNC! Error initializing main module 0x%x", status);
  285. goto error;
  286. }
  287. NdisAcquireSpinLock(& univ_bind_lock);
  288. adapterp -> inited = TRUE;
  289. /* Mark the operation in progress flag. This MUST be re-set upon exit from this bind
  290. function. We set this flag to prevent IOCTL control operations from proceeding
  291. before we're done binding. Once we set the inited flag above, IOCTLs will be allowed
  292. to proceed (i.e., Main_ioctl and Main_ctrl will let them pass). Because we have not
  293. yet quite finished initializing and setting cluster state, etc., we don't want IOCTLs
  294. to go through. Marking the control operation in progress flag will ensure that any
  295. incoming IOCTLs (and remote control, although at this point, remote control packets
  296. cannot be received) fail until we're done binding and we re-set the flag. */
  297. ctxtp->ctrl_op_in_progress = TRUE;
  298. NdisReleaseSpinLock(& univ_bind_lock);
  299. /* WLBS 2.3 start off by opening the config section and reading our instance
  300. which we want to export for this binding */
  301. NdisOpenProtocolConfiguration (& status, & config_handle, reg_path);
  302. if (status != NDIS_STATUS_SUCCESS)
  303. {
  304. UNIV_PRINT_CRIT(("Prot_bind: Error openning protocol configuration %x", status));
  305. TRACE_CRIT("%!FUNC! Error openning protocol configuration 0x%x", status);
  306. goto error;
  307. }
  308. NdisReadConfiguration (& status, & param, config_handle, & device_str,
  309. NdisParameterString);
  310. if (status != NDIS_STATUS_SUCCESS)
  311. {
  312. UNIV_PRINT_CRIT(("Prot_bind: Error reading binding configuration %x", status));
  313. TRACE_CRIT("%!FUNC! Error reading binding configuration 0x%x", status);
  314. goto error;
  315. }
  316. /* free up whatever params allocated and get a new string to fit the
  317. device name */
  318. if (param -> ParameterData . StringData . Length >=
  319. sizeof (ctxtp -> virtual_nic_name) - sizeof (WCHAR))
  320. {
  321. UNIV_PRINT_CRIT(("Prot_bind: Nic name string too big %d %d\n", param -> ParameterData . StringData . Length, sizeof (ctxtp -> virtual_nic_name) - sizeof (WCHAR)));
  322. TRACE_CRIT("%!FUNC! Nic name string too big %d %d", param -> ParameterData . StringData . Length, sizeof (ctxtp -> virtual_nic_name) - sizeof (WCHAR));
  323. }
  324. NdisMoveMemory (ctxtp -> virtual_nic_name,
  325. param -> ParameterData . StringData . Buffer,
  326. param -> ParameterData . StringData . Length <
  327. sizeof (ctxtp -> virtual_nic_name) - sizeof (WCHAR) ?
  328. param -> ParameterData . StringData . Length :
  329. sizeof (ctxtp -> virtual_nic_name) - sizeof (WCHAR));
  330. * (PWSTR) ((PCHAR) ctxtp -> virtual_nic_name +
  331. param -> ParameterData . StringData . Length) = UNICODE_NULL;
  332. /* PASSIVE_LEVEL - %ls is OK. */
  333. UNIV_PRINT_VERB(("Prot_bind: Read binding name %ls\n", ctxtp -> virtual_nic_name));
  334. TRACE_VERB("%!FUNC! Read binding name %ls", ctxtp -> virtual_nic_name);
  335. /* By default, we assume that the NIC is connected. This will be changed by
  336. Nic_init and/or Prot_status later by querying the NIC miniport. */
  337. ctxtp->media_connected = TRUE;
  338. /* we should be all inited at this point! during announcement, Nic_init
  339. will be called and it will start ping timer */
  340. /* announce ourselves to the protocol above */
  341. UNIV_PRINT_VERB(("Prot_bind: Calling nic_announce"));
  342. TRACE_VERB("%!FUNC! Calling nic_announce");
  343. status = Nic_announce (ctxtp);
  344. if (status != NDIS_STATUS_SUCCESS)
  345. {
  346. UNIV_PRINT_CRIT(("Prot_bind: Error announcing driver %x", status));
  347. TRACE_CRIT("%!FUNC! Error announcing driver 0x%x", status);
  348. goto error;
  349. }
  350. /* PASSIVE_LEVEL - %ls is OK. */
  351. UNIV_PRINT_INFO(("Prot_bind: Bound to %ls with mac_handle=0x%p", device_name -> Buffer, ctxtp -> mac_handle));
  352. TRACE_INFO("%!FUNC! Bound to %ls with mac_handle=0x%p", device_name -> Buffer, ctxtp -> mac_handle);
  353. //
  354. // If it is the first miniport that NLB is binding to, fire "Startup" wmi event.
  355. // Ideally, this event should be fired from Init_register_device(), where the
  356. // determination of, if it is the first miniport that NLB is binding to, is made.
  357. // It is not being fired from Init_register_device() for the following reason:
  358. // The request for registration with WMI happens in Init_register_device().
  359. // WMI, in response to our request, sends down Ioctls to help us register with WMI,
  360. // tell us of the events that any subscriber may be interested in.
  361. // Only after these Ioctls are sent down, can we start firing the events.
  362. // I have observed that the delay between our request for registration and the reception
  363. // of Ioctls from WMI could sometimes be big. Ie. big enough to preclude us
  364. // from firing this event from Init_register_device().
  365. //
  366. // Why did I choose this point in the function to fire the event ?
  367. // This is logically the furthest point (thereby giving us the best possible chance that the Ioctls
  368. // have come down and we are ready to fire events) in the function that we could fire this event from.
  369. // Now, it is possible that even at this point, we have not yet received the Ioctls. We can not do
  370. // much about that.
  371. //
  372. // Are there any side-effects of firing the Startup event from here instead of Init_register_device( ) ?
  373. // There is one side-effect. If we encountered an error in the steps (above) after the call to
  374. // Init_register_device(), we do a "goto error" whic calls Prot_unbind(). Prot_unbind() will
  375. // fire a "Shutdown" event (if subscribed, ofcourse). So, in this case, a "Shutdown" event will
  376. // have been fired without a preceding "Startup" event. This could confuse the subscriber.
  377. // I have decided to live this side-effect for the following reasons:
  378. // 1. Chances of encountering error in the steps after the call to Init_register_device() is quite rare.
  379. // 2. A "Shutdown" event without a "Startup" event does NOT necessarily have to be confusing. It could
  380. // be construed as "Attempted to start, but had problems, so shutting down". Yeah, that may be a
  381. // bit of a copout.
  382. //
  383. // --KarthicN, 03-06-02
  384. //
  385. if (bFirstMiniport)
  386. {
  387. if(NlbWmiEvents[StartupEvent].Enable)
  388. {
  389. NlbWmi_Fire_Event(StartupEvent, NULL, 0);
  390. }
  391. else
  392. {
  393. TRACE_VERB("%!FUNC! NOT generating Startup event 'cos its generation is disabled");
  394. }
  395. }
  396. /* at this point TCP/IP should have bound to us after we announced ourselves
  397. to it and we are all done binding to NDIS below - all set! */
  398. if (! ctxtp -> convoy_enabled)
  399. {
  400. LOG_MSG (MSG_ERROR_DISABLED, MSG_NONE);
  401. TRACE_INFO("%!FUNC! Cluster mode cannot be enabled due to NLB parameters not being set, or set to incorrect values");
  402. // If enabled, fire wmi event indicating binding & stopping of nlb
  403. if (NlbWmiEvents[NodeControlEvent].Enable)
  404. {
  405. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_BOUND_AND_STOPPED);
  406. }
  407. else
  408. {
  409. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_BOUND_AND_STOPPED 'cos NodeControlEvent generation disabled");
  410. }
  411. }
  412. else
  413. {
  414. switch (ctxtp->params.init_state) {
  415. case CVY_HOST_STATE_STARTED:
  416. {
  417. WCHAR num[20];
  418. Univ_ulong_to_str(ctxtp->params.host_priority, num, 10);
  419. LOG_MSG(MSG_INFO_STARTED, num);
  420. TRACE_INFO("%!FUNC! Cluster mode started");
  421. // If enabled, fire wmi event indicating binding & starting of nlb
  422. if (NlbWmiEvents[NodeControlEvent].Enable)
  423. {
  424. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_BOUND_AND_STARTED);
  425. }
  426. else
  427. {
  428. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_BOUND_AND_STARTED 'cos NodeControlEvent generation disabled");
  429. }
  430. // Assuming start of convergence
  431. if (NlbWmiEvents[ConvergingEvent].Enable)
  432. {
  433. NlbWmi_Fire_ConvergingEvent(ctxtp,
  434. NLB_EVENT_CONVERGING_NEW_MEMBER,
  435. ctxtp->params.ded_ip_addr,
  436. ctxtp->params.host_priority);
  437. }
  438. else
  439. {
  440. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_CONVERGING_NEW_MEMBER, Convergnce NOT Initiated by Load_start() OR ConvergingEvent generation disabled");
  441. }
  442. ctxtp->convoy_enabled = TRUE;
  443. break;
  444. }
  445. case CVY_HOST_STATE_STOPPED:
  446. {
  447. LOG_MSG(MSG_INFO_STOPPED, MSG_NONE);
  448. TRACE_INFO("%!FUNC! Cluster mode stopped");
  449. ctxtp->convoy_enabled = FALSE;
  450. // If enabled, fire wmi event indicating binding & stopping of nlb
  451. if (NlbWmiEvents[NodeControlEvent].Enable)
  452. {
  453. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_BOUND_AND_STOPPED);
  454. }
  455. else
  456. {
  457. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_BOUND_AND_STOPPED 'cos NodeControlEvent generation disabled");
  458. }
  459. break;
  460. }
  461. case CVY_HOST_STATE_SUSPENDED:
  462. {
  463. LOG_MSG(MSG_INFO_SUSPENDED, MSG_NONE);
  464. TRACE_INFO("%!FUNC! Cluster mode suspended");
  465. ctxtp->convoy_enabled = FALSE;
  466. // If enabled, fire wmi event indicating binding & suspending of nlb
  467. if (NlbWmiEvents[NodeControlEvent].Enable)
  468. {
  469. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_BOUND_AND_SUSPENDED);
  470. }
  471. else
  472. {
  473. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_BOUND_AND_SUSPENDED 'cos NodeControlEvent generation disabled");
  474. }
  475. break;
  476. }
  477. default:
  478. LOG_MSG(MSG_INFO_STOPPED, MSG_NONE);
  479. TRACE_CRIT("%!FUNC! Cluster mode invalid - cluster has been stopped");
  480. ctxtp->convoy_enabled = FALSE;
  481. // If enabled, fire wmi event indicating binding & stopping of nlb
  482. if (NlbWmiEvents[NodeControlEvent].Enable)
  483. {
  484. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_BOUND_AND_STOPPED);
  485. }
  486. else
  487. {
  488. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_BOUND_AND_STOPPED 'cos NodeControlEvent generation disabled");
  489. }
  490. break;
  491. }
  492. }
  493. /* Re-set the operation in progress flag to begin allowing IOCTLs to proceed.
  494. Note that it is not strictly necessary to hold the lock while resetting the
  495. flag, but a condition may arise that an IOCTL that could have proceeded into
  496. the critical section may fail unnecessarily. To prevent that possibility,
  497. hold the univ_bind_lock while resetting the flag. Note that in "error" cases
  498. (goto error;), it is not necessary to re-set the flag, as it will result in
  499. a call to Prot_unbind and a failure of the bind anyway. */
  500. ctxtp->ctrl_op_in_progress = FALSE;
  501. UNIV_PRINT_INFO(("Prot_bind: return=0x%x", status));
  502. TRACE_INFO("%!FUNC! return=0x%x", status);
  503. * statusp = status;
  504. return;
  505. error:
  506. * statusp = status;
  507. Prot_unbind (& status, ctxtp, ctxtp);
  508. UNIV_PRINT_INFO(("Prot_bind: return=0x%x", status));
  509. TRACE_INFO("%!FUNC! return=0x%x", status);
  510. return;
  511. } /* end Prot_bind */
  512. VOID Prot_unbind ( /* PASSIVE_IRQL */
  513. PNDIS_STATUS statusp,
  514. NDIS_HANDLE adapter_handle,
  515. NDIS_HANDLE unbind_handle)
  516. {
  517. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  518. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  519. PMAIN_ACTION actp;
  520. PMAIN_ADAPTER adapterp;
  521. INT adapter_index;
  522. UNIV_PRINT_INFO(("Prot_unbind: Unbinding, adapter_handle=0x%p", adapter_handle));
  523. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  524. adapter_index = ctxtp -> adapter_id;
  525. adapterp = & (univ_adapters [adapter_index]);
  526. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  527. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  528. ctxtp -> unbind_handle = unbind_handle;
  529. if (ctxtp->out_request != NULL)
  530. {
  531. actp = ctxtp->out_request;
  532. ctxtp->out_request = NULL;
  533. Prot_request_complete(ctxtp, & actp->op.request.req, NDIS_STATUS_FAILURE);
  534. /* Note: No need to decrement the pending request counter for the second
  535. time here, because we only ended up incrementing it once (in the initial
  536. call to Prot_request). Prot_request_complete will effectively cancel
  537. the request and decrement the counter appropriately. */
  538. }
  539. /* unannounce the nic now if it was announced before */
  540. status = Nic_unannounce (ctxtp);
  541. UNIV_PRINT_INFO(("Prot_unbind: Unannounced, status=0x%x", status));
  542. TRACE_INFO("%!FUNC! Unannounced, status=0x%x", status);
  543. /* if still bound (Prot_close was not called from Nic_halt) then close now */
  544. status = Prot_close (adapterp);
  545. UNIV_PRINT_INFO(("Prot_unbind: Closed, status=0x%x", status));
  546. TRACE_INFO("%!FUNC! Closed, status=0x%x", status);
  547. /* karthicn, 11.28.01 - If it is the last nic that we are unbinding from, remove the IOCTL interface.
  548. This was previously done at the beginning of Nic_halt, which prevented firing of wmi events after
  549. Nic_halt was called. This move allows us to fire events from Prot_close() (which is called at the
  550. end of Nic_halt() & after as well)
  551. DO NOT call this function with the univ_bind_lock acquired. */
  552. Init_deregister_device();
  553. Main_adapter_put (adapterp);
  554. * statusp = status;
  555. UNIV_PRINT_INFO(("Prot_unbind: return=0x%x", status));
  556. TRACE_INFO("%!FUNC! return=0x%x", status);
  557. return;
  558. } /* end Prot_unbind */
  559. VOID Prot_open_complete ( /* PASSIVE_IRQL */
  560. NDIS_HANDLE adapter_handle,
  561. NDIS_STATUS open_status,
  562. NDIS_STATUS error_status)
  563. {
  564. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  565. UNIV_PRINT_VERB(("Prot_open_complete: Called %x", ctxtp));
  566. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  567. ctxtp -> completion_status = open_status;
  568. NdisSetEvent (& ctxtp -> completion_event);
  569. } /* end Prot_open_complete */
  570. VOID Prot_close_complete ( /* PASSIVE_IRQL */
  571. NDIS_HANDLE adapter_handle,
  572. NDIS_STATUS status)
  573. {
  574. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  575. UNIV_PRINT_VERB(("Prot_close_complete: Called %x %x", ctxtp, status));
  576. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  577. ctxtp -> completion_status = status;
  578. NdisSetEvent (& ctxtp -> completion_event);
  579. } /* end Prot_close_complete */
  580. VOID Prot_request_complete (
  581. NDIS_HANDLE adapter_handle,
  582. PNDIS_REQUEST request,
  583. NDIS_STATUS status)
  584. {
  585. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  586. PMAIN_ACTION actp;
  587. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  588. actp = CONTAINING_RECORD (request, MAIN_ACTION, op . request . req);
  589. UNIV_ASSERT (actp -> code == MAIN_ACTION_CODE);
  590. /* if request came from above - pass completion up */
  591. if (actp -> op . request . external)
  592. {
  593. actp -> status = status;
  594. Nic_request_complete (ctxtp -> prot_handle, actp);
  595. }
  596. /* handle internal request completion */
  597. else
  598. {
  599. if (request -> RequestType == NdisRequestSetInformation)
  600. {
  601. * actp -> op . request . xferred =
  602. request -> DATA . SET_INFORMATION . BytesRead;
  603. * actp -> op . request . needed =
  604. request -> DATA . SET_INFORMATION . BytesNeeded;
  605. }
  606. else
  607. {
  608. * actp -> op . request . xferred =
  609. request -> DATA . QUERY_INFORMATION . BytesWritten;
  610. * actp -> op . request . needed =
  611. request -> DATA . QUERY_INFORMATION . BytesNeeded;
  612. }
  613. actp->status = status;
  614. NdisSetEvent(&actp->op.request.event);
  615. }
  616. NdisInterlockedDecrement(&ctxtp->requests_pending);
  617. } /* end Prot_request_complete */
  618. #ifdef PERIODIC_RESET
  619. extern ULONG resetting;
  620. #endif
  621. VOID Prot_reset_complete (
  622. NDIS_HANDLE adapter_handle,
  623. NDIS_STATUS status)
  624. {
  625. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  626. PMAIN_ADAPTER adapterp;
  627. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  628. adapterp = & (univ_adapters [ctxtp -> adapter_id]);
  629. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  630. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  631. if (! adapterp -> inited)
  632. {
  633. TRACE_CRIT("%!FUNC! adapter not initialized");
  634. return;
  635. }
  636. #ifdef PERIODIC_RESET
  637. if (resetting)
  638. {
  639. resetting = FALSE;
  640. TRACE_INFO("%!FUNC! resetting");
  641. return;
  642. }
  643. #endif
  644. Nic_reset_complete (ctxtp, status);
  645. } /* end Prot_reset_complete */
  646. VOID Prot_send_complete (
  647. NDIS_HANDLE adapter_handle,
  648. PNDIS_PACKET packet,
  649. NDIS_STATUS status)
  650. {
  651. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  652. PNDIS_PACKET oldp;
  653. PNDIS_PACKET_STACK pktstk;
  654. BOOLEAN stack_left;
  655. PMAIN_PROTOCOL_RESERVED resp;
  656. LONG lock_value;
  657. PMAIN_ADAPTER adapterp;
  658. BOOLEAN set = FALSE;
  659. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  660. adapterp = & (univ_adapters [ctxtp -> adapter_id]);
  661. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  662. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  663. if (! adapterp -> inited)
  664. {
  665. TRACE_CRIT("%!FUNC! adapter not initialized");
  666. return;
  667. }
  668. MAIN_RESP_FIELD(packet, stack_left, pktstk, resp, TRUE);
  669. if (resp -> type == MAIN_PACKET_TYPE_PING ||
  670. resp -> type == MAIN_PACKET_TYPE_IGMP ||
  671. resp -> type == MAIN_PACKET_TYPE_IDHB)
  672. {
  673. Main_send_done (ctxtp, packet, status);
  674. return;
  675. }
  676. if (resp -> type == MAIN_PACKET_TYPE_CTRL)
  677. {
  678. UNIV_PRINT_VERB(("Prot_send_complete: Control packet send complete\n"));
  679. Main_packet_put (ctxtp, packet, TRUE, status);
  680. return;
  681. }
  682. UNIV_ASSERT_VAL (resp -> type == MAIN_PACKET_TYPE_PASS, resp -> type);
  683. oldp = Main_packet_put (ctxtp, packet, TRUE, status);
  684. if (ctxtp -> packets_exhausted)
  685. {
  686. ctxtp -> packets_exhausted = FALSE;
  687. }
  688. Nic_send_complete (ctxtp, status, oldp);
  689. } /* end Prot_send_complete */
  690. NDIS_STATUS Prot_recv_indicate (
  691. NDIS_HANDLE adapter_handle,
  692. NDIS_HANDLE recv_handle,
  693. PVOID head_buf,
  694. UINT head_len,
  695. PVOID look_buf,
  696. UINT look_len,
  697. UINT packet_len)
  698. {
  699. PMAIN_CTXT ctxtp = (PMAIN_CTXT)adapter_handle;
  700. PMAIN_ADAPTER adapterp;
  701. PNDIS_PACKET packet;
  702. UNIV_ASSERT(ctxtp->code == MAIN_CTXT_CODE);
  703. adapterp = &(univ_adapters[ctxtp->adapter_id]);
  704. UNIV_ASSERT(adapterp->code == MAIN_ADAPTER_CODE);
  705. UNIV_ASSERT(adapterp->ctxtp == ctxtp);
  706. /* Check whether the driver has been announced to tcpip before processing any packets. */
  707. if (!adapterp->inited || !adapterp->announced)
  708. {
  709. TRACE_CRIT("%!FUNC! Adapter not initialized or not announced");
  710. return NDIS_STATUS_NOT_ACCEPTED;
  711. }
  712. /* Do not accept frames if the card below is resetting. */
  713. if (ctxtp->reset_state != MAIN_RESET_NONE)
  714. {
  715. TRACE_CRIT("%!FUNC! Adapter is resetting");
  716. return NDIS_STATUS_NOT_ACCEPTED;
  717. }
  718. /* Get the received packet from NDIS, if there is one. */
  719. packet = NdisGetReceivedPacket(ctxtp->mac_handle, recv_handle);
  720. /* If we successfully got a packet from NDIS, process the packet. */
  721. if (packet != NULL)
  722. {
  723. INT references = 0;
  724. /* Get the status from the received packet. */
  725. NDIS_STATUS original_status = NDIS_GET_PACKET_STATUS(packet);
  726. /* Set the status to be STATUS_RESOURCES to make sure the packet is
  727. processed synchonrously within the context of this function call. */
  728. NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_RESOURCES);
  729. /* Call our packet receive handler. */
  730. references = Prot_packet_recv(ctxtp, packet);
  731. /* The remaining references on the packet MUST be zero, as enforced
  732. by setting the packet status to STATUS_RESOURCES. */
  733. UNIV_ASSERT(references == 0);
  734. /* Restore the original packet status. */
  735. NDIS_SET_PACKET_STATUS(packet, original_status);
  736. }
  737. /* If there was no associated packet, drop it - we don't handle this case anymore. */
  738. else
  739. {
  740. UNIV_ASSERT(0);
  741. /* Only warn the user if we haven't done so already. */
  742. if (!ctxtp->recv_indicate_warned)
  743. {
  744. TRACE_CRIT("%!FUNC! Indicated receives with no corresponding packet are NOT supported");
  745. /* Log an event to warn the user that this NIC is not supported by NLB. */
  746. LOG_MSG(MSG_ERROR_RECEIVE_INDICATE, MSG_NONE);
  747. /* Note that we have warned the user about this so we don't log an event
  748. every time we receive a packet via this code path. */
  749. ctxtp->recv_indicate_warned = TRUE;
  750. }
  751. return NDIS_STATUS_NOT_ACCEPTED;
  752. }
  753. /* Always return success, whether we accepted or dropped the packet
  754. in the call to Prot_packet_recv. */
  755. return NDIS_STATUS_SUCCESS;
  756. }
  757. VOID Prot_recv_complete (
  758. NDIS_HANDLE adapter_handle)
  759. {
  760. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  761. UNIV_ASSERT(ctxtp->code == MAIN_CTXT_CODE);
  762. Nic_recv_complete(ctxtp);
  763. }
  764. VOID Prot_transfer_complete (
  765. NDIS_HANDLE adapter_handle,
  766. PNDIS_PACKET packet,
  767. NDIS_STATUS status,
  768. UINT xferred)
  769. {
  770. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  771. PNDIS_PACKET oldp;
  772. PNDIS_PACKET_STACK pktstk;
  773. BOOLEAN stack_left;
  774. PMAIN_PROTOCOL_RESERVED resp;
  775. LONG lock_value;
  776. PNDIS_BUFFER bufp;
  777. PMAIN_ADAPTER adapterp;
  778. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  779. adapterp = & (univ_adapters [ctxtp -> adapter_id]);
  780. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  781. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  782. if (! adapterp -> inited)
  783. {
  784. TRACE_CRIT("%!FUNC! adapter not initialized");
  785. return;
  786. }
  787. MAIN_RESP_FIELD (packet, stack_left, pktstk, resp, FALSE);
  788. UNIV_ASSERT_VAL (resp -> type == MAIN_PACKET_TYPE_TRANSFER, resp -> type);
  789. if (status == NDIS_STATUS_SUCCESS)
  790. {
  791. MAIN_PACKET_INFO PacketInfo;
  792. /* Call Main_recv_frame_parse merely to extract the packet length and "group". */
  793. if (Main_recv_frame_parse(ctxtp, packet, &PacketInfo))
  794. {
  795. resp->len = PacketInfo.Length;
  796. resp->group = PacketInfo.Group;
  797. }
  798. /* If we fail to fill in the group and length, just populate these
  799. parameters with values that will not affect the statistics that
  800. are updated in Main_packet_put. */
  801. else
  802. {
  803. resp->len = 0;
  804. resp->group = MAIN_FRAME_DIRECTED;
  805. }
  806. }
  807. oldp = Main_packet_put (ctxtp, packet, FALSE, status);
  808. Nic_transfer_complete (ctxtp, status, packet, xferred);
  809. } /* end Prot_transfer_complete */
  810. NDIS_STATUS Prot_PNP_handle (
  811. NDIS_HANDLE adapter_handle,
  812. PNET_PNP_EVENT pnp_event)
  813. {
  814. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  815. PNDIS_DEVICE_POWER_STATE device_state;
  816. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  817. IOCTL_CVY_BUF ioctl_buf;
  818. PMAIN_ACTION actp;
  819. /* can happen when first initializing */
  820. switch (pnp_event -> NetEvent)
  821. {
  822. case NetEventSetPower:
  823. if (adapter_handle == NULL)
  824. {
  825. return NDIS_STATUS_SUCCESS;
  826. }
  827. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  828. device_state = (PNDIS_DEVICE_POWER_STATE) (pnp_event -> Buffer);
  829. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventSetPower %x", * device_state));
  830. TRACE_VERB("%!FUNC! NetEventSetPower 0x%x", * device_state);
  831. // If the specified device state is D0, then handle it first,
  832. // else notify the protocols first and then handle it.
  833. if (*device_state != NdisDeviceStateD0)
  834. {
  835. status = Nic_PNP_handle (ctxtp, pnp_event);
  836. }
  837. //
  838. // Is the protocol transitioning from an On (D0) state to an Low Power State (>D0)
  839. // If so, then set the standby_state Flag - (Block all incoming requests)
  840. //
  841. if (ctxtp->prot_pnp_state == NdisDeviceStateD0 &&
  842. *device_state > NdisDeviceStateD0)
  843. {
  844. ctxtp->standby_state = TRUE;
  845. }
  846. //
  847. // If the protocol is transitioning from a low power state to ON (D0), then clear the standby_state flag
  848. // All incoming requests will be pended until the physical miniport turns ON.
  849. //
  850. if (ctxtp->prot_pnp_state > NdisDeviceStateD0 &&
  851. *device_state == NdisDeviceStateD0)
  852. {
  853. ctxtp->standby_state = FALSE;
  854. }
  855. ctxtp -> prot_pnp_state = *device_state;
  856. /* if we are being sent to standby, block outstanding requests and
  857. sends */
  858. if (*device_state > NdisDeviceStateD0)
  859. {
  860. /* sleep till outstanding sends complete */
  861. while (1)
  862. {
  863. ULONG i;
  864. /* #ps# -- ramkrish */
  865. while (1)
  866. {
  867. NDIS_STATUS hide_status;
  868. ULONG count;
  869. hide_status = NdisQueryPendingIOCount (ctxtp -> mac_handle, & count);
  870. if (hide_status != NDIS_STATUS_SUCCESS || count == 0)
  871. break;
  872. Nic_sleep (10);
  873. }
  874. // ASSERT - NdisQueryPendingIOCount should handle this
  875. for (i = 0; i < ctxtp->num_send_packet_allocs; i++)
  876. {
  877. if (NdisPacketPoolUsage(ctxtp->send_pool_handle[i]) != 0)
  878. break;
  879. }
  880. if (i >= ctxtp->num_send_packet_allocs)
  881. break;
  882. Nic_sleep(10);
  883. }
  884. /* sleep till outstanding requests complete */
  885. while (ctxtp->requests_pending > 0)
  886. {
  887. Nic_sleep(10);
  888. }
  889. }
  890. else
  891. {
  892. if (ctxtp->out_request != NULL)
  893. {
  894. NDIS_STATUS hide_status;
  895. actp = ctxtp->out_request;
  896. ctxtp->out_request = NULL;
  897. hide_status = Prot_request(ctxtp, actp, actp->op.request.external);
  898. if (hide_status != NDIS_STATUS_PENDING)
  899. Prot_request_complete(ctxtp, & actp->op.request.req, hide_status);
  900. /* Upon pending this request initially, we incremented the request pending
  901. counter. Now that we have processed it, and in the process incremented
  902. the pending request counter for the second time, we need to decrement it
  903. here once. The second decrement is done in Prot_request_complete, which
  904. either we just called explicitly, or will be called subsequently when
  905. NDIS completes the request asynchronously. */
  906. NdisInterlockedDecrement(&ctxtp->requests_pending);
  907. }
  908. }
  909. if (*device_state == NdisDeviceStateD0)
  910. {
  911. status = Nic_PNP_handle (ctxtp, pnp_event);
  912. }
  913. break;
  914. case NetEventReconfigure:
  915. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventReconfigure"));
  916. TRACE_VERB("%!FUNC! NetEventReconfigure");
  917. if (adapter_handle == NULL) // This happens if the device is being enabled through the device manager.
  918. {
  919. UNIV_PRINT_VERB(("Prot_PNP_handle: Enumerate protocol bindings"));
  920. NdisReEnumerateProtocolBindings (univ_prot_handle);
  921. TRACE_VERB("%!FUNC! Enumerate protocol bindings");
  922. return NDIS_STATUS_SUCCESS;
  923. }
  924. /* gets called when something changes in our setup from notify
  925. object */
  926. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  927. Main_ctrl (ctxtp, IOCTL_CVY_RELOAD, &ioctl_buf, NULL, NULL, NULL);
  928. status = Nic_PNP_handle (ctxtp, pnp_event);
  929. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventReconfigure done %d %x", ioctl_buf . ret_code, status));
  930. TRACE_VERB("%!FUNC! NetEventReconfigure done %d 0x%x", ioctl_buf . ret_code, status);
  931. break;
  932. case NetEventQueryPower:
  933. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventQueryPower"));
  934. TRACE_VERB("%!FUNC! NetEventQueryPower");
  935. if (adapter_handle == NULL)
  936. {
  937. return NDIS_STATUS_SUCCESS;
  938. }
  939. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  940. status = Nic_PNP_handle (ctxtp, pnp_event);
  941. break;
  942. case NetEventQueryRemoveDevice:
  943. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventQueryRemoveDevice"));
  944. TRACE_VERB("%!FUNC! NetEventQueryRemoveDevice");
  945. if (adapter_handle == NULL)
  946. {
  947. return NDIS_STATUS_SUCCESS;
  948. }
  949. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  950. status = Nic_PNP_handle (ctxtp, pnp_event);
  951. break;
  952. case NetEventCancelRemoveDevice:
  953. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventCancelRemoveDevice"));
  954. TRACE_VERB("%!FUNC! NetEventCancelRemoveDevice");
  955. if (adapter_handle == NULL)
  956. {
  957. return NDIS_STATUS_SUCCESS;
  958. }
  959. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  960. status = Nic_PNP_handle (ctxtp, pnp_event);
  961. break;
  962. case NetEventBindList:
  963. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventBindList"));
  964. TRACE_VERB("%!FUNC! NetEventBindList");
  965. if (adapter_handle == NULL)
  966. {
  967. return NDIS_STATUS_SUCCESS;
  968. }
  969. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  970. status = Nic_PNP_handle (ctxtp, pnp_event);
  971. break;
  972. case NetEventBindsComplete:
  973. UNIV_PRINT_VERB(("Prot_PNP_handle: NetEventBindComplete"));
  974. TRACE_VERB("%!FUNC! NetEventBindComplete");
  975. if (adapter_handle == NULL)
  976. {
  977. return NDIS_STATUS_SUCCESS;
  978. }
  979. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  980. status = Nic_PNP_handle (ctxtp, pnp_event);
  981. break;
  982. default:
  983. UNIV_PRINT_VERB(("Prot_PNP_handle: New event"));
  984. TRACE_VERB("%!FUNC! New event");
  985. if (adapter_handle == NULL)
  986. {
  987. return NDIS_STATUS_SUCCESS;
  988. }
  989. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  990. status = Nic_PNP_handle (ctxtp, pnp_event);
  991. break;
  992. }
  993. return status; /* Always return NDIS_STATUS_SUCCESS or
  994. the return value of NdisIMNotifyPnPEvent */
  995. } /* end Nic_PNP_handle */
  996. VOID Prot_status (
  997. NDIS_HANDLE adapter_handle,
  998. NDIS_STATUS status,
  999. PVOID stat_buf,
  1000. UINT stat_len)
  1001. {
  1002. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  1003. KIRQL irql;
  1004. PMAIN_ADAPTER adapterp;
  1005. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1006. adapterp = & (univ_adapters [ctxtp -> adapter_id]);
  1007. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  1008. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  1009. UNIV_PRINT_VERB(("Prot_status: Called for adapter %d for notification %d: inited=%d, announced=%d", ctxtp -> adapter_id, status, adapterp->inited, adapterp->announced));
  1010. TRACE_VERB("%!FUNC! Adapter %d for notification %d: inited=%d, announced=%d", ctxtp -> adapter_id, status, adapterp->inited, adapterp->announced);
  1011. if (! adapterp -> inited || ! adapterp -> announced)
  1012. {
  1013. TRACE_CRIT("%!FUNC! adapter not initialized or not announced");
  1014. return;
  1015. }
  1016. switch (status)
  1017. {
  1018. case NDIS_STATUS_WAN_LINE_UP:
  1019. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_WAN_LINE_UP"));
  1020. break;
  1021. case NDIS_STATUS_WAN_LINE_DOWN:
  1022. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_WAN_LINE_DOWN"));
  1023. break;
  1024. case NDIS_STATUS_MEDIA_CONNECT:
  1025. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_MEDIA_CONNECT"));
  1026. /* V1.3.2b */
  1027. ctxtp -> media_connected = TRUE;
  1028. break;
  1029. case NDIS_STATUS_MEDIA_DISCONNECT:
  1030. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_MEDIA_DISCONNECT"));
  1031. /* V1.3.2b */
  1032. ctxtp -> media_connected = FALSE;
  1033. break;
  1034. case NDIS_STATUS_HARDWARE_LINE_UP:
  1035. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_HARDWARE_LINE_UP"));
  1036. break;
  1037. case NDIS_STATUS_HARDWARE_LINE_DOWN:
  1038. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_HARDWARE_LINE_DOWN"));
  1039. break;
  1040. case NDIS_STATUS_INTERFACE_UP:
  1041. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_INTERFACE_UP"));
  1042. break;
  1043. case NDIS_STATUS_INTERFACE_DOWN:
  1044. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_INTERFACE_DOWN"));
  1045. break;
  1046. /* V1.1.2 */
  1047. case NDIS_STATUS_RESET_START:
  1048. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_RESET_START"));
  1049. ctxtp -> reset_state = MAIN_RESET_START;
  1050. ctxtp -> recv_indicated = FALSE;
  1051. break;
  1052. case NDIS_STATUS_RESET_END:
  1053. UNIV_PRINT_VERB(("Prot_status: NDIS_STATUS_RESET_END"));
  1054. // apparently alteon adapter does not call status complete function,
  1055. // so need to transition to none state here in order to prevent hangs
  1056. //ctxtp -> reset_state = MAIN_RESET_END;
  1057. ctxtp -> reset_state = MAIN_RESET_NONE;
  1058. break;
  1059. default:
  1060. break;
  1061. }
  1062. if (! MAIN_PNP_DEV_ON(ctxtp))
  1063. {
  1064. TRACE_CRIT("%!FUNC! return pnp device not on");
  1065. return;
  1066. }
  1067. Nic_status (ctxtp, status, stat_buf, stat_len);
  1068. } /* end Prot_status */
  1069. VOID Prot_status_complete (
  1070. NDIS_HANDLE adapter_handle)
  1071. {
  1072. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  1073. PMAIN_ADAPTER adapterp;
  1074. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1075. adapterp = & (univ_adapters [ctxtp -> adapter_id]);
  1076. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  1077. UNIV_ASSERT (adapterp -> ctxtp == ctxtp);
  1078. if (! adapterp -> inited)
  1079. {
  1080. TRACE_CRIT("%!FUNC! adapter not initialized");
  1081. return;
  1082. }
  1083. /* V1.1.2 */
  1084. if (ctxtp -> reset_state == MAIN_RESET_END)
  1085. {
  1086. ctxtp -> reset_state = MAIN_RESET_NONE;
  1087. UNIV_PRINT_VERB(("Prot_status_complete: NDIS_STATUS_RESET_END completed"));
  1088. }
  1089. else if (ctxtp -> reset_state == MAIN_RESET_START)
  1090. {
  1091. ctxtp -> reset_state = MAIN_RESET_START_DONE;
  1092. UNIV_PRINT_VERB(("Prot_status_complete: NDIS_STATUS_RESET_START completed"));
  1093. }
  1094. if (! MAIN_PNP_DEV_ON(ctxtp))
  1095. {
  1096. TRACE_CRIT("%!FUNC! return pnp device not on");
  1097. return;
  1098. }
  1099. Nic_status_complete (ctxtp);
  1100. } /* end Prot_status_complete */
  1101. /* helpers for nic layer */
  1102. NDIS_STATUS Prot_close ( /* PASSIVE_IRQL */
  1103. PMAIN_ADAPTER adapterp
  1104. )
  1105. {
  1106. NDIS_STATUS status;
  1107. ULONG ret;
  1108. PMAIN_CTXT ctxtp;
  1109. UNIV_ASSERT (adapterp -> code == MAIN_ADAPTER_CODE);
  1110. ctxtp = adapterp -> ctxtp;
  1111. /* close binding */
  1112. NdisAcquireSpinLock(& univ_bind_lock);
  1113. if ( ! adapterp -> bound || ctxtp->mac_handle == NULL)
  1114. {
  1115. /* cleanup only on the second time we are entering Prot_close, which
  1116. is called by both Nic_halt and Prot_unbind. the last one to be
  1117. called will cleanup the context since they both use it. if both
  1118. do not get called, then it will be cleaned up by Prot_bind before
  1119. allocating a new one of Init_unload before unloading the driver. */
  1120. if (adapterp -> inited)
  1121. {
  1122. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1123. adapterp -> inited = FALSE;
  1124. NdisReleaseSpinLock(& univ_bind_lock);
  1125. Main_cleanup (ctxtp);
  1126. }
  1127. else
  1128. NdisReleaseSpinLock(& univ_bind_lock);
  1129. Main_adapter_put (adapterp);
  1130. return NDIS_STATUS_SUCCESS;
  1131. }
  1132. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1133. adapterp -> bound = FALSE;
  1134. ctxtp -> convoy_enabled = FALSE;
  1135. NdisReleaseSpinLock(& univ_bind_lock);
  1136. LOG_MSG (MSG_INFO_STOPPED, MSG_NONE);
  1137. // If enabled, fire wmi event indicating unbinding of nlb
  1138. if (NlbWmiEvents[NodeControlEvent].Enable)
  1139. {
  1140. NlbWmi_Fire_NodeControlEvent(ctxtp, NLB_EVENT_NODE_UNBOUND);
  1141. }
  1142. else
  1143. {
  1144. TRACE_VERB("%!FUNC! NOT generating NLB_EVENT_NODE_UNBOUND 'cos NodeControlEvent generation disabled");
  1145. }
  1146. NdisResetEvent (& ctxtp -> completion_event);
  1147. NdisCloseAdapter (& status, ctxtp -> mac_handle);
  1148. /* if pending - wait for Prot_close_complete to set the completion event */
  1149. if (status == NDIS_STATUS_PENDING)
  1150. {
  1151. /* We can't wait at DISPATCH_LEVEL. */
  1152. UNIV_ASSERT(KeGetCurrentIrql() <= PASSIVE_LEVEL);
  1153. ret = NdisWaitEvent(& ctxtp -> completion_event, UNIV_WAIT_TIME);
  1154. if (! ret)
  1155. {
  1156. UNIV_PRINT_CRIT(("Prot_close: Error waiting for event"));
  1157. LOG_MSG1 (MSG_ERROR_INTERNAL, MSG_NONE, status);
  1158. TRACE_CRIT("%!FUNC! Error waiting for event");
  1159. return NDIS_STATUS_FAILURE;
  1160. }
  1161. status = ctxtp -> completion_status;
  1162. }
  1163. /* At this point,wait for all pending recvs to be completed and then return */
  1164. ctxtp -> mac_handle = NULL;
  1165. ctxtp -> prot_handle = NULL;
  1166. /* check binding status */
  1167. if (status != NDIS_STATUS_SUCCESS)
  1168. {
  1169. UNIV_PRINT_CRIT(("Prot_close: Error closing adapter %x", status));
  1170. LOG_MSG1 (MSG_ERROR_INTERNAL, MSG_NONE, status);
  1171. TRACE_CRIT("%!FUNC! Error closing adapter 0x%x", status);
  1172. }
  1173. /* if nic level is not announced anymore - safe to remove context now */
  1174. NdisAcquireSpinLock(& univ_bind_lock);
  1175. if (! adapterp -> announced || ctxtp -> prot_handle == NULL)
  1176. {
  1177. if (adapterp -> inited)
  1178. {
  1179. adapterp -> inited = FALSE;
  1180. NdisReleaseSpinLock(& univ_bind_lock);
  1181. Main_cleanup (ctxtp);
  1182. }
  1183. else
  1184. NdisReleaseSpinLock(& univ_bind_lock);
  1185. Main_adapter_put (adapterp);
  1186. }
  1187. else
  1188. NdisReleaseSpinLock(& univ_bind_lock);
  1189. return status;
  1190. } /* end Prot_close */
  1191. NDIS_STATUS Prot_request (
  1192. PMAIN_CTXT ctxtp,
  1193. PMAIN_ACTION actp,
  1194. ULONG external)
  1195. {
  1196. NDIS_STATUS status;
  1197. PNDIS_REQUEST request = &actp->op.request.req;
  1198. ULONG ret;
  1199. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1200. actp->op.request.external = external;
  1201. if (ctxtp -> unbind_handle) // Prot_unbind was called
  1202. {
  1203. return NDIS_STATUS_FAILURE;
  1204. }
  1205. // if the Protocol device state is OFF, then the IM driver cannot send the
  1206. // request below and must pend it
  1207. if (ctxtp->prot_pnp_state > NdisDeviceStateD0)
  1208. {
  1209. if (external) {
  1210. /* If the request was external (from the protocol bound to our miniport,
  1211. then pend the request. Ndis serializes requests such that only one
  1212. request can ever be outstanding at a given time. Therefore, a queue
  1213. is not necessary. */
  1214. UNIV_ASSERT (ctxtp->out_request == NULL);
  1215. if (ctxtp->out_request == NULL)
  1216. {
  1217. /* If there are no outstanding requests as of yet, store a pointer
  1218. to the request so that we can complete it later. */
  1219. ctxtp->out_request = actp;
  1220. }
  1221. else
  1222. {
  1223. /* Otherwise, if a request is already pending, fail this new one.
  1224. This should never happen, as NDIS serializes miniport requests. */
  1225. return NDIS_STATUS_FAILURE;
  1226. }
  1227. /* Note: this counter will also be incremented when we call Prot_request
  1228. again later to continue processing the request. We have to ensure,
  1229. then, that it is likewise decremented twice whenever serviced. */
  1230. NdisInterlockedIncrement(&ctxtp->requests_pending);
  1231. return NDIS_STATUS_PENDING;
  1232. } else {
  1233. /* If the request was internal, then fail it - if we return PENDING, it
  1234. will fail anyway, as it expects us to wait for the request to complete
  1235. before returning. */
  1236. return NDIS_STATUS_FAILURE;
  1237. }
  1238. }
  1239. NdisResetEvent(&actp->op.request.event);
  1240. NdisInterlockedIncrement(&ctxtp->requests_pending);
  1241. NdisRequest(&status, ctxtp->mac_handle, request);
  1242. /* if pending - wait for Prot_request_complete to set the completion event */
  1243. if (status != NDIS_STATUS_PENDING)
  1244. {
  1245. NdisInterlockedDecrement(&ctxtp->requests_pending);
  1246. if (request -> RequestType == NdisRequestSetInformation)
  1247. {
  1248. * actp -> op . request . xferred =
  1249. request -> DATA . SET_INFORMATION . BytesRead;
  1250. * actp -> op . request . needed =
  1251. request -> DATA . SET_INFORMATION . BytesNeeded;
  1252. }
  1253. else
  1254. {
  1255. * actp -> op . request . xferred =
  1256. request -> DATA . QUERY_INFORMATION . BytesWritten;
  1257. * actp -> op . request . needed =
  1258. request -> DATA . QUERY_INFORMATION . BytesNeeded;
  1259. }
  1260. }
  1261. else if (! external)
  1262. {
  1263. /* We can't wait at DISPATCH_LEVEL. */
  1264. UNIV_ASSERT(KeGetCurrentIrql() <= PASSIVE_LEVEL);
  1265. ret = NdisWaitEvent(&actp->op.request.event, UNIV_WAIT_TIME);
  1266. if (! ret)
  1267. {
  1268. UNIV_PRINT_CRIT(("Prot_request: Error waiting for event"));
  1269. TRACE_CRIT("%!FUNC! Error=0x%x waiting for event", status);
  1270. LOG_MSG1 (MSG_ERROR_INTERNAL, MSG_NONE, status);
  1271. status = NDIS_STATUS_FAILURE;
  1272. return status;
  1273. }
  1274. status = actp->status;
  1275. }
  1276. return status;
  1277. } /* end Prot_request */
  1278. NDIS_STATUS Prot_reset (
  1279. PMAIN_CTXT ctxtp)
  1280. {
  1281. NDIS_STATUS status;
  1282. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1283. NdisReset (& status, ctxtp -> mac_handle);
  1284. return status;
  1285. } /* end Prot_reset */
  1286. VOID Prot_packets_send (
  1287. PMAIN_CTXT ctxtp,
  1288. PPNDIS_PACKET packets,
  1289. UINT num_packets)
  1290. {
  1291. PNDIS_PACKET array[CVY_MAX_SEND_PACKETS];
  1292. PNDIS_PACKET filtered_array[CVY_MAX_SEND_PACKETS];
  1293. UINT count = 0, filtered_count = 0, i;
  1294. NDIS_STATUS status;
  1295. PNDIS_PACKET newp;
  1296. LONG lock_value;
  1297. PMAIN_ACTION actp;
  1298. ULONG exhausted;
  1299. PNDIS_PACKET_STACK pktstk;
  1300. BOOLEAN stack_left;
  1301. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1302. /* Do not accept frames if the card below is resetting. */
  1303. if (ctxtp->reset_state != MAIN_RESET_NONE || ! MAIN_PNP_DEV_ON(ctxtp))
  1304. {
  1305. TRACE_CRIT("%!FUNC! card is resetting");
  1306. ctxtp->cntr_xmit_err++;
  1307. status = NDIS_STATUS_FAILURE;
  1308. goto fail;
  1309. }
  1310. for (count = i = 0;
  1311. count < (num_packets > CVY_MAX_SEND_PACKETS ? CVY_MAX_SEND_PACKETS : num_packets);
  1312. count ++)
  1313. {
  1314. /* Figure out if we need to handle this packet. */
  1315. newp = Main_send(ctxtp, packets[count], &exhausted);
  1316. if (newp == NULL)
  1317. {
  1318. /* If we ran out of packets, get out of the loop. */
  1319. if (exhausted)
  1320. {
  1321. UNIV_PRINT_CRIT(("Prot_packets_send: Error xlating packet"));
  1322. TRACE_CRIT("%!FUNC! Error xlating packet");
  1323. ctxtp->packets_exhausted = TRUE;
  1324. break;
  1325. }
  1326. /* If the packet was filtered out, set status to success
  1327. to calm TCP/IP down and go on to the next one. */
  1328. else
  1329. {
  1330. /* Mark the packet as success. */
  1331. NDIS_SET_PACKET_STATUS(packets[count], NDIS_STATUS_SUCCESS);
  1332. /* Store a pointer to the filtered packet in the filtered
  1333. packet array. */
  1334. filtered_array[filtered_count] = packets[count];
  1335. /* Increment the array index. */
  1336. filtered_count++;
  1337. // ctxtp->sends_filtered ++;
  1338. continue;
  1339. }
  1340. }
  1341. /* Mark the packet as pending send. */
  1342. NDIS_SET_PACKET_STATUS(packets[count], NDIS_STATUS_PENDING);
  1343. /* Store a pointer to this packet in the array of packets to send. */
  1344. array[i] = newp;
  1345. /* Increment the array index. */
  1346. i++;
  1347. }
  1348. /* If there are packets to send, send them. */
  1349. if (i > 0)
  1350. NdisSendPackets(ctxtp->mac_handle, array, i);
  1351. /* For those packets we've filtered out, notify the protocol that
  1352. the send is "complete". */
  1353. for (i = 0; i < filtered_count; i++)
  1354. Nic_send_complete(ctxtp, NDIS_STATUS_SUCCESS, filtered_array[i]);
  1355. fail:
  1356. /* Any remaining packets cannot be handled; there is no space in the
  1357. pending queue, which is limited to CVY_MAX_SEND_PACKETS packets. */
  1358. for (i = count; i < num_packets; i++)
  1359. {
  1360. /* Mark the packet as failed. */
  1361. NDIS_SET_PACKET_STATUS(packets[i], NDIS_STATUS_FAILURE);
  1362. /* Notify the protocol that the send is "complete". */
  1363. Nic_send_complete(ctxtp, NDIS_STATUS_FAILURE, packets[i]);
  1364. }
  1365. }
  1366. INT Prot_packet_recv (
  1367. NDIS_HANDLE adapter_handle,
  1368. PNDIS_PACKET packet)
  1369. {
  1370. PMAIN_CTXT ctxtp = (PMAIN_CTXT) adapter_handle;
  1371. PMAIN_ADAPTER adapterp;
  1372. PNDIS_PACKET newp;
  1373. NDIS_STATUS status;
  1374. PMAIN_PROTOCOL_RESERVED resp;
  1375. LONG lock_value;
  1376. PNDIS_PACKET_STACK pktstk;
  1377. BOOLEAN stack_left;
  1378. UNIV_ASSERT(ctxtp->code == MAIN_CTXT_CODE);
  1379. adapterp = &(univ_adapters[ctxtp->adapter_id]);
  1380. UNIV_ASSERT(adapterp->code == MAIN_ADAPTER_CODE);
  1381. UNIV_ASSERT(adapterp->ctxtp == ctxtp);
  1382. /* Check whether the driver has been announced to tcpip before processing any packets. */
  1383. if (!adapterp->inited || !adapterp->announced)
  1384. {
  1385. TRACE_CRIT("%!FUNC! Adapter not initialized or not announced");
  1386. return 0;
  1387. }
  1388. /* Do not accept frames if the card below is resetting. */
  1389. if (ctxtp->reset_state != MAIN_RESET_NONE)
  1390. {
  1391. TRACE_CRIT("%!FUNC! Adapter is resetting");
  1392. return 0;
  1393. }
  1394. /* Figure out if we need to handle this packet. */
  1395. newp = Main_recv(ctxtp, packet);
  1396. /* A return value of NULL indicates rejection of the packet - return zero to
  1397. indicate that no references remain on the packet (it can be dropped). */
  1398. if (newp == NULL)
  1399. {
  1400. return 0;
  1401. }
  1402. MAIN_RESP_FIELD(newp, stack_left, pktstk, resp, FALSE);
  1403. /* Process remote control. */
  1404. if (resp->type == MAIN_PACKET_TYPE_CTRL)
  1405. {
  1406. /* Handle remote control request now. */
  1407. (VOID)Main_ctrl_process(ctxtp, newp);
  1408. /* Packet has been copied into our own packet; return zero to
  1409. indicate that no references remain on the original packet. */
  1410. return 0;
  1411. }
  1412. UNIV_ASSERT_VAL(resp->type == MAIN_PACKET_TYPE_PASS, resp->type);
  1413. /* Pass packet up. Note reference counting to determine who will
  1414. be disposing of the packet. */
  1415. resp->data = 2;
  1416. Nic_recv_packet(ctxtp, newp);
  1417. lock_value = InterlockedDecrement(&resp->data);
  1418. UNIV_ASSERT_VAL(lock_value == 0 || lock_value == 1, lock_value);
  1419. if (lock_value == 0)
  1420. {
  1421. /* If we're done with the packet, reverse any changes we've made
  1422. to it and return zero to indication no lingering references. */
  1423. Main_packet_put(ctxtp, newp, FALSE, NDIS_STATUS_SUCCESS);
  1424. return 0;
  1425. }
  1426. /* Otherwise, the packet is still being processed, so return 1 to make
  1427. sure that the packet is not immediately released. */
  1428. return 1;
  1429. }
  1430. VOID Prot_return (
  1431. PMAIN_CTXT ctxtp,
  1432. PNDIS_PACKET packet)
  1433. {
  1434. PNDIS_PACKET oldp;
  1435. PMAIN_PROTOCOL_RESERVED resp;
  1436. LONG lock_value;
  1437. ULONG type;
  1438. PNDIS_PACKET_STACK pktstk;
  1439. BOOLEAN stack_left;
  1440. UNIV_ASSERT(ctxtp->code == MAIN_CTXT_CODE);
  1441. MAIN_RESP_FIELD(packet, stack_left, pktstk, resp, FALSE);
  1442. /* Check to see if we need to be disposing of this packet. */
  1443. lock_value = InterlockedDecrement(&resp->data);
  1444. UNIV_ASSERT_VAL(lock_value == 0 || lock_value == 1, lock_value);
  1445. if (lock_value == 1)
  1446. {
  1447. return;
  1448. }
  1449. /* Resp will become invalid after the call to Main_packet_put.
  1450. Save type for assertion below. */
  1451. type = resp->type;
  1452. oldp = Main_packet_put(ctxtp, packet, FALSE, NDIS_STATUS_SUCCESS);
  1453. /* If oldp is NULL, this is our internal packet. */
  1454. if (oldp != NULL)
  1455. {
  1456. UNIV_ASSERT_VAL(type == MAIN_PACKET_TYPE_PASS, type);
  1457. NdisReturnPackets(&oldp, 1);
  1458. }
  1459. }
  1460. NDIS_STATUS Prot_transfer (
  1461. PMAIN_CTXT ctxtp,
  1462. NDIS_HANDLE recv_handle,
  1463. PNDIS_PACKET packet,
  1464. UINT offset,
  1465. UINT len,
  1466. PUINT xferred)
  1467. {
  1468. NDIS_STATUS status;
  1469. PNDIS_PACKET newp;
  1470. PMAIN_PROTOCOL_RESERVED resp;
  1471. PNDIS_PACKET_STACK pktstk;
  1472. BOOLEAN stack_left;
  1473. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1474. /* V1.1.2 do not accept frames if the card below is resetting */
  1475. if (ctxtp -> reset_state != MAIN_RESET_NONE)
  1476. {
  1477. TRACE_CRIT("%!FUNC! adapter is resetting");
  1478. return NDIS_STATUS_FAILURE;
  1479. }
  1480. /* we are trying to prevent transfer requests from stale receive indicates
  1481. that have been made to the protocol layer prior to the reset operation.
  1482. we do not know what is the old inbound frame state and cannot expect
  1483. to be able to carry out any transfers. */
  1484. if (! ctxtp -> recv_indicated)
  1485. {
  1486. UNIV_PRINT_CRIT(("Prot_transfer: stale receive indicate after reset"));
  1487. TRACE_CRIT("%!FUNC! stale receive indicate after reset");
  1488. return NDIS_STATUS_FAILURE;
  1489. }
  1490. newp = Main_packet_get (ctxtp, packet, FALSE, 0, 0);
  1491. if (newp == NULL)
  1492. {
  1493. UNIV_PRINT_CRIT(("Prot_transfer: Error xlating packet"));
  1494. TRACE_CRIT("%!FUNC! Error translating packet");
  1495. return NDIS_STATUS_RESOURCES;
  1496. }
  1497. MAIN_RESP_FIELD (newp, stack_left, pktstk, resp, FALSE);
  1498. resp -> type = MAIN_PACKET_TYPE_TRANSFER;
  1499. NdisTransferData (& status, ctxtp -> mac_handle, recv_handle, offset, len,
  1500. newp, xferred); /* V1.1.2 */
  1501. if (status != NDIS_STATUS_PENDING)
  1502. {
  1503. if (status == NDIS_STATUS_SUCCESS)
  1504. {
  1505. MAIN_PACKET_INFO PacketInfo;
  1506. /* Call Main_recv_frame_parse merely to extract the packet length and "group". */
  1507. if (Main_recv_frame_parse(ctxtp, newp, &PacketInfo))
  1508. {
  1509. resp->len = PacketInfo.Length;
  1510. resp->group = PacketInfo.Group;
  1511. }
  1512. /* If we fail to fill in the group and length, just populate these
  1513. parameters with values that will not affect the statistics that
  1514. are updated in Main_packet_put. */
  1515. else
  1516. {
  1517. resp->len = 0;
  1518. resp->group = MAIN_FRAME_DIRECTED;
  1519. }
  1520. }
  1521. Main_packet_put (ctxtp, newp, FALSE, status);
  1522. }
  1523. return status;
  1524. } /* end Prot_transfer */
  1525. VOID Prot_cancel_send_packets (
  1526. PMAIN_CTXT ctxtp,
  1527. PVOID cancel_id)
  1528. {
  1529. UNIV_ASSERT (ctxtp -> code == MAIN_CTXT_CODE);
  1530. NdisCancelSendPackets (ctxtp -> mac_handle, cancel_id);
  1531. return;
  1532. } /* Prot_cancel_send_packets */