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.

408 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 - 2001 Microsoft Corporation
  3. Module Name:
  4. #### ##### #### ##### #####
  5. ## ## ## ## # ## ## ## ##
  6. ## ## ## ## ## ## ## ##
  7. ## ## ## ## ## ## ## ##
  8. ## ## ## ## ##### #####
  9. ## ## ## ## ## # ## ##
  10. #### ##### ## #### ## ##
  11. Abstract:
  12. This module contains the code to process basic I/O
  13. requests for read and write IRPs.
  14. Author:
  15. Wesley Witt (wesw) 1-Oct-2001
  16. Environment:
  17. Kernel mode only.
  18. Notes:
  19. --*/
  20. #include "internal.h"
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE,SaPortRead)
  23. #pragma alloc_text(PAGE,SaPortWrite)
  24. #endif
  25. NTSTATUS
  26. SaPortWrite(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp
  29. )
  30. /*++
  31. Routine Description:
  32. This routine is the dispatch point for all writes. The function
  33. calls the miniport specific I/O validation function to verify that
  34. the input parameters are correct. The IRP is then marked as pending
  35. and placed in the device queue for processing.
  36. Arguments:
  37. DeviceObject - The device object for the target device.
  38. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  39. Return Value:
  40. NT status code.
  41. --*/
  42. {
  43. NTSTATUS status;
  44. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  45. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  46. DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "SaPortWrite\n" ));
  47. if (!DeviceExtension->IsStarted) {
  48. return CompleteRequest( Irp, STATUS_NO_SUCH_DEVICE, 0 );
  49. }
  50. __try {
  51. //
  52. // Do any device specific verification
  53. //
  54. if (!IS_IRP_INTERNAL( Irp )) {
  55. switch (DeviceExtension->DriverExtension->InitData.DeviceType) {
  56. case SA_DEVICE_DISPLAY:
  57. status = SaDisplayIoValidation( (PDISPLAY_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  58. break;
  59. case SA_DEVICE_KEYPAD:
  60. status = SaKeypadIoValidation( (PKEYPAD_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  61. break;
  62. case SA_DEVICE_NVRAM:
  63. status = SaNvramIoValidation( (PNVRAM_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  64. break;
  65. case SA_DEVICE_WATCHDOG:
  66. status = SaWatchdogIoValidation( (PWATCHDOG_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  67. break;
  68. }
  69. if (!NT_SUCCESS(status)) {
  70. ERROR_RETURN( DeviceExtension->DeviceType, "I/O validation failed", status );
  71. }
  72. }
  73. IoMarkIrpPending( Irp );
  74. IoStartPacket( DeviceObject, Irp, NULL, SaPortCancelRoutine );
  75. status = STATUS_PENDING;
  76. } __finally {
  77. }
  78. if (status != STATUS_PENDING) {
  79. status = CompleteRequest( Irp, status, Irp->IoStatus.Information );
  80. }
  81. return status;
  82. }
  83. NTSTATUS
  84. SaPortRead(
  85. IN PDEVICE_OBJECT DeviceObject,
  86. IN PIRP Irp
  87. )
  88. /*++
  89. Routine Description:
  90. This routine is the dispatch point for all reads. The function
  91. calls the miniport specific I/O validation function to verify that
  92. the input parameters are correct. The IRP is then marked as pending
  93. and placed in the device queue for processing.
  94. Arguments:
  95. DeviceObject - The device object for the target device.
  96. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  97. Return Value:
  98. NT status code.
  99. --*/
  100. {
  101. NTSTATUS status;
  102. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  103. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  104. DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "SaPortRead\n" ));
  105. if (!DeviceExtension->IsStarted) {
  106. return CompleteRequest( Irp, STATUS_NO_SUCH_DEVICE, 0 );
  107. }
  108. __try {
  109. if (!IS_IRP_INTERNAL( Irp )) {
  110. //
  111. // Do any device specific verification, but
  112. // only if the request is NOT internal
  113. //
  114. switch (DeviceExtension->DriverExtension->InitData.DeviceType) {
  115. case SA_DEVICE_DISPLAY:
  116. status = SaDisplayIoValidation( (PDISPLAY_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  117. break;
  118. case SA_DEVICE_KEYPAD:
  119. status = SaKeypadIoValidation( (PKEYPAD_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  120. break;
  121. case SA_DEVICE_NVRAM:
  122. status = SaNvramIoValidation( (PNVRAM_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  123. break;
  124. case SA_DEVICE_WATCHDOG:
  125. status = SaWatchdogIoValidation( (PWATCHDOG_DEVICE_EXTENSION)DeviceExtension, Irp, IrpSp );
  126. break;
  127. }
  128. if (!NT_SUCCESS(status)) {
  129. ERROR_RETURN( DeviceExtension->DeviceType, "I/O validation failed", status );
  130. }
  131. }
  132. IoMarkIrpPending( Irp );
  133. IoStartPacket( DeviceObject, Irp, NULL, SaPortCancelRoutine );
  134. status = STATUS_PENDING;
  135. } __finally {
  136. }
  137. if (status != STATUS_PENDING) {
  138. status = CompleteRequest( Irp, status, Irp->IoStatus.Information );
  139. }
  140. return status;
  141. }
  142. VOID
  143. SaPortCancelRoutine(
  144. IN PDEVICE_OBJECT DeviceObject,
  145. IN PIRP Irp
  146. )
  147. /*++
  148. Routine Description:
  149. This routine is the dispatch point for all IRP cancellation. Every IRP
  150. that is pending has this function specified as the global cancel routine.
  151. The associated miniport can specify a cancel routine that it uses for I/O
  152. specific processing, specifically for stopping I/O on it's hardware device.
  153. Arguments:
  154. DeviceObject - The device object for the target device.
  155. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  156. Return Value:
  157. None.
  158. --*/
  159. {
  160. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  161. if (DeviceObject->CurrentIrp == Irp) {
  162. IoReleaseCancelSpinLock( Irp->CancelIrql );
  163. if (DeviceExtension->InitData->CancelRoutine) {
  164. DeviceExtension->InitData->CancelRoutine( DeviceExtension->MiniPortDeviceExtension, Irp, TRUE );
  165. }
  166. CompleteRequest( Irp, STATUS_CANCELLED, 0 );
  167. IoReleaseRemoveLock( &DeviceExtension->RemoveLock, DeviceExtension->DeviceObject->CurrentIrp );
  168. IoStartNextPacket( DeviceExtension->DeviceObject, TRUE );
  169. } else {
  170. if (KeRemoveEntryDeviceQueue( &DeviceObject->DeviceQueue, &Irp->Tail.Overlay.DeviceQueueEntry )) {
  171. IoReleaseCancelSpinLock( Irp->CancelIrql );
  172. if (DeviceExtension->InitData->CancelRoutine) {
  173. DeviceExtension->InitData->CancelRoutine( DeviceExtension->MiniPortDeviceExtension, Irp, FALSE );
  174. }
  175. CompleteRequest( Irp, STATUS_CANCELLED, 0 );
  176. IoReleaseRemoveLock( &DeviceExtension->RemoveLock, DeviceExtension->DeviceObject->CurrentIrp );
  177. IoStartNextPacket( DeviceExtension->DeviceObject, TRUE );
  178. } else {
  179. IoReleaseCancelSpinLock( Irp->CancelIrql );
  180. }
  181. }
  182. }
  183. BOOLEAN
  184. SaPortStartIoSynchRoutine(
  185. IN PVOID SynchronizeContext
  186. )
  187. /*++
  188. Routine Description:
  189. This routine is called through a call to KeSynchronizeExecution and is used
  190. to synchronize the StartIO calls for a miniport with it's ISR access to any
  191. hardware. This function is currently used for read and write IRPS only and
  192. passes the calls through to the miniport, returning any status code to the
  193. caller of KeSynchronizeExecution.
  194. Arguments:
  195. SynchronizeContext - Void pointer that is really a SAPORT_IOCONTEXT packet.
  196. Return Value:
  197. Always TRUE, the status code is found in IoContext->Status.
  198. --*/
  199. {
  200. PSAPORT_IOCONTEXT IoContext = (PSAPORT_IOCONTEXT)SynchronizeContext;
  201. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(IoContext->Irp);
  202. IoContext->Status = IoContext->IoRoutine(
  203. IoContext->MiniPortDeviceExtension,
  204. IoContext->Irp,
  205. IrpSp->FileObject ? IrpSp->FileObject->FsContext : NULL,
  206. IoContext->StartingOffset,
  207. IoContext->IoBuffer,
  208. IoContext->IoLength
  209. );
  210. return TRUE;
  211. }
  212. VOID
  213. SaPortStartIo(
  214. IN PDEVICE_OBJECT DeviceObject,
  215. IN PIRP Irp
  216. )
  217. /*++
  218. Routine Description:
  219. This routine is the dispatch point for the StartIo call by the I/O manager.
  220. The function simply calls the associated miniport's I/O handler and completes
  221. the IRP if the miniport returns STATUS_PENDING.
  222. Arguments:
  223. DeviceObject - The device object for the target device.
  224. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  225. Return Value:
  226. NT status code.
  227. --*/
  228. {
  229. NTSTATUS Status = STATUS_SUCCESS;
  230. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  231. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  232. SAPORT_IOCONTEXT IoContext;
  233. __try {
  234. Status = IoAcquireRemoveLock( &DeviceExtension->RemoveLock, Irp );
  235. if (!NT_SUCCESS(Status)) {
  236. ERROR_RETURN( DeviceExtension->DeviceType, "IoAcquireRemoveLock failed", Status );
  237. }
  238. IoContext.IoBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  239. if (IoContext.IoBuffer == NULL) {
  240. ERROR_RETURN( DeviceExtension->DeviceType, "MmGetSystemAddressForMdlSafe failed", Status );
  241. }
  242. switch (IrpSp->MajorFunction) {
  243. case IRP_MJ_READ:
  244. IoContext.IoRoutine = DeviceExtension->InitData->Read;
  245. IoContext.IoLength = IrpSp->Parameters.Read.Length;
  246. IoContext.StartingOffset = IrpSp->Parameters.Read.ByteOffset.QuadPart;
  247. break;
  248. case IRP_MJ_WRITE:
  249. IoContext.IoRoutine = DeviceExtension->InitData->Write;
  250. IoContext.IoLength = IrpSp->Parameters.Write.Length;
  251. IoContext.StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart;
  252. break;
  253. default:
  254. IoContext.IoRoutine = NULL;
  255. break;
  256. }
  257. if (IoContext.IoRoutine) {
  258. if (DeviceExtension->InterruptObject) {
  259. IoContext.MiniPortDeviceExtension = DeviceExtension->MiniPortDeviceExtension;
  260. IoContext.Irp = Irp;
  261. KeSynchronizeExecution(
  262. DeviceExtension->InterruptObject,
  263. SaPortStartIoSynchRoutine,
  264. &IoContext
  265. );
  266. Status = IoContext.Status;
  267. } else {
  268. Status = IoContext.IoRoutine(
  269. DeviceExtension->MiniPortDeviceExtension,
  270. Irp,
  271. IrpSp->FileObject ? IrpSp->FileObject->FsContext : NULL,
  272. IoContext.StartingOffset,
  273. IoContext.IoBuffer,
  274. IoContext.IoLength
  275. );
  276. }
  277. } else {
  278. Status = STATUS_NOT_SUPPORTED;
  279. }
  280. } __finally {
  281. }
  282. if (Status != STATUS_SUCCESS && Status != STATUS_PENDING) {
  283. REPORT_ERROR( DeviceExtension->DeviceType, "Miniport I/O routine failed", Status );
  284. }
  285. if (Status == STATUS_SUCCESS || Status != STATUS_PENDING) {
  286. IoReleaseRemoveLock( &DeviceExtension->RemoveLock, Irp );
  287. CompleteRequest( Irp, Status, 0 );
  288. IoStartNextPacket( DeviceExtension->DeviceObject, TRUE );
  289. }
  290. }