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.

555 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. device.c
  5. Abstract:
  6. This module contains code which implements the DEVICE_CONTEXT object.
  7. Routines are provided to reference, and dereference transport device
  8. context objects.
  9. The transport device context object is a structure which contains a
  10. system-defined DEVICE_OBJECT followed by information which is maintained
  11. by the transport provider, called the context.
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. Sanjay Anand (SanjayAn) - 22-Sept-1995
  16. BackFill optimization changes added under #if BACK_FILL
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(INIT,IpxCreateDevice)
  22. #endif
  23. VOID
  24. IpxRefDevice(
  25. IN PDEVICE Device
  26. )
  27. /*++
  28. Routine Description:
  29. This routine increments the reference count on a device context.
  30. Arguments:
  31. Device - Pointer to a transport device context object.
  32. Return Value:
  33. none.
  34. --*/
  35. {
  36. CTEAssert (Device->ReferenceCount > 0); // not perfect, but...
  37. (VOID)InterlockedIncrement(&Device->ReferenceCount);
  38. } /* IpxRefDevice */
  39. VOID
  40. IpxDerefDevice(
  41. IN PDEVICE Device
  42. )
  43. /*++
  44. Routine Description:
  45. This routine dereferences a device context by decrementing the
  46. reference count contained in the structure. Currently, we don't
  47. do anything special when the reference count drops to zero, but
  48. we could dynamically unload stuff then.
  49. Arguments:
  50. Device - Pointer to a transport device context object.
  51. Return Value:
  52. none.
  53. --*/
  54. {
  55. LONG result;
  56. #if DBG
  57. int i;
  58. #endif
  59. result = InterlockedDecrement (&Device->ReferenceCount);
  60. CTEAssert (result >= 0);
  61. if (result == 0) {
  62. #if DBG
  63. for (i = 0; i < DREF_TOTAL; i++) {
  64. CTEAssert(Device->RefTypes[i] == 0);
  65. }
  66. #endif
  67. IpxDestroyDevice (Device);
  68. }
  69. } /* IpxDerefDevice */
  70. NTSTATUS
  71. IpxCreateDevice(
  72. IN PDRIVER_OBJECT DriverObject,
  73. IN PUNICODE_STRING DeviceName,
  74. IN ULONG SegmentCount,
  75. IN OUT PDEVICE *DevicePtr
  76. )
  77. /*++
  78. Routine Description:
  79. This routine creates and initializes a device context structure.
  80. Arguments:
  81. DriverObject - pointer to the IO subsystem supplied driver object.
  82. Device - Pointer to a pointer to a transport device context object.
  83. SegmentCount - The number of segments in the RIP router table.
  84. DeviceName - pointer to the name of the device this device object points to.
  85. Return Value:
  86. STATUS_SUCCESS if all is well; STATUS_INSUFFICIENT_RESOURCES otherwise.
  87. --*/
  88. {
  89. NTSTATUS status;
  90. PDEVICE_OBJECT deviceObject;
  91. PDEVICE Device;
  92. ULONG DeviceSize;
  93. ULONG LocksOffset;
  94. ULONG SegmentsOffset;
  95. ULONG DeviceNameOffset;
  96. UINT i;
  97. //
  98. // Create the device object for the sample transport, allowing
  99. // room at the end for the device name to be stored (for use
  100. // in logging errors) and the RIP fields.
  101. //
  102. DeviceSize = sizeof(DEVICE) +
  103. (sizeof(CTELock) * SegmentCount) +
  104. (sizeof(ROUTER_SEGMENT) * SegmentCount) +
  105. DeviceName->Length + sizeof(UNICODE_NULL);
  106. status = IoCreateDevice(
  107. DriverObject,
  108. DeviceSize,
  109. DeviceName,
  110. FILE_DEVICE_TRANSPORT,
  111. FILE_DEVICE_SECURE_OPEN,
  112. FALSE,
  113. &deviceObject);
  114. if (!NT_SUCCESS(status)) {
  115. IPX_DEBUG(DEVICE, ("Create device %ws failed %lx\n", DeviceName->Buffer, status));
  116. return status;
  117. }
  118. deviceObject->Flags |= DO_DIRECT_IO;
  119. Device = (PDEVICE)deviceObject->DeviceExtension;
  120. IPX_DEBUG(DEVICE, ("Create device %ws succeeded %lx\n", DeviceName->Buffer,Device));
  121. //
  122. // Initialize our part of the device context.
  123. //
  124. RtlZeroMemory(
  125. ((PUCHAR)Device) + sizeof(DEVICE_OBJECT),
  126. sizeof(DEVICE) - sizeof(DEVICE_OBJECT));
  127. Device->DeviceObject = deviceObject;
  128. LocksOffset = sizeof(DEVICE);
  129. SegmentsOffset = LocksOffset + (sizeof(CTELock) * SegmentCount);
  130. DeviceNameOffset = SegmentsOffset + (sizeof(ROUTER_SEGMENT) * SegmentCount);
  131. //
  132. // Set some internal pointers.
  133. //
  134. Device->SegmentLocks = (CTELock *)(((PUCHAR)Device) + LocksOffset);
  135. Device->Segments = (PROUTER_SEGMENT)(((PUCHAR)Device) + SegmentsOffset);
  136. Device->SegmentCount = SegmentCount;
  137. for (i = 0; i < SegmentCount; i++) {
  138. CTEInitLock (&Device->SegmentLocks[i]);
  139. InitializeListHead (&Device->Segments[i].WaitingForRoute);
  140. InitializeListHead (&Device->Segments[i].FindWaitingForRoute);
  141. InitializeListHead (&Device->Segments[i].WaitingLocalTarget);
  142. InitializeListHead (&Device->Segments[i].WaitingReripNetnum);
  143. InitializeListHead (&Device->Segments[i].Entries);
  144. Device->Segments[i].EnumerateLocation = &Device->Segments[i].Entries;
  145. }
  146. //
  147. // Copy over the device name.
  148. //
  149. Device->DeviceNameLength = DeviceName->Length + sizeof(WCHAR);
  150. Device->DeviceName = (PWCHAR)(((PUCHAR)Device) + DeviceNameOffset);
  151. RtlCopyMemory(
  152. Device->DeviceName,
  153. DeviceName->Buffer,
  154. DeviceName->Length);
  155. Device->DeviceName[DeviceName->Length/sizeof(WCHAR)] = UNICODE_NULL;
  156. //
  157. // Initialize the reference count.
  158. //
  159. Device->ReferenceCount = 1;
  160. #if DBG
  161. Device->RefTypes[DREF_CREATE] = 1;
  162. #endif
  163. #if DBG
  164. RtlCopyMemory(Device->Signature1, "IDC1", 4);
  165. RtlCopyMemory(Device->Signature2, "IDC2", 4);
  166. #endif
  167. Device->Information.Version = 0x0100;
  168. Device->Information.MaxSendSize = 0; // no sends allowed
  169. Device->Information.MaxDatagramSize = 500; // 500 bytes
  170. Device->Information.MaxConnectionUserData = 0;
  171. Device->Information.ServiceFlags =
  172. TDI_SERVICE_CONNECTIONLESS_MODE | TDI_SERVICE_BROADCAST_SUPPORTED |
  173. TDI_SERVICE_ROUTE_DIRECTED | TDI_SERVICE_FORCE_ACCESS_CHECK;
  174. Device->Information.MinimumLookaheadData = 128;
  175. Device->Information.NumberOfResources = IPX_TDI_RESOURCES;
  176. KeQuerySystemTime (&Device->Information.StartTime);
  177. Device->Statistics.Version = 0x0100;
  178. #if 0
  179. //
  180. // These will be filled in after all the binding is done.
  181. //
  182. Device->Information.MaxDatagramSize = 0;
  183. Device->Information.MaximumLookaheadData = 0;
  184. Device->SourceRoutingUsed = FALSE;
  185. Device->SourceRoutingTime = 0;
  186. Device->RipPacketCount = 0;
  187. Device->RipShortTimerActive = FALSE;
  188. Device->RipSendTime = 0;
  189. #endif
  190. //
  191. // Initialize the resource that guards address ACLs.
  192. //
  193. ExInitializeResourceLite (&Device->AddressResource);
  194. //
  195. // Init the resource that guards the binding array/indices
  196. //
  197. // CTEInitLock (&Device->BindAccessLock);
  198. InitializeListHead (&Device->WaitingRipPackets);
  199. CTEInitTimer (&Device->RipShortTimer);
  200. CTEInitTimer (&Device->RipLongTimer);
  201. CTEInitTimer (&Device->SourceRoutingTimer);
  202. //
  203. // [FW] Initialize the timer used to update inactivity counters
  204. // on WAN lines.
  205. //
  206. CTEInitTimer (&Device->WanInactivityTimer);
  207. //
  208. // initialize the various fields in the device context
  209. //
  210. CTEInitLock (&Device->Interlock);
  211. CTEInitLock (&Device->Lock);
  212. CTEInitLock (&Device->SListsLock);
  213. Device->ControlChannelIdentifier.QuadPart = 1;
  214. InitializeListHead (&Device->GlobalSendPacketList);
  215. InitializeListHead (&Device->GlobalReceivePacketList);
  216. InitializeListHead (&Device->GlobalReceiveBufferList);
  217. #if BACK_FILL
  218. InitializeListHead (&Device->GlobalBackFillPacketList);
  219. #endif
  220. InitializeListHead (&Device->AddressNotifyQueue);
  221. InitializeListHead (&Device->LineChangeQueue);
  222. for (i = 0; i < IPX_ADDRESS_HASH_COUNT; i++) {
  223. InitializeListHead (&Device->AddressDatabases[i]);
  224. }
  225. #if BACK_FILL
  226. InitializeListHead (&Device->BackFillPoolList);
  227. #endif
  228. InitializeListHead (&Device->SendPoolList);
  229. InitializeListHead (&Device->ReceivePoolList);
  230. InitializeListHead (&Device->BindingPoolList);
  231. ExInitializeSListHead (&Device->SendPacketList);
  232. ExInitializeSListHead (&Device->ReceivePacketList);
  233. #if BACK_FILL
  234. ExInitializeSListHead (&Device->BackFillPacketList);
  235. #endif
  236. ExInitializeSListHead (&Device->BindingList);
  237. #if 0
  238. Device->MemoryUsage = 0;
  239. Device->SendPacketList.Next = NULL;
  240. Device->ReceivePacketList.Next = NULL;
  241. Device->Bindings = NULL;
  242. Device->BindingCount = 0;
  243. #endif
  244. KeQuerySystemTime (&Device->IpxStartTime);
  245. Device->State = DEVICE_STATE_CLOSED;
  246. Device->AutoDetectState = AUTO_DETECT_STATE_INIT;
  247. Device->NetPnPEvent = NULL;
  248. Device->Type = IPX_DEVICE_SIGNATURE;
  249. Device->Size = sizeof (DEVICE);
  250. #ifdef SNMP
  251. //
  252. // what are the values for these?
  253. //
  254. IPX_MIB_ENTRY(Device, SysInstance) = 0;
  255. IPX_MIB_ENTRY(Device, SysExistState) = 0;
  256. #endif SNMP
  257. *DevicePtr = Device;
  258. return STATUS_SUCCESS;
  259. } /* IpxCreateDevice */
  260. VOID
  261. IpxDestroyDevice(
  262. IN PDEVICE Device
  263. )
  264. /*++
  265. Routine Description:
  266. This routine destroys a device context structure.
  267. Arguments:
  268. Device - Pointer to a pointer to a transport device context object.
  269. Return Value:
  270. None.
  271. --*/
  272. {
  273. PLIST_ENTRY p;
  274. PSINGLE_LIST_ENTRY s;
  275. PIPX_SEND_POOL SendPool;
  276. PIPX_SEND_PACKET SendPacket;
  277. PIPX_RECEIVE_POOL ReceivePool;
  278. PIPX_RECEIVE_PACKET ReceivePacket;
  279. PIPX_ROUTE_ENTRY RouteEntry;
  280. UINT SendPoolSize;
  281. UINT ReceivePoolSize;
  282. UINT i;
  283. #if BACK_FILL
  284. PIPX_SEND_POOL BackFillPool;
  285. UINT BackFillPoolSize;
  286. PIPX_SEND_PACKET BackFillPacket;
  287. #endif
  288. PIPX_BINDING_POOL BindingPool;
  289. UINT BindingPoolSize;
  290. PBINDING Binding;
  291. CTELockHandle LockHandle;
  292. IPX_DEBUG (DEVICE, ("Destroy device %lx\n", Device));
  293. //
  294. // Take all the packets out of its pools.
  295. //
  296. BindingPoolSize = FIELD_OFFSET (IPX_BINDING_POOL, Bindings[0]) +
  297. (sizeof(BINDING) * Device->InitBindings);
  298. while (!IsListEmpty (&Device->BindingPoolList)) {
  299. p = RemoveHeadList (&Device->BindingPoolList);
  300. BindingPool = CONTAINING_RECORD (p, IPX_BINDING_POOL, Linkage);
  301. IPX_DEBUG (PACKET, ("Free binding pool %lx\n", BindingPool));
  302. IpxFreeMemory (BindingPool, BindingPoolSize, MEMORY_PACKET, "BindingPool");
  303. }
  304. #if BACK_FILL
  305. while (s = IPX_POP_ENTRY_LIST(&Device->BackFillPacketList, &Device->Lock)) {
  306. PIPX_SEND_RESERVED Reserved = CONTAINING_RECORD (s, IPX_SEND_RESERVED, PoolLinkage);
  307. IPX_SEND_PACKET BackFillPacket;
  308. BackFillPacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  309. IpxDeinitializeBackFillPacket (Device, &BackFillPacket);
  310. Device->MemoryUsage -= sizeof(IPX_SEND_RESERVED);
  311. }
  312. while (!IsListEmpty (&Device->BackFillPoolList)) {
  313. p = RemoveHeadList (&Device->BackFillPoolList);
  314. BackFillPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
  315. IPX_DEBUG (PACKET, ("Free packet pool %lx\n", BackFillPool));
  316. NdisFreePacketPool (BackFillPool->PoolHandle);
  317. IpxFreeMemory (BackFillPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "BafiPool");
  318. }
  319. #endif
  320. while (s = IPX_POP_ENTRY_LIST(&Device->SendPacketList, &Device->Lock)){
  321. PIPX_SEND_RESERVED Reserved = CONTAINING_RECORD (s, IPX_SEND_RESERVED, PoolLinkage);
  322. IPX_SEND_PACKET SendPacket;
  323. PUCHAR Header = Reserved->Header;
  324. SendPacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  325. IpxDeinitializeSendPacket (Device, &SendPacket);
  326. Device->MemoryUsage -= sizeof(IPX_SEND_RESERVED);
  327. }
  328. while (!IsListEmpty (&Device->SendPoolList)) {
  329. p = RemoveHeadList (&Device->SendPoolList);
  330. SendPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
  331. IPX_DEBUG (PACKET, ("Free packet pool %lx\n", SendPool));
  332. NdisFreePacketPool (SendPool->PoolHandle);
  333. IpxFreeMemory (SendPool->Header, PACKET_HEADER_SIZE * Device->InitDatagrams, MEMORY_PACKET, "SendPool");
  334. IpxFreeMemory (SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
  335. }
  336. while (s = IPX_POP_ENTRY_LIST(&Device->ReceivePacketList, &Device->Lock)){
  337. PIPX_RECEIVE_RESERVED Reserved = CONTAINING_RECORD (s, IPX_RECEIVE_RESERVED, PoolLinkage);
  338. IPX_RECEIVE_PACKET ReceivePacket;
  339. ReceivePacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  340. IpxDeinitializeReceivePacket (Device, &ReceivePacket);
  341. Device->MemoryUsage -= sizeof(IPX_RECEIVE_RESERVED);
  342. }
  343. while (!IsListEmpty (&Device->ReceivePoolList)) {
  344. p = RemoveHeadList (&Device->ReceivePoolList);
  345. ReceivePool = CONTAINING_RECORD (p, IPX_RECEIVE_POOL, Linkage);
  346. IPX_DEBUG (PACKET, ("Free packet pool %lx\n", ReceivePool));
  347. NdisFreePacketPool (ReceivePool->PoolHandle);
  348. IpxFreeMemory (ReceivePool, sizeof(IPX_RECEIVE_POOL), MEMORY_PACKET, "ReceivePool");
  349. }
  350. //
  351. // Destroy all rip table entries.
  352. //
  353. for (i = 0; i < Device->SegmentCount; i++) {
  354. RouteEntry = RipGetFirstRoute(i);
  355. while (RouteEntry != NULL) {
  356. (VOID)RipDeleteRoute(i, RouteEntry);
  357. IpxFreeMemory(RouteEntry, sizeof(IPX_ROUTE_ENTRY), MEMORY_RIP, "RouteEntry");
  358. RouteEntry = RipGetNextRoute(i);
  359. }
  360. }
  361. IPX_DEBUG (DEVICE, ("Final memory use is %d\n", Device->MemoryUsage));
  362. #if DBG
  363. for (i = 0; i < MEMORY_MAX; i++) {
  364. if (IpxMemoryTag[i].BytesAllocated != 0) {
  365. IPX_DEBUG (DEVICE, ("Tag %d: %d bytes left\n", i, IpxMemoryTag[i].BytesAllocated));
  366. }
  367. }
  368. #endif
  369. //
  370. // If we are being unloaded then someone is waiting for this
  371. // event to finish the cleanup, since we may be at DISPATCH_LEVEL;
  372. // otherwise it is during load and we can just kill ourselves here.
  373. //
  374. CTEGetLock (&Device->Lock, &LockHandle);
  375. if (Device->UnloadWaiting) {
  376. CTEFreeLock (&Device->Lock, LockHandle);
  377. KeSetEvent(
  378. &Device->UnloadEvent,
  379. 0L,
  380. FALSE);
  381. } else {
  382. CTEFreeLock (&Device->Lock, LockHandle);
  383. CTEAssert (KeGetCurrentIrql() < DISPATCH_LEVEL);
  384. ExDeleteResourceLite (&Device->AddressResource);
  385. IoDeleteDevice (Device->DeviceObject);
  386. }
  387. } /* IpxDestroyDevice */