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.

702 lines
15 KiB

  1. // Copyright (c) 2000-2002, Microsoft Corporation, all rights reserved
  2. //
  3. // driver.c
  4. //
  5. // IEEE1394 mini-port/call-manager driver
  6. //
  7. //
  8. // Loads and unload the ARP module when the
  9. // bridge is activated
  10. //
  11. // Created by Adube
  12. //
  13. //--------------------------------------------------------//
  14. // //
  15. // //
  16. // ZwLoadDriver is locally declared because if I try //
  17. // and include ZwApi.h there are conflicts with //
  18. // structures defined in wdm.h //
  19. // //
  20. // //
  21. //--------------------------------------------------------//
  22. #include "precomp.h"
  23. NDIS_STRING ArpName = NDIS_STRING_CONST("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ARP1394");
  24. //----------------------------------------------------------//
  25. // Local Prototypes //
  26. //----------------------------------------------------------//
  27. NTSYSAPI
  28. NTSTATUS
  29. NTAPI
  30. ZwLoadDriver(
  31. IN PUNICODE_STRING DriverServiceName
  32. );
  33. NTSYSAPI
  34. NTSTATUS
  35. NTAPI
  36. ZwUnloadDriver(
  37. IN PUNICODE_STRING DriverServiceName
  38. );
  39. VOID
  40. nicEthStartArpWorkItem (
  41. PNDIS_WORK_ITEM pWorkItem,
  42. IN PVOID Context
  43. );
  44. NTSYSAPI
  45. NTSTATUS
  46. NTAPI
  47. ZwDeviceIoControlFile(
  48. IN HANDLE FileHandle,
  49. IN HANDLE Event OPTIONAL,
  50. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  51. IN PVOID ApcContext OPTIONAL,
  52. OUT PIO_STATUS_BLOCK IoStatusBlock,
  53. IN ULONG IoControlCode,
  54. IN PVOID InputBuffer OPTIONAL,
  55. IN ULONG InputBufferLength,
  56. OUT PVOID OutputBuffer OPTIONAL,
  57. IN ULONG OutputBufferLength
  58. );
  59. VOID
  60. nicSetupIoctlToLoadArp (
  61. IN PADAPTERCB pAdapter,
  62. IN PARP_INFO pArpInfo
  63. );
  64. VOID
  65. nicSetupAndSendIoctlToArp (
  66. IN PADAPTERCB pAdapter,
  67. IN PARP_INFO pArpInfo
  68. );
  69. //----------------------------------------------------------//
  70. // Functions //
  71. //----------------------------------------------------------//
  72. VOID
  73. nicSendIoctlToArp(
  74. PARP1394_IOCTL_COMMAND pCmd
  75. )
  76. /*++
  77. Routine Description:
  78. Send the start Ioctl to the ARp module
  79. Arguments:
  80. Return Value:
  81. --*/
  82. {
  83. BOOLEAN fRet = FALSE;
  84. PUCHAR pc;
  85. HANDLE DeviceHandle;
  86. ULONG BytesReturned;
  87. OBJECT_ATTRIBUTES Atts;
  88. NDIS_STRING strArp1394 = NDIS_STRING_CONST ("\\Device\\Arp1394");
  89. HANDLE Handle;
  90. NTSTATUS status = STATUS_UNSUCCESSFUL;
  91. IO_STATUS_BLOCK ioStatusBlock;
  92. do
  93. {
  94. InitializeObjectAttributes(&Atts,
  95. &strArp1394,
  96. OBJ_CASE_INSENSITIVE,
  97. NULL,
  98. NULL);
  99. status = ZwCreateFile(&Handle,
  100. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  101. &Atts,
  102. &ioStatusBlock,
  103. NULL,
  104. FILE_ATTRIBUTE_NORMAL,
  105. FILE_SHARE_READ | FILE_SHARE_WRITE,
  106. FILE_OPEN_IF,
  107. 0,
  108. NULL,
  109. 0);
  110. if (!NT_SUCCESS(status))
  111. {
  112. Handle = NULL;
  113. break;
  114. }
  115. //
  116. // Submit the request to the forwarder
  117. //
  118. status = ZwDeviceIoControlFile(
  119. Handle,
  120. NULL,
  121. NULL,
  122. NULL,
  123. &ioStatusBlock,
  124. ARP_IOCTL_CLIENT_OPERATION,
  125. pCmd,
  126. sizeof(*pCmd),
  127. pCmd,
  128. sizeof(*pCmd));
  129. //
  130. // Close the device.
  131. //
  132. ZwClose(Handle);
  133. if (!NT_SUCCESS(status))
  134. {
  135. ASSERT (status == STATUS_SUCCESS);
  136. break;
  137. }
  138. } while (FALSE);
  139. }
  140. VOID
  141. nicLoadArpDriver ()
  142. /*++
  143. Routine Description:
  144. Load the arp module
  145. Arguments:
  146. Return Value:
  147. --*/
  148. {
  149. ZwLoadDriver(&ArpName);
  150. TRACE (TL_T, TM_Mp,("Loaded the Arp Module %p\n", &ArpName));
  151. }
  152. VOID
  153. nicGetAdapterName (
  154. IN PADAPTERCB pAdapter,
  155. IN WCHAR* pAdapterName,
  156. IN ULONG BufferSize,
  157. IN PULONG pSizeReturned
  158. )
  159. /*++
  160. Routine Description:
  161. Get the Adapter Name From NDIS. All sizes are in bytes
  162. Arguments:
  163. Return Value:
  164. --*/
  165. {
  166. //
  167. // The BufferSize always has to be greater than SizeReturned
  168. //
  169. if (BufferSize > pAdapter->AdapterNameSize)
  170. {
  171. NdisMoveMemory (pAdapterName,
  172. &pAdapter->AdapterName[0],
  173. pAdapter->AdapterNameSize);
  174. if (pSizeReturned != NULL)
  175. {
  176. *pSizeReturned = pAdapter->AdapterNameSize ;
  177. }
  178. }
  179. else
  180. {
  181. //
  182. // The else case cannot be hit because the size of the AdapterName buffer
  183. // is 1 less than the sizeof pEthCmd->AdapterName[]. if this is ever changed,
  184. // the Assert will be hit.
  185. //
  186. ASSERT (BufferSize > pAdapter->AdapterNameSize);
  187. *pSizeReturned = 0;
  188. }
  189. }
  190. VOID
  191. nicSetupIoctlToArp (
  192. IN PADAPTERCB pAdapter,
  193. IN PARP_INFO pArpInfo
  194. )
  195. /*++
  196. Routine Description:
  197. Sets up the Ioctl to be sent to the Arp module
  198. Arguments:
  199. Return Value:
  200. --*/
  201. {
  202. PARP1394_IOCTL_ETHERNET_NOTIFICATION pEthCmd = &pAdapter->ArpIoctl.EthernetNotification;
  203. ADAPTER_ACQUIRE_LOCK(pAdapter);
  204. if (BindArp == pArpInfo->Action || LoadArp == pArpInfo->Action)
  205. {
  206. pEthCmd->Hdr.Op = ARP1394_IOCTL_OP_ETHERNET_START_EMULATION;
  207. pAdapter->fIsArpStarted = TRUE;
  208. ADAPTER_SET_FLAG(pAdapter,fADAPTER_BridgeMode);
  209. }
  210. if (UnloadArp == pArpInfo->Action || UnloadArpNoRequest== pArpInfo->Action)
  211. {
  212. pEthCmd->Hdr.Op = ARP1394_IOCTL_OP_ETHERNET_STOP_EMULATION;
  213. pAdapter->fIsArpStarted = FALSE;
  214. ADAPTER_CLEAR_FLAG(pAdapter,fADAPTER_BridgeMode);
  215. }
  216. ADAPTER_RELEASE_LOCK(pAdapter);
  217. }
  218. VOID
  219. nicSetupAndSendIoctlToArp (
  220. IN PADAPTERCB pAdapter,
  221. PARP_INFO pArpInfo )
  222. /*++
  223. Routine Description:
  224. Sets up an Ioctl and Sends it to the Arp module
  225. Arguments:
  226. Return Value:
  227. --*/
  228. {
  229. nicSetupIoctlToArp (pAdapter, pArpInfo);
  230. nicSendIoctlToArp(&pAdapter->ArpIoctl);
  231. }
  232. VOID
  233. nicSendNotificationToArp(
  234. IN PADAPTERCB pAdapter,
  235. IN PARP_INFO pArpInfo
  236. )
  237. /*++
  238. Routine Description:
  239. Send the notification to the arp module
  240. Arguments:
  241. Return Value:
  242. --*/
  243. {
  244. PNDIS_REQUEST pRequest = NULL;
  245. ULONG Start = FALSE;
  246. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  247. ARP1394_IOCTL_COMMAND ArpIoctl;
  248. //
  249. // Extract our variables from the workitem
  250. //
  251. TRACE (TL_T, TM_Mp, ("==>nicEthStartArpWorkItem Start %x", Start ));
  252. do
  253. {
  254. //
  255. // First complete the request, so that protocols can start sending new
  256. // requests . Notes 11/30/00
  257. //
  258. if (pArpInfo->Action == LoadArp || pArpInfo->Action == UnloadArp)
  259. {
  260. //
  261. // in either of these cases, it is a request that has initiated the action.
  262. //
  263. //
  264. if (pRequest == NULL)
  265. {
  266. //
  267. // This came in through our CL SetInformation Handler
  268. //
  269. NdisMSetInformationComplete (pAdapter->MiniportAdapterHandle, NdisStatus );
  270. }
  271. else
  272. {
  273. NdisMCoRequestComplete ( NdisStatus ,
  274. pAdapter->MiniportAdapterHandle,
  275. pRequest);
  276. }
  277. }
  278. //
  279. // "arp13 -bstart adapter"
  280. // If we are asked to Load Arp, we verify that the arp hasn't
  281. // already been started
  282. //
  283. if (pArpInfo->Action == LoadArp && pAdapter->fIsArpStarted == FALSE)// we are turning ON
  284. {
  285. //
  286. // Load the driver
  287. //
  288. nicLoadArpDriver ();
  289. //
  290. // Send it an IOCTL to open the nic1394 adapter
  291. //
  292. }
  293. if (pArpInfo->Action == BindArp && pAdapter->fIsArpStarted == FALSE)
  294. {
  295. //
  296. // if the arp module has not been started and we are asking to bind,
  297. // then it means that an unload was ahead of us in the queue and
  298. // unbound nic1394 from arp1394. This thread can exit.
  299. //
  300. break;
  301. }
  302. //
  303. // Send the Ioctl to the Arp module
  304. //
  305. nicSetupAndSendIoctlToArp (pAdapter, pArpInfo);
  306. } while (FALSE);
  307. //
  308. // end of function
  309. //
  310. FREE_NONPAGED (pArpInfo);
  311. TRACE (TL_T, TM_Mp, ("<==nicEthStartArpWorkItem fLoadArp %x", pArpInfo->Action));
  312. return;
  313. }
  314. VOID
  315. nicProcessNotificationForArp(
  316. IN PNDIS_WORK_ITEM pWorkItem,
  317. IN PVOID Context
  318. )
  319. /*++
  320. Routine Description:
  321. This function extracts the notification from the workitem and
  322. sends the Load/Unload/ BInd notfication to ARp 1394
  323. Arguments:
  324. Return Value:
  325. --*/
  326. {
  327. PADAPTERCB pAdapter = (PADAPTERCB) Context;
  328. ADAPTER_ACQUIRE_LOCK (pAdapter);
  329. //
  330. // Empty the Queue indicating as many packets as possible
  331. //
  332. while (IsListEmpty(&pAdapter->LoadArp.Queue)==FALSE)
  333. {
  334. PARP_INFO pArpInfo;
  335. PLIST_ENTRY pLink;
  336. NDIS_STATUS NdisStatus;
  337. pAdapter->LoadArp.PktsInQueue--;
  338. pLink = RemoveHeadList(&pAdapter->LoadArp.Queue);
  339. ADAPTER_RELEASE_LOCK (pAdapter);
  340. //
  341. // Extract the send context
  342. //
  343. if (pLink != NULL)
  344. {
  345. pArpInfo = CONTAINING_RECORD(
  346. pLink,
  347. ARP_INFO,
  348. Link);
  349. nicSendNotificationToArp(pAdapter, pArpInfo);
  350. }
  351. ADAPTER_ACQUIRE_LOCK (pAdapter);
  352. }
  353. //
  354. // clear the flag
  355. //
  356. ASSERT (pAdapter->LoadArp.PktsInQueue==0);
  357. ASSERT (IsListEmpty(&pAdapter->LoadArp.Queue));
  358. pAdapter->LoadArp.bTimerAlreadySet = FALSE;
  359. ADAPTER_RELEASE_LOCK (pAdapter);
  360. NdisInterlockedDecrement (&pAdapter->OutstandingWorkItems);
  361. }
  362. VOID
  363. nicInitializeLoadArpStruct(
  364. PADAPTERCB pAdapter
  365. )
  366. /*++
  367. Routine Description:
  368. This function initializes the LoadArp struct in _ADAPTERCB
  369. Arguments:
  370. Return Value:
  371. --*/
  372. {
  373. if (pAdapter->LoadArp.bInitialized == FALSE)
  374. {
  375. PARP1394_IOCTL_ETHERNET_NOTIFICATION pEthCmd = &pAdapter->ArpIoctl.EthernetNotification;
  376. ULONG Size;
  377. //
  378. // Initialize the Load Arp struct
  379. //
  380. NdisZeroMemory (&pAdapter->LoadArp, sizeof(pAdapter->LoadArp));
  381. InitializeListHead(&pAdapter->LoadArp.Queue);
  382. pAdapter->LoadArp.bInitialized = TRUE;
  383. NdisInitializeWorkItem (&pAdapter->LoadArp.WorkItem,
  384. nicProcessNotificationForArp,
  385. pAdapter);
  386. //
  387. // Initialize the AdapterName, this will ensure that the string is
  388. // NULL terminated
  389. //
  390. NdisZeroMemory( pEthCmd->AdapterName, sizeof(pEthCmd->AdapterName));
  391. nicGetAdapterName (pAdapter,
  392. pEthCmd->AdapterName,
  393. sizeof(pEthCmd->AdapterName)-sizeof(WCHAR),
  394. &Size );
  395. pEthCmd->Hdr.Version = ARP1394_IOCTL_VERSION;
  396. }
  397. }
  398. NDIS_STATUS
  399. nicQueueRequestToArp(
  400. PADAPTERCB pAdapter,
  401. ARP_ACTION Action,
  402. PNDIS_REQUEST pRequest
  403. )
  404. /*++
  405. Routine Description:
  406. This function inserts a request to load/unload or bind the Arp module
  407. If there is no timer servicing the queue
  408. then it queues a timer to dequeue the packet in Global Event's context
  409. Arguments:
  410. Self explanatory
  411. Return Value:
  412. Success - if inserted into the the queue
  413. --*/
  414. {
  415. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  416. BOOLEAN fSetWorkItem = FALSE;
  417. PARP_INFO pArpInfo;
  418. do
  419. {
  420. pArpInfo = ALLOC_NONPAGED(sizeof (ARP_INFO), MTAG_DEFAULT);
  421. if (pArpInfo == NULL)
  422. {
  423. break;
  424. }
  425. ADAPTER_ACQUIRE_LOCK (pAdapter);
  426. //
  427. // Find out if this thread needs to fire the timer
  428. //
  429. pArpInfo->Action = Action;
  430. pArpInfo->pRequest = pRequest;
  431. if (pAdapter->LoadArp.bTimerAlreadySet == FALSE)
  432. {
  433. fSetWorkItem = TRUE;
  434. pAdapter->LoadArp.bTimerAlreadySet = TRUE;
  435. }
  436. InsertTailList(
  437. &pAdapter->LoadArp.Queue,
  438. &pArpInfo->Link
  439. );
  440. pAdapter->LoadArp.PktsInQueue++;
  441. ADAPTER_RELEASE_LOCK (pAdapter);
  442. //
  443. // Now queue the workitem
  444. //
  445. if (fSetWorkItem== TRUE)
  446. {
  447. PNDIS_WORK_ITEM pWorkItem;
  448. //
  449. // Initialize the timer
  450. //
  451. pWorkItem = &pAdapter->LoadArp.WorkItem;
  452. TRACE( TL_V, TM_Recv, ( " Set Timer "));
  453. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  454. NdisScheduleWorkItem (pWorkItem);
  455. }
  456. Status = NDIS_STATUS_SUCCESS;
  457. } while (FALSE);
  458. ASSERT (Status == NDIS_STATUS_SUCCESS);
  459. return Status;
  460. }