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.

541 lines
13 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. parclass.c
  5. Abstract:
  6. This module contains the code for the parallel class driver.
  7. Author:
  8. Anthony V. Ercolano 1-Aug-1992
  9. Norbert P. Kusters 22-Oct-1993
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. Timothy T. Wells (v-timtw) 13-Mar-97
  14. Pretty serious overhaul to this and other files on this project to support additional modes
  15. (EPP, ECP and others), as well as some new filter driver interfaces.
  16. --*/
  17. #include "pch.h"
  18. #include <initguid.h>
  19. #include <ntddpar.h>
  20. #include <wdmguid.h>
  21. #if DBG
  22. //
  23. // Initialize both debug variables even though both will be set
  24. // based on registry values in function ParInitDebugLevel(...)
  25. // during DriverEntry(...)
  26. //
  27. // How verbose do we want parallel.sys to be with DbgPrint messages?
  28. // ULONG ParDebugLevel = PARDUMP_VERBOSE_MAX;
  29. ULONG ParDebugLevel = PARDUMP_VERBOSE_MAX;
  30. // What conditions do we want to break on?
  31. // ULONG ParBreakOn = PAR_BREAK_ON_NOTHING;
  32. ULONG ParBreakOn = PAR_BREAK_ON_NOTHING;
  33. ULONG ParUseAsserts = 0;
  34. #endif // DBG
  35. // enable scans for Legacy Zip?
  36. ULONG ParEnableLegacyZip = 0;
  37. PCHAR ParLegacyZipPseudoId = PAR_LGZIP_PSEUDO_1284_ID_STRING;
  38. ULONG DumpDevExtTable = 0; // want to default to zero in non-debugging environment
  39. ULONG SppNoRaiseIrql = 0;
  40. ULONG DefaultModes = 0;
  41. ULONG gSppLoopDelay = 0;
  42. ULONG gSppLoopBytesPerDelay = 0;
  43. //
  44. // Temporary Development Globals - used as switches in debug code
  45. //
  46. ULONG tdev1 = 1;
  47. ULONG tdev2 = 0;
  48. extern const PHYSICAL_ADDRESS PhysicalZero = {0};
  49. //
  50. // Definition of OpenCloseMutex. RMT DO WE NEED THIS ???
  51. //
  52. extern ULONG OpenCloseReferenceCount = 1;
  53. extern PFAST_MUTEX OpenCloseMutex = NULL;
  54. //
  55. // Declarations only (Definition in Ieee1284.c)
  56. //
  57. extern FORWARD_PTCL afpForward[];
  58. extern REVERSE_PTCL arpReverse[];
  59. UCHAR
  60. ParInitializeDevice(
  61. IN PDEVICE_EXTENSION Extension
  62. )
  63. /*++
  64. Routine Description:
  65. This routine is invoked to initialize the parallel port drive.
  66. It performs the following actions:
  67. o Send INIT to the driver and if the device is online.
  68. Arguments:
  69. Context - Really the device extension.
  70. Return Value:
  71. The last value that we got from the status register.
  72. --*/
  73. {
  74. KIRQL OldIrql;
  75. UCHAR DeviceStatus = 0;
  76. LARGE_INTEGER StartOfSpin = {0,0};
  77. LARGE_INTEGER NextQuery = {0,0};
  78. LARGE_INTEGER Difference = {0,0};
  79. ParDump2(PARENTRY, ("Enter ParInitializeDevice(...)\n") );
  80. //
  81. // Tim Wells (WestTek, L.L.C.)
  82. //
  83. // - Removed the deferred initialization code from DriverEntry, device creation
  84. // code. This code will be better utilized in the Create/Open logic or from
  85. // the calling application.
  86. //
  87. // - Changed this code to always reset when asked, and to return after a fixed
  88. // interval reqardless of the response. Additional responses can be provided by
  89. // read and write code.
  90. //
  91. //
  92. // Clear the register.
  93. //
  94. if (GetControl(Extension->Controller) & PAR_CONTROL_NOT_INIT) {
  95. //
  96. // We should stall for at least 60 microseconds after the init.
  97. //
  98. KeRaiseIrql( DISPATCH_LEVEL, &OldIrql );
  99. StoreControl( Extension->Controller, (UCHAR)(PAR_CONTROL_WR_CONTROL | PAR_CONTROL_SLIN) );
  100. KeStallExecutionProcessor(60);
  101. KeLowerIrql(OldIrql);
  102. }
  103. StoreControl( Extension->Controller,
  104. (UCHAR)(PAR_CONTROL_WR_CONTROL | PAR_CONTROL_NOT_INIT | PAR_CONTROL_SLIN) );
  105. //
  106. // Spin waiting for the device to initialize.
  107. //
  108. KeQueryTickCount(&StartOfSpin);
  109. ParDumpV( ("Starting init wait loop\n") );
  110. do {
  111. KeQueryTickCount(&NextQuery);
  112. Difference.QuadPart = NextQuery.QuadPart - StartOfSpin.QuadPart;
  113. ASSERT(KeQueryTimeIncrement() <= MAXLONG);
  114. if (Difference.QuadPart*KeQueryTimeIncrement() >= Extension->AbsoluteOneSecond.QuadPart) {
  115. //
  116. // Give up on getting PAR_OK.
  117. //
  118. ParDump2(PARINITDEV, ("Did spin of one second - StartOfSpin: %x NextQuery: %x\n",
  119. StartOfSpin.LowPart,NextQuery.LowPart) );
  120. ParDump2(PARINITDEV, ("ParInitialize 1 seconds wait\n") );
  121. break;
  122. }
  123. DeviceStatus = GetStatus(Extension->Controller);
  124. } while (!PAR_OK(DeviceStatus));
  125. return (DeviceStatus);
  126. }
  127. VOID
  128. ParNotInitError(
  129. IN PDEVICE_EXTENSION Extension,
  130. IN UCHAR DeviceStatus
  131. )
  132. /*++
  133. Routine Description:
  134. Arguments:
  135. Extension - Supplies the device extension.
  136. deviceStatus - Last read status.
  137. Return Value:
  138. None.
  139. --*/
  140. {
  141. PIRP Irp = Extension->CurrentOpIrp;
  142. if (PAR_OFF_LINE(DeviceStatus)) {
  143. Irp->IoStatus.Status = STATUS_DEVICE_OFF_LINE;
  144. ParDump(PARSTARTER | PARDUMP_VERBOSE_MAX,
  145. ("PARALLEL: "
  146. "Init Error - off line - "
  147. "STATUS/INFORMATON: %x/%x\n",
  148. Irp->IoStatus.Status, Irp->IoStatus.Information) );
  149. } else if (PAR_NO_CABLE(DeviceStatus)) {
  150. Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
  151. ParDump(PARSTARTER | PARDUMP_VERBOSE_MAX,
  152. ("PARALLEL: "
  153. "Init Error - no cable - not connected - "
  154. "STATUS/INFORMATON: %x/%x\n",
  155. Irp->IoStatus.Status, Irp->IoStatus.Information) );
  156. } else if (PAR_PAPER_EMPTY(DeviceStatus)) {
  157. Irp->IoStatus.Status = STATUS_DEVICE_PAPER_EMPTY;
  158. ParDump(PARSTARTER | PARDUMP_VERBOSE_MAX,
  159. ("PARALLEL: "
  160. "Init Error - paper empty - "
  161. "STATUS/INFORMATON: %x/%x\n",
  162. Irp->IoStatus.Status, Irp->IoStatus.Information) );
  163. } else if (PAR_POWERED_OFF(DeviceStatus)) {
  164. Irp->IoStatus.Status = STATUS_DEVICE_POWERED_OFF;
  165. ParDump(PARSTARTER | PARDUMP_VERBOSE_MAX,
  166. ("PARALLEL: "
  167. "Init Error - power off - "
  168. "STATUS/INFORMATON: %x/%x\n",
  169. Irp->IoStatus.Status, Irp->IoStatus.Information) );
  170. } else {
  171. Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
  172. ParDump(PARSTARTER | PARDUMP_VERBOSE_MAX,
  173. ("PARALLEL: "
  174. "Init Error - not conn - "
  175. "STATUS/INFORMATON: %x/%x\n",
  176. Irp->IoStatus.Status, Irp->IoStatus.Information) );
  177. }
  178. }
  179. VOID
  180. ParCancelRequest(
  181. PDEVICE_OBJECT DeviceObject,
  182. PIRP Irp
  183. )
  184. /*++
  185. Routine Description:
  186. This routine is used to cancel any request in the parallel driver.
  187. Arguments:
  188. DeviceObject - Pointer to the device object for this device
  189. Irp - Pointer to the IRP to be canceled.
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. ParDumpV( ("ParCancelRequest: DO= %x , Irp= %x Cancel=%d, CancelRoutine= %x\n",
  195. DeviceObject, Irp, Irp->Cancel, Irp->CancelRoutine) );
  196. //
  197. // The only reason that this irp can be on the queue is
  198. // if it's not the current irp. Pull it off the queue
  199. // and complete it as canceled.
  200. //
  201. ASSERT(!IsListEmpty(&Irp->Tail.Overlay.ListEntry));
  202. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  203. IoReleaseCancelSpinLock(Irp->CancelIrql);
  204. Irp->IoStatus.Status = STATUS_CANCELLED;
  205. Irp->IoStatus.Information = 0;
  206. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  207. }
  208. NTSTATUS
  209. ParQueryInformationFile(
  210. IN PDEVICE_OBJECT DeviceObject,
  211. IN PIRP Irp
  212. )
  213. /*++
  214. Routine Description:
  215. This routine is used to query the end of file information on
  216. the opened parallel port. Any other file information request
  217. is retured with an invalid parameter.
  218. This routine always returns an end of file of 0.
  219. Arguments:
  220. DeviceObject - Supplies the device object.
  221. Irp - Supplies the I/O request packet.
  222. Return Value:
  223. STATUS_SUCCESS - Success.
  224. STATUS_INVALID_PARAMETER - Invalid file information request.
  225. STATUS_BUFFER_TOO_SMALL - Buffer too small.
  226. --*/
  227. {
  228. NTSTATUS Status;
  229. PIO_STACK_LOCATION IrpSp;
  230. PFILE_STANDARD_INFORMATION StdInfo;
  231. PFILE_POSITION_INFORMATION PosInfo;
  232. PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  233. UNREFERENCED_PARAMETER(DeviceObject);
  234. // ParDumpV( ("In query information file\n") );
  235. //
  236. // bail out if device has been removed
  237. //
  238. if(Extension->DeviceStateFlags & (PAR_DEVICE_REMOVED|PAR_DEVICE_SURPRISE_REMOVAL) ) {
  239. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  240. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  241. return STATUS_DEVICE_REMOVED;
  242. }
  243. Irp->IoStatus.Information = 0;
  244. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  245. switch (IrpSp->Parameters.QueryFile.FileInformationClass) {
  246. case FileStandardInformation:
  247. if (IrpSp->Parameters.QueryFile.Length < sizeof(FILE_STANDARD_INFORMATION)) {
  248. Status = STATUS_BUFFER_TOO_SMALL;
  249. } else {
  250. StdInfo = Irp->AssociatedIrp.SystemBuffer;
  251. StdInfo->AllocationSize.QuadPart = 0;
  252. StdInfo->EndOfFile = StdInfo->AllocationSize;
  253. StdInfo->NumberOfLinks = 0;
  254. StdInfo->DeletePending = FALSE;
  255. StdInfo->Directory = FALSE;
  256. Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
  257. Status = STATUS_SUCCESS;
  258. }
  259. break;
  260. case FilePositionInformation:
  261. if (IrpSp->Parameters.SetFile.Length < sizeof(FILE_POSITION_INFORMATION)) {
  262. Status = STATUS_BUFFER_TOO_SMALL;
  263. } else {
  264. PosInfo = Irp->AssociatedIrp.SystemBuffer;
  265. PosInfo->CurrentByteOffset.QuadPart = 0;
  266. Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
  267. Status = STATUS_SUCCESS;
  268. }
  269. break;
  270. default:
  271. Status = STATUS_INVALID_PARAMETER;
  272. break;
  273. }
  274. Irp->IoStatus.Status = Status;
  275. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  276. return Status;
  277. }
  278. NTSTATUS
  279. ParSetInformationFile(
  280. IN PDEVICE_OBJECT DeviceObject,
  281. IN PIRP Irp
  282. )
  283. /*++
  284. Routine Description:
  285. This routine is used to set the end of file information on
  286. the opened parallel port. Any other file information request
  287. is retured with an invalid parameter.
  288. This routine always ignores the actual end of file since
  289. the query information code always returns an end of file of 0.
  290. Arguments:
  291. DeviceObject - Supplies the device object.
  292. Irp - Supplies the I/O request packet.
  293. Return Value:
  294. STATUS_SUCCESS - Success.
  295. STATUS_INVALID_PARAMETER - Invalid file information request.
  296. --*/
  297. {
  298. NTSTATUS Status;
  299. FILE_INFORMATION_CLASS fileInfoClass;
  300. PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  301. UNREFERENCED_PARAMETER(DeviceObject);
  302. //
  303. // bail out if device has been removed
  304. //
  305. if(Extension->DeviceStateFlags & (PAR_DEVICE_REMOVED|PAR_DEVICE_SURPRISE_REMOVAL) ) {
  306. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  307. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  308. return STATUS_DEVICE_REMOVED;
  309. }
  310. // ParDump(PARIRPPATH | PARDUMP_VERBOSE_MAX,
  311. // ("PARALLEL: "
  312. // "In set information with IRP: %08x\n",
  313. // Irp) );
  314. Irp->IoStatus.Information = 0;
  315. fileInfoClass = IoGetCurrentIrpStackLocation(Irp)->Parameters.SetFile.FileInformationClass;
  316. if (fileInfoClass == FileEndOfFileInformation) {
  317. Status = STATUS_SUCCESS;
  318. } else {
  319. // ParDump(PARDUMP_VERBOSE_MAX,
  320. // ("PARALLEL: "
  321. // "In ParSetInformationFile(...): "
  322. // "Invalid FileInformationClass: %d , only %d is valid\n"
  323. // "PARALLEL: "
  324. // " - Returning STATUS_INVALID_PARAMETER\n",
  325. // fileInfoClass, FileEndOfFileInformation) );
  326. Status = STATUS_INVALID_PARAMETER;
  327. }
  328. Irp->IoStatus.Status = Status;
  329. // ParDump(PARDUMP_VERBOSE_MAX,
  330. // ("PARALLEL: "
  331. // "About to complete IRP in set information - "
  332. // "Irp: %x status: %x Information: %x\n",
  333. // Irp, Irp->IoStatus.Status, Irp->IoStatus.Information) );
  334. ParCompleteRequest(Irp, IO_NO_INCREMENT);
  335. return Status;
  336. }
  337. #if PAR_NO_FAST_CALLS
  338. // temp debug functions so params show up on stack trace
  339. VOID
  340. ParCompleteRequest(
  341. IN PIRP Irp,
  342. IN CCHAR PriorityBoost
  343. )
  344. {
  345. // KIRQL CancelIrql;
  346. // IoAcquireCancelSpinLock(&CancelIrql);
  347. // ASSERT( !Irp->CancelRoutine );
  348. // IoReleaseCancelSpinLock(CancelIrql);
  349. if( Irp->UserEvent ) {
  350. ASSERT_EVENT( Irp->UserEvent );
  351. }
  352. IoCompleteRequest(Irp, PriorityBoost);
  353. }
  354. NTSTATUS
  355. ParCallDriver(
  356. IN PDEVICE_OBJECT DeviceObject,
  357. IN OUT PIRP Irp
  358. )
  359. {
  360. return IoCallDriver(DeviceObject, Irp);
  361. }
  362. #endif