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.

645 lines
19 KiB

  1. /*
  2. (C) Copyright 1999
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the same terms
  7. outlined in the Microsoft Windows Device Driver Development Kit.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL Adapter Adapter_c
  12. @module Adapter.c |
  13. This module implements the interface to the <t MINIPORT_ADAPTER_OBJECT>.
  14. Supports the high-level adapter control functions used by the NDIS WAN
  15. Minport driver.
  16. @comm
  17. This module isolates most the NDIS specific, logical adapter interfaces.
  18. It should require very little change if you follow this same overall
  19. architecture. You should try to isolate your changes to the <t CARD_OBJECT>
  20. that is contained within the logical adapter <t MINIPORT_ADAPTER_OBJECT>.
  21. @head3 Contents |
  22. @index class,mfunc,func,msg,mdata,struct,enum | Adapter_c
  23. @end
  24. */
  25. #define __FILEID__ MINIPORT_ADAPTER_OBJECT_TYPE
  26. // Unique file ID for error logging
  27. #include "Miniport.h" // Defines all the miniport objects
  28. #if defined(NDIS_LCODE)
  29. # pragma NDIS_LCODE // Windows 9x wants this code locked down!
  30. # pragma NDIS_LDATA
  31. #endif
  32. PMINIPORT_ADAPTER_OBJECT g_Adapters[MAX_ADAPTERS] // @globalv
  33. // Keeps track of all the <t MINIPORT_ADAPTER_OBJECT>s created by the driver.
  34. = { 0 };
  35. DBG_STATIC ULONG g_AdapterInstanceCounter // @globalv
  36. // Keeps track of how many <t MINIPORT_ADAPTER_OBJECT>s are created and
  37. // stored in the <p g_Adapters> array.
  38. = 0;
  39. DBG_STATIC UCHAR g_AnsiDriverName[] // @globalv
  40. // ANSI string used to identify the driver to the system; usually defined
  41. // as VER_PRODUCT_STR.
  42. = VER_PRODUCT_STR;
  43. DBG_STATIC UCHAR g_AnsiVendorDescription[] // @globalv
  44. // ANSI string used to identify the vendor's device to the system; usually
  45. // defined as VER_DEVICE_STR " Adapter".
  46. = VER_DEVICE_STR " Adapter";
  47. /* @doc INTERNAL EXTERNAL Adapter Adapter_c g_AdapterParameters
  48. @topic 5.1 Adapter Parameters |
  49. This section describes the registry parameters read into the
  50. <t MINIPORT_ADAPTER_OBJECT>.
  51. @globalv DBG_STATIC <t PARAM_TABLE> | g_AdapterParameters |
  52. This table defines the registry based parameters to be assigned to data
  53. members of the <t MINIPORT_ADAPTER_OBJECT>.
  54. <f Note>:
  55. If you add any registry based data members to <t MINIPORT_ADAPTER_OBJECT>
  56. you will need to modify <f AdapterReadParameters> and add the parameter
  57. definitions to the <f g_AdapterParameters> table.
  58. @flag <f DebugFlags> (OPTIONAL) (DEBUG VERSION ONLY) |
  59. This DWORD parameter allows you to control how much debug information is
  60. displayed to the debug monitor. This is a bit OR'd flag using the values
  61. defined in <t DBG_FLAGS>. This value is not used by the released version
  62. of the driver.<nl>
  63. */
  64. DBG_STATIC PARAM_TABLE g_AdapterParameters[] =
  65. {
  66. #if DBG
  67. PARAM_ENTRY(MINIPORT_ADAPTER_OBJECT,
  68. DbgFlags, PARAM_DebugFlags,
  69. FALSE, NdisParameterHexInteger, 0,
  70. DBG_DEFAULTS | DBG_TAPICALL_ON, 0, 0xffffffff),
  71. // TODO: Change the debug flags to meet your needs.
  72. #endif
  73. /* The last entry must be an empty string! */
  74. { { 0 } }
  75. };
  76. /* @doc INTERNAL Adapter Adapter_c AdapterReadParameters
  77. @func
  78. <f AdapterReadParameters> reads the adapter parameters from the registry
  79. and initializes the associated data members. This should only be called
  80. by <f AdapterCreate>.
  81. <f Note>:
  82. If you add any registry based data members to <t MINIPORT_ADAPTER_OBJECT>
  83. you will need to modify <f AdapterReadParameters> and add the parameter
  84. definitions to the <f g_AdapterParameters> table.
  85. @rdesc
  86. <f AdapterReadParameters> returns zero if it is successful.<nl>
  87. Otherwise, a non-zero return value indicates an error condition.
  88. */
  89. DBG_STATIC NDIS_STATUS AdapterReadParameters(
  90. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  91. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  92. // <f AdapterCreate>.
  93. )
  94. {
  95. DBG_FUNC("AdapterReadParameters")
  96. NDIS_STATUS Result;
  97. // Holds the result code returned by this function.
  98. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  99. DBG_ENTER(DbgInfo);
  100. /*
  101. // Parse the registry parameters.
  102. */
  103. Result = ParamParseRegistry(
  104. pAdapter->MiniportAdapterHandle,
  105. pAdapter->WrapperConfigurationContext,
  106. (PUCHAR)pAdapter,
  107. g_AdapterParameters
  108. );
  109. if (Result == NDIS_STATUS_SUCCESS)
  110. {
  111. /*
  112. // Make sure the parameters are valid.
  113. */
  114. if (pAdapter->TODO)
  115. {
  116. DBG_ERROR(DbgInfo,("Invalid value 'TODO'\n",
  117. pAdapter->TODO));
  118. NdisWriteErrorLogEntry(
  119. pAdapter->MiniportAdapterHandle,
  120. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  121. 3,
  122. pAdapter->TODO,
  123. __FILEID__,
  124. __LINE__
  125. );
  126. Result = NDIS_STATUS_FAILURE;
  127. }
  128. }
  129. DBG_RETURN(DbgInfo, Result);
  130. return (Result);
  131. }
  132. /* @doc INTERNAL Adapter Adapter_c AdapterCreateObjects
  133. @func
  134. <f AdapterCreateObjects> calls the create routines for all the objects
  135. contained in <t MINIPORT_ADAPTER_OBJECT>. This should only be called
  136. by <f AdapterCreate>.
  137. <f Note>:
  138. If you add any new objects to <t MINIPORT_ADAPTER_OBJECT> you will need
  139. to modify <f AdapterCreateObjects> and <f AdapterDestroyObjects> so they
  140. will get created and destroyed properly.
  141. @rdesc
  142. <f AdapterCreateObjects> returns zero if it is successful.<nl>
  143. Otherwise, a non-zero return value indicates an error condition.
  144. */
  145. DBG_STATIC NDIS_STATUS AdapterCreateObjects(
  146. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  147. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  148. // <f AdapterCreate>.
  149. )
  150. {
  151. DBG_FUNC("AdapterCreateObjects")
  152. NDIS_STATUS Result;
  153. // Holds the result code returned by this function.
  154. ULONG Index;
  155. // Loop counter.
  156. ULONG NumBChannels;
  157. // The number of BChannels supported by the NIC.
  158. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  159. DBG_ENTER(DbgInfo);
  160. /*
  161. // Create the Card object.
  162. */
  163. Result = CardCreate(&pAdapter->pCard, pAdapter);
  164. /*
  165. // Create the DChannel object.
  166. */
  167. if (Result == NDIS_STATUS_SUCCESS)
  168. {
  169. Result = DChannelCreate(&pAdapter->pDChannel, pAdapter);
  170. }
  171. /*
  172. // Allocate space for the BChannels.
  173. */
  174. if (Result == NDIS_STATUS_SUCCESS)
  175. {
  176. NumBChannels = CardNumChannels(pAdapter->pCard);
  177. Result = ALLOCATE_MEMORY(pAdapter->pBChannelArray,
  178. sizeof(PVOID) * NumBChannels,
  179. pAdapter->MiniportAdapterHandle);
  180. }
  181. /*
  182. // Create the BChannel objects.
  183. */
  184. InitializeListHead(&pAdapter->BChannelAvailableList);
  185. for (Index = 0; Result == NDIS_STATUS_SUCCESS &&
  186. Index < NumBChannels; Index++)
  187. {
  188. Result = BChannelCreate(&pAdapter->pBChannelArray[Index],
  189. Index,
  190. pAdapter);
  191. /*
  192. // Put entry on available list.
  193. */
  194. InsertTailList(&pAdapter->BChannelAvailableList,
  195. &pAdapter->pBChannelArray[Index]->LinkList);
  196. /*
  197. // Keep track of how many are created.
  198. */
  199. if (Result == NDIS_STATUS_SUCCESS)
  200. {
  201. pAdapter->NumBChannels++;
  202. }
  203. }
  204. DBG_RETURN(DbgInfo, Result);
  205. return (Result);
  206. }
  207. /* @doc INTERNAL Adapter Adapter_c AdapterCreate
  208. @func
  209. <f AdapterCreate> allocates memory for a <t MINIPORT_ADAPTER_OBJECT> and
  210. then initializes the data members to their starting state.
  211. If successful, <p ppAdapter> will be set to point to the newly created
  212. <t MINIPORT_ADAPTER_OBJECT>. Otherwise, <p ppAdapter> will be set to
  213. NULL.
  214. @comm
  215. This function should be called only once when the Miniport is loaded.
  216. Before the Miniport is unloaded, <f AdapterDestroy> must be called to
  217. release the <t MINIPORT_ADAPTER_OBJECT> created by this function.
  218. @rdesc
  219. <f AdapterCreate> returns zero if it is successful.<nl>
  220. Otherwise, a non-zero return value indicates an error condition.
  221. */
  222. NDIS_STATUS AdapterCreate(
  223. OUT PMINIPORT_ADAPTER_OBJECT *ppAdapter, // @parm
  224. // Points to a caller-defined memory location to which this function
  225. // writes the virtual address of the allocated <t MINIPORT_ADAPTER_OBJECT>.
  226. IN NDIS_HANDLE MiniportAdapterHandle, // @parm
  227. // Specifies a handle identifying the miniport's NIC, which is assigned
  228. // by the NDIS library. MiniportInitialize should save this handle; it
  229. // is a required parameter in subsequent calls to NdisXxx functions.
  230. IN NDIS_HANDLE WrapperConfigurationContext // @parm
  231. // Specifies a handle used only during initialization for calls to
  232. // NdisXxx configuration and initialization functions. For example,
  233. // this handle is a required parameter to NdisOpenConfiguration and
  234. // the NdisImmediateReadXxx and NdisImmediateWriteXxx functions.
  235. )
  236. {
  237. DBG_FUNC("AdapterCreate")
  238. NDIS_STATUS Result;
  239. // Holds the result code returned by this function.
  240. PMINIPORT_ADAPTER_OBJECT pAdapter;
  241. // Pointer to our newly allocated object.
  242. DBG_ENTER(DbgInfo);
  243. /*
  244. // Make sure the caller's object pointer is NULL to begin with.
  245. // It will be set later only if everything is successful.
  246. */
  247. *ppAdapter = NULL;
  248. /*
  249. // Allocate memory for the object.
  250. */
  251. Result = ALLOCATE_OBJECT(pAdapter, MiniportAdapterHandle);
  252. if (Result == NDIS_STATUS_SUCCESS)
  253. {
  254. /*
  255. // Zero everything to begin with.
  256. // Then set the object type and assign a unique ID .
  257. */
  258. pAdapter->ObjectType = MINIPORT_ADAPTER_OBJECT_TYPE;
  259. pAdapter->ObjectID = ++g_AdapterInstanceCounter;
  260. ASSERT(g_AdapterInstanceCounter <= MAX_ADAPTERS);
  261. if (g_AdapterInstanceCounter <= MAX_ADAPTERS)
  262. {
  263. g_Adapters[g_AdapterInstanceCounter-1] = pAdapter;
  264. }
  265. /*
  266. // We use the instance number in debug messages to help when debugging
  267. // with multiple adapters.
  268. */
  269. #if DBG
  270. pAdapter->DbgID[0] = (UCHAR) ((pAdapter->ObjectID & 0x0F) + '0');
  271. pAdapter->DbgID[1] = ':';
  272. if (sizeof(VER_TARGET_STR) < sizeof(pAdapter->DbgID)-3)
  273. {
  274. memcpy(&pAdapter->DbgID[2], VER_TARGET_STR, sizeof(VER_TARGET_STR));
  275. }
  276. else
  277. {
  278. memcpy(&pAdapter->DbgID[2], VER_TARGET_STR, sizeof(pAdapter->DbgID)-3);
  279. pAdapter->DbgID[sizeof(pAdapter->DbgID)-1] = 0;
  280. }
  281. #endif
  282. /*
  283. // Initialize the member variables to their default settings.
  284. */
  285. pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
  286. pAdapter->WrapperConfigurationContext = WrapperConfigurationContext;
  287. /*
  288. // Allocate spin locks to use for MUTEX queue protection.
  289. */
  290. NdisAllocateSpinLock(&pAdapter->EventLock);
  291. NdisAllocateSpinLock(&pAdapter->TransmitLock);
  292. NdisAllocateSpinLock(&pAdapter->ReceiveLock);
  293. /*
  294. // Parse the registry parameters.
  295. */
  296. Result = AdapterReadParameters(pAdapter);
  297. #if DBG
  298. // DbgInfo->DbgFlags = pAdapter->DbgFlags;
  299. #endif // DBG
  300. DBG_DISPLAY(("NOTICE: Adapter#%d=0x%X DbgFlags=0x%X\n",
  301. pAdapter->ObjectID, pAdapter, pAdapter->DbgFlags));
  302. /*
  303. // If all goes well, we are ready to create the sub-components.
  304. */
  305. if (Result == NDIS_STATUS_SUCCESS)
  306. {
  307. Result = AdapterCreateObjects(pAdapter);
  308. }
  309. if (Result == NDIS_STATUS_SUCCESS)
  310. {
  311. /*
  312. // All is well, so return the object pointer to the caller.
  313. */
  314. *ppAdapter = pAdapter;
  315. }
  316. else
  317. {
  318. /*
  319. // Something went wrong, so let's make sure everything is
  320. // cleaned up.
  321. */
  322. AdapterDestroy(pAdapter);
  323. }
  324. }
  325. DBG_RETURN(DbgInfo, Result);
  326. return (Result);
  327. }
  328. /* @doc INTERNAL Adapter Adapter_c AdapterDestroyObjects
  329. @func
  330. <f AdapterDestroyObjects> calls the destroy routines for all the objects
  331. contained in <t MINIPORT_ADAPTER_OBJECT>. This should only be called
  332. by <f AdapterDestroy>.
  333. <f Note>:
  334. If you add any new objects to <t MINIPORT_ADAPTER_OBJECT> you will need
  335. to modify <f AdapterCreateObjects> and <f AdapterDestroyObjects> so they
  336. will get created and destroyed properly.
  337. */
  338. DBG_STATIC void AdapterDestroyObjects(
  339. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  340. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  341. // <f AdapterCreate>.
  342. )
  343. {
  344. DBG_FUNC("AdapterDestroyObjects")
  345. UINT NumBChannels;
  346. // The number of BChannels supported by the NIC.
  347. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  348. DBG_ENTER(DbgInfo);
  349. /*
  350. // Destroy the BChannel objects.
  351. */
  352. NumBChannels = pAdapter->NumBChannels;
  353. while (NumBChannels--)
  354. {
  355. BChannelDestroy(pAdapter->pBChannelArray[NumBChannels]);
  356. }
  357. pAdapter->NumBChannels = 0;
  358. /*
  359. // Free space for the BChannels.
  360. */
  361. if (pAdapter->pBChannelArray)
  362. {
  363. NumBChannels = CardNumChannels(pAdapter->pCard);
  364. FREE_MEMORY(pAdapter->pBChannelArray, sizeof(PVOID) * NumBChannels);
  365. }
  366. /*
  367. // Destroy the DChannel object.
  368. */
  369. DChannelDestroy(pAdapter->pDChannel);
  370. /*
  371. // Destroy the Card object.
  372. */
  373. CardDestroy(pAdapter->pCard);
  374. DBG_LEAVE(DbgInfo);
  375. }
  376. /* @doc INTERNAL Adapter Adapter_c AdapterDestroy
  377. @func
  378. <f AdapterDestroy> frees the memory for this <t MINIPORT_ADAPTER_OBJECT>.
  379. All memory allocated by <f AdapterCreate> will be released back to the OS.
  380. */
  381. void AdapterDestroy(
  382. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  383. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  384. // <f AdapterCreate>.
  385. )
  386. {
  387. DBG_FUNC("AdapterDestroy")
  388. DBG_ENTER(DbgInfo);
  389. if (pAdapter)
  390. {
  391. ASSERT(pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  392. /*
  393. // Release all objects allocated within this object.
  394. */
  395. AdapterDestroyObjects(pAdapter);
  396. if (pAdapter->EventLock.SpinLock)
  397. {
  398. NdisFreeSpinLock(&pAdapter->EventLock);
  399. }
  400. if (pAdapter->TransmitLock.SpinLock)
  401. {
  402. NdisFreeSpinLock(&pAdapter->TransmitLock);
  403. }
  404. if (pAdapter->ReceiveLock.SpinLock)
  405. {
  406. NdisFreeSpinLock(&pAdapter->ReceiveLock);
  407. }
  408. /*
  409. // Make sure we fail the ASSERT if we see this object again.
  410. */
  411. if (pAdapter->ObjectType <= MAX_ADAPTERS)
  412. {
  413. g_Adapters[pAdapter->ObjectType-1] = NULL;
  414. }
  415. pAdapter->ObjectType = 0;
  416. FREE_OBJECT(pAdapter);
  417. }
  418. DBG_LEAVE(DbgInfo);
  419. }
  420. /* @doc INTERNAL Adapter Adapter_c AdapterInitialize
  421. @func
  422. <f AdapterInitialize> prepares the <t MINIPORT_ADAPTER_OBJECT> and all
  423. its sub-components for use by the NDIS wrapper. Upon successful
  424. completion of this routine, the NIC will be ready to accept requests
  425. from the NDIS wrapper.
  426. @rdesc
  427. <f AdapterInitialize> returns zero if it is successful.<nl>
  428. Otherwise, a non-zero return value indicates an error condition.
  429. */
  430. NDIS_STATUS AdapterInitialize(
  431. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  432. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance return by
  433. // <f AdapterCreate>.
  434. )
  435. {
  436. DBG_FUNC("AdapterInitialize")
  437. NDIS_STATUS Result;
  438. // Holds the result code returned by this function.
  439. PBCHANNEL_OBJECT pBChannel;
  440. // A Pointer to one of our <t BCHANNEL_OBJECT>'s.
  441. ULONG Index;
  442. // Loop counter.
  443. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  444. DBG_ENTER(pAdapter);
  445. /*
  446. // Initialize the WAN information structure to match the capabilities of
  447. // the adapter.
  448. */
  449. pAdapter->WanInfo.MaxFrameSize = pAdapter->pCard->BufferSize - NDISWAN_EXTRA_SIZE;
  450. pAdapter->WanInfo.MaxSendWindow = pAdapter->pCard->TransmitBuffersPerLink;
  451. /*
  452. // We only support PPP, and multi-link PPP framing.
  453. */
  454. pAdapter->WanInfo.FramingBits = PPP_FRAMING |
  455. PPP_MULTILINK_FRAMING;
  456. /*
  457. // This value is ignored by this driver, but its default behavior is such
  458. // that all these control bytes would appear to be handled transparently.
  459. */
  460. pAdapter->WanInfo.DesiredACCM = 0;
  461. /*
  462. // Initialize the packet management queues to empty.
  463. */
  464. InitializeListHead(&pAdapter->EventList);
  465. InitializeListHead(&pAdapter->TransmitPendingList);
  466. InitializeListHead(&pAdapter->TransmitCompleteList);
  467. InitializeListHead(&pAdapter->ReceiveCompleteList);
  468. /*
  469. // Setup the timer event handler.
  470. */
  471. NdisMInitializeTimer(&pAdapter->EventTimer,
  472. pAdapter->MiniportAdapterHandle,
  473. MiniportTimer,
  474. pAdapter);
  475. /*
  476. // Initialize the DChannel object.
  477. */
  478. DChannelInitialize(pAdapter->pDChannel);
  479. /*
  480. // Initialize all the BChannel objects.
  481. */
  482. for (Index = 0; Index < pAdapter->NumBChannels; ++Index)
  483. {
  484. pBChannel = GET_BCHANNEL_FROM_INDEX(pAdapter, Index);
  485. BChannelInitialize(pBChannel);
  486. }
  487. /*
  488. // Now, we can initialize the Card object.
  489. */
  490. Result = CardInitialize(pAdapter->pCard);
  491. DBG_RETURN(pAdapter, Result);
  492. return (Result);
  493. }