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.

625 lines
15 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. sdbus.c
  5. Abstract:
  6. Author:
  7. Neil Sandlin (neilsa) 1-Jan-02
  8. Environment:
  9. Kernel mode only.
  10. --*/
  11. #include <ntddk.h>
  12. #if DBG
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #endif
  16. #include "ntddsd.h"
  17. #include "sdbuslib.h"
  18. //
  19. // Prototypes
  20. //
  21. NTSTATUS
  22. SdbusIoctlCompletion(
  23. IN PDEVICE_OBJECT DeviceObject,
  24. IN PIRP Irp,
  25. IN PKEVENT pdoIoCompletedEvent
  26. );
  27. NTSTATUS
  28. SdBusSendIoctl(
  29. IN ULONG IoControlCode,
  30. IN PDEVICE_OBJECT DeviceObject,
  31. IN PVOID InputBuffer OPTIONAL,
  32. IN ULONG InputBufferLength,
  33. OUT PVOID OutputBuffer OPTIONAL,
  34. IN ULONG OutputBufferLength
  35. );
  36. NTSTATUS
  37. SdbusRequestCompletion(
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP Irp,
  40. IN PSDBUS_REQUEST_PACKET SdRp
  41. );
  42. #if DBG
  43. VOID
  44. SdbusDebugPrint(
  45. PCCHAR DebugMessage,
  46. ...
  47. );
  48. #define DebugPrint(X) SdbusDebugPrint X
  49. BOOLEAN SdbusDebugEnabled = FALSE;
  50. #else
  51. #define DebugPrint(X)
  52. #endif
  53. //
  54. // External entry points
  55. //
  56. NTSTATUS
  57. SdBusOpenInterface(
  58. IN PSDBUS_INTERFACE_DATA InterfaceData,
  59. IN PVOID *pContext
  60. )
  61. {
  62. NTSTATUS status;
  63. PSDBUS_INTERFACE_DATA pIdataEntry;
  64. ULONG size = InterfaceData->Size;
  65. ULONG_PTR information;
  66. if (size > sizeof(SDBUS_INTERFACE_DATA)) {
  67. return STATUS_INVALID_PARAMETER;
  68. }
  69. status = SdBusSendIoctl(IOCTL_SD_INTERFACE_OPEN,
  70. InterfaceData->TargetObject,
  71. InterfaceData,
  72. size,
  73. &information,
  74. sizeof(information));
  75. if (!NT_SUCCESS(status)) {
  76. return status;
  77. }
  78. pIdataEntry = ExAllocatePool(NonPagedPool, sizeof(SDBUS_INTERFACE_DATA));
  79. if (pIdataEntry == NULL) {
  80. return STATUS_INSUFFICIENT_RESOURCES;
  81. }
  82. RtlCopyMemory(pIdataEntry, InterfaceData, size);
  83. *pContext = pIdataEntry;
  84. return STATUS_SUCCESS;
  85. }
  86. NTSTATUS
  87. SdBusCloseInterface(
  88. IN PSDBUS_INTERFACE_DATA InterfaceData
  89. )
  90. {
  91. if (InterfaceData) {
  92. SdBusSendIoctl(IOCTL_SD_INTERFACE_CLOSE,
  93. InterfaceData->TargetObject,
  94. NULL,
  95. 0,
  96. NULL,
  97. 0);
  98. ExFreePool(InterfaceData);
  99. }
  100. return STATUS_SUCCESS;
  101. }
  102. NTSTATUS
  103. SdBusSubmitRequest(
  104. IN PSDBUS_INTERFACE_DATA InterfaceData,
  105. IN PSDBUS_REQUEST_PACKET SdRp
  106. )
  107. {
  108. IO_STATUS_BLOCK statusBlock;
  109. NTSTATUS status;
  110. PIRP irp;
  111. PIO_STACK_LOCATION irpSp;
  112. DebugPrint(("sdbuslib: Request - %08x %02x\n", SdRp, SdRp->Function));
  113. irp = IoAllocateIrp(InterfaceData->TargetObject->StackSize, FALSE);
  114. if (!irp) {
  115. return STATUS_INSUFFICIENT_RESOURCES;
  116. }
  117. irpSp = IoGetNextIrpStackLocation(irp);
  118. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  119. irpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
  120. irpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof(SDBUS_REQUEST_PACKET);
  121. irpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_SD_SUBMIT_REQUEST;
  122. irp->AssociatedIrp.SystemBuffer = SdRp;
  123. irp->Flags = 0;
  124. irp->UserBuffer = NULL;
  125. irp->UserIosb = NULL;
  126. IoSetCompletionRoutine(irp,
  127. SdbusRequestCompletion,
  128. SdRp,
  129. TRUE,
  130. TRUE,
  131. TRUE);
  132. status = IoCallDriver(InterfaceData->TargetObject, irp);
  133. DebugPrint(("sdbuslib: Request exiting status %08x \n", status));
  134. return status;
  135. }
  136. NTSTATUS
  137. SdbusRequestCompletion(
  138. IN PDEVICE_OBJECT DeviceObject,
  139. IN PIRP Irp,
  140. IN PSDBUS_REQUEST_PACKET SdRp
  141. )
  142. {
  143. NTSTATUS status = Irp->IoStatus.Status;
  144. ULONG_PTR information = Irp->IoStatus.Information;
  145. DebugPrint(("sdbuslib: Request Complete %08x\n", status));
  146. IoFreeIrp(Irp);
  147. SdRp->Status = status;
  148. SdRp->Information = information;
  149. (*(SdRp->CompletionRoutine))(SdRp);
  150. return STATUS_MORE_PROCESSING_REQUIRED;
  151. }
  152. VOID
  153. SdBusReadWriteCompletion(
  154. IN PSDBUS_REQUEST_PACKET SdRp
  155. )
  156. {
  157. KeSetEvent(SdRp->UserContext, IO_NO_INCREMENT, FALSE);
  158. }
  159. NTSTATUS
  160. SdBusReadMemory(
  161. IN PVOID Context,
  162. IN ULONGLONG Offset,
  163. IN PVOID Buffer,
  164. IN ULONG Length,
  165. IN ULONG *LengthRead
  166. )
  167. {
  168. NTSTATUS status;
  169. IN PSDBUS_REQUEST_PACKET SdRp;
  170. KEVENT event;
  171. KeInitializeEvent(&event, NotificationEvent, FALSE);
  172. SdRp = ExAllocatePool(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET));
  173. if (!SdRp) {
  174. return STATUS_INSUFFICIENT_RESOURCES;
  175. }
  176. RtlZeroMemory(SdRp, sizeof(SDBUS_REQUEST_PACKET));
  177. SdRp->Function = SDRP_READ_BLOCK;
  178. SdRp->Parameters.ReadBlock.ByteOffset = Offset;
  179. SdRp->Parameters.ReadBlock.Buffer = Buffer;
  180. SdRp->Parameters.ReadBlock.Length = Length;
  181. SdRp->CompletionRoutine = SdBusReadWriteCompletion;
  182. SdRp->UserContext = &event;
  183. status = SdBusSubmitRequest(Context, SdRp);
  184. if (status == STATUS_PENDING) {
  185. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  186. status = SdRp->Status;
  187. }
  188. if (NT_SUCCESS(status)) {
  189. *LengthRead = SdRp->Information;
  190. }
  191. ExFreePool(SdRp);
  192. return status;
  193. }
  194. NTSTATUS
  195. SdBusWriteMemory(
  196. IN PVOID Context,
  197. IN ULONGLONG Offset,
  198. IN PVOID Buffer,
  199. IN ULONG Length,
  200. IN ULONG *LengthWritten
  201. )
  202. {
  203. NTSTATUS status;
  204. IN PSDBUS_REQUEST_PACKET SdRp;
  205. KEVENT event;
  206. KeInitializeEvent(&event, NotificationEvent, FALSE);
  207. SdRp = ExAllocatePool(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET));
  208. if (!SdRp) {
  209. return STATUS_INSUFFICIENT_RESOURCES;
  210. }
  211. RtlZeroMemory(SdRp, sizeof(SDBUS_REQUEST_PACKET));
  212. SdRp->Function = SDRP_WRITE_BLOCK;
  213. SdRp->Parameters.WriteBlock.ByteOffset = Offset;
  214. SdRp->Parameters.WriteBlock.Buffer = Buffer;
  215. SdRp->Parameters.WriteBlock.Length = Length;
  216. SdRp->CompletionRoutine = SdBusReadWriteCompletion;
  217. SdRp->UserContext = &event;
  218. status = SdBusSubmitRequest(Context, SdRp);
  219. if (status == STATUS_PENDING) {
  220. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  221. status = SdRp->Status;
  222. }
  223. if (NT_SUCCESS(status)) {
  224. *LengthWritten = SdRp->Information;
  225. }
  226. ExFreePool(SdRp);
  227. return status;
  228. }
  229. NTSTATUS
  230. SdBusReadIo(
  231. IN PVOID Context,
  232. IN UCHAR CmdType,
  233. IN ULONG Offset,
  234. IN PVOID Buffer,
  235. IN ULONG Length,
  236. IN ULONG *LengthRead
  237. )
  238. {
  239. NTSTATUS status;
  240. IN PSDBUS_REQUEST_PACKET SdRp;
  241. KEVENT event;
  242. KeInitializeEvent(&event, NotificationEvent, FALSE);
  243. SdRp = ExAllocatePool(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET));
  244. if (!SdRp) {
  245. return STATUS_INSUFFICIENT_RESOURCES;
  246. }
  247. RtlZeroMemory(SdRp, sizeof(SDBUS_REQUEST_PACKET));
  248. if (CmdType == 52) {
  249. SdRp->Function = SDRP_READ_IO;
  250. SdRp->Parameters.ReadIo.Offset = Offset;
  251. SdRp->Parameters.ReadIo.Buffer = Buffer;
  252. } else {
  253. SdRp->Function = SDRP_READ_IO_EXTENDED;
  254. SdRp->Parameters.ReadIoExtended.Offset = Offset;
  255. SdRp->Parameters.ReadIoExtended.Buffer = Buffer;
  256. SdRp->Parameters.ReadIoExtended.Length = Length;
  257. }
  258. SdRp->CompletionRoutine = SdBusReadWriteCompletion;
  259. SdRp->UserContext = &event;
  260. status = SdBusSubmitRequest(Context, SdRp);
  261. if (status == STATUS_PENDING) {
  262. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  263. status = SdRp->Status;
  264. }
  265. if (NT_SUCCESS(status)) {
  266. *LengthRead = SdRp->Information;
  267. }
  268. ExFreePool(SdRp);
  269. return status;
  270. }
  271. NTSTATUS
  272. SdBusWriteIo(
  273. IN PVOID Context,
  274. IN UCHAR CmdType,
  275. IN ULONG Offset,
  276. IN PVOID Buffer,
  277. IN ULONG Length,
  278. IN ULONG *LengthWritten
  279. )
  280. {
  281. NTSTATUS status;
  282. IN PSDBUS_REQUEST_PACKET SdRp;
  283. KEVENT event;
  284. KeInitializeEvent(&event, NotificationEvent, FALSE);
  285. SdRp = ExAllocatePool(NonPagedPool, sizeof(SDBUS_REQUEST_PACKET));
  286. if (!SdRp) {
  287. return STATUS_INSUFFICIENT_RESOURCES;
  288. }
  289. RtlZeroMemory(SdRp, sizeof(SDBUS_REQUEST_PACKET));
  290. if (CmdType == 52) {
  291. SdRp->Function = SDRP_WRITE_IO;
  292. SdRp->Parameters.WriteIo.Offset = Offset;
  293. SdRp->Parameters.WriteIo.Data = *(PUCHAR)Buffer;
  294. } else {
  295. SdRp->Function = SDRP_WRITE_IO_EXTENDED;
  296. SdRp->Parameters.WriteIoExtended.Offset = Offset;
  297. SdRp->Parameters.WriteIoExtended.Buffer = Buffer;
  298. SdRp->Parameters.WriteIoExtended.Length = Length;
  299. }
  300. SdRp->CompletionRoutine = SdBusReadWriteCompletion;
  301. SdRp->UserContext = &event;
  302. status = SdBusSubmitRequest(Context, SdRp);
  303. if (status == STATUS_PENDING) {
  304. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  305. status = SdRp->Status;
  306. }
  307. if (NT_SUCCESS(status)) {
  308. *LengthWritten = SdRp->Information;
  309. }
  310. ExFreePool(SdRp);
  311. return status;
  312. }
  313. NTSTATUS
  314. SdBusAcknowledgeCardInterrupt(
  315. IN PSDBUS_INTERFACE_DATA InterfaceData
  316. )
  317. {
  318. NTSTATUS status;
  319. status = SdBusSendIoctl(IOCTL_SD_ACKNOWLEDGE_CARD_IRQ,
  320. InterfaceData->TargetObject,
  321. NULL,
  322. 0,
  323. NULL,
  324. 0);
  325. return status;
  326. }
  327. NTSTATUS
  328. SdBusGetDeviceParameters(
  329. IN PSDBUS_INTERFACE_DATA InterfaceData,
  330. IN PSDBUS_DEVICE_PARAMETERS pDeviceParameters,
  331. IN ULONG Length
  332. )
  333. {
  334. NTSTATUS status;
  335. status = SdBusSendIoctl(IOCTL_SD_GET_DEVICE_PARMS,
  336. InterfaceData->TargetObject,
  337. NULL,
  338. 0,
  339. pDeviceParameters,
  340. Length);
  341. return status;
  342. }
  343. //
  344. // Internal routines
  345. //
  346. NTSTATUS
  347. SdBusSendIoctl(
  348. IN ULONG IoControlCode,
  349. IN PDEVICE_OBJECT DeviceObject,
  350. IN PVOID InputBuffer OPTIONAL,
  351. IN ULONG InputBufferLength,
  352. OUT PVOID OutputBuffer OPTIONAL,
  353. IN ULONG OutputBufferLength
  354. )
  355. {
  356. KEVENT event;
  357. IO_STATUS_BLOCK statusBlock;
  358. NTSTATUS status;
  359. PIRP irp;
  360. PIO_STACK_LOCATION irpSp;
  361. DebugPrint(("SEND - %08x %08x %08x %08x %08x\n", IoControlCode,
  362. InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength));
  363. KeInitializeEvent(&event, NotificationEvent, FALSE);
  364. irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
  365. if (!irp) {
  366. return STATUS_INSUFFICIENT_RESOURCES;
  367. }
  368. irpSp = IoGetNextIrpStackLocation(irp);
  369. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  370. irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
  371. irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
  372. irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
  373. if (InputBufferLength != 0 || OutputBufferLength != 0) {
  374. irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag( NonPagedPoolCacheAligned,
  375. InputBufferLength > OutputBufferLength ? InputBufferLength : OutputBufferLength,
  376. ' oI' );
  377. if (irp->AssociatedIrp.SystemBuffer == NULL) {
  378. IoFreeIrp( irp );
  379. return STATUS_INSUFFICIENT_RESOURCES;
  380. }
  381. if (ARGUMENT_PRESENT( InputBuffer )) {
  382. RtlCopyMemory( irp->AssociatedIrp.SystemBuffer,
  383. InputBuffer,
  384. InputBufferLength );
  385. }
  386. irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
  387. irp->UserBuffer = OutputBuffer;
  388. if (ARGUMENT_PRESENT( OutputBuffer )) {
  389. irp->Flags |= IRP_INPUT_OPERATION;
  390. }
  391. } else {
  392. irp->Flags = 0;
  393. irp->UserBuffer = (PVOID) NULL;
  394. }
  395. irp->UserIosb = &statusBlock;
  396. IoSetCompletionRoutine(irp,
  397. SdbusIoctlCompletion,
  398. &event,
  399. TRUE,
  400. TRUE,
  401. TRUE);
  402. status = IoCallDriver(DeviceObject, irp);
  403. if (status == STATUS_PENDING) {
  404. DebugPrint(("SEND - %08x wait on event %08x \n", IoControlCode, &event));
  405. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  406. status = statusBlock.Status;
  407. }
  408. DebugPrint(("SEND - %08x exiting status %08x \n", IoControlCode, status));
  409. return status;
  410. }
  411. NTSTATUS
  412. SdbusIoctlCompletion(
  413. IN PDEVICE_OBJECT DeviceObject,
  414. IN PIRP Irp,
  415. IN PKEVENT pdoIoCompletedEvent
  416. )
  417. {
  418. DebugPrint(("SEND - on event %08x Complete %08x\n", pdoIoCompletedEvent, Irp->IoStatus.Status));
  419. if (NT_SUCCESS(Irp->IoStatus.Status) &&
  420. (Irp->IoStatus.Information != 0) &&
  421. (Irp->UserBuffer)) {
  422. RtlCopyMemory( Irp->UserBuffer,
  423. Irp->AssociatedIrp.SystemBuffer,
  424. Irp->IoStatus.Information);
  425. }
  426. if (Irp->AssociatedIrp.SystemBuffer) {
  427. ExFreePool (Irp->AssociatedIrp.SystemBuffer);
  428. }
  429. Irp->UserIosb->Status = Irp->IoStatus.Status;
  430. IoFreeIrp(Irp);
  431. KeSetEvent(pdoIoCompletedEvent, IO_NO_INCREMENT, FALSE);
  432. return STATUS_MORE_PROCESSING_REQUIRED;
  433. }
  434. #if DBG
  435. VOID
  436. SdbusDebugPrint(
  437. PCCHAR DebugMessage,
  438. ...
  439. )
  440. /*++
  441. Routine Description:
  442. Debug print for the SDBUS enabler.
  443. Arguments:
  444. Check the mask value to see if the debug message is requested.
  445. Return Value:
  446. None
  447. --*/
  448. {
  449. va_list ap;
  450. char buffer[256];
  451. if (SdbusDebugEnabled) {
  452. va_start(ap, DebugMessage);
  453. sprintf(buffer, "%s ", "Sdbuslib:");
  454. vsprintf(&buffer[strlen(buffer)], DebugMessage, ap);
  455. DbgPrint(buffer);
  456. va_end(ap);
  457. }
  458. } // end SdbusDebugPrint()
  459. #endif