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.

479 lines
13 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. util.c
  5. Abstract:
  6. This module contains utility code used by other 1284 modules.
  7. Author:
  8. Robbie Harris (Hewlett-Packard) 20-May-1998
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "pch.h"
  14. #include "ecp.h"
  15. //============================================================================
  16. // NAME: BusReset()
  17. //
  18. // Performs a bus reset as defined in Chapter 7.2 of the
  19. // 1284-1994 spec.
  20. //
  21. // PARAMETERS:
  22. // DCRController - Supplies the base address of of the DCR.
  23. //
  24. // RETURNS:
  25. // nothing
  26. //============================================================================
  27. void BusReset(
  28. IN PUCHAR DCRController
  29. )
  30. {
  31. UCHAR dcr;
  32. dcr = READ_PORT_UCHAR(DCRController);
  33. // Set 1284 and nInit low.
  34. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, INACTIVE, DONT_CARE, DONT_CARE);
  35. WRITE_PORT_UCHAR(DCRController, dcr);
  36. KeStallExecutionProcessor(100); // Legacy Zip will hold what looks to be
  37. // a bus reset for 9us. Since this proc is used
  38. // to trigger a logic analyzer... let's hold
  39. // for 100us
  40. }
  41. BOOLEAN
  42. CheckPort(
  43. IN PUCHAR wPortAddr,
  44. IN UCHAR bMask,
  45. IN UCHAR bValue,
  46. IN USHORT msTimeDelay
  47. )
  48. /*++
  49. Routine Description:
  50. This routine will loop for a given time period (actual time is
  51. passed in as an arguement) and wait for the dsr to match
  52. predetermined value (dsr value is passed in).
  53. Arguments:
  54. wPortAddr - Supplies the base address of the parallel port + some offset.
  55. This will have us point directly to the dsr (controller + 1).
  56. bMask - Mask used to determine which bits we are looking at
  57. bValue - Value we are looking for.
  58. msTimeDelay - Max time to wait for peripheral response (in ms)
  59. Return Value:
  60. TRUE if a dsr match was found.
  61. FALSE if the time period expired before a match was found.
  62. --*/
  63. {
  64. UCHAR dsr;
  65. LARGE_INTEGER Wait;
  66. LARGE_INTEGER Start;
  67. LARGE_INTEGER End;
  68. // Do a quick check in case we have one stinkingly fast peripheral!
  69. dsr = READ_PORT_UCHAR(wPortAddr);
  70. if ((dsr & bMask) == bValue)
  71. return TRUE;
  72. Wait.QuadPart = (msTimeDelay * 10 * 1000) + KeQueryTimeIncrement();
  73. KeQueryTickCount(&Start);
  74. CheckPort_Start:
  75. KeQueryTickCount(&End);
  76. dsr = READ_PORT_UCHAR(wPortAddr);
  77. if ((dsr & bMask) == bValue)
  78. return TRUE;
  79. if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart)
  80. {
  81. // We timed out!!!
  82. // do one last check
  83. dsr = READ_PORT_UCHAR(wPortAddr);
  84. if ((dsr & bMask) == bValue)
  85. return TRUE;
  86. #if DVRH_BUS_RESET_ON_ERROR
  87. BusReset(wPortAddr+1); // Pass in the dcr address
  88. #endif
  89. #if DBG
  90. ParDump2(PARERRORS, ("CheckPort: Timeout\n"));
  91. ParDump2(PARERRORS, ("<==========================================================\n"));
  92. {
  93. int i;
  94. for (i = 3; i < 8; i++) {
  95. if ((bMask >> i) & 1) {
  96. if (((bValue >> i) & 1) != ((dsr >> i) & 1)) {
  97. ParDump2(PARERRORS, ("\t\t Bit %d is %d and should be %d!!!\n",
  98. i, (dsr >> i) & 1, (bValue >> i) & 1));
  99. }
  100. }
  101. }
  102. }
  103. ParDump2(PARERRORS, ("<==========================================================\n"));
  104. #endif
  105. goto CheckPort_TimeOut;
  106. }
  107. goto CheckPort_Start;
  108. CheckPort_TimeOut:
  109. return FALSE;
  110. }
  111. BOOLEAN
  112. CheckTwoPorts(
  113. PUCHAR pPortAddr1,
  114. UCHAR bMask1,
  115. UCHAR bValue1,
  116. PUCHAR pPortAddr2,
  117. UCHAR bMask2,
  118. UCHAR bValue2,
  119. USHORT msTimeDelay
  120. )
  121. {
  122. int i;
  123. UCHAR bPort1;
  124. UCHAR bPort2;
  125. LARGE_INTEGER Wait;
  126. LARGE_INTEGER Start;
  127. LARGE_INTEGER End;
  128. // Do a quick check in case we have one stinkingly fast peripheral!
  129. bPort1 = READ_PORT_UCHAR( pPortAddr1 );
  130. if ( ( bPort1 & bMask1 ) == bValue1 )
  131. {
  132. return TRUE;
  133. }
  134. bPort2 = READ_PORT_UCHAR( pPortAddr2 );
  135. if ( ( bPort2 & bMask2 ) == bValue2 )
  136. {
  137. return FALSE;
  138. }
  139. Wait.QuadPart = (msTimeDelay * 10 * 1000) + KeQueryTimeIncrement();
  140. KeQueryTickCount(&Start);
  141. CheckTwoPorts_Start:
  142. KeQueryTickCount(&End);
  143. bPort1 = READ_PORT_UCHAR( pPortAddr1 );
  144. if ( ( bPort1 & bMask1 ) == bValue1 )
  145. {
  146. return TRUE;
  147. }
  148. bPort2 = READ_PORT_UCHAR( pPortAddr2 );
  149. if ( ( bPort2 & bMask2 ) == bValue2 )
  150. {
  151. return FALSE;
  152. }
  153. if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() > Wait.QuadPart)
  154. {
  155. // We timed out!!!
  156. // Recheck the values
  157. bPort1 = READ_PORT_UCHAR( pPortAddr1 );
  158. if ( ( bPort1 & bMask1 ) == bValue1 )
  159. {
  160. return TRUE;
  161. }
  162. bPort2 = READ_PORT_UCHAR( pPortAddr2 );
  163. if ( ( bPort2 & bMask2 ) == bValue2 )
  164. {
  165. return FALSE;
  166. }
  167. #if DVRH_BUS_RESET_ON_ERROR
  168. BusReset(pPortAddr1+1); // Pass in the dcr address
  169. #endif
  170. // Device never responded, return timeout status.
  171. return FALSE;
  172. }
  173. goto CheckTwoPorts_Start;
  174. return FALSE;
  175. } // CheckPort2...
  176. PWSTR
  177. ParCreateWideStringFromUnicodeString(PUNICODE_STRING UnicodeString)
  178. /*++
  179. Routine Description:
  180. Create a UNICODE_NULL terminated WSTR given a UNICODE_STRING.
  181. This function allocates PagedPool, copies the UNICODE_STRING buffer
  182. to the allocation, and appends a UNICODE_NULL to terminate the WSTR
  183. *** This function allocates pool. ExFreePool must be called to free
  184. the allocation when the buffer is no longer needed.
  185. Arguments:
  186. UnicodeString - The source
  187. Return Value:
  188. PWSTR - if successful
  189. NULL - otherwise
  190. --*/
  191. {
  192. PWSTR buffer;
  193. ULONG length = UnicodeString->Length;
  194. buffer = ExAllocatePool( PagedPool, length + sizeof(UNICODE_NULL) );
  195. if(!buffer) {
  196. return NULL; // unable to allocate pool, bail out
  197. } else {
  198. RtlCopyMemory(buffer, UnicodeString->Buffer, length);
  199. buffer[length/2] = UNICODE_NULL;
  200. return buffer;
  201. }
  202. }
  203. NTSTATUS
  204. ParCreateDevice(
  205. IN PDRIVER_OBJECT DriverObject,
  206. IN ULONG DeviceExtensionSize,
  207. IN PUNICODE_STRING DeviceName OPTIONAL,
  208. IN DEVICE_TYPE DeviceType,
  209. IN ULONG DeviceCharacteristics,
  210. IN BOOLEAN Exclusive,
  211. OUT PDEVICE_OBJECT *DeviceObject
  212. )
  213. {
  214. NTSTATUS status;
  215. status = IoCreateDevice( DriverObject,
  216. DeviceExtensionSize,
  217. DeviceName,
  218. DeviceType,
  219. (DeviceCharacteristics | FILE_DEVICE_SECURE_OPEN),
  220. Exclusive,
  221. DeviceObject );
  222. return status;
  223. }
  224. VOID
  225. ParInitializeExtension1284Info(
  226. IN PDEVICE_EXTENSION Extension
  227. )
  228. // make this a function since it is now called from two places:
  229. // - 1) when initializing a new devobj
  230. // - 2) from CreateOpen
  231. {
  232. USHORT i;
  233. Extension->Connected = FALSE;
  234. if (DefaultModes)
  235. {
  236. USHORT rev = (USHORT) (DefaultModes & 0xffff);
  237. USHORT fwd = (USHORT)((DefaultModes & 0xffff0000)>>16);
  238. switch (fwd)
  239. {
  240. case BOUNDED_ECP:
  241. Extension->IdxForwardProtocol = BOUNDED_ECP_FORWARD;
  242. break;
  243. case ECP_HW_NOIRQ:
  244. case ECP_HW_IRQ:
  245. Extension->IdxForwardProtocol = ECP_HW_FORWARD_NOIRQ;
  246. break;
  247. case ECP_SW:
  248. Extension->IdxForwardProtocol = ECP_SW_FORWARD;
  249. break;
  250. case EPP_HW:
  251. Extension->IdxForwardProtocol = EPP_HW_FORWARD;
  252. break;
  253. case EPP_SW:
  254. Extension->IdxForwardProtocol = EPP_SW_FORWARD;
  255. break;
  256. case IEEE_COMPATIBILITY:
  257. Extension->IdxForwardProtocol = IEEE_COMPAT_MODE;
  258. break;
  259. case CENTRONICS:
  260. default:
  261. Extension->IdxForwardProtocol = CENTRONICS_MODE;
  262. break;
  263. }
  264. switch (rev)
  265. {
  266. case BOUNDED_ECP:
  267. Extension->IdxReverseProtocol = BOUNDED_ECP_REVERSE;
  268. break;
  269. case ECP_HW_NOIRQ:
  270. case ECP_HW_IRQ:
  271. Extension->IdxReverseProtocol = ECP_HW_REVERSE_NOIRQ;
  272. break;
  273. case ECP_SW:
  274. Extension->IdxReverseProtocol = ECP_SW_REVERSE;
  275. break;
  276. case EPP_HW:
  277. Extension->IdxReverseProtocol = EPP_HW_REVERSE;
  278. break;
  279. case EPP_SW:
  280. Extension->IdxReverseProtocol = EPP_SW_REVERSE;
  281. break;
  282. case BYTE_BIDIR:
  283. Extension->IdxReverseProtocol = BYTE_MODE;
  284. break;
  285. case CHANNEL_NIBBLE:
  286. case NIBBLE:
  287. default:
  288. Extension->IdxReverseProtocol = NIBBLE_MODE;
  289. break;
  290. }
  291. }
  292. else
  293. {
  294. Extension->IdxReverseProtocol = NIBBLE_MODE;
  295. Extension->IdxForwardProtocol = CENTRONICS_MODE;
  296. }
  297. Extension->bShadowBuffer = FALSE;
  298. Extension->ProtocolModesSupported = 0;
  299. Extension->BadProtocolModes = 0;
  300. Extension->IsCritical = FALSE;
  301. #if (1 == DVRH_USE_CORRECT_PTRS)
  302. Extension->fnRead = NULL;
  303. Extension->fnWrite = NULL;
  304. // Extension->fnRead = arpReverse[Extension->IdxReverseProtocol].fnRead;
  305. // Extension->fnWrite = afpForward[Extension->IdxForwardProtocol].fnWrite;
  306. #endif
  307. Extension->ForwardInterfaceAddress = DEFAULT_ECP_CHANNEL;
  308. Extension->ReverseInterfaceAddress = DEFAULT_ECP_CHANNEL;
  309. Extension->SetForwardAddress = FALSE;
  310. Extension->SetReverseAddress = FALSE;
  311. Extension->bIsHostRecoverSupported = FALSE;
  312. Extension->IsIeeeTerminateOk = FALSE;
  313. for (i = FAMILY_NONE; i < FAMILY_MAX; i++) {
  314. Extension->ProtocolData[i] = 0;
  315. }
  316. }
  317. #if (1 == DVRH_DELAY_THEORY)
  318. void DVRH_Diagnostic_Delay()
  319. {
  320. LARGE_INTEGER Interval;
  321. //in 100ns increments
  322. Interval.QuadPart = 1000;
  323. KeDelayExecutionThread(
  324. KernelMode,
  325. FALSE,
  326. &Interval
  327. );
  328. }
  329. #endif
  330. VOID
  331. ParGetDriverParameterDword(
  332. IN PUNICODE_STRING ServicePath,
  333. IN PWSTR ParameterName,
  334. IN OUT PULONG ParameterValue
  335. )
  336. /*++
  337. Read registry DWORD from <ServicePath>\Parameters
  338. --*/
  339. {
  340. NTSTATUS status;
  341. RTL_QUERY_REGISTRY_TABLE paramTable[2];
  342. PWSTR suffix = L"\\Parameters";
  343. ULONG defaultValue;
  344. UNICODE_STRING path = {0,0,0};
  345. ULONG length;
  346. //
  347. // Sanity check parameters
  348. //
  349. if( ( NULL == ServicePath->Buffer ) || ( NULL == ParameterName ) || ( NULL == ParameterValue ) ) {
  350. return;
  351. }
  352. //
  353. // set up table entries for call to RtlQueryRegistryValues
  354. //
  355. RtlZeroMemory( paramTable, sizeof(paramTable));
  356. defaultValue = *ParameterValue;
  357. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  358. paramTable[0].Name = ParameterName;
  359. paramTable[0].EntryContext = ParameterValue;
  360. paramTable[0].DefaultType = REG_DWORD;
  361. paramTable[0].DefaultData = &defaultValue;
  362. paramTable[0].DefaultLength = sizeof(ULONG);
  363. //
  364. // leave paramTable[2] as all zeros - this terminates the table
  365. //
  366. //
  367. // compute the size of the path including the "parameters" suffix
  368. //
  369. length = ( sizeof(WCHAR) * wcslen( suffix ) ) + sizeof(UNICODE_NULL);
  370. length += RegistryPath.Length;
  371. //
  372. // construct the path as: <ServiceName>\Parameters
  373. //
  374. path.Buffer = ExAllocatePool( PagedPool, length );
  375. if( NULL == path.Buffer ) {
  376. return;
  377. }
  378. RtlZeroMemory( path.Buffer, length );
  379. path.MaximumLength = (USHORT)length;
  380. RtlCopyUnicodeString( &path, &RegistryPath );
  381. RtlAppendUnicodeToString( &path, suffix );
  382. ParDump2(PARREG,("util::ParGetDriverParameterDword - path = <%wZ>\n", &path));
  383. ParDump2(PARREG,("util::ParGetDriverParameterDword - pre-query value = %x\n", *ParameterValue));
  384. //
  385. // query registry
  386. //
  387. status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  388. path.Buffer,
  389. &paramTable[0],
  390. NULL,
  391. NULL);
  392. RtlFreeUnicodeString( &path );
  393. ParDump2(PARREG,("util::ParGetDriverParameterDword - post-query value = %x\n", *ParameterValue));
  394. ParDump2(PARREG,("util::ParGetDriverParameterDword - status from RtlQueryRegistryValues on SubKey = %x\n", status) );
  395. return;
  396. }