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.

1367 lines
58 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the terms outlined in
  7. the TriplePoint Software Services Agreement.
  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 Miniport Miniport_c
  12. @module Miniport.c |
  13. This module implements the <f DriverEntry> routine, which is the first
  14. routine called when the driver is loaded into memory. The Miniport
  15. initialization and termination routines are also implemented here.
  16. @head3 Contents |
  17. @index class,mfunc,func,msg,mdata,struct,enum | Miniport_c
  18. @end
  19. */
  20. /* @doc EXTERNAL INTERNAL
  21. @topic 1.0 Miniport Overview |
  22. The NDIS wrapper provides services to both the Transport drivers, and the
  23. Miniport drivers. The NDIS wrapper provides an abstraction layer between
  24. the two which allows them to interoperate with each other as long as they
  25. both adhere to the NDIS interfaces defined for Transports and Miniports.
  26. The NDIS wrapper also provides a set of services which isolate NDIS
  27. drivers from the specifics of the Operating System (Win 3.11, Win95,
  28. WinNT), as well as the platform specifics (Processor, Bus, Interrupts).
  29. The advantage of using the NDIS wrapper is that the Miniport can be
  30. easily ported to other Windows environments with little or no re-coding.
  31. @iex
  32. This diagram shows how the NDIS wrapper provides services
  33. to both the Transport drivers, and the Miniport drivers.
  34. | +--------+ +-----+ +---------------------------------+
  35. | | | | |<-->| Windows Transport Drivers (TDI) |
  36. | | | | | +---------------------------------+
  37. | | | | | | Lower-Edge Functions ^
  38. | | | | | | |
  39. | | | | | v |
  40. | | | | +--------------------------------------+
  41. | | | | NDIS Interface Library (Wrapper) |
  42. | | | | +--------------------------------------+
  43. | |Windows | | | | ^
  44. | | OS | | | | |
  45. | |Services| | | v Upper-Edge Functions |
  46. | | | | | +---------------------------------+
  47. | | | | | | NDIS WAN/TAPI Driver (Miniport) |
  48. | | | | | +---------------------------------+
  49. | | | | | ^ Lower-Edge Functions
  50. | | | | | |
  51. | | | | | v
  52. | | | | +--------------------------------------+
  53. | | +---|<-->|------------+ |
  54. | +----|---+ +--------------------------------------------+
  55. | ^
  56. | |
  57. | v Hardware Bus
  58. | +------------------------------+
  59. | | Network Interface Card (NIC) |
  60. | +------------------------------+
  61. An NDISWAN Miniport consists of two, cooperating, drivers contained in
  62. the same binary. The NDIS WAN portion of the driver handles packet
  63. transmits and receives. While the WAN TAPI portion handles call setup
  64. and tear down. Ultimately, it would be better if these two drivers
  65. were separated, and there was an interface defined between them, but
  66. history and expedience lead Microsoft to develop this interface model.
  67. The NDIS WAN side of the Miniport is very similar to an NDIS LAN style
  68. Miniport, except that some of the NDIS interfaces have been modified to
  69. support the WAN media type. The primary difference from the Miniport's
  70. point of view is the packet structure and different set of NDIS requests,
  71. and more importantly the line can go up and down.
  72. The WAN TAPI portion of the Miniport adds significant complexity to the
  73. Miniport. The WAN Miniport must provide a pseudo Telephony Service
  74. Provider Interface (TSPI) which lives under the WAN TSPI. The NDIS WAN
  75. TSPI loads under TAPI as the 'real' service provider, and then routes all
  76. RAS related TAPI events to the Miniport's TSPI.
  77. The WAN TSPI can have multiple Miniport TSPI's living under its TSPI
  78. interface. And since Remote Access Services (RAS) use the TAPI interface
  79. to place and accept all calls, any Dial Up Networking (DUN) requests
  80. associated with the Miniport, will end up at the Miniport's TSPI.
  81. @topic 1.1 Call Control Interface |
  82. FIXME_DESCRIPTION
  83. @topic 1.2 Data Channel Interface |
  84. FIXME_DESCRIPTION
  85. Once a call is connected, the data channel associated with the call is
  86. configured to transmit and receive raw HDLC packets. Then NDIS is
  87. notified that the coresponding 'link' is up. The NDIS documentation
  88. refers to a data pipe as a link, and the Miniport also uses this
  89. nomenclature. In addition, NDIS/RAS wants to see each data channel as a
  90. separate TAPI line device, so the Miniport also uses this link structure
  91. to keep track of TAPI calls and lines since they are all mapped 1:1:1.
  92. Keep this in mind as you read through the code and documentation, because
  93. I often use line and link interchangeably.
  94. @topic 1.3 Implementation Notes |
  95. The Miniport is built as a Windows NT Portable Executable (PE) system
  96. file (.SYS). The reason for this is that the NDIS WAN interfaces
  97. routines are currently only defined in the Windows NT version of the NDIS
  98. library. On Windows 95, the Miniport's binary image file is dynamically
  99. loaded by the NDIS wrapper during initialization, and runs in Ring-0. A
  100. Windows 95 version of the NDIS.VXD is available which supports the new
  101. WAN interrfaces.
  102. @end
  103. */
  104. /* @doc EXTERNAL INTERNAL
  105. @topic 2.0 Reference Documents |
  106. The most reliable source of information is provided on the Microsoft
  107. Developer Network CD. These documents will provide you with the complete
  108. NDIS interface requirements and architectural overviews. In addition,
  109. there are many addendums and developer notes in the Microsoft Knowledge
  110. Base. The most important references are:
  111. @iex
  112. Product Documentation\DDKs\Windows 95 DDK\Network Drivers\
  113. Windows 95 Network Drivers
  114. NDIS 3.0 Netcard Driver
  115. NDIS Netcard Driver Tester
  116. Network Driver Installer
  117. Product Documentation\DDKs\Windows NT DDK\Network Drivers\
  118. Design Guide\PART2 NDIS 3.0 Driver Design
  119. Chapters 1-7 discuss all the NDIS interface routines.
  120. Chapters 8-11,17-18 provide details on WAN/TAPI extensions.
  121. Product Documentation\SDKs\Win32 SDK\Win32 Telephony\
  122. This section defines the Windows 95 TAPI implementation.
  123. Note that this is slightly different than the Windows 3.1 TAPI
  124. spec. Pay special attention to lineGetID and line device classes.
  125. @topic 2.1 NDIS Background Information |
  126. Microsoft is phasing out what they call the NDIS 3.0 Full MAC driver.
  127. These drivers were written to the NDIS 3.0 specification using the older
  128. interface routines which have now been augmented by the Miniport
  129. routines. The Miniport extensions were added to the NDIS 3.0 interface
  130. with the goal of making network drivers easier to write. By using the
  131. Miniport routines rather than the original NDIS routines, the driver
  132. writer can make many simplifying assumptions, because the NDIS Wrapper
  133. will provide most of the queuing, scheduling, and sychronization code.
  134. The Miniport only has to deal with moving packets on and off the wire.
  135. The WAN and TAPI extensions were added into the NDIS 3.0 specification
  136. shortly after the Miniport extensions. These new WAN interface routines
  137. are very similar to the LAN interface routines. The only significant
  138. difference is the packet format passed between the Miniport and the NDIS
  139. Wrapper. The TAPI extensions have no counterpart in the LAN interface,
  140. so these are all new. In fact, they turn out to be about half of the
  141. implementation in a typical WAN/TAPI Miniport.
  142. It would have been nice if Microsoft would have added these changes and
  143. bumped the version numbers, but they didn't. So we are left with a real
  144. problem trying to identifiy which NDIS 3.0 we are talking about. The
  145. thing to remember is that you should avoid the Full MAC interface routines,
  146. because Microsoft has said that these routines will not be supported in
  147. future releases. This is largely due to the Plug-and-Play extensions
  148. that were introduced in NDIS 3.1 for Windows 95.
  149. In the near future Microsoft will be adding more features to NDIS 3.5 to
  150. support advanced routing and some other enhancements. In addition,
  151. NDIS 4.0 will be coming out with MANY new features to support ATM and
  152. other virtual circuit type media. There are also more TAPI services
  153. being defined for the NDIS interface. So don't expect this specification
  154. to stand still long enough to read it all...
  155. @topic 2.2 Differences between LAN and WAN miniports |
  156. There are several differences in the way a WAN miniport interfaces
  157. with NDIS as compared to a LAN miniport driver described in the
  158. previous chapters. Such differences affect how a WAN driver is
  159. implemented.
  160. A WAN miniport must not register a MiniportTransferData handler with
  161. NdisMRegisterMiniport. Instead, a WAN miniport always passes an entire
  162. packet to the NdisMWanIndicateReceive function. When
  163. NdisMWanIndicateReceive returns, the packet has been copied and the
  164. WAN miniport can reuse the packet resources it allocated.
  165. WAN miniports provide a MiniportWanSend function instead of a MiniportSend
  166. function. The MiniportWanSend function accepts an additional parameter that
  167. specifies a specific data channel on which a packet is to be sent.
  168. WAN miniports never return NDIS_STATUS_RESOURCES as the status of
  169. MiniportWanSend or any other MiniportXxx function and cannot call
  170. NdisMSendResourcesAvailable.
  171. WAN miniports support a set of WAN-specific OIDs to set and query
  172. operating characteristics.
  173. WAN miniports support a set of WAN-specific status indications
  174. which are passed to NdisMIndicateStatus. These status indications
  175. report changes in the status of a link.
  176. WAN miniports call alternative WAN-specific NDIS functions to
  177. complete the WAN-specific NDIS calls for send and receive. <nl>
  178. The two completion calls are: <nl>
  179. NdisMWanIndicateReceiveComplete <nl>
  180. NdisMWanSendComplete <nl>
  181. WAN miniport drivers use an NDIS_WAN_PACKET instead of an
  182. NDIS_PACKET-type descriptor.
  183. WAN miniport drivers keep a WAN-specific set of statistics.
  184. WAN miniport drivers never do loopback; it is always
  185. provided by NDIS.
  186. WAN miniport drivers cannot be full-duplex miniports.
  187. @end
  188. */
  189. /* @doc EXTERNAL INTERNAL
  190. @topic 3.0 NDISWAN Miniport Interface |
  191. The Miniport provides the following functions to the NDIS wrapper.
  192. The NDIS wrapper calls these functions on behalf of other layers of the
  193. network software, such as a transport driver bound to a network interface
  194. card. The Miniport uses <f NdisMRegisterMiniport> to give NDIS a list of
  195. entry points for the supported routines, unused routines are set to NULL.
  196. Some of the Miniport functions are synchronous, while others can
  197. complete either synchronously or asynchronously. The Miniport must
  198. indicate to the NDIS library when an asynchronous function has completed
  199. by calling the appropriate NDIS library completion function. The NDIS
  200. library can subsequently call completion functions in other layers of the
  201. network software for postprocessing, if necessary.
  202. <f DriverEntry> Called by the operating system to activate and
  203. initialize the Miniport. (Synchronous)
  204. <f MiniportCheckForHang> Checks the internal state of the network interface
  205. card. (Synchronous)
  206. <f MiniportHalt> Halts the network interface card so it is no longer
  207. functioning. (Synchronous)
  208. <f MiniportInitialize> Initializes the network interface card. (Synchronous)
  209. <f MiniportQueryInformation> Queries the capabilities and current status of
  210. the Miniport. NDISTAPI functions are also passed through this
  211. interface. (Asynchronous)
  212. <f MiniportReset> Issues a hardware reset to the network interface card.
  213. (Asynchronous)
  214. <f MiniportWanSend> Transmits a packet through the network interface card
  215. onto the network. (Asynchronous)
  216. <f MiniportSetInformation> Changes (sets) information about the Miniport
  217. driver. NDISTAPI functions are also passed through this interface.
  218. (Asynchronous)
  219. @iex
  220. The following routines are defined in the NDIS Miniport interface,
  221. but they are not used by this implementation.
  222. MiniportISR NOT USED by this Miniport.
  223. Associated with each Miniport upper-edge driver function that may operate
  224. asynchronously is a corresponding completion function in the NDIS library.
  225. When the Miniport function returns a status of NDIS_STATUS_PENDING
  226. indicating asynchronous operation, this is the completion function that
  227. must be called when the Miniport has finally completed the request.
  228. @iex
  229. This table shows how each asynchronous Miniport routine maps to its
  230. associated NDIS completion routine.
  231. Miniport Function Asynchronous Completion Routine
  232. ----------------- -------------------------------
  233. MiniportQueryInformation NdisMQueryInformationComplete
  234. MiniportReset NdisMResetComplete
  235. MiniportWanSend NdisMSendComplete
  236. MiniportSetInformation NdisMSetInformationComplete
  237. MiniportTransferData NdisMTransferDataComplete (NOT USED)
  238. @end
  239. */
  240. /* @doc EXTERNAL INTERNAL
  241. @topic 3.1 Initialization and Setup |
  242. The following diagram shows the typical call sequence used during system
  243. initialization. Typically this occurs once when Windows loads. However,
  244. NDIS does allow drivers to be unloaded, and then reloaded at any time, so
  245. you must be prepared to handle this event.
  246. @iex
  247. | NDIS Wrapper | Miniport
  248. | -----------------------------+------------------------------------
  249. | Load NDIS Wrapper |
  250. | >---------+---->+ DriverEntry
  251. | | |
  252. | NdisMInitializeWrapper <----+---->+
  253. | | |
  254. | NdisMRegisterMiniport <----+---->+
  255. | | |
  256. | <---------+----<+
  257. | ~~~ TIME PASSES
  258. | >---------+---->+ MiniportInitialize
  259. | | |
  260. | NdisOpenConfiguration <---+---->+
  261. | | |
  262. | NdisReadConfiguration... <---+---->+
  263. | | |
  264. | NdisCloseConfiguration <---+---->+
  265. | | |
  266. | NdisMSetAttributes <---+---->+
  267. | | |
  268. | <---------+----<+
  269. | ~~~ TIME PASSES
  270. | >---------+---->+ MiniportQueryInformation
  271. | <---------+----<+ OID_WAN_CURRENT_ADDRESS
  272. | ~~~ TIME PASSES
  273. | >---------+---->+ MiniportQueryInformation
  274. | <---------+----<+ OID_WAN_MEDIUM_SUBTYPE
  275. | ~~~ TIME PASSES
  276. | >---------+---->+ MiniportQueryInformation
  277. | <---------+----<+ OID_WAN_GET_INFO
  278. @end
  279. */
  280. /* @doc EXTERNAL INTERNAL
  281. @topic 3.6 Reset and Shutdown |
  282. Aside from the initialization and run-time operations, the Miniport must
  283. support being reset <f MiniportReset> and being shutdown <f MiniportHalt>.
  284. The reset routine is only called when the NDIS wrapper detects an error
  285. with the Miniport's operation. There are two ways in which the wrapper
  286. determines an error condition. First, the NDIS wrapper calls
  287. <f MiniportCheckForHang> once every couple seconds to ask the Miniport
  288. if it thinks it needs to be reset. Second, the wrapper may detect a
  289. timeout condition on an outstanding request to the Miniport. These are
  290. both fail-safe conditions which should not happen under normal, run-time
  291. conditions.
  292. <f Note>: My feeling is that if you see a reset call, the Miniport is
  293. broken, and you should find and fix the bug -- not the symptom.
  294. The shutdown routine is normally only called when Windows is shutting
  295. down. However, with the advent of plug and play devices, it is likely to
  296. become more common to get a shutdown request followed by another load
  297. request in the same Windows session. So it is very important to clean up
  298. properly when <f MiniportHalt> is called. All memory and other resources
  299. must be released, and all intefaces must be properly closed so they can
  300. release their resources too.
  301. NDIS will cleanup any outstanding requests, but the Miniport should
  302. bring down all calls, and close all TAPI lines using synchronous
  303. TAPI events. You can't depend on any NDIS WAN or TAPI events because
  304. none will be passed through the wrapper as long as the reset is in
  305. progress.
  306. @end
  307. */
  308. #define __FILEID__ MINIPORT_DRIVER_OBJECT_TYPE
  309. // Unique file ID for error logging
  310. #include "Miniport.h" // Defines all the miniport objects
  311. #include "TpiParam.h"
  312. #if defined(NDIS_LCODE)
  313. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  314. # pragma NDIS_LDATA
  315. #endif
  316. DBG_STATIC NDIS_HANDLE g_NdisWrapperHandle = NULL;
  317. // Receives the context value representing the Miniport wrapper
  318. // as returned from NdisMInitializeWrapper.
  319. NDIS_PHYSICAL_ADDRESS g_HighestAcceptableAddress =
  320. NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
  321. // This constant is used for places where NdisAllocateMemory needs to be
  322. // called and the g_HighestAcceptableAddress does not matter.
  323. /* @doc INTERNAL Miniport Miniport_c DriverEntry
  324. @func
  325. <f DriverEntry> is called by the operating system when a driver is loaded.
  326. This function creates an association between the miniport NIC driver and
  327. the NDIS library and registers the miniport's characteristics with NDIS.
  328. <f DriverEntry> calls NdisMInitializeWrapper and then NdisMRegisterMiniport.
  329. <f DriverEntry> passes both pointers it received to NdisMInitializeWrapper,
  330. which returns a wrapper handle. <f DriverEntry> passes the wrapper handle to
  331. NdisMRegisterMiniport.
  332. The registry contains data that is persistent across system boots, as well
  333. as configuration information generated anew at each system boot. During
  334. driver installation, data describing the driver and the NIC is stored in
  335. the registry. The registry contains adapter characteristics that are read
  336. by the NIC driver to initialize itself and the NIC. See the Kernel-Mode
  337. Driver Design Guide for more about the registry and the Programmer's Guide
  338. for more information about the .inf files that install the driver and
  339. write to the registry.
  340. @comm
  341. Every miniport driver must provide a function called DriverEntry. By
  342. convention, DriverEntry is the entry point address for a driver. If a
  343. driver does not use the name DriverEntry, the driver developer must define
  344. the name of its entry function to the linker so that the entry point
  345. address can be known into the OS loader.
  346. It is interesting to note, that at the time DriverEntry is called, the OS
  347. doesn't know that the driver is an NDIS driver. The OS thinks it is just
  348. another driver being loaded. So it is possible to do anything any driver
  349. might do at this point. Since NDIS is the one who requested this driver
  350. to be loaded, it would be polite to register with the NDIS wrapper. But
  351. you can also hook into other OS functions to use and provide interfaces
  352. outside the NDIS wrapper. (Not recommended for the faint of heart).<nl>
  353. NDIS miniports and intermediate drivers carry out two basic tasks in
  354. their <f DriverEntry> functions:<nl>
  355. 1) Call NdisMInitializeWrapper to notify the NDIS library that the
  356. driver is about to register itself as a miniport.
  357. NDIS sets up the state it needs to track the driver and
  358. returns an NdisWrapperHandle, which the driver saves for
  359. subsequent calls to NdisXxx configuration and initialization
  360. functions.<nl>
  361. 2) Fill in an NDISXX_MINIPORT_CHARCTERISTICS structure with the
  362. appropriate version numbers and the entry points for
  363. driver-supplied MiniportXxx functions and, then, call
  364. NdisMRegisterMiniport or NdisIMRegisterLayeredMiniport.
  365. Usually, NIC drivers call NdisMRegisterMiniport, as do
  366. intermediate drivers that export only a set of MiniportXxx
  367. functions. Usually, NDIS intermediate drivers call
  368. NdisIMRegisterLayeredMiniport, which effectively defers the
  369. initialization of such a driver's virtual NIC until the driver
  370. calls NdisIMInitializeDeviceInstance from its
  371. ProtocolBindAdapter function.<nl>
  372. <f DriverEntry> can allocate the NDISXX_MINIPORT_CHARACTERISTICS
  373. structure on the stack since the NDIS library copies the relevant
  374. information to its own storage. DriverEntry should clear the memory
  375. for this structure with NdisZeroMemory before setting any driver-supplied
  376. values in its members. The current MajorNdisVersion is 0x05, and the current
  377. MinorNdisVersion is 0x00. In each XxxHandler member of the
  378. characteristics structure, <f DriverEntry> must set the name of a
  379. driver-supplied MiniportXxx function, or the member must be NULL.
  380. Calling NdisMRegisterMiniport causes the driver's <f MiniportInitialize>
  381. function to run in the context of NdisMRegisterMiniport. Calling
  382. NdisIMRegisterLayeredMiniport defers the call to MiniportInitialize
  383. until the driver calls NdisIMInitializeDeviceInstance.
  384. Drivers that call NdisMRegisterMiniport must be prepared for an
  385. immediate call to their <f MiniportInitialize> functions. Such a driver
  386. must have sufficient installation and configuration information
  387. stored in the registry or available from calls to an NdisXxx
  388. bus-type-specific configuration function to set up any NIC-specific
  389. resources the driver will need to carry out network I/O operations.
  390. Drivers that call NdisIMRegisterLayeredMiniport defer the call to
  391. their <f MiniportInitialize> functions to another driver-supplied
  392. function that makes a call to NdisIMInitializeDeviceInstance.
  393. NDIS intermediate drivers usually register a ProtocolBindAdapter
  394. function and call NdisIMRegisterLayeredMiniport so that NDIS will
  395. call the ProtocolBindAdapter function after all underlying NIC
  396. drivers have initialized. This strategy gives such an NDIS
  397. intermediate driver, which makes the call to
  398. NdisIMInitializeDeviceInstance from ProtocolBindAdapter,
  399. the advantage of having its <f MiniportInitialize> function configure
  400. driver-allocated resources for the intermediate's virtual NIC to
  401. the features of the underlying NIC driver to which the intermediate
  402. has already bound itself.
  403. If NdisMRegisterMiniport or NdisIMRegisterLayeredMiniport does
  404. not return NDIS_STATUS_SUCCESS, <f DriverEntry> must release any
  405. resources it allocated, such as memory to hold the NdisWrapperHandle,
  406. and must call NdisTerminateWrapper before it returns control.
  407. The driver will not be loaded if this occurs.
  408. By default, <f DriverEntry> runs at IRQL PASSIVE_LEVEL in a
  409. system-thread context.
  410. @devnote
  411. The parameters passed to <f DriverEntry> are OS specific! NT passes in valid
  412. values, but Windows 3.1 and Windows 95 just pass in zeros. We don't
  413. care, because we just pass them to the NDIS wrapper anyway.
  414. @rdesc
  415. <f DriverEntry> returns zero if it is successful.<nl>
  416. Otherwise, a non-zero return value indicates an error condition.
  417. @xref
  418. <f MiniportInitialize>
  419. */
  420. NTSTATUS DriverEntry(
  421. IN PDRIVER_OBJECT DriverObject, // @parm
  422. // A pointer to the driver object, which was created by the I/O system.
  423. IN PUNICODE_STRING RegistryPath // @parm
  424. // A pointer to the registry path, which specifies where driver-specific
  425. // parameters are stored.
  426. )
  427. {
  428. DBG_FUNC("DriverEntry")
  429. NDIS_STATUS Status;
  430. // Status result returned from an NDIS function call.
  431. NTSTATUS Result;
  432. // Result code returned by this function.
  433. NDIS_WAN_MINIPORT_CHARACTERISTICS WanCharacteristics;
  434. // Characteristics table passed to NdisMWanRegisterMiniport.
  435. /*
  436. // Setup default debug flags then breakpoint so we can tweak them
  437. // when this module is first loaded. It is also useful to see the
  438. // build date and time to be sure it's the one you think it is.
  439. */
  440. #if DBG
  441. DbgInfo->DbgFlags = DBG_DEFAULTS;
  442. DbgInfo->DbgID[0] = '0';
  443. DbgInfo->DbgID[1] = ':';
  444. ASSERT (sizeof(VER_TARGET_STR) <= sizeof(DbgInfo->DbgID)-2);
  445. memcpy(&DbgInfo->DbgID[2], VER_TARGET_STR, sizeof(VER_TARGET_STR));
  446. #endif // DBG
  447. DBG_PRINT((VER_TARGET_STR": Build Date:"__DATE__" Time:"__TIME__"\n"));
  448. DBG_PRINT((VER_TARGET_STR": DbgInfo=0x%X DbgFlags=0x%X\n",
  449. DbgInfo, DbgInfo->DbgFlags));
  450. DBG_BREAK(DbgInfo);
  451. DBG_ENTER(DbgInfo);
  452. DBG_PARAMS(DbgInfo,
  453. ("\n"
  454. "\t|DriverObject=0x%X\n"
  455. "\t|RegistryPath=0x%X\n",
  456. DriverObject,
  457. RegistryPath
  458. ));
  459. /*
  460. // Initialize the Miniport wrapper - THIS MUST BE THE FIRST NDIS CALL.
  461. */
  462. NdisMInitializeWrapper(
  463. &g_NdisWrapperHandle,
  464. DriverObject,
  465. RegistryPath,
  466. NULL
  467. );
  468. ASSERT(g_NdisWrapperHandle);
  469. /*
  470. // Initialize the characteristics table, exporting the Miniport's entry
  471. // points to the Miniport wrapper.
  472. */
  473. NdisZeroMemory((PVOID)&WanCharacteristics, sizeof(WanCharacteristics));
  474. WanCharacteristics.MajorNdisVersion = NDIS_MAJOR_VERSION;
  475. WanCharacteristics.MinorNdisVersion = NDIS_MINOR_VERSION;
  476. WanCharacteristics.Reserved = NDIS_USE_WAN_WRAPPER;
  477. WanCharacteristics.InitializeHandler = MiniportInitialize;
  478. WanCharacteristics.WanSendHandler = MiniportWanSend;
  479. WanCharacteristics.QueryInformationHandler = MiniportQueryInformation;
  480. WanCharacteristics.SetInformationHandler = MiniportSetInformation;
  481. WanCharacteristics.CheckForHangHandler = MiniportCheckForHang;
  482. WanCharacteristics.ResetHandler = MiniportReset;
  483. WanCharacteristics.HaltHandler = MiniportHalt;
  484. /*
  485. // If the adapter does not generate an interrupt, these entry points
  486. // are not required. Otherwise, you can use the have the ISR routine
  487. // called each time an interupt is generated, or you can use the
  488. // enable/disable routines.
  489. */
  490. #if defined(CARD_REQUEST_ISR)
  491. #if (CARD_REQUEST_ISR == FALSE)
  492. WanCharacteristics.DisableInterruptHandler = MiniportDisableInterrupt;
  493. WanCharacteristics.EnableInterruptHandler = MiniportEnableInterrupt;
  494. #endif // CARD_REQUEST_ISR == FALSE
  495. WanCharacteristics.HandleInterruptHandler = MiniportHandleInterrupt;
  496. WanCharacteristics.ISRHandler = MiniportISR;
  497. #endif // defined(CARD_REQUEST_ISR)
  498. /*
  499. // Register the driver with the Miniport wrapper.
  500. */
  501. Status = NdisMRegisterMiniport(
  502. g_NdisWrapperHandle,
  503. (PNDIS_MINIPORT_CHARACTERISTICS) &WanCharacteristics,
  504. sizeof(WanCharacteristics)
  505. );
  506. /*
  507. // The driver will not load if this call fails.
  508. // The system will log the error for us.
  509. */
  510. if (Status != NDIS_STATUS_SUCCESS)
  511. {
  512. DBG_ERROR(DbgInfo,("Status=0x%X\n",Status));
  513. Result = STATUS_UNSUCCESSFUL;
  514. }
  515. else
  516. {
  517. DBG_NOTICE(DbgInfo,("Status=0x%X\n",Status));
  518. Result = STATUS_SUCCESS;
  519. }
  520. DBG_RETURN(DbgInfo, Result);
  521. return (Result);
  522. }
  523. /* @doc INTERNAL Miniport Miniport_c MiniportInitialize
  524. @func
  525. <f MiniportInitialize> is a required function that sets up a NIC (or
  526. virtual NIC) for network I/O operations, claims all hardware resources
  527. necessary to the NIC in the registry, and allocates resources the driver
  528. needs to carry out network I/O operations.
  529. @comm
  530. NDIS submits no requests to a driver until its initialization
  531. is completed.
  532. In NIC and intermediate drivers that call NdisMRegisterMiniport
  533. from their DriverEntry functions, NDIS calls MiniportInitialize
  534. in the context of NdisMRegisterMiniport. The underlying device
  535. driver must initialize before an intermediate driver that depends
  536. on that device calls NdisMRegisterMiniport.
  537. For NDIS intermediate drivers that export both ProtocolXxx and
  538. MiniportXxx functions and that call NdisIMRegisterLayeredMiniport
  539. from their DriverEntry functions, NDIS calls <f MiniportInitialize>
  540. in the context of NdisIMInitializeDeviceInstance. Such a driver's
  541. ProtocolBindAdapter function usually makes the call to
  542. NdisIMInitializeDeviceInstance.
  543. For NIC drivers, NDIS must find at least the NIC's I/O bus
  544. interface type and, if it is not an ISA bus, the bus number
  545. already installed in the registry by the driver's installation
  546. script. For more information about installing Windows 2000 drivers,
  547. see the Driver Writer's Guide.
  548. The NIC driver obtains configuration information for its
  549. NIC by calling NdisOpenConfiguration and NdisReadConfiguration.
  550. The NIC driver obtains bus-specific information by calling the
  551. appropriate bus-specific function:
  552. Bus Function for Obtaining Bus-Specific Information:<nl>
  553. EISA:<nl>
  554. NdisReadEisaSlotInformation or NdisReadEisaSlotInformationEx
  555. PCI:<nl>
  556. NdisReadPciSlotInformation
  557. PCMCIA:<nl>
  558. NdisReadPcmciaAttributeMemory
  559. The NIC driver for an EISA NIC obtains information on the
  560. hardware resources for its NIC by calling
  561. NdisReadEisaSlotInformation or NdisReadEisaSlotInformationEx.
  562. NIC drivers for PCI NICs and PCMCIA NICs obtain such information
  563. by calling NdisMQueryAdapterResources.
  564. When it calls <f MiniportInitialize>, the NDIS library supplies an
  565. array of supported media types, specified as system-defined
  566. NdisMediumXxx values. <f MiniportInitialize> reads the array
  567. elements and provides the index of the medium type that NDIS
  568. should use with this driver for its NIC. If the miniport is
  569. emulating a medium type, its emulation must be transparent to NDIS.
  570. The <f MiniportInitialize> function of a NIC driver must call
  571. NdisMSetAttributes or NdisMSetAttributesEx before it calls
  572. any NdisXxx function, such as NdisRegisterIoPortRange or NdisMMapIoSpace,
  573. that claims hardware resources in the registry for the NIC.
  574. MiniportInitialize must call NdisMSetAttributes(Ex) before it
  575. attempts to allocate resources for DMA operations as well. If
  576. the NIC is a busmaster, <f MiniportInitialize> must call
  577. NdisMAllocateMapRegisters following its call to
  578. NdisMSetAttributes(Ex) and before it calls NdisMAllocateSharedMemory.
  579. If the NIC is a slave, MiniportInitialize must call
  580. NdisMSetAttributes(Ex) before it calls NdisMRegisterDmaChannel.
  581. Intermediate driver <f MiniportInitialize> functions must call
  582. NdisMSetAttributesEx with NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER
  583. set in the AttributeFlags argument. Setting this flag causes
  584. NDIS to treat every intermediate driver as a full-duplex miniport,
  585. thereby preventing rare but intermittant deadlocks when concurrent
  586. send and receive events occur. Consequently, every intermediate
  587. driver must be written as a full-duplex driver capable of handling
  588. concurrent sends and indications.
  589. If the NDIS library's default four-second time-out interval on
  590. outstanding sends and requests is too short for the driver's NIC,
  591. <f MiniportInitialize> can call NdisMSetAttributesEx to extend the
  592. interval. Every intermediate driver also should call
  593. NdisMSetAttributesEx with NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
  594. and NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT set in the AttributeFlags
  595. so that NDIS will not attempt to time out sends and requests that
  596. NDIS holds queued to the intermediate driver.
  597. The call to NdisMSetAttributes or NdisMSetAttributesEx includes a
  598. MiniportAdapterContext handle to a driver-allocated context area,
  599. in which the miniport maintains runtime state information. NDIS
  600. subsequently passes the supplied <t MiniportAdapterContext> handle as
  601. an input parameter to other MiniportXxx functions.
  602. Consequently, the <f MiniportInitialize> function of an intermediate
  603. driver must call NdisMSetAttributesEx to set up the <t MiniportAdapterContext>
  604. handle for a driver-allocated per-virtual-NIC context area. Otherwise,
  605. NDIS would pass a NULL <t MiniportAdapterContext> handle in its subsequent
  606. calls to the intermediate driver's other MiniportXxx functions.
  607. After a call to NdisMRegisterIoPortRange, a miniport must call
  608. the NdisRawXxx functions with the PortOffset value returned by
  609. NdisMRegisterIoPortRange to communicate with its NIC. The NIC
  610. driver can no longer call the NdisImmediateRead/WritePortXxx
  611. functions. Similarly, after a call to NdisMMapIoSpace, a NIC
  612. driver can no longer call NdisImmediateRead/WriteSharedMemory.
  613. After it has claimed any bus-relative hardware resources for its
  614. NIC in the registry, a miniport should no longer call any
  615. bus-type-specific NdisReadXxx function.
  616. After <f MiniportInitialize> calls NdisMRegisterInterrupt, the driver's
  617. <f MiniportISR> function is called if the driver's NIC generates an
  618. interrupt or if any other device with which the NIC shares an IRQ
  619. interrupts. NDIS does not call the <f MiniportDisableInterrupt> and
  620. <f MiniportEnableInterrupt> functions, if the driver supplied them,
  621. during initialization, so it is such a miniport's responsibility
  622. to acknowledge and clear any interrupts its NIC generates. If the
  623. NIC shares an IRQ, the driver must first determine whether its NIC
  624. generated the interrupt; if not, the miniport must return FALSE as
  625. soon as possible.
  626. If the NIC does not generate interrupts, <f MiniportInitialize> should
  627. call NdisMInitializeTimer with a driver-supplied polling
  628. MiniportTimer function and a pointer to driver-allocated memory
  629. for a timer object. Drivers of NICs that generate interrupts and
  630. intermediate drivers also can set up one or more <f MiniportTimer>
  631. functions, each with its own timer object. <f MiniportInitialize> usually
  632. calls NdisMSetPeriodicTimer to enable a polling <f MiniportTimer> function;
  633. a driver calls NdisMSetTimer subsequently when conditions occur such
  634. that the driver's nonpolling <f MiniportTimer> function should be run.
  635. If the driver subsequently indicates receives with
  636. NdisMIndicateReceivePacket, the MiniportInitialize function
  637. should call NdisAllocatePacketPool and NdisAllocateBufferPool
  638. and save the handles returned by these NDIS functions. The packets
  639. that the driver subsequently indicates with NdisMIndicateReceivePacket
  640. must reference descriptors that were allocated with NdisAllocatePacket
  641. and NdisAllocateBuffer.
  642. If driver functions other than <f MiniportISR> or <f MiniportDisableInterrupt>
  643. share resources, <f MiniportInitialize> should call NdisAllocateSpinLock
  644. to set up any spin lock necessary to synchronize access to such a set
  645. of shared resources, particularly in a full-duplex driver or in a
  646. driver with a polling <f MiniportTimer> function rather than an ISR.
  647. Resources shared by other driver functions with <f MiniportISR> or
  648. <f MiniportDisableInterrupt>, such as NIC registers, are protected
  649. by the interrupt object set up when <f MiniportInitialize> calls
  650. NdisMRegisterInterrupt and accessed subsequently by calling
  651. NdisMSynchronizeWithInterrupt.
  652. Any NIC driver's <f MiniportInitialize> function should test the
  653. NIC to be sure the hardware is configured correctly to carry
  654. out subsequent network I/O operations. If it must wait for
  655. state changes to occur in the hardware, <f MiniportInitialize>
  656. either can call NdisWaitEvent with the pointer to a driver-initialized
  657. event object, or it can call NdisMSleep.
  658. Unless the <f MiniportInitialize> function of a NIC driver will
  659. return an error status, it should call
  660. NdisMRegisterAdapterShutdownHandler with a driver-supplied
  661. MiniportShutdown function.
  662. If <f MiniportInitialize> will fail the initialization, it must
  663. release all resources it has already allocated before it
  664. returns control.
  665. If <f MiniportInitialize> returns NDIS_STATUS_OPEN_ERROR, NDIS can
  666. examine the value returned at OpenErrorStatus to obtain more
  667. information about the error.
  668. When <f MiniportInitialize> returns NDIS_STATUS_SUCCESS, the NDIS
  669. library calls the driver's <f MiniportQueryInformation> function next.
  670. By default, <f MiniportInitialize> runs at IRQL PASSIVE_LEVEL and in
  671. the context of a system thread.
  672. @rdesc
  673. <f MiniportInitialize> can return either of the following:
  674. @flag NDIS_STATUS_SUCCESS |
  675. <f MiniportInitialize> configured and set up the NIC, and it allocated
  676. all the resources the driver needs to carry out network I/O operations.
  677. @flag NDIS_STATUS_FAILURE |
  678. <f MiniportInitialize> could not set up the NIC to an
  679. operational state or could not allocate needed resources.
  680. <f MiniportInitialize> called NdisWriteErrorLogEntry with parameters
  681. specifying the configuration or resource allocation failure.<nl>
  682. As alternatives to NDIS_STATUS_FAILURE, <f MiniportInitialize>
  683. can return one of the following values, as appropriate,
  684. when it fails an initialization:
  685. @flag NDIS_STATUS_UNSUPPORTED_MEDIA |
  686. The values at MediumArray did not include a medium
  687. the driver (or its NIC) can support.
  688. @flag NDIS_STATUS_ADAPTER_NOT_FOUND |
  689. <f MiniportInitialize> did not recognize the NIC either
  690. from its description in the registry, using
  691. NdisOpenConfiguration and NdisReadConfiguration,
  692. or by probing the NIC on a particular I/O bus, using
  693. one of the NdisImmediateXxx or bus-type-specific
  694. NdisXxx configuration functions. This return can be
  695. propagated from the miniport's call to certain NdisXxx
  696. functions, such as NdisOpenConfiguration.
  697. @flag NDIS_STATUS_OPEN_ERROR |
  698. <f MiniportInitialize> attempted to set up a NIC
  699. but was unsuccessful.
  700. @flag NDIS_STATUS_NOT_ACCEPTED |
  701. <f MiniportInitialize> could not get its NIC to
  702. accept the configuration parameters that it got from
  703. the registry or from a bus-type-specific NdisXxx
  704. configuration function.
  705. @flag NDIS_STATUS_RESOURCES |
  706. Either <f MiniportInitialize> could not allocate
  707. sufficient resources to carry out network I/O
  708. operations or an attempt to claim bus-relative
  709. hardware resources in the registry for the NIC
  710. failed. This return can be propagated from the
  711. miniport's call to an NdisXxx function.
  712. If another device has already claimed a
  713. resource in the registry that its NIC needs,
  714. <f MiniportInitialize> also should call
  715. NdisWriteErrorLogEntry to record the
  716. particular resource conflict (I/O port range,
  717. interrupt vector, device memory range, as appropriate).
  718. Supplying an error log record gives the user or system
  719. administrator information that can be used to reconfigure
  720. the machine to avoid such hardware resource conflicts.
  721. @xref
  722. <f DriverEntry>
  723. <f MiniportDisableInterrupt>
  724. <f MiniportEnableInterrupt>
  725. <f MiniportEnableInterrupt>
  726. <f MiniportISR>
  727. <f MiniportQueryInformation>
  728. <f MiniportShutdown>
  729. <f MiniportTimer>
  730. */
  731. NDIS_STATUS MiniportInitialize(
  732. OUT PNDIS_STATUS OpenErrorStatus, // @parm
  733. // Points to a variable that MiniportInitialize sets to an
  734. // NDIS_STATUS_XXX code specifying additional information about the
  735. // error if MiniportInitialize will return NDIS_STATUS_OPEN_ERROR.
  736. OUT PUINT SelectedMediumIndex, // @parm
  737. // Points to a variable in which MiniportInitialize sets the index of
  738. // the MediumArray element that specifies the medium type the driver
  739. // or its NIC uses.
  740. IN PNDIS_MEDIUM MediumArray, // @parm
  741. // Specifies an array of NdisMediumXxx values from which
  742. // MiniportInitialize selects one that its NIC supports or that the
  743. // driver supports as an interface to higher-level drivers.
  744. IN UINT MediumArraySize, // @parm
  745. // Specifies the number of elements at MediumArray.
  746. IN NDIS_HANDLE MiniportAdapterHandle, // @parm
  747. // Specifies a handle identifying the miniport's NIC, which is assigned
  748. // by the NDIS library. MiniportInitialize should save this handle; it
  749. // is a required parameter in subsequent calls to NdisXxx functions.
  750. IN NDIS_HANDLE WrapperConfigurationContext // @parm
  751. // Specifies a handle used only during initialization for calls to
  752. // NdisXxx configuration and initialization functions. For example,
  753. // this handle is a required parameter to NdisOpenConfiguration and
  754. // the NdisImmediateReadXxx and NdisImmediateWriteXxx functions.
  755. )
  756. {
  757. DBG_FUNC("MiniportInitialize")
  758. NDIS_STATUS Status;
  759. // Status result returned from an NDIS function call.
  760. PMINIPORT_ADAPTER_OBJECT pAdapter;
  761. // Pointer to our newly allocated object.
  762. UINT Index;
  763. // Loop counter.
  764. DBG_ENTER(DbgInfo);
  765. DBG_PARAMS(DbgInfo,
  766. ("\n"
  767. "\t|OpenErrorStatus=0x%X\n"
  768. "\t|SelectedMediumIndex=0x%X\n"
  769. "\t|MediumArray=0x%X\n"
  770. "\t|MediumArraySize=0x%X\n"
  771. "\t|MiniportAdapterHandle=0x%X\n"
  772. "\t|WrapperConfigurationContext=0x%X\n",
  773. OpenErrorStatus,
  774. SelectedMediumIndex,
  775. MediumArray,
  776. MediumArraySize,
  777. MiniportAdapterHandle,
  778. WrapperConfigurationContext
  779. ));
  780. /*
  781. // Search the MediumArray for the NdisMediumWan media type.
  782. */
  783. for (Index = 0; Index < MediumArraySize; Index++)
  784. {
  785. if (MediumArray[Index] == NdisMediumWan)
  786. {
  787. break;
  788. }
  789. }
  790. /*
  791. // Make sure the protocol has requested the proper media type.
  792. */
  793. if (Index < MediumArraySize)
  794. {
  795. /*
  796. // Allocate memory for the adapter information structure.
  797. */
  798. Status = AdapterCreate(
  799. &pAdapter,
  800. MiniportAdapterHandle,
  801. WrapperConfigurationContext
  802. );
  803. if (Status == NDIS_STATUS_SUCCESS)
  804. {
  805. /*
  806. // Now it's time to initialize the hardware resources.
  807. */
  808. Status = AdapterInitialize(pAdapter);
  809. if (Status == NDIS_STATUS_SUCCESS)
  810. {
  811. /*
  812. // Save the selected media type.
  813. */
  814. *SelectedMediumIndex = Index;
  815. }
  816. else
  817. {
  818. /*
  819. // Something went wrong, so let's make sure everything is
  820. // cleaned up.
  821. */
  822. MiniportHalt(pAdapter);
  823. }
  824. }
  825. }
  826. else
  827. {
  828. DBG_ERROR(DbgInfo,("No NdisMediumWan found (Array=0x%X, ArraySize=%d)\n",
  829. MediumArray, MediumArraySize));
  830. /*
  831. // Log error message and return.
  832. */
  833. NdisWriteErrorLogEntry(
  834. MiniportAdapterHandle,
  835. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  836. 3,
  837. Index,
  838. __FILEID__,
  839. __LINE__
  840. );
  841. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  842. }
  843. /*
  844. // If all goes well, register a shutdown handler for this adapter.
  845. */
  846. if (Status == NDIS_STATUS_SUCCESS)
  847. {
  848. NdisMRegisterAdapterShutdownHandler(MiniportAdapterHandle,
  849. pAdapter, MiniportShutdown);
  850. }
  851. DBG_NOTICE(DbgInfo,("Status=0x%X\n",Status));
  852. DBG_RETURN(DbgInfo, Status);
  853. return (Status);
  854. }
  855. /* @doc INTERNAL Miniport Miniport_c MiniportHalt
  856. @func
  857. <f MiniportHalt> request is used to halt the adapter such that it is
  858. no longer functioning.
  859. @comm
  860. <f MiniportHalt> should stop the NIC, if it controls a physical
  861. NIC, and must free all resources that the driver allocated for
  862. it's NIC before <f MiniportHalt> returns control. In effect,
  863. <f MiniportHalt> undoes everything that was done by <f MiniportInitialize>
  864. for a particular NIC.
  865. If the NIC driver allocated memory, claimed an I/O port range,
  866. mapped on-board device memory to host memory, initialized timer(s)
  867. and/or spin lock(s), allocated map registers or claimed a DMA channel,
  868. and registered an interrupt, that driver must call the reciprocals of the
  869. NdisXxx functions with which it originally allocated these resources.
  870. As a general rule, a <f MiniportHalt> function should call reciprocal
  871. NdisXxx functions in inverse order to the calls the driver made from
  872. <f MiniportInitialize>. That is, if a NIC driver's <f MiniportInitialize>
  873. function called NdisMRegisterAdapterShutdownHandler just before
  874. it returned control, its <f MiniportHalt> function would call
  875. NdisMDeregisterAdapterShutdownHandler first.
  876. If its NIC generates interrupts or shares an IRQ, a NIC driver's
  877. <f MiniportHalt> function can be pre-empted by its <f MiniportISR> or
  878. <f MiniportDisableInterrupt> function until <f MiniportHalt> calls
  879. NdisMDeregisterInterrupt. Such a driver's <f MiniportHalt>
  880. function usually disables interrupts on the NIC, if
  881. possible, and calls NdisMDeregisterInterrupt as soon
  882. as it can.
  883. If the driver has a <f MiniportTimer> function associated
  884. with any timer object that might be in the system timer
  885. queue, <f MiniportHalt> should call NdisMCancelTimer.
  886. Otherwise, it is unnecessary for the miniport to complete
  887. outstanding requests to its NIC before <f MiniportHalt> begins
  888. releasing allocated resources. NDIS submits no further
  889. requests to the miniport for the NIC designated by the
  890. MiniportAdapterContext handle when NDIS has called <f MiniportHalt>.
  891. On return from <f MiniportHalt>, NDIS cleans up any state it was
  892. maintaining about this NIC and about its driver if this
  893. miniport supports no other NICs in the current machine.
  894. An NDIS intermediate driver's call to
  895. NdisIMDeinitializeDeviceInstance causes a
  896. call to it's <f MiniportHalt> function.
  897. By default, <f MiniportHalt> runs at IRQL PASSIVE_LEVEL.
  898. Interrupts are enabled during the call to this routine.
  899. @xref
  900. <f MiniportInitialize>
  901. <f MiniportShutdown>
  902. */
  903. VOID MiniportHalt(
  904. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  905. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  906. )
  907. {
  908. DBG_FUNC("MiniportHalt")
  909. NDIS_TAPI_PROVIDER_SHUTDOWN TapiShutDown;
  910. // We use this message to make sure TAPI is cleaned up.
  911. ULONG DummyLong;
  912. // Don't care about the return value.
  913. DBG_ENTER(DbgInfo);
  914. /*
  915. // Remove our shutdown handler from the system.
  916. */
  917. NdisMDeregisterAdapterShutdownHandler(pAdapter->MiniportAdapterHandle);
  918. /*
  919. // Make sure all the lines are hungup and indicated.
  920. // This should already be the case, but let's be sure.
  921. */
  922. TapiShutDown.ulRequestID = OID_TAPI_PROVIDER_SHUTDOWN;
  923. TspiProviderShutdown(pAdapter, &TapiShutDown, &DummyLong, &DummyLong);
  924. /*
  925. // Free adapter instance.
  926. */
  927. AdapterDestroy(pAdapter);
  928. DBG_LEAVE(DbgInfo);
  929. }
  930. /* @doc INTERNAL Miniport Miniport_c MiniportShutdown
  931. @func
  932. <f MiniportShutdown> is an optional function that restores a NIC to its
  933. initial state when the system is shut down, whether by the user or because
  934. an unrecoverable system error occurred.
  935. @comm
  936. Every NIC driver should have a <f MiniportShutdown> function.
  937. <f MiniportShutdown> does nothing more than restore the NIC
  938. to its initial state (before the miniport's <f DriverEntry>
  939. function runs). However, this ensures that the NIC is in a
  940. known state and ready to be reinitialized when the machine is
  941. rebooted after a system shutdown occurs for any reason,
  942. including a crash dump.
  943. A NIC driver's <f MiniportInitialize> function must call
  944. NdisMRegisterAdapterShutdownHandler to set up a <f MiniportShutdown>
  945. function. The driver's <f MiniportHalt> function must make a
  946. reciprocal call to NdisMDeregisterAdapterShutdownHandler.
  947. If <f MiniportShutdown> is called due to a user-initiated
  948. system shutdown, it runs at IRQL PASSIVE_LEVEL in a
  949. system-thread context. If it is called due to an
  950. unrecoverable error, <f MiniportShutdown> runs at an
  951. arbitrary IRQL and in the context of whatever component
  952. raised the error. For example, <f MiniportShutdown> might be
  953. run at high DIRQL in the context of an ISR for a device
  954. essential to continued execution of the system.
  955. <f MiniportShutdown> should call no NdisXxx functions.
  956. @xref
  957. <f MiniportHalt>
  958. <f MiniportInitialize>
  959. */
  960. VOID MiniportShutdown(
  961. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  962. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  963. // This was supplied when the NIC driver's <f MiniportInitialize>
  964. // function called NdisMRegisterAdapterShutdownHandler. Usually,
  965. // this input parameter is the NIC-specific <t MINIPORT_ADAPTER_CONTEXT>
  966. // pointer passed to other MiniportXxx functions
  967. )
  968. {
  969. DBG_FUNC("MiniportShutdown")
  970. DBG_ENTER(pAdapter);
  971. /*
  972. // Reset the hardware and bial out - don't release any resources!
  973. */
  974. CardReset(pAdapter->pCard);
  975. DBG_LEAVE(pAdapter);
  976. }
  977. /* @doc INTERNAL Miniport Miniport_c MiniportReset
  978. @func
  979. <f MiniportReset> request instructs the Miniport to issue a hardware
  980. reset to the network adapter. The Miniport also resets its software
  981. state.
  982. @comm
  983. <f MiniportReset> can reset the parameters of its NIC. If a reset
  984. causes a change in the NIC's station address, the miniport
  985. automatically restores the station address following the reset
  986. to its prior value. Any multicast or functional addressing masks
  987. reset by the hardware do not have to be reset in this function.
  988. If other information, such as multicast or functional addressing
  989. information or the lookahead size, is changed by a reset,
  990. <f MiniportReset> must set the variable at AddressingReset to TRUE
  991. before it returns control. This causes NDIS to call the
  992. <f MiniportSetInformation> function to restore the information.
  993. As a general rule, the <f MiniportReset> function of an NDIS
  994. intermediate driver should always set AddressingReset to TRUE.
  995. Until the underlying NIC driver resets its NIC, such an intermediate
  996. driver cannot determine whether it must restore addressing
  997. information for its virtual NIC. Because an intermediate driver
  998. disables the NDIS library's timing out of queued sends and requests
  999. to itself with an initialization-time call to NdisMSetAttributesEx,
  1000. such a driver's <f MiniportReset> function is called only when a reset
  1001. request is directed to the underlying NIC driver.
  1002. Intermediate drivers that layer themselves above other types of
  1003. device drivers also must have a <f MiniportReset> function. Such a
  1004. <f MiniportReset> function must handle reset requests initiated by
  1005. protocol drivers' calls to NdisReset. If the intermediate driver
  1006. also has a <f MiniportCheckForHang> function, its <f MiniportReset> function
  1007. will be called whenever MiniportCheckForHang returns TRUE.
  1008. It is unnecessary for a driver to complete outstanding requests
  1009. before <f MiniportReset> begins resetting the NIC or updating its
  1010. software state. NDIS submits no further requests to the miniport
  1011. for the NIC designated by the <t MINIPORT_ADAPTER_CONTEXT> handle when
  1012. NDIS has called <f MiniportReset> until the reset operation is completed.
  1013. A miniport need not call NdisM(Co)IndicateStatus to signal the start
  1014. and finish of each reset operation because NDIS notifies bound
  1015. protocols when a reset begins and ends.
  1016. If <f MiniportReset> must wait for state changes in the NIC during
  1017. reset operations, it can call NdisStallExecution. However, a
  1018. MiniportReset function should never call NdisStallExecution
  1019. with an interval greater than 50 microseconds.
  1020. If <f MiniportReset> returns NDIS_STATUS_PENDING, the driver must
  1021. complete the original request subsequently with a call to
  1022. NdisMResetComplete.
  1023. <f MiniportReset> can be pre-empted by an interrupt.
  1024. If a NIC driver supplies a <f MiniportCheckForHang> function,
  1025. the NDIS library calls it periodically to determine whether
  1026. to call the driver's <f MiniportReset> function. Otherwise, the
  1027. NDIS library calls a NIC driver's <f MiniportReset> function whenever
  1028. requests NDIS submitted to the <f MiniportQueryInformation>,
  1029. <f MiniportSetInformation>, MiniportSendPackets, MiniportSend,
  1030. or <f MiniportWanSend> function seem to have timed out. (NDIS does
  1031. not call a deserialized NIC driver's <f MiniportReset> function if
  1032. the driver's MiniportSend or MiniportSendPackets function seems
  1033. to have timed out, nor does NDIS call a connection-oriented NIC
  1034. driver's <f MiniportReset> function if the driver's MiniportCoSendPackets
  1035. function seems to have timed out.) By default, the NDIS-determined
  1036. time-out interval for outstanding sends and requests is around
  1037. four seconds. If this default is too short, a NIC driver can make
  1038. an initialization-time call to NdisMSetAttributesEx, rather than
  1039. NdisMSetAttributes, to lengthen the time-out interval to suit its NIC.
  1040. Every NDIS intermediate driver should call NdisMSetAttributesEx
  1041. from <f MiniportInitialize> and disable NDIS's attempts to time out
  1042. requests and sends in the intermediate driver. NDIS runs an
  1043. intermediate driver's <f MiniportCheckForHang> function, if any,
  1044. approximately every two seconds.
  1045. NDIS cannot determine whether a NIC might be hung on receives,
  1046. so supplying a <f MiniportCheckForHang> function allows a driver to
  1047. monitor its NIC for this condition and to force a reset if it occurs.
  1048. By default, MiniportReset runs at IRQL DISPATCH_LEVEL.
  1049. @devnote
  1050. I have only seen MiniportReset called when the driver is not working
  1051. properly. If this gets called, your code is probably broken, so fix
  1052. it. Don't try to recover here unless there is some hardware/firmware
  1053. problem you must work around.
  1054. @rdesc
  1055. <f MiniportReset> allways returns <f NDIS_STATUS_HARD_ERRORS>.
  1056. @xref
  1057. <f MiniportCheckForHang>
  1058. <f MiniportInitialize>
  1059. <f MiniportQueryInformation>
  1060. <f MiniportSetInformation>
  1061. <f MiniportWanSend>
  1062. */
  1063. NDIS_STATUS MiniportReset(
  1064. OUT PBOOLEAN AddressingReset, // @parm
  1065. // The Miniport indicates if the wrapper needs to call
  1066. // <f MiniportSetInformation> to restore the addressing information
  1067. // to the current values by setting this value to TRUE.
  1068. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  1069. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  1070. )
  1071. {
  1072. DBG_FUNC("MiniportReset")
  1073. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  1074. // Result code returned by this function.
  1075. DBG_ENTER(pAdapter);
  1076. DBG_ERROR(pAdapter,("##### !!! THIS SHOULD NEVER BE CALLED !!! #####\n"));
  1077. /*
  1078. // If anything goes wrong here, it's very likely an unrecoverable
  1079. // hardware failure. So we'll just shut this thing down for good.
  1080. */
  1081. Result = NDIS_STATUS_HARD_ERRORS;
  1082. *AddressingReset = TRUE;
  1083. return (Result);
  1084. }