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.

427 lines
10 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 entire implementation of
  13. the keypad miniport for the ServerWorks
  14. CSB5 server chip set.
  15. Author:
  16. Wesley Witt (wesw) 1-Oct-2001
  17. Environment:
  18. Kernel mode only.
  19. Notes:
  20. --*/
  21. #include "swkeypad.h"
  22. #define CLEARBITS(_val,_mask) ((_val) &= ~(_mask))
  23. #define SETBITS(_val,_mask) ((_val) |= (_mask))
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(INIT,DriverEntry)
  26. #endif
  27. BOOLEAN
  28. SaKeypadInterruptService(
  29. IN PKINTERRUPT InterruptObject,
  30. IN PVOID ServiceContext
  31. )
  32. /*++
  33. Routine Description:
  34. This function is the device's interrupt service routine and
  35. is called by the OS to service the interrupt. The interrupt
  36. spin lock is held so work here is kept to a minimum.
  37. Arguments:
  38. InterruptObject - Pointer to an interrupt object.
  39. DeviceExtension - Pointer to the mini-port's device extension
  40. Context:
  41. IRQL: DIRQL, arbitrary thread context
  42. Return Value:
  43. A value of TRUE is returned if the interrupt is serviced by
  44. this function. Otherwise a value of FALSE is returned.
  45. --*/
  46. {
  47. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) ServiceContext;
  48. UCHAR KeyChar;
  49. //
  50. // Fetch the character from the keypad device
  51. //
  52. KeyChar = READ_PORT_UCHAR( DeviceExtension->PortAddress );
  53. //
  54. // Check to see if this is our interrupt
  55. //
  56. if (((KeyChar & KEYPAD_DATA_PRESSED) == 0) || ((KeyChar & KEYPAD_ALL_KEYS) == 0)) {
  57. DebugPrint(( SA_DEVICE_KEYPAD, SAPORT_DEBUG_INFO_LEVEL, "Interrupt: passing on [%02x]\n", KeyChar ));
  58. return FALSE;
  59. }
  60. DebugPrint(( SA_DEVICE_KEYPAD, SAPORT_DEBUG_INFO_LEVEL, "Interrupt: processing [%02x]\n", KeyChar ));
  61. SETBITS( KeyChar, KEYPAD_DATA_PRESSED );
  62. WRITE_PORT_UCHAR( DeviceExtension->PortAddress, KeyChar );
  63. //
  64. // Queue a DPC to process the key press
  65. //
  66. SaPortRequestDpc( DeviceExtension, (PVOID)KeyChar );
  67. //
  68. // return success
  69. //
  70. return TRUE;
  71. }
  72. VOID
  73. SaKeypadDpcRoutine(
  74. IN PKDPC Dpc,
  75. IN PDEVICE_OBJECT DeviceObject,
  76. IN PIRP Irp,
  77. IN PVOID Context
  78. )
  79. /*++
  80. Routine Description:
  81. This function is the device's DPC-for-ISR function. It is called
  82. only by the ISR function and it's only function is to start the
  83. next I/O.
  84. Arguments:
  85. DeviceObject - Pointer to the target device object.
  86. DeviceExtension - Pointer to the mini-port's device extension.
  87. Context - Mini-port supplied context pointer.
  88. Context:
  89. IRQL: DISPATCH_LEVEL, DPC context
  90. Return Value:
  91. None.
  92. --*/
  93. {
  94. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Irp;
  95. KIRQL OldIrql;
  96. KeAcquireSpinLock( &DeviceExtension->KeypadLock, &OldIrql );
  97. if (DeviceExtension->DataBuffer) {
  98. DeviceExtension->Keypress = (UCHAR)Context;
  99. DeviceExtension->DataBuffer[0] = DeviceExtension->Keypress & KEYPAD_ALL_KEYS;
  100. DeviceExtension->DataBuffer = NULL;
  101. SaPortCompleteRequest( DeviceExtension, NULL, sizeof(UCHAR), STATUS_SUCCESS, TRUE );
  102. DeviceExtension->Keypress = 0;
  103. }
  104. KeReleaseSpinLock( &DeviceExtension->KeypadLock, OldIrql );
  105. }
  106. VOID
  107. SaKeypadCancelRoutine(
  108. IN PVOID DeviceExtensionIn,
  109. IN PIRP Irp,
  110. IN BOOLEAN CurrentIo
  111. )
  112. /*++
  113. Routine Description:
  114. This function is the miniport's IRP cancel routine.
  115. Arguments:
  116. DeviceExtension - Pointer to the mini-port's device extension.
  117. CurrentIo - TRUE if this is called for the current I/O
  118. Return Value:
  119. None.
  120. --*/
  121. {
  122. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtensionIn;
  123. KIRQL OldIrql;
  124. if (CurrentIo) {
  125. KeAcquireSpinLock( &DeviceExtension->KeypadLock, &OldIrql );
  126. DeviceExtension->Keypress = 0;
  127. DeviceExtension->DataBuffer = NULL;
  128. KeReleaseSpinLock( &DeviceExtension->KeypadLock, OldIrql );
  129. }
  130. }
  131. NTSTATUS
  132. SaKeypadRead(
  133. IN PVOID DeviceExtensionIn,
  134. IN PIRP Irp,
  135. IN PVOID FsContext,
  136. IN LONGLONG StartingOffset,
  137. IN PVOID DataBuffer,
  138. IN ULONG DataBufferLength
  139. )
  140. /*++
  141. Routine Description:
  142. This routine processes the read requests for the local display miniport.
  143. Arguments:
  144. DeviceExtensionIn - Miniport's device extension
  145. StartingOffset - Starting offset for the I/O
  146. DataBuffer - Pointer to the data buffer
  147. DataBufferLength - Length of the data buffer in bytes
  148. Return Value:
  149. NT status code.
  150. --*/
  151. {
  152. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtensionIn;
  153. KIRQL OldIrql;
  154. if (DeviceExtension->Keypress) {
  155. *((PUCHAR)DataBuffer) = DeviceExtension->Keypress;
  156. return STATUS_SUCCESS;
  157. }
  158. DeviceExtension->DataBuffer = (PUCHAR) DataBuffer;
  159. return STATUS_PENDING;
  160. }
  161. NTSTATUS
  162. SaKeypadDeviceIoctl(
  163. IN PVOID DeviceExtension,
  164. IN PIRP Irp,
  165. IN PVOID FsContext,
  166. IN ULONG FunctionCode,
  167. IN PVOID InputBuffer,
  168. IN ULONG InputBufferLength,
  169. IN PVOID OutputBuffer,
  170. IN ULONG OutputBufferLength
  171. )
  172. /*++
  173. Routine Description:
  174. This function is called by the SAPORT driver so that
  175. the mini-port driver can service an IOCTL call.
  176. Arguments:
  177. DeviceExtension - A pointer to the mini-port's device extension
  178. FunctionCode - The IOCTL function code
  179. InputBuffer - Pointer to the input buffer, contains the data sent down by the I/O
  180. InputBufferLength - Length in bytes of the InputBuffer
  181. OutputBuffer - Pointer to the output buffer, contains the data generated by this call
  182. OutputBufferLength - Length in bytes of the OutputBuffer
  183. Context:
  184. IRQL: IRQL PASSIVE_LEVEL, arbitrary thread context
  185. Return Value:
  186. If the function succeeds, it must return STATUS_SUCCESS.
  187. Otherwise, it must return one of the error status values defined in ntstatus.h.
  188. --*/
  189. {
  190. NTSTATUS Status = STATUS_SUCCESS;
  191. switch (FunctionCode) {
  192. case FUNC_SA_GET_VERSION:
  193. *((PULONG)OutputBuffer) = SA_INTERFACE_VERSION;
  194. break;
  195. default:
  196. Status = STATUS_NOT_SUPPORTED;
  197. REPORT_ERROR( SA_DEVICE_KEYPAD, "Unsupported device control", Status );
  198. break;
  199. }
  200. return Status;
  201. }
  202. NTSTATUS
  203. SaKeypadHwInitialize(
  204. IN PDEVICE_OBJECT DeviceObject,
  205. IN PIRP Irp,
  206. IN PVOID DeviceExtensionIn,
  207. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources,
  208. IN ULONG PartialResourceCount
  209. )
  210. /*++
  211. Routine Description:
  212. This function is called by the SAPORT driver so that
  213. the mini-port driver can initialize it's hardware
  214. resources.
  215. Arguments:
  216. DeviceObject - Pointer to the target device object.
  217. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  218. DeviceExtension - A pointer to the mini-port's device extension.
  219. PartialResources - Pointer to the translated resources alloacted by the system.
  220. PartialResourceCount - The number of resources in the PartialResources array.
  221. Context:
  222. IRQL: IRQL PASSIVE_LEVEL, system thread context
  223. Return Value:
  224. If the function succeeds, it must return STATUS_SUCCESS.
  225. Otherwise, it must return one of the error status values defined in ntstatus.h.
  226. --*/
  227. {
  228. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  229. PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourcePort = NULL;
  230. NTSTATUS Status;
  231. ULONG i;
  232. for (i=0; i<PartialResourceCount; i++) {
  233. if (PartialResources[i].Type == CmResourceTypePort) {
  234. ResourcePort = &PartialResources[i];
  235. }
  236. }
  237. if (ResourcePort == NULL) {
  238. REPORT_ERROR( SA_DEVICE_KEYPAD, "Missing port resource", STATUS_UNSUCCESSFUL );
  239. return STATUS_UNSUCCESSFUL;
  240. }
  241. //
  242. // Setup the I/O port address
  243. //
  244. DeviceExtension->PortAddress = (PUCHAR) ResourcePort->u.Port.Start.QuadPart;
  245. KeInitializeSpinLock( &DeviceExtension->KeypadLock );
  246. //
  247. // Enable interrupts on the hardware
  248. //
  249. WRITE_PORT_UCHAR( DeviceExtension->PortAddress, KEYPAD_DATA_INTERRUPT_ENABLE );
  250. return STATUS_SUCCESS;
  251. }
  252. NTSTATUS
  253. DriverEntry(
  254. IN PDRIVER_OBJECT DriverObject,
  255. IN PUNICODE_STRING RegistryPath
  256. )
  257. /*++
  258. Routine Description:
  259. This routine is the driver's entry point, called by the I/O system
  260. to load the driver. The driver's entry points are initialized and
  261. a mutex to control paging is initialized.
  262. In DBG mode, this routine also examines the registry for special
  263. debug parameters.
  264. Arguments:
  265. DriverObject - a pointer to the object that represents this device driver.
  266. RegistryPath - a pointer to this driver's key in the Services tree.
  267. Return Value:
  268. STATUS_SUCCESS
  269. --*/
  270. {
  271. NTSTATUS Status;
  272. SAPORT_INITIALIZATION_DATA SaPortInitData;
  273. RtlZeroMemory( &SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) );
  274. SaPortInitData.StructSize = sizeof(SAPORT_INITIALIZATION_DATA);
  275. SaPortInitData.DeviceType = SA_DEVICE_KEYPAD;
  276. SaPortInitData.HwInitialize = SaKeypadHwInitialize;
  277. SaPortInitData.DeviceIoctl = SaKeypadDeviceIoctl;
  278. SaPortInitData.Read = SaKeypadRead;
  279. SaPortInitData.CancelRoutine = SaKeypadCancelRoutine;
  280. SaPortInitData.InterruptServiceRoutine = SaKeypadInterruptService;
  281. SaPortInitData.IsrForDpcRoutine = SaKeypadDpcRoutine;
  282. SaPortInitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
  283. Status = SaPortInitialize( DriverObject, RegistryPath, &SaPortInitData );
  284. if (!NT_SUCCESS(Status)) {
  285. REPORT_ERROR( SA_DEVICE_KEYPAD, "SaPortInitialize failed\n", Status );
  286. return Status;
  287. }
  288. return STATUS_SUCCESS;
  289. }