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.

519 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. smbhc.c
  5. Abstract:
  6. SMB Host Controller Driver
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "smbhcp.h"
  14. ULONG SMBHCDebug = 0x0;
  15. //
  16. // Prototypes
  17. //
  18. typedef struct {
  19. ULONG Base;
  20. ULONG Query;
  21. } NEW_HC_DEVICE, *PNEW_HC_DEVICE;
  22. NTSTATUS
  23. DriverEntry(
  24. IN PDRIVER_OBJECT DriverObject,
  25. IN PUNICODE_STRING RegistryPath
  26. );
  27. NTSTATUS
  28. SmbHcAddDevice(
  29. IN PDRIVER_OBJECT DriverObject,
  30. IN PDEVICE_OBJECT Pdo
  31. );
  32. NTSTATUS
  33. SmbHcNewHc (
  34. IN PSMB_CLASS SmbClass,
  35. IN PVOID Extension,
  36. IN PVOID Context
  37. );
  38. NTSTATUS
  39. SmbHcSynchronousRequest (
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP Irp,
  42. IN PVOID Context
  43. );
  44. NTSTATUS
  45. SmbHcResetDevice (
  46. IN struct _SMB_CLASS *SmbClass,
  47. IN PVOID SmbMiniport
  48. );
  49. NTSTATUS
  50. SmbHcStopDevice (
  51. IN struct _SMB_CLASS *SmbClass,
  52. IN PVOID SmbMiniport
  53. );
  54. #ifdef ALLOC_PRAGMA
  55. #pragma alloc_text(INIT,DriverEntry)
  56. #pragma alloc_text(PAGE,SmbHcAddDevice)
  57. #pragma alloc_text(PAGE,SmbHcResetDevice)
  58. #pragma alloc_text(PAGE,SmbHcStopDevice)
  59. #pragma alloc_text(PAGE,SmbHcNewHc)
  60. #pragma alloc_text(PAGE,SmbHcSynchronousRequest)
  61. #endif
  62. NTSTATUS
  63. DriverEntry(
  64. IN PDRIVER_OBJECT DriverObject,
  65. IN PUNICODE_STRING RegistryPath
  66. )
  67. /*++
  68. Routine Description:
  69. This routine initializes the SM Bus Host Controller Driver
  70. Arguments:
  71. DriverObject - Pointer to driver object created by system.
  72. RegistryPath - Pointer to the Unicode name of the registry path
  73. for this driver.
  74. Return Value:
  75. The function value is the final status from the initialization operation.
  76. --*/
  77. {
  78. NTSTATUS Status;
  79. //
  80. // Have class driver allocate a new SMB miniport device
  81. //
  82. Status = SmbClassInitializeDevice (
  83. SMB_HC_MAJOR_VERSION,
  84. SMB_HC_MINOR_VERSION,
  85. DriverObject
  86. );
  87. //
  88. // AddDevice comes directly to this miniport
  89. //
  90. DriverObject->DriverExtension->AddDevice = SmbHcAddDevice;
  91. return (Status);
  92. }
  93. NTSTATUS
  94. SmbHcAddDevice(
  95. IN PDRIVER_OBJECT DriverObject,
  96. IN PDEVICE_OBJECT Pdo
  97. )
  98. /*++
  99. Routine Description:
  100. This routine creates functional device objects for each SmbHc controller in the
  101. system and attaches them to the physical device objects for the controllers
  102. Arguments:
  103. DriverObject - a pointer to the object for this driver
  104. PhysicalDeviceObject - a pointer to the physical object we need to attach to
  105. Return Value:
  106. Status from device creation and initialization
  107. --*/
  108. {
  109. NTSTATUS status;
  110. PDEVICE_OBJECT fdo = NULL;
  111. PAGED_CODE();
  112. SmbPrint(SMB_LOW, ("SmbHcAddDevice Entered with pdo %x\n", Pdo));
  113. if (Pdo == NULL) {
  114. //
  115. // Have we been asked to do detection on our own?
  116. // if so just return no more devices
  117. //
  118. SmbPrint(SMB_LOW, ("SmbHcAddDevice - asked to do detection\n"));
  119. return STATUS_NO_MORE_ENTRIES;
  120. }
  121. //
  122. // Create and initialize the new functional device object
  123. //
  124. status = SmbClassCreateFdo(
  125. DriverObject,
  126. Pdo,
  127. sizeof (SMB_DATA),
  128. SmbHcNewHc,
  129. NULL,
  130. &fdo
  131. );
  132. if (!NT_SUCCESS(status) || fdo == NULL) {
  133. SmbPrint(SMB_LOW, ("SmbHcAddDevice - error creating Fdo. Status = %08x\n", status));
  134. }
  135. return status;
  136. }
  137. NTSTATUS
  138. SmbHcNewHc (
  139. IN PSMB_CLASS SmbClass,
  140. IN PVOID Extension,
  141. IN PVOID Context
  142. )
  143. /*++
  144. Routine Description:
  145. This function is called by the smb bus class driver for the
  146. miniport to perform miniport specific initialization
  147. Arguments:
  148. SmbClass - Shared class driver & miniport structure.
  149. Extension - Buffer for miniport specific storage
  150. Context - Passed through class driver
  151. Return Value:
  152. Status
  153. --*/
  154. {
  155. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  156. ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  157. IO_STATUS_BLOCK ioStatusBlock;
  158. KEVENT event;
  159. NTSTATUS status;
  160. PACPI_METHOD_ARGUMENT argument;
  161. PIRP irp;
  162. PSMB_DATA smbData;
  163. ULONG cmReturn;
  164. PAGED_CODE();
  165. SmbPrint(SMB_LOW, ("SmbHcNewHc: Entry\n") );
  166. smbData = (PSMB_DATA) Extension;
  167. //
  168. // Fill in SmbClass info
  169. //
  170. SmbClass->StartIo = SmbHcStartIo;
  171. SmbClass->ResetDevice = SmbHcResetDevice;
  172. SmbClass->StopDevice = SmbHcStopDevice;
  173. //
  174. // Lower device is the EC driver, but we will use the ACPI PDO, since
  175. // the ACPI filter driver will pass it thru.
  176. //
  177. smbData->Pdo = SmbClass->PDO;
  178. smbData->LowerDeviceObject = SmbClass->LowerDeviceObject; // ACPI filter will handle it
  179. //
  180. // Initialize the input parameters
  181. //
  182. RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
  183. inputBuffer.MethodNameAsUlong = CM_EC_METHOD;
  184. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  185. //
  186. // Initialize the even to wait on
  187. //
  188. KeInitializeEvent( &event, NotificationEvent, FALSE);
  189. //
  190. // Build the synchronouxe request
  191. //
  192. irp = IoBuildDeviceIoControlRequest(
  193. IOCTL_ACPI_ASYNC_EVAL_METHOD,
  194. SmbClass->LowerDeviceObject,
  195. &inputBuffer,
  196. sizeof(ACPI_EVAL_INPUT_BUFFER),
  197. &outputBuffer,
  198. sizeof(ACPI_EVAL_OUTPUT_BUFFER),
  199. FALSE,
  200. &event,
  201. &ioStatusBlock
  202. );
  203. if (!irp) {
  204. SmbPrint(SMB_ERROR, ("SmbHcNewHc: Couldn't allocate Irp\n"));
  205. return STATUS_INSUFFICIENT_RESOURCES;
  206. }
  207. //
  208. // Send to ACPI driver
  209. //
  210. status = IoCallDriver (smbData->LowerDeviceObject, irp);
  211. if (status == STATUS_PENDING) {
  212. KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL);
  213. status = ioStatusBlock.Status;
  214. }
  215. argument = outputBuffer.Argument;
  216. if (!NT_SUCCESS(status) ||
  217. outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
  218. outputBuffer.Count == 0 ||
  219. argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
  220. SmbPrint(SMB_LOW, ("SmbHcNewHc: _EC Control Method failed, status = %Lx\n", status));
  221. return status;
  222. }
  223. //
  224. // Remember the result
  225. //
  226. cmReturn = argument->Argument;
  227. //
  228. // Fill in miniport info
  229. //
  230. smbData->Class = SmbClass;
  231. smbData->IoState = SMB_IO_IDLE;
  232. smbData->EcQuery = (UCHAR) cmReturn; // Per ACPI Spec, LSB=Query
  233. smbData->EcBase = (UCHAR) (cmReturn >> 8); // Per ACPI Spec, MSB=Base
  234. SmbPrint(SMB_LOW, ("SmbHcNewHc: Exit\n"));
  235. return status;
  236. }
  237. NTSTATUS
  238. SmbHcSynchronousRequest (
  239. IN PDEVICE_OBJECT DeviceObject,
  240. IN PIRP Irp,
  241. IN PVOID Context
  242. )
  243. /*++
  244. Routine Description:
  245. Completion function for synchronous IRPs sent to this driver.
  246. Context is the event to set
  247. --*/
  248. {
  249. PAGED_CODE();
  250. return STATUS_MORE_PROCESSING_REQUIRED;
  251. }
  252. NTSTATUS
  253. SmbHcResetDevice (
  254. IN struct _SMB_CLASS *SmbClass,
  255. IN PVOID SmbMiniport
  256. )
  257. {
  258. EC_HANDLER_REQUEST queryConnect;
  259. PSMB_DATA smbData;
  260. KEVENT event;
  261. NTSTATUS status;
  262. IO_STATUS_BLOCK ioStatusBlock;
  263. PIRP irp;
  264. SmbPrint(SMB_LOW, ("SmbHcResetDevice: Entry\n") );
  265. PAGED_CODE();
  266. smbData = (PSMB_DATA) SmbMiniport;
  267. //
  268. // Initialize the even to wait on
  269. //
  270. KeInitializeEvent( &event, NotificationEvent, FALSE);
  271. //
  272. // Build the input data to the EC
  273. //
  274. queryConnect.Vector = smbData->EcQuery;
  275. queryConnect.Handler = SmbHcQueryEvent;
  276. queryConnect.Context = smbData;
  277. //
  278. // Connect Query notify with EC driver
  279. //
  280. irp = IoBuildDeviceIoControlRequest(
  281. EC_CONNECT_QUERY_HANDLER,
  282. smbData->LowerDeviceObject,
  283. &queryConnect,
  284. sizeof(EC_HANDLER_REQUEST),
  285. NULL,
  286. 0,
  287. TRUE,
  288. &event,
  289. &ioStatusBlock
  290. );
  291. if (!irp) {
  292. SmbPrint(SMB_ERROR, ("SmbHcResetDevice: Couldn't allocate Irp\n"));
  293. return STATUS_INSUFFICIENT_RESOURCES;
  294. }
  295. //
  296. // Send off to EC driver
  297. //
  298. status = IoCallDriver (smbData->LowerDeviceObject, irp);
  299. if (status == STATUS_PENDING) {
  300. KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL);
  301. status = ioStatusBlock.Status;
  302. }
  303. if (!NT_SUCCESS(status)) {
  304. SmbPrint(SMB_LOW, ("SmbHcResetDevice: Connect query failed, status = %Lx\n", status));
  305. }
  306. SmbPrint(SMB_LOW, ("SmbHcResetDevice: Exit\n"));
  307. return status;
  308. }
  309. NTSTATUS
  310. SmbHcStopDevice (
  311. IN struct _SMB_CLASS *SmbClass,
  312. IN PVOID SmbMiniport
  313. )
  314. {
  315. EC_HANDLER_REQUEST queryConnect;
  316. PSMB_DATA smbData;
  317. KEVENT event;
  318. NTSTATUS status;
  319. IO_STATUS_BLOCK ioStatusBlock;
  320. PIRP irp;
  321. SmbPrint(SMB_LOW, ("SmbHcStopDevice: Entry\n") );
  322. //
  323. // There is currently no way to test this code path.
  324. // Leaving untested code for potential future use/development
  325. //
  326. DbgPrint("SmbHcStopDevice: Encountered previously untested code.\n"
  327. "enter 'g' to continue, or contact the appropriate developer.\n");
  328. DbgBreakPoint();
  329. // Cutting code to reduce file size (see above comment)
  330. #if 0
  331. PAGED_CODE();
  332. smbData = (PSMB_DATA) SmbMiniport;
  333. //
  334. // Initialize the even to wait on
  335. //
  336. KeInitializeEvent( &event, NotificationEvent, FALSE);
  337. //
  338. // Build the input data to the EC
  339. //
  340. queryConnect.Vector = smbData->EcQuery;
  341. queryConnect.Handler = SmbHcQueryEvent;
  342. queryConnect.Context = smbData;
  343. //
  344. // Connect Query notify with EC driver
  345. //
  346. irp = IoBuildDeviceIoControlRequest(
  347. EC_DISCONNECT_QUERY_HANDLER,
  348. smbData->LowerDeviceObject,
  349. &queryConnect,
  350. sizeof(EC_HANDLER_REQUEST),
  351. NULL,
  352. 0,
  353. TRUE,
  354. &event,
  355. &ioStatusBlock
  356. );
  357. if (!irp) {
  358. SmbPrint(SMB_ERROR, ("SmbHcStopDevice: Couldn't allocate Irp\n"));
  359. return STATUS_INSUFFICIENT_RESOURCES;
  360. }
  361. //
  362. // Send off to EC driver
  363. //
  364. status = IoCallDriver (smbData->LowerDeviceObject, irp);
  365. if (status == STATUS_PENDING) {
  366. KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL);
  367. status = ioStatusBlock.Status;
  368. }
  369. if (!NT_SUCCESS(status)) {
  370. SmbPrint(SMB_LOW, ("SmbHcStopDevice: Connect query failed, status = %Lx\n", status));
  371. }
  372. SmbPrint(SMB_LOW, ("SmbHcStopDevice: Exit\n"));
  373. return status;
  374. #endif
  375. return STATUS_SUCCESS;
  376. }