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.

305 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. llcmain.c
  5. Abstract:
  6. This module implements data link object for NDIS 3.0.
  7. Data link driver provides 802.2 LLC Class I and II services
  8. and also interface to send and receive direct network data.
  9. This module may later be used as general packet router
  10. for the protocol modules => smaller system overhead, when
  11. the NDIS packet header is checked only once. LLC interface
  12. is also much easier to use than NDIS.
  13. Its main tasks are:
  14. - implement simple and realiable LLC Class II
  15. connection-oriented services for the other drivers
  16. - provide network independent interface 802.2 interface
  17. - remove the system overhead of the packet and indication
  18. routing to all protocol modules
  19. - provide transmit packet queueing for the protocol drivers
  20. - provide 802.2 compatible connect, disconnect and close
  21. services, that calls back, when the transmit queue is
  22. empty.
  23. The services provides the module are somewhat extended
  24. 802.2 services, because the protocol engine is a IBM version
  25. of ISO-HDLC ABM. LlcDisconnet and LlcConnect primitives
  26. implements both Request and Confirm of Connect/Disconnect
  27. Data link driver does not make any buffering for the data.
  28. All data buffer except the LLC header and lan header with the
  29. I-frames must be provided by the calling protocol driver.
  30. *********************** SPINLOCK RULES *************************
  31. DataLink driver uses extensively several spin locks to make it
  32. as re-entrant as possible with multiple processors and to
  33. minimize unnecessary spin locking calls.
  34. The main problem with multiple spin locks are the dead locks.
  35. The spin locks must always be acquired the same order (and
  36. released in a reverse order):
  37. This is the order used with DataLink spin locks:
  38. 1. Adapter->ObjectDataBase
  39. Protects objects from close/delete. This is always locked in
  40. the receive indication routine.
  41. 2. Link->SpinLock
  42. Protects the link. This lock is needed to prevent to upper
  43. protocol to call the link station, when we are changing it state.
  44. SendSpinLock cannot protect it, because it must be switched off,
  45. when the pending commands are executed. (But could we keep
  46. SendSpinLock locked, when the transmit commands are completed).
  47. There will occure a dead lock in any way, if the upper protocol
  48. is waiting the last transmit to complete before it disconnects
  49. a link station.
  50. 3. Adapter->SendSpinLock // protects queues and packet pools
  51. ---
  52. Timer spin locks is used only by timer servives:
  53. 4. TimerSpinLock // protects the timer queues
  54. ****************************************************************
  55. Contents:
  56. LlcInitialize
  57. LlcTerminate
  58. Author:
  59. Antti Saarenheimo (o-anttis) 17-MAY-1991
  60. Revision History:
  61. --*/
  62. //
  63. // This define enables the private DLC function prototypes
  64. // We don't want to export our data types to the dlc layer.
  65. // MIPS compiler doesn't accept hiding of the internal data
  66. // structures by a PVOID in the function prototype.
  67. // i386 will check the type defines
  68. //
  69. #ifndef i386
  70. #define LLC_PUBLIC_NDIS_PROTOTYPES
  71. #endif
  72. #include <llc.h>
  73. #include "dbgmsg.h"
  74. //
  75. // These are the defaults defined in the IBM LAN Architecture reference,
  76. // this may be set by a DLC application, if it want to change the defaults.
  77. //
  78. DLC_LINK_PARAMETERS DefaultParameters = {
  79. 3, // T1 600 milliseconds (3 * 5 * 40)
  80. 2, // T2 80 milliseconds (2 * 1 * 40)
  81. 10, // Ti 25 seconds ((10 - 5) * 125 * 4)
  82. 127, // TW: maximum transmit window size
  83. 127, // RW: The maximum receive window size
  84. 20, // Nw: number of LPDUs acknowledged, before Ww is incr.)
  85. 5, // N2: Number of retires allowed (both Polls and I LPDSs)
  86. 0, // lowest proirity by default
  87. 600 // default for info field length by default
  88. };
  89. KMUTEX NdisAccessMutex;
  90. KSEMAPHORE OpenAdapterSemaphore;
  91. #define LLC_PROTOCOL_NAME L"DLC"
  92. #ifdef NDIS40
  93. extern ULONG gWaitForAdapter;
  94. #endif // NDIS40
  95. DLC_STATUS
  96. LlcInitialize(
  97. VOID
  98. )
  99. /*++
  100. Routine Description:
  101. The routines initializes the protocol module and
  102. does the minimal stuff, that must be done in the
  103. serialized initialization routine.
  104. Arguments:
  105. None.
  106. Return Value:
  107. NDIS_STATUS
  108. --*/
  109. {
  110. NDIS_STATUS Status;
  111. NDIS_PROTOCOL_CHARACTERISTICS LlcChars;
  112. ASSUME_IRQL(PASSIVE_LEVEL);
  113. //
  114. // We must build a MDL for the XID information used
  115. // when the link level takes care of XID handling.
  116. //
  117. pXidMdl = IoAllocateMdl(&Ieee802Xid,
  118. sizeof(Ieee802Xid),
  119. FALSE,
  120. FALSE,
  121. NULL
  122. );
  123. if (pXidMdl == NULL) {
  124. return DLC_STATUS_NO_MEMORY;
  125. }
  126. #ifdef NDIS40
  127. //
  128. // Event to signal all adapters have been bound - OK for LlcOpenAdapter
  129. // to bind.
  130. //
  131. NdisInitializeEvent(&PnPBindsComplete);
  132. NdisResetEvent(&PnPBindsComplete);
  133. #endif // NDIS40
  134. #if LLC_DBG
  135. ALLOCATE_SPIN_LOCK(&MemCheckLock);
  136. #endif
  137. MmBuildMdlForNonPagedPool(pXidMdl);
  138. LlcInitializeTimerSystem();
  139. NdisZeroMemory(&LlcChars, sizeof(LlcChars));
  140. NdisInitUnicodeString(&LlcChars.Name, LLC_PROTOCOL_NAME);
  141. #ifdef NDIS40
  142. LlcChars.MajorNdisVersion = 4;
  143. LlcChars.MinorNdisVersion = 0;
  144. LlcChars.OpenAdapterCompleteHandler = LlcNdisOpenAdapterComplete;
  145. LlcChars.CloseAdapterCompleteHandler = LlcNdisCloseComplete;
  146. LlcChars.SendCompleteHandler = LlcNdisSendComplete;
  147. LlcChars.TransferDataCompleteHandler = LlcNdisTransferDataComplete;
  148. LlcChars.ResetCompleteHandler = LlcNdisResetComplete;
  149. LlcChars.RequestCompleteHandler = LlcNdisRequestComplete;
  150. LlcChars.ReceiveHandler = LlcNdisReceiveIndication;
  151. LlcChars.ReceiveCompleteHandler = LlcNdisReceiveComplete;
  152. LlcChars.StatusHandler = NdisStatusHandler;
  153. LlcChars.StatusCompleteHandler = LlcNdisReceiveComplete;
  154. // DLC supports bind/unbind/pnp, but not unload.
  155. LlcChars.UnloadHandler = NULL;
  156. LlcChars.PnPEventHandler = LlcPnPEventHandler;
  157. LlcChars.BindAdapterHandler = LlcBindAdapterHandler;
  158. LlcChars.UnbindAdapterHandler = LlcUnbindAdapterHandler;
  159. //
  160. // Need to get value for waiting on uninitialized adapters.
  161. //
  162. if (!NT_SUCCESS(GetAdapterWaitTimeout(&gWaitForAdapter)))
  163. {
  164. ASSERT(FALSE);
  165. gWaitForAdapter = 15; // Default.
  166. }
  167. DEBUGMSG(DBG_WARN, (TEXT("WaitForAdapter delay = %d sec\n"), gWaitForAdapter));
  168. #else // NDIS40
  169. LlcChars.MajorNdisVersion = 3;
  170. LlcChars.MinorNdisVersion = 0;
  171. LlcChars.OpenAdapterCompleteHandler = LlcNdisOpenAdapterComplete;
  172. LlcChars.CloseAdapterCompleteHandler = LlcNdisCloseComplete;
  173. LlcChars.SendCompleteHandler = LlcNdisSendComplete;
  174. LlcChars.TransferDataCompleteHandler = LlcNdisTransferDataComplete;
  175. LlcChars.ResetCompleteHandler = LlcNdisResetComplete;
  176. LlcChars.RequestCompleteHandler = LlcNdisRequestComplete;
  177. LlcChars.ReceiveHandler = LlcNdisReceiveIndication;
  178. LlcChars.ReceiveCompleteHandler = LlcNdisReceiveComplete;
  179. LlcChars.StatusHandler = NdisStatusHandler;
  180. LlcChars.StatusCompleteHandler = LlcNdisReceiveComplete;
  181. #endif // !NDIS40
  182. NdisRegisterProtocol(&Status,
  183. &LlcProtocolHandle,
  184. &LlcChars,
  185. sizeof(LlcChars));
  186. KeInitializeSpinLock(&LlcSpinLock);
  187. ASSUME_IRQL(PASSIVE_LEVEL);
  188. KeInitializeMutex(&NdisAccessMutex, 1);
  189. //
  190. // We use the OpenAdapterSemaphore in the LlcOpenAdapter function. We really
  191. // want a mutex, but a mutex causes us problems on a checked build if we
  192. // make a call into NTOS. In either case, we just need a mechanism to ensure
  193. // only one thread is creating the ADAPTER_CONTEXT & opening the adapter at
  194. // NDIS level
  195. //
  196. KeInitializeSemaphore(&OpenAdapterSemaphore, 1, 1);
  197. if (Status != STATUS_SUCCESS) {
  198. IoFreeMdl(pXidMdl);
  199. }
  200. return Status;
  201. }
  202. VOID
  203. LlcTerminate(
  204. VOID
  205. )
  206. /*++
  207. Routine Description:
  208. The routines terminates the LLC protocol module and frees its global
  209. resources. This assumes all adapter bindings to be closed.
  210. Arguments:
  211. None.
  212. Return Value:
  213. None.
  214. --*/
  215. {
  216. NDIS_STATUS Status;
  217. ASSUME_IRQL(PASSIVE_LEVEL);
  218. DEBUGMSG(DBG_INIT, (TEXT("+LlcTerminate()\n")));
  219. LlcTerminateTimerSystem();
  220. #ifdef NDIS40
  221. CloseAllAdapters();
  222. #endif // NDIS40
  223. NdisDeregisterProtocol(&Status, LlcProtocolHandle);
  224. IoFreeMdl(pXidMdl);
  225. }
  226.