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.

327 lines
10 KiB

  1. /*****************************************************************************
  2. * adapter.cpp - MPU401 adapter driver implementation.
  3. *****************************************************************************
  4. * Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved.
  5. *
  6. * Created 6/19/97, a-seemap
  7. *
  8. */
  9. //
  10. // All the GUIDS for all the miniports end up in this object.
  11. //
  12. #define PUT_GUIDS_HERE
  13. #define STR_MODULENAME "MPU401Adapter: "
  14. #define PC_NEW_NAMES 1
  15. #define kUseDMusicMiniport 1
  16. #include "portcls.h"
  17. #include "ksdebug.h"
  18. #if (kUseDMusicMiniport)
  19. #include "dmusicks.h"
  20. #endif // kUseDMusicMiniport
  21. /*****************************************************************************
  22. * Defines
  23. */
  24. #define MAX_MINIPORTS 1
  25. #if (DBG)
  26. #define SUCCEEDS(s) ASSERT(NT_SUCCESS(s))
  27. #else
  28. #define SUCCEEDS(s) (s)
  29. #endif
  30. /*****************************************************************************
  31. * Referenced forward
  32. */
  33. extern "C"
  34. NTSTATUS
  35. AddDevice
  36. (
  37. IN PVOID Context1,
  38. IN PVOID Context2
  39. );
  40. NTSTATUS
  41. StartDevice
  42. (
  43. IN PDEVICE_OBJECT pDeviceObject, // Context for the class driver.
  44. IN PIRP pIrp, // Context for the class driver.
  45. IN PRESOURCELIST ResourceList // List of hardware resources.
  46. );
  47. #pragma code_seg("INIT")
  48. /*****************************************************************************
  49. * DriverEntry()
  50. *****************************************************************************
  51. * This function is called by the operating system when the driver is loaded.
  52. * All adapter drivers can use this code without change.
  53. */
  54. extern "C"
  55. NTSTATUS
  56. DriverEntry
  57. (
  58. IN PVOID Context1, // Context for the class driver.
  59. IN PVOID Context2 // Context for the class driver.
  60. )
  61. {
  62. PAGED_CODE();
  63. _DbgPrintF(DEBUGLVL_VERBOSE, ("DriverEntry"));
  64. // _DbgPrintF(DEBUGLVL_ERROR, ("Starting breakpoint for debugging"));
  65. //
  66. // Tell the class driver to initialize the driver.
  67. //
  68. return PcInitializeAdapterDriver((PDRIVER_OBJECT)Context1,
  69. (PUNICODE_STRING)Context2,
  70. (PDRIVER_ADD_DEVICE)AddDevice);
  71. }
  72. #pragma code_seg("PAGE")
  73. /*****************************************************************************
  74. * AddDevice()
  75. *****************************************************************************
  76. * This function is called by the operating system when the device is added.
  77. * All adapter drivers can use this code without change.
  78. */
  79. NTSTATUS
  80. AddDevice
  81. (
  82. IN PVOID Context1, // Context for the class driver.
  83. IN PVOID Context2 // Context for the class driver.
  84. )
  85. {
  86. PAGED_CODE();
  87. _DbgPrintF(DEBUGLVL_VERBOSE, ("AddDevice"));
  88. //
  89. // Tell the class driver to add the device.
  90. //
  91. return PcAddAdapterDevice((PDRIVER_OBJECT)Context1,(PDEVICE_OBJECT)Context2,StartDevice,MAX_MINIPORTS,0);
  92. }
  93. #pragma code_seg("PAGE")
  94. /*****************************************************************************
  95. * InstallSubdevice()
  96. *****************************************************************************
  97. * This function creates and registers a subdevice consisting of a port
  98. * driver, a minport driver and a set of resources bound together. It will
  99. * also optionally place a pointer to an interface on the port driver in a
  100. * specified location before initializing the port driver. This is done so
  101. * that a common ISR can have access to the port driver during initialization,
  102. * when the ISR might fire.
  103. */
  104. NTSTATUS
  105. InstallSubdevice
  106. (
  107. IN PVOID Context1,
  108. IN PVOID Context2,
  109. IN PWCHAR Name,
  110. IN REFGUID PortClassId,
  111. IN REFGUID MiniportClassId,
  112. IN PUNKNOWN UnknownAdapter OPTIONAL, //not used - null
  113. IN PRESOURCELIST ResourceList, //not optional, but can be EMPTY!
  114. IN REFGUID PortInterfaceId,
  115. OUT PUNKNOWN * OutPortInterface, OPTIONAL //not used - null
  116. OUT PUNKNOWN * OutPortUnknown OPTIONAL //not used - null
  117. )
  118. {
  119. PAGED_CODE();
  120. _DbgPrintF(DEBUGLVL_VERBOSE, ("InstallSubdevice"));
  121. ASSERT(Context1);
  122. ASSERT(Context2);
  123. ASSERT(Name);
  124. ASSERT(ResourceList);
  125. //
  126. // Create the port driver object
  127. //
  128. PPORT port;
  129. NTSTATUS ntStatus = PcNewPort(&port,PortClassId);
  130. if (NT_SUCCESS(ntStatus))
  131. {
  132. //
  133. // Deposit the port somewhere if it's needed.
  134. //
  135. if (OutPortInterface)
  136. {
  137. //
  138. // Failure here doesn't cause the entire routine to fail.
  139. //
  140. (void) port->QueryInterface
  141. (
  142. PortInterfaceId,
  143. (PVOID *) OutPortInterface
  144. );
  145. }
  146. PMINIPORT miniport;
  147. //
  148. // Create the miniport object
  149. //
  150. ntStatus = PcNewMiniport(&miniport,MiniportClassId);
  151. if (NT_SUCCESS(ntStatus))
  152. {
  153. //
  154. // Init the port driver and miniport in one go.
  155. //
  156. ntStatus = port->Init( (PDEVICE_OBJECT)Context1,
  157. (PIRP)Context2,
  158. miniport,
  159. NULL, // interruptsync created in miniport.
  160. ResourceList);
  161. if (NT_SUCCESS(ntStatus))
  162. {
  163. //
  164. // Register the subdevice (port/miniport combination).
  165. //
  166. ntStatus = PcRegisterSubdevice( (PDEVICE_OBJECT)Context1,
  167. Name,
  168. port );
  169. if (!(NT_SUCCESS(ntStatus)))
  170. {
  171. _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: PcRegisterSubdevice failed"));
  172. }
  173. }
  174. else
  175. {
  176. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: port->Init failed"));
  177. }
  178. //
  179. // We don't need the miniport any more. Either the port has it,
  180. // or we've failed, and it should be deleted.
  181. //
  182. miniport->Release();
  183. }
  184. else
  185. {
  186. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewMiniport failed"));
  187. }
  188. if (NT_SUCCESS(ntStatus))
  189. {
  190. //
  191. // Deposit the port as an unknown if it's needed.
  192. //
  193. if (OutPortUnknown)
  194. {
  195. //
  196. // Failure here doesn't cause the entire routine to fail.
  197. //
  198. (void) port->QueryInterface
  199. (
  200. IID_IUnknown,
  201. (PVOID *) OutPortUnknown
  202. );
  203. }
  204. }
  205. else
  206. {
  207. //
  208. // Retract previously delivered port interface.
  209. //
  210. if (OutPortInterface && (*OutPortInterface))
  211. {
  212. (*OutPortInterface)->Release();
  213. *OutPortInterface = NULL;
  214. }
  215. }
  216. //
  217. // Release the reference which existed when PcNewPort() gave us the
  218. // pointer in the first place. This is the right thing to do
  219. // regardless of the outcome.
  220. //
  221. port->Release();
  222. }
  223. else
  224. {
  225. _DbgPrintF(DEBUGLVL_TERSE, ("InstallSubdevice: PcNewPort failed"));
  226. }
  227. return ntStatus;
  228. }
  229. #pragma code_seg("PAGE")
  230. /*****************************************************************************
  231. * StartDevice()
  232. *****************************************************************************
  233. * This function is called by the operating system when the device is started.
  234. * It is responsible for starting the miniport.
  235. * This code is specific to the adapter because it calls out miniports for
  236. * functions that are specific to the adapter.
  237. */
  238. NTSTATUS
  239. StartDevice
  240. (
  241. IN PDEVICE_OBJECT pDeviceObject, // Context for the class driver.
  242. IN PIRP pIrp, // Context for the class driver.
  243. IN PRESOURCELIST ResourceList // List of hardware resources.
  244. )
  245. {
  246. PAGED_CODE();
  247. ASSERT(pDeviceObject);
  248. ASSERT(pIrp);
  249. ASSERT(ResourceList);
  250. if (!ResourceList)
  251. {
  252. _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: NULL resource list"));
  253. return STATUS_INVALID_PARAMETER;
  254. }
  255. NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  256. if (ResourceList->NumberOfEntries())
  257. {
  258. #if (kUseDMusicMiniport)
  259. //
  260. // Start the UART miniport.
  261. //
  262. ntStatus = InstallSubdevice(
  263. pDeviceObject,
  264. pIrp,
  265. L"Uart",
  266. CLSID_PortDMus,
  267. CLSID_MiniportDriverDMusUART,
  268. NULL,
  269. ResourceList,
  270. IID_IPortDMus,
  271. NULL,
  272. NULL // Not physically connected to anything.
  273. );
  274. #else // (kUseDMusicMiniport)
  275. //
  276. // Start the UART miniport.
  277. //
  278. ntStatus = InstallSubdevice(
  279. pDeviceObject,
  280. pIrp,
  281. L"Uart",
  282. CLSID_PortMidi,
  283. CLSID_MiniportDriverUart,
  284. NULL,
  285. ResourceList,
  286. IID_IPortMidi,
  287. NULL,
  288. NULL // Not physically connected to anything.
  289. );
  290. #endif // (kUseDMusicMiniport)
  291. }
  292. else
  293. {
  294. _DbgPrintF(DEBUGLVL_TERSE, ("StartDevice: no entries in resource list"));
  295. }
  296. return ntStatus;
  297. }