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.

410 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. smbclass.c
  5. Abstract:
  6. SMBus Class Driver
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Notes:
  11. Revision History:
  12. 27-Feb-97
  13. Pnp support - Bob Moore
  14. --*/
  15. #include "smbc.h"
  16. ULONG SMBCDebug = SMB_ERRORS;
  17. //
  18. // Prototypes
  19. //
  20. NTSTATUS
  21. DriverEntry (
  22. IN PDRIVER_OBJECT DriverObject,
  23. IN PUNICODE_STRING RegistryPath
  24. );
  25. NTSTATUS
  26. SmbClassInitializeDevice (
  27. IN ULONG MajorVersion,
  28. IN ULONG MinorVersion,
  29. IN PDRIVER_OBJECT DriverObject
  30. );
  31. NTSTATUS
  32. SmbClassDeviceInitialize (
  33. PSMB_CLASS SmbClass
  34. );
  35. VOID
  36. SmbCUnload(
  37. IN PDRIVER_OBJECT DriverObject
  38. );
  39. NTSTATUS
  40. SmbCOpenClose(
  41. IN PDEVICE_OBJECT DeviceObject,
  42. IN PIRP Irp
  43. );
  44. NTSTATUS
  45. SmbCInternalIoctl(
  46. IN PDEVICE_OBJECT DeviceObject,
  47. IN PIRP Irp
  48. );
  49. NTSTATUS
  50. SmbCPnpDispatch(
  51. IN PDEVICE_OBJECT DeviceObject,
  52. IN PIRP Irp
  53. );
  54. NTSTATUS
  55. SmbCPowerDispatch(
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN PIRP Irp
  58. );
  59. NTSTATUS
  60. SmbCForwardRequest(
  61. IN PDEVICE_OBJECT DeviceObject,
  62. IN PIRP Irp
  63. );
  64. #ifdef ALLOC_PRAGMA
  65. #pragma alloc_text(PAGE,DriverEntry)
  66. #pragma alloc_text(PAGE,SmbClassInitializeDevice)
  67. #pragma alloc_text(PAGE,SmbCOpenClose)
  68. #pragma alloc_text(PAGE,SmbCUnload)
  69. #endif
  70. NTSTATUS
  71. DriverEntry (
  72. IN PDRIVER_OBJECT DriverObject,
  73. IN PUNICODE_STRING RegistryPath
  74. )
  75. {
  76. return STATUS_SUCCESS;
  77. }
  78. NTSTATUS
  79. SmbClassInitializeDevice (
  80. IN ULONG MajorVersion,
  81. IN ULONG MinorVersion,
  82. IN PDRIVER_OBJECT DriverObject
  83. )
  84. /*++
  85. Routine Description:
  86. This function is called by the SM bus miniport driver/DriverEntry
  87. to perform class specific initialization
  88. Arguments:
  89. MajorVersion - Version #
  90. MinorVersion - Version #
  91. DriverObject - From miniport DriverEntry
  92. Return Value:
  93. Status
  94. --*/
  95. {
  96. if (MajorVersion != SMB_CLASS_MAJOR_VERSION) {
  97. return STATUS_REVISION_MISMATCH;
  98. }
  99. //
  100. // Set up the device driver entry points.
  101. //
  102. DriverObject->DriverUnload = SmbCUnload;
  103. DriverObject->MajorFunction[IRP_MJ_CREATE] = SmbCOpenClose;
  104. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SmbCOpenClose;
  105. DriverObject->MajorFunction[IRP_MJ_POWER] = SmbCPowerDispatch;
  106. DriverObject->MajorFunction[IRP_MJ_PNP] = SmbCPnpDispatch;
  107. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SmbCInternalIoctl;
  108. // DriverObject->MajorFunction[IRP_MJ_READ] = SmbCForwardRequest;
  109. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SmbCForwardRequest;
  110. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SmbCForwardRequest;
  111. //
  112. // Miniport will set up the AddDevice entry
  113. //
  114. return STATUS_SUCCESS;
  115. }
  116. VOID
  117. SmbCUnload(
  118. IN PDRIVER_OBJECT DriverObject
  119. )
  120. {
  121. SmbPrint (SMB_NOTE, ("SmBCUnLoad: \n"));
  122. if (DriverObject->DeviceObject != NULL) {
  123. SmbPrint (SMB_ERROR, ("SmBCUnLoad: Unload called before all devices removed.\n"));
  124. }
  125. }
  126. NTSTATUS
  127. SmbCOpenClose(
  128. IN PDEVICE_OBJECT DeviceObject,
  129. IN PIRP Irp
  130. )
  131. {
  132. PAGED_CODE();
  133. //
  134. // Complete the request and return status.
  135. //
  136. Irp->IoStatus.Status = STATUS_SUCCESS;
  137. Irp->IoStatus.Information = 0;
  138. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  139. return(STATUS_SUCCESS);
  140. }
  141. NTSTATUS
  142. SmbCPowerDispatch(
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN PIRP Irp
  145. )
  146. /*++
  147. Routine Description:
  148. This is the dispatch routine for power requests.
  149. Arguments:
  150. DeviceObject - Pointer to class device object.
  151. Irp - Pointer to the request packet.
  152. Return Value:
  153. Status is returned.
  154. --*/
  155. {
  156. PIO_STACK_LOCATION irpStack;
  157. PSMBDATA SmbData;
  158. NTSTATUS status;
  159. SmbData = DeviceObject->DeviceExtension;
  160. //
  161. // What do we do with the irp?
  162. //
  163. PoStartNextPowerIrp( Irp );
  164. if (SmbData->Class.LowerDeviceObject != NULL) {
  165. //
  166. // Forward the request along
  167. //
  168. IoSkipCurrentIrpStackLocation( Irp );
  169. status = PoCallDriver( SmbData->Class.LowerDeviceObject, Irp );
  170. } else {
  171. //
  172. // Complete the request with the current status
  173. //
  174. status = Irp->IoStatus.Status;
  175. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  176. }
  177. return status;
  178. }
  179. NTSTATUS
  180. SmbCInternalIoctl (
  181. IN PDEVICE_OBJECT DeviceObject,
  182. IN PIRP Irp
  183. )
  184. /*++
  185. Routine Description:
  186. This routine is the dispatch routine for internal IOCTLs.
  187. Arguments:
  188. DeviceObject - Pointer to class device object.
  189. Irp - Pointer to the request packet.
  190. Return Value:
  191. Status is returned.
  192. --*/
  193. {
  194. PIO_STACK_LOCATION IrpSp;
  195. PSMB_REQUEST SmbReq;
  196. PSMBDATA Smb;
  197. NTSTATUS Status;
  198. //
  199. // Get a pointer to the current parameters for this request. The
  200. // information is contained in the current stack location.
  201. //
  202. Status = STATUS_INVALID_PARAMETER;
  203. Irp->IoStatus.Information = 0;
  204. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  205. Smb = (PSMBDATA) DeviceObject->DeviceExtension;
  206. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  207. case SMB_BUS_REQUEST:
  208. //
  209. // Verify bus request is valid
  210. //
  211. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SMB_REQUEST)) {
  212. // Invalid buffer length
  213. SmbPrint(SMB_NOTE, ("SmbCIoctl: Invalid bus_req length\n"));
  214. Status = STATUS_BUFFER_TOO_SMALL;
  215. Irp->IoStatus.Information = sizeof(SMB_REQUEST);
  216. break;
  217. }
  218. SmbReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  219. if (SmbReq->Protocol > SMB_MAXIMUM_PROTOCOL ||
  220. SmbReq->Address > 0x7F ||
  221. (SmbReq->Protocol == SMB_WRITE_BLOCK &&
  222. SmbReq->BlockLength > SMB_MAX_DATA_SIZE)) {
  223. // Invalid param in request
  224. SmbPrint(SMB_NOTE, ("SmbCIoctl: Invalid bus_req\n"));
  225. break;
  226. }
  227. //
  228. // Mark request pending and queue it to the service queue
  229. //
  230. Status = STATUS_PENDING;
  231. Irp->IoStatus.Status = STATUS_PENDING;
  232. IoMarkIrpPending (Irp);
  233. SmbClassLockDevice (&Smb->Class);
  234. InsertTailList (&Smb->WorkQueue, &Irp->Tail.Overlay.ListEntry);
  235. //
  236. // Start IO if needed
  237. //
  238. SmbClassStartIo (Smb);
  239. SmbClassUnlockDevice (&Smb->Class);
  240. break;
  241. case SMB_REGISTER_ALARM_NOTIFY:
  242. //
  243. // Registry for alarm notifications
  244. //
  245. Status = SmbCRegisterAlarm (Smb, Irp);
  246. break;
  247. case SMB_DEREGISTER_ALARM_NOTIFY:
  248. //
  249. // Deregister for alarm notifications
  250. //
  251. Status = SmbCDeregisterAlarm (Smb, Irp);
  252. break;
  253. default:
  254. // complete with invalid parameter
  255. break;
  256. }
  257. if (Status != STATUS_PENDING) {
  258. Irp->IoStatus.Status = Status;
  259. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  260. }
  261. return Status;
  262. }
  263. NTSTATUS
  264. SmbCForwardRequest(
  265. IN PDEVICE_OBJECT DeviceObject,
  266. IN PIRP Irp
  267. )
  268. /*++
  269. Routine Description:
  270. This routine forwards the irp down the stack
  271. Arguments:
  272. DeviceObject - The target
  273. Irp - The request
  274. Return Value:
  275. NTSTATUS
  276. --*/
  277. {
  278. NTSTATUS Status;
  279. PSMBDATA Smb = (PSMBDATA) DeviceObject->DeviceExtension;
  280. if (Smb->Class.LowerDeviceObject != NULL) {
  281. IoSkipCurrentIrpStackLocation( Irp );
  282. Status = IoCallDriver( Smb->Class.LowerDeviceObject, Irp );
  283. } else {
  284. Status = Irp->IoStatus.Status;
  285. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  286. }
  287. return Status;
  288. }