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.

409 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. pcmcia.c
  5. Abstract:
  6. This module contains the code that controls the PCMCIA slots.
  7. Author:
  8. Bob Rinne (BobRi) 3-Aug-1994
  9. Jeff McLeman 12-Apr-1994
  10. Ravisankar Pudipeddi (ravisp) 1-Nov-96
  11. Neil Sandlin (neilsa) 1-Jun-1999
  12. Environment:
  13. Kernel mode
  14. Revision History :
  15. 6-Apr-95
  16. Modified for databook support - John Keys Databook
  17. 1-Nov-96
  18. Total overhaul to make this a bus enumerator - Ravisankar Pudipeddi (ravisp)
  19. --*/
  20. #include "pch.h"
  21. //
  22. // Internal References
  23. //
  24. NTSTATUS
  25. DriverEntry(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PUNICODE_STRING RegistryPath
  28. );
  29. VOID
  30. PcmciaUnload(
  31. IN PDRIVER_OBJECT DriverObject
  32. );
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text(INIT,DriverEntry)
  35. #pragma alloc_text(PAGE, PcmciaUnload)
  36. #pragma alloc_text(PAGE, PcmciaOpenCloseDispatch)
  37. #pragma alloc_text(PAGE, PcmciaCleanupDispatch)
  38. #pragma alloc_text(PAGE, PcmciaFdoSystemControl)
  39. #pragma alloc_text(PAGE, PcmciaPdoSystemControl)
  40. #endif
  41. PUNICODE_STRING DriverRegistryPath;
  42. NTSTATUS
  43. DriverEntry(
  44. IN PDRIVER_OBJECT DriverObject,
  45. IN PUNICODE_STRING RegistryPath
  46. )
  47. /*++
  48. Routine Description:
  49. The entry point that the system point calls to initialize
  50. any driver.
  51. Since this is a plug'n'play driver, we should return after setting
  52. the entry points & initializing our dispatch table.
  53. Currently we also detect our own PCMCIA controllers and report
  54. them - which should not be needed in the future when a root bus
  55. driver such as PCI or ISAPNP will locate the controllers for us.
  56. Arguments:
  57. DriverObject - Pointer to object representing this driver
  58. RegistryPath - Pointer the the registry key for this driver
  59. under \CurrentControlSet\Services
  60. Return Value:
  61. --*/
  62. {
  63. NTSTATUS status = STATUS_SUCCESS;
  64. ULONG i;
  65. PAGED_CODE();
  66. DebugPrint((PCMCIA_DEBUG_INFO,"Initializing Driver\n"));
  67. //
  68. // Load in common parameters from the registry
  69. //
  70. status = PcmciaLoadGlobalRegistryValues();
  71. if (!NT_SUCCESS(status)) {
  72. return status;
  73. }
  74. //
  75. //
  76. // Set up the device driver entry points.
  77. //
  78. DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
  79. DriverObject->DriverUnload = PcmciaUnload;
  80. //
  81. //
  82. // Save our registry path
  83. DriverRegistryPath = RegistryPath;
  84. //
  85. // Initialize the event used by the delay execution
  86. // routine.
  87. //
  88. KeInitializeEvent (&PcmciaDelayTimerEvent,
  89. NotificationEvent,
  90. FALSE);
  91. //
  92. // Initialize tone generation objects
  93. //
  94. KeInitializeTimer(&PcmciaToneTimer);
  95. KeInitializeDpc(&PcmciaToneDpc, PcmciaPlayToneCompletion, NULL);
  96. KeInitializeSpinLock(&PcmciaToneLock);
  97. //
  98. // Initialize global lock
  99. //
  100. KeInitializeSpinLock(&PcmciaGlobalLock);
  101. //
  102. // Init device dispatch table
  103. //
  104. PcmciaInitDeviceDispatchTable(DriverObject);
  105. //
  106. // Locate PCMCIA controllers and report them - this
  107. // is temporary - till the detection for these
  108. // controllers is moved into
  109. // appropriate root bus driver such as the PCI bus driver..
  110. // if (PcmciaLegacyDetectionOk()) {
  111. status = PcmciaDetectPcmciaControllers(DriverObject,RegistryPath);
  112. // }
  113. //
  114. // Ignore the status. Regardless of whether we found controllers or not
  115. // we need to stick around since we might get an AddDevice non-legacy
  116. // controllers
  117. //
  118. return STATUS_SUCCESS;
  119. }
  120. NTSTATUS
  121. PcmciaOpenCloseDispatch(
  122. IN PDEVICE_OBJECT DeviceObject,
  123. IN PIRP Irp
  124. )
  125. /*++
  126. Routine Description:
  127. Open or Close device routine
  128. Arguments:
  129. DeviceObject - Pointer to the device object.
  130. Irp - Pointer to the IRP
  131. Return Value:
  132. Status
  133. --*/
  134. {
  135. NTSTATUS status;
  136. PAGED_CODE();
  137. DebugPrint((PCMCIA_DEBUG_INFO, "PCMCIA: Open / close of Pcmcia controller for IO \n"));
  138. status = STATUS_SUCCESS;
  139. Irp->IoStatus.Status = STATUS_SUCCESS;
  140. Irp->IoStatus.Information = 0;
  141. IoCompleteRequest(Irp, 0);
  142. return status;
  143. }
  144. NTSTATUS
  145. PcmciaCleanupDispatch(
  146. IN PDEVICE_OBJECT DeviceObject,
  147. IN PIRP Irp
  148. )
  149. /*++
  150. Routine Description:
  151. Handles IRP_MJ_CLEANUP
  152. Arguments:
  153. DeviceObject - Pointer to the device object.
  154. Irp - Pointer to the IRP
  155. Return Value:
  156. Status
  157. --*/
  158. {
  159. NTSTATUS status;
  160. PAGED_CODE();
  161. DebugPrint((PCMCIA_DEBUG_INFO, "PCMCIA: Cleanup of Pcmcia controller for IO \n"));
  162. status = STATUS_SUCCESS;
  163. Irp->IoStatus.Status = STATUS_SUCCESS;
  164. Irp->IoStatus.Information = 0;
  165. IoCompleteRequest(Irp, 0);
  166. return status;
  167. }
  168. NTSTATUS
  169. PcmciaFdoSystemControl(
  170. IN PDEVICE_OBJECT DeviceObject,
  171. IN PIRP Irp
  172. )
  173. /*++
  174. Routine Description:
  175. Handles IRP_MJ_SYSTEM_CONTROL
  176. Arguments:
  177. DeviceObject - Pointer to the device object.
  178. Irp - Pointer to the IRP
  179. Return Value:
  180. Status
  181. --*/
  182. {
  183. PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  184. PAGED_CODE();
  185. IoSkipCurrentIrpStackLocation(Irp);
  186. return IoCallDriver(fdoExtension->LowerDevice, Irp);
  187. }
  188. NTSTATUS
  189. PcmciaPdoSystemControl(
  190. IN PDEVICE_OBJECT DeviceObject,
  191. IN PIRP Irp
  192. )
  193. /*++
  194. Routine Description:
  195. Handles IRP_MJ_SYSTEM_CONTROL
  196. Arguments:
  197. DeviceObject - Pointer to the device object.
  198. Irp - Pointer to the IRP
  199. Return Value:
  200. Status
  201. --*/
  202. {
  203. NTSTATUS status;
  204. PPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
  205. PAGED_CODE();
  206. if (IsCardBusCard(pdoExtension)) {
  207. //
  208. // Pass irp down the stack for cardbus cards
  209. //
  210. IoSkipCurrentIrpStackLocation(Irp);
  211. status = IoCallDriver(pdoExtension->LowerDevice, Irp);
  212. } else {
  213. //
  214. // Complete the irp for R2 cards
  215. //
  216. status = Irp->IoStatus.Status;
  217. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  218. }
  219. return status;
  220. }
  221. VOID
  222. PcmciaUnload(
  223. IN PDRIVER_OBJECT DriverObject
  224. )
  225. /*++
  226. Description:
  227. Unloads the driver after cleaning up
  228. Arguments:
  229. DriverObject -- THe device drivers object
  230. Return Value:
  231. None
  232. --*/
  233. {
  234. PDEVICE_OBJECT fdo, pdo, nextFdo, nextPdo;
  235. PFDO_EXTENSION fdoExtension;
  236. PSOCKET socket, nextSocket;
  237. PPCMCIA_NTDETECT_DATA pData, pNextData;
  238. PAGED_CODE();
  239. DebugPrint((PCMCIA_DEBUG_INFO, "PcmciaUnload Entered\n"));
  240. pData = pNtDetectDataList;
  241. while(pData != NULL) {
  242. pNextData = pData->Next;
  243. ExFreePool(pData);
  244. pData = pNextData;
  245. }
  246. for (fdo = FdoList; fdo !=NULL ; fdo = nextFdo) {
  247. fdoExtension = fdo->DeviceExtension;
  248. MarkDeviceDeleted(fdoExtension);
  249. if (fdoExtension->PcmciaInterruptObject) {
  250. IoDisconnectInterrupt(fdoExtension->PcmciaInterruptObject);
  251. }
  252. //
  253. // Cleanup socket structures
  254. //
  255. for (socket=fdoExtension->SocketList; socket !=NULL; socket=nextSocket) {
  256. nextSocket = socket->NextSocket;
  257. ExFreePool(socket);
  258. }
  259. //
  260. // Remove symbolic links
  261. //
  262. if (fdoExtension->LinkName.Buffer != NULL) {
  263. IoDeleteSymbolicLink(&fdoExtension->LinkName);
  264. RtlFreeUnicodeString(&fdoExtension->LinkName);
  265. }
  266. //
  267. // Clean up all the PDOs
  268. //
  269. for (pdo=fdoExtension->PdoList; pdo != NULL; pdo=nextPdo) {
  270. nextPdo = ((PPDO_EXTENSION) pdo->DeviceExtension)->NextPdoInFdoChain;
  271. MarkDeviceDeleted((PPDO_EXTENSION)pdo->DeviceExtension);
  272. PcmciaCleanupPdo(pdo);
  273. IoDeleteDevice(pdo);
  274. }
  275. if (fdoExtension->Flags & PCMCIA_USE_POLLED_CSC) {
  276. //
  277. // Cancel the poll timer
  278. //
  279. KeCancelTimer(&fdoExtension->PollTimer);
  280. }
  281. IoDetachDevice(fdoExtension->LowerDevice);
  282. nextFdo = fdoExtension->NextFdo;
  283. IoDeleteDevice(fdo);
  284. }
  285. }