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.

897 lines
31 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. p12843dl.c
  5. Abstract:
  6. This module contains utility code used by 1284.3 Data Link.
  7. Author:
  8. Robbie Harris (Hewlett-Packard) 10-September-1998
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "pch.h"
  14. UCHAR Dot3_StartOfFrame1 = 0x55;
  15. UCHAR Dot3_StartOfFrame2 = 0xaa;
  16. UCHAR Dot3_EndOfFrame1 = 0x00;
  17. UCHAR Dot3_EndOfFrame2 = 0xff;
  18. NTSTATUS
  19. ParDot3Connect(
  20. IN PPDO_EXTENSION Pdx
  21. )
  22. {
  23. NTSTATUS Status = STATUS_SUCCESS;
  24. ULONG ParFwdSkip = 0, ParRevSkip = 0;
  25. ULONG ParResetChannel = (ULONG)~0, ParResetByteCount = 4, ParResetByte = 0;
  26. ULONG ParSkipDefault = 0;
  27. ULONG ParResetChannelDefault = (ULONG)~0;
  28. // If an MLC device hangs we can sometimes wake it up by wacking it with
  29. // 4 Zeros sent to the reset channel (typically 78 or 0x4E). Make this
  30. // configurable via registry setting.
  31. ULONG ParResetByteCountDefault = 4; // from MLC spec
  32. ULONG ParResetByteDefault = 0; // from MLC spec
  33. BOOLEAN bConsiderEppDangerous = FALSE;
  34. DD((PCE)Pdx,DDT,"ParDot3Connect: enter\n");
  35. if (P12843DL_OFF == Pdx->P12843DL.DataLinkMode) {
  36. DD((PCE)Pdx,DDT,"ParDot3Connect: Neither Dot3 or MLC are supported - FAIL request\n");
  37. return STATUS_UNSUCCESSFUL;
  38. }
  39. if (Pdx->P12843DL.bEventActive) {
  40. DD((PCE)Pdx,DDT,"ParDot3Connect: Already connected - FAIL request\n");
  41. return STATUS_UNSUCCESSFUL;
  42. }
  43. // Let's get a Device Id so we can pull settings for this device
  44. ParTerminate(Pdx);
  45. { // local block
  46. PCHAR buffer = NULL;
  47. ULONG bufferLength;
  48. UCHAR resultString[MAX_ID_SIZE];
  49. ANSI_STRING AnsiIdString;
  50. UNICODE_STRING UnicodeTemp;
  51. RTL_QUERY_REGISTRY_TABLE paramTable[6];
  52. UNICODE_STRING Dot3Key;
  53. USHORT Dot3NameSize;
  54. NTSTATUS status;
  55. RtlZeroMemory(resultString, MAX_ID_SIZE);
  56. // ask the device how large of a buffer is needed to hold it's raw device id
  57. if ( Pdx->Ieee1284Flags & ( 1 << Pdx->Ieee1284_3DeviceId ) ) {
  58. buffer = Par3QueryDeviceId(Pdx, NULL, 0, &bufferLength, FALSE, TRUE);
  59. } else{
  60. buffer = Par3QueryDeviceId(Pdx, NULL, 0, &bufferLength, FALSE, FALSE);
  61. }
  62. if( !buffer ) {
  63. DD((PCE)Pdx,DDT,"ParDot3Connect - Couldn't alloc pool for DevId - FAIL request\n");
  64. return STATUS_UNSUCCESSFUL;
  65. }
  66. DD((PCE)Pdx,DDT,"ParDot3Connect - 1284 ID string = <%s>\n",buffer);
  67. // extract the part of the ID that we want from the raw string
  68. // returned by the hardware
  69. Status = ParPnpGetId( buffer, BusQueryDeviceID, (PCHAR)resultString, NULL );
  70. StringSubst( (PCHAR)resultString, ' ', '_', (USHORT)strlen((const PCHAR)resultString) );
  71. DD((PCE)Pdx,DDT,"ParDot3Connect: resultString Post StringSubst = <%s>\n",resultString);
  72. // were we able to extract the info that we want from the raw ID string?
  73. if( !NT_SUCCESS(Status) ) {
  74. DD((PCE)Pdx,DDT,"ParDot3Connect - Call to ParPnpGetId Failed - FAIL request\n");
  75. if( buffer ) {
  76. ExFreePool( buffer );
  77. }
  78. return STATUS_UNSUCCESSFUL;
  79. }
  80. // Does the ID that we just retrieved from the device match the one
  81. // that we previously saved in the device extension?
  82. if(0 != strcmp( (const PCHAR)Pdx->DeviceIdString, (const PCHAR)resultString)) {
  83. DD((PCE)Pdx,DDT,"ParDot3Connect - strcmp shows NO MATCH\n");
  84. // DVDF - we may want to trigger a reenumeration since we know that the device changed
  85. }
  86. // Ok, now we have what we need to look in the registry
  87. // and pull some prefs.
  88. RtlZeroMemory(&paramTable[0], sizeof(paramTable));
  89. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  90. paramTable[0].Name = (PWSTR)L"ParFwdSkip";
  91. paramTable[0].EntryContext = &ParFwdSkip;
  92. paramTable[0].DefaultType = REG_DWORD;
  93. paramTable[0].DefaultData = &ParSkipDefault;
  94. paramTable[0].DefaultLength = sizeof(ULONG);
  95. paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  96. paramTable[1].Name = (PWSTR)L"ParRevSkip";
  97. paramTable[1].EntryContext = &ParRevSkip;
  98. paramTable[1].DefaultType = REG_DWORD;
  99. paramTable[1].DefaultData = &ParSkipDefault;
  100. paramTable[1].DefaultLength = sizeof(ULONG);
  101. paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
  102. paramTable[2].Name = (PWSTR)L"ParRC";
  103. paramTable[2].EntryContext = &ParResetChannel;
  104. paramTable[2].DefaultType = REG_DWORD;
  105. paramTable[2].DefaultData = &ParResetChannelDefault;
  106. paramTable[2].DefaultLength = sizeof(ULONG);
  107. paramTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
  108. paramTable[3].Name = (PWSTR)L"ParRBC";
  109. paramTable[3].EntryContext = &ParResetByteCount;
  110. paramTable[3].DefaultType = REG_DWORD;
  111. paramTable[3].DefaultData = &ParResetByteCountDefault;
  112. paramTable[3].DefaultLength = sizeof(ULONG);
  113. paramTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  114. paramTable[4].Name = (PWSTR)L"ParRBD";
  115. paramTable[4].EntryContext = &ParResetByte;
  116. paramTable[4].DefaultType = REG_DWORD;
  117. paramTable[4].DefaultData = &ParResetByteDefault;
  118. paramTable[4].DefaultLength = sizeof(ULONG);
  119. Dot3Key.Buffer = NULL;
  120. Dot3Key.Length = 0;
  121. Dot3NameSize = sizeof(L"Dot3\\") + sizeof(UNICODE_NULL);
  122. Dot3Key.MaximumLength = (USHORT)( Dot3NameSize + (MAX_ID_SIZE * sizeof(WCHAR)) );
  123. Dot3Key.Buffer = ExAllocatePool(PagedPool,
  124. Dot3Key.MaximumLength);
  125. if( !Dot3Key.Buffer ) {
  126. DD((PCE)Pdx,DDT,"ParDot3Connect - ExAllocatePool for Registry Check failed - FAIL request\n");
  127. if( buffer ) {
  128. ExFreePool( buffer );
  129. }
  130. return STATUS_UNSUCCESSFUL;
  131. }
  132. DD((PCE)Pdx,DDT,"ParDot3Connect: ready to Zero buffer, &Dot3Key= %x , MaximumLength=%d\n",&Dot3Key, Dot3Key.MaximumLength);
  133. RtlZeroMemory(Dot3Key.Buffer, Dot3Key.MaximumLength);
  134. status = RtlAppendUnicodeToString(&Dot3Key, (PWSTR)L"Dot3\\");
  135. ASSERT( NT_SUCCESS(status) );
  136. DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key S = <%S>\n",Dot3Key.Buffer);
  137. DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key wZ = <%wZ>\n",&Dot3Key);
  138. DD((PCE)Pdx,DDT,"ParDot3Connect:\"RAW\" resultString string = <%s>\n",resultString);
  139. RtlInitAnsiString(&AnsiIdString,(const PCHAR)resultString);
  140. status = RtlAnsiStringToUnicodeString(&UnicodeTemp,&AnsiIdString,TRUE);
  141. if( NT_SUCCESS( status ) ) {
  142. DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" UnicodeTemp = <%S>\n",UnicodeTemp.Buffer);
  143. Dot3Key.Buffer[(Dot3NameSize / sizeof(WCHAR)) - 1] = UNICODE_NULL;
  144. DD((PCE)Pdx,DDT,"ParDot3Connect:\"UNICODE\" Dot3Key (preappend) = <%S>\n",Dot3Key.Buffer);
  145. status = RtlAppendUnicodeStringToString(&Dot3Key, &UnicodeTemp);
  146. if( NT_SUCCESS( status ) ) {
  147. DD((PCE)Pdx,DDT,"ParDot3Connect: ready to call RtlQuery...\n");
  148. Status = RtlQueryRegistryValues( RTL_REGISTRY_CONTROL, Dot3Key.Buffer, &paramTable[0], NULL, NULL);
  149. DD((PCE)Pdx,DDT,"ParDot3Connect: RtlQueryRegistryValues Status = %x\n",Status);
  150. }
  151. RtlFreeUnicodeString(&UnicodeTemp);
  152. }
  153. if( Dot3Key.Buffer ) {
  154. ExFreePool (Dot3Key.Buffer);
  155. }
  156. // no longer needed
  157. ExFreePool(buffer);
  158. if (!NT_SUCCESS(Status)) {
  159. // registry read failed
  160. DD((PCE)Pdx,DDT,"ParDot3Connect: No Periph Defaults in Registry\n");
  161. DD((PCE)Pdx,DDT,"ParDot3Connect: No Periph Defaults in Registry\n");
  162. // registry read failed, use defaults and consider EPP to be dangerous
  163. ParRevSkip = ParFwdSkip = ParSkipDefault;
  164. bConsiderEppDangerous = TRUE;
  165. }
  166. DD((PCE)Pdx,DDT,"ParDot3Connect: pre IeeeNegotiateBestMode\n");
  167. // if we don't have registry overrides then use what the
  168. // peripheral told us otherwise stick with defaults.
  169. if (ParSkipDefault == ParRevSkip) {
  170. ParRevSkip = Pdx->P12843DL.RevSkipMask;
  171. } else {
  172. Pdx->P12843DL.RevSkipMask = (USHORT)ParRevSkip;
  173. }
  174. if (ParSkipDefault == ParFwdSkip) {
  175. ParFwdSkip = Pdx->P12843DL.FwdSkipMask;
  176. } else {
  177. Pdx->P12843DL.FwdSkipMask = (USHORT)ParFwdSkip;
  178. }
  179. if( bConsiderEppDangerous ) {
  180. ParFwdSkip |= EPP_ANY;
  181. ParRevSkip |= EPP_ANY;
  182. }
  183. Status = IeeeNegotiateBestMode(Pdx, (USHORT)ParRevSkip, (USHORT)ParFwdSkip);
  184. if( !NT_SUCCESS(Status) ) {
  185. DD((PCE)Pdx,DDT,"ParDot3Connect - Peripheral Negotiation Failed - FAIL dataLink connect\n");
  186. return Status;
  187. }
  188. Pdx->ForwardInterfaceAddress = Pdx->P12843DL.DataChannel;
  189. if (Pdx->P12843DL.DataLinkMode == P12843DL_MLC_DL) {
  190. if (ParResetChannel != ParResetChannelDefault) {
  191. Pdx->P12843DL.ResetByte = (UCHAR) ParResetByte & 0xff;
  192. Pdx->P12843DL.ResetByteCount = (UCHAR) ParResetByteCount & 0xff;
  193. if (ParResetChannel == PAR_COMPATIBILITY_RESET) {
  194. Pdx->P12843DL.fnReset = ParMLCCompatReset;
  195. } else {
  196. // Max ECP channel is 127 so let's mask off bogus bits.
  197. Pdx->P12843DL.ResetChannel = (UCHAR) ParResetChannel & 0x7f;
  198. Pdx->P12843DL.fnReset = ParMLCECPReset;
  199. }
  200. }
  201. }
  202. if (Pdx->P12843DL.fnReset) {
  203. DD((PCE)Pdx,DDT,"ParDot3Connect: MLCReset is supported on %x\n",Pdx->P12843DL.ResetChannel);
  204. Status = ((PDOT3_RESET_ROUTINE) (Pdx->P12843DL.fnReset))(Pdx);
  205. } else {
  206. DD((PCE)Pdx,DDT,"ParDot3Connect - MLCReset is not supported\n");
  207. Status = ParSetFwdAddress(Pdx);
  208. }
  209. if( !NT_SUCCESS(Status) ) {
  210. DD((PCE)Pdx,DDT,"ParDot3Connect - Couldn't Set Address - FAIL request\n");
  211. return Status;
  212. }
  213. // Check to make sure we are ECP, BECP, or EPP
  214. DD((PCE)Pdx,DDT,"ParDot3Connect: pre check of ECP, BECP, EPP\n");
  215. if (afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_BECP &&
  216. afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_ECP &&
  217. afpForward[Pdx->IdxForwardProtocol].ProtocolFamily != FAMILY_EPP) {
  218. DD((PCE)Pdx,DDT,"ParDot3Connect - We did not reach ECP or EPP - FAIL request\n");
  219. return STATUS_UNSUCCESSFUL;
  220. }
  221. } // end local block
  222. if (Pdx->P12843DL.DataLinkMode == P12843DL_DOT3_DL) {
  223. DD((PCE)Pdx,DDT,"ParDot3Connect - P12843DL_DOT3_DL\n");
  224. Pdx->P12843DL.fnRead = arpReverse[Pdx->IdxReverseProtocol].fnRead;
  225. Pdx->P12843DL.fnWrite = afpForward[Pdx->IdxForwardProtocol].fnWrite;
  226. Pdx->fnRead = ParDot3Read;
  227. Pdx->fnWrite = ParDot3Write;
  228. }
  229. DD((PCE)Pdx,DDT,"ParDot3Connect - Exit with status %x\n",Status);
  230. return Status;
  231. }
  232. VOID
  233. ParDot3CreateObject(
  234. IN PPDO_EXTENSION Pdx,
  235. IN PCHAR DOT3DL,
  236. IN PCHAR DOT3C
  237. )
  238. {
  239. Pdx->P12843DL.DataLinkMode = P12843DL_OFF;
  240. Pdx->P12843DL.fnReset = NULL;
  241. DD((PCE)Pdx,DDT,"ParDot3CreateObject - DOT3DL [%s] DOT3C\n",DOT3DL, DOT3C);
  242. if (DOT3DL) {
  243. ULONG dataChannel;
  244. ULONG pid = 0x285; // pid for dot4
  245. // Only use the first channel.
  246. if( !String2Num(&DOT3DL, ',', &dataChannel) ) {
  247. dataChannel = 77;
  248. DD((PCE)Pdx,DDT,"ParDot3CreateObject - No DataChannel Defined\n");
  249. }
  250. if( DOT3C ) {
  251. if (!String2Num(&DOT3C, ',', &pid)) {
  252. pid = 0x285;
  253. DD((PCE)Pdx,DDT,"ParDot3CreateObject - No CurrentPID Defined\n");
  254. }
  255. DD((PCE)Pdx,DDT,"ParDot3CreateObject - .3 mode is ON\n");
  256. }
  257. Pdx->P12843DL.DataChannel = (UCHAR)dataChannel;
  258. Pdx->P12843DL.CurrentPID = (USHORT)pid;
  259. Pdx->P12843DL.DataLinkMode = P12843DL_DOT3_DL;
  260. DD((PCE)Pdx,DDT,"ParDot3CreateObject - Data [%x] CurrentPID [%x]\n",Pdx->P12843DL.DataChannel, Pdx->P12843DL.CurrentPID);
  261. }
  262. if (Pdx->P12843DL.DataLinkMode == P12843DL_OFF) {
  263. DD((PCE)Pdx,DDT,"ParDot3CreateObject - DANGER: .3 mode is OFF\n");
  264. }
  265. }
  266. VOID
  267. ParDot4CreateObject(
  268. IN PPDO_EXTENSION Pdx,
  269. IN PCHAR DOT4DL
  270. )
  271. {
  272. Pdx->P12843DL.DataLinkMode = P12843DL_OFF;
  273. Pdx->P12843DL.fnReset = NULL;
  274. DD((PCE)Pdx,DDT,"ParDot3CreateObject: DOT4DL [%s]\n",DOT4DL);
  275. if (DOT4DL) {
  276. UCHAR numValues = StringCountValues( (PCHAR)DOT4DL, ',' );
  277. ULONG dataChannel, resetChannel, ResetByteCount;
  278. DD((PCE)Pdx,DDT,"ParDot3CreateObject: numValues [%d]\n",numValues);
  279. if (!String2Num(&DOT4DL, ',', &dataChannel)) {
  280. dataChannel = 77;
  281. DD((PCE)Pdx,DDT,"ParDot4CreateObject: No DataChannel Defined.\r\n");
  282. }
  283. if ((String2Num(&DOT4DL, ',', &resetChannel)) && (numValues > 1)) {
  284. if (resetChannel == -1) {
  285. Pdx->P12843DL.fnReset = ParMLCCompatReset;
  286. } else {
  287. Pdx->P12843DL.fnReset = ParMLCECPReset;
  288. }
  289. DD((PCE)Pdx,DDT,"ParDot4CreateObject: ResetChannel Defined.\r\n");
  290. } else {
  291. Pdx->P12843DL.fnReset = NULL;
  292. DD((PCE)Pdx,DDT,"ParDot4CreateObject: No ResetChannel Defined.\r\n");
  293. }
  294. if ((!String2Num(&DOT4DL, 0, &ResetByteCount)) && (numValues > 2)) {
  295. ResetByteCount = 4;
  296. DD((PCE)Pdx,DDT,"ParDot4CreateObject: No ResetByteCount Defined.\r\n");
  297. }
  298. Pdx->P12843DL.DataChannel = (UCHAR)dataChannel;
  299. Pdx->P12843DL.ResetChannel = (UCHAR)resetChannel;
  300. Pdx->P12843DL.ResetByteCount = (UCHAR)ResetByteCount;
  301. Pdx->P12843DL.DataLinkMode = P12843DL_DOT4_DL;
  302. DD((PCE)Pdx,DDT,"ParDot4CreateObject: .4DL mode is ON.\r\n");
  303. DD((PCE)Pdx,DDT,"ParDot4CreateObject: Data [%x] Reset [%x] Bytes [%x]\r\n",
  304. Pdx->P12843DL.DataChannel,
  305. Pdx->P12843DL.ResetChannel,
  306. Pdx->P12843DL.ResetByteCount);
  307. }
  308. #if DBG
  309. if (Pdx->P12843DL.DataLinkMode == P12843DL_OFF) {
  310. DD((PCE)Pdx,DDT,"ParDot4CreateObject: DANGER: .4DL mode is OFF.\r\n");
  311. }
  312. #endif
  313. }
  314. VOID
  315. ParMLCCreateObject(
  316. IN PPDO_EXTENSION Pdx,
  317. IN PCHAR CMDField
  318. )
  319. {
  320. Pdx->P12843DL.DataLinkMode = P12843DL_OFF;
  321. Pdx->P12843DL.fnReset = NULL;
  322. if (CMDField)
  323. {
  324. Pdx->P12843DL.DataChannel = 77;
  325. Pdx->P12843DL.DataLinkMode = P12843DL_MLC_DL;
  326. DD((PCE)Pdx,DDT,"ParMLCCreateObject: MLC mode is on.\r\n");
  327. }
  328. #if DBG
  329. if (Pdx->P12843DL.DataLinkMode == P12843DL_OFF)
  330. {
  331. DD((PCE)Pdx,DDT,"ParMLCCreateObject: DANGER: MLC mode is OFF.\r\n");
  332. }
  333. #endif
  334. }
  335. VOID
  336. ParDot3DestroyObject(
  337. IN PPDO_EXTENSION Pdx
  338. )
  339. {
  340. Pdx->P12843DL.DataLinkMode = P12843DL_OFF;
  341. }
  342. NTSTATUS
  343. ParDot3Disconnect(
  344. IN PPDO_EXTENSION Pdx
  345. )
  346. {
  347. if (Pdx->P12843DL.DataLinkMode == P12843DL_DOT3_DL) {
  348. Pdx->fnRead = arpReverse[Pdx->IdxReverseProtocol].fnRead;
  349. Pdx->fnWrite = afpForward[Pdx->IdxForwardProtocol].fnWrite;
  350. }
  351. Pdx->P12843DL.bEventActive = FALSE;
  352. Pdx->P12843DL.Event = 0;
  353. return STATUS_SUCCESS;
  354. }
  355. VOID
  356. ParDot3ParseModes(
  357. IN PPDO_EXTENSION Pdx,
  358. IN PCHAR DOT3M
  359. )
  360. {
  361. ULONG fwd = 0;
  362. ULONG rev = 0;
  363. DD((PCE)Pdx,DDT,"ParDot3ParseModes: DOT3M [%s]\n",DOT3M);
  364. if (DOT3M) {
  365. UCHAR numValues = StringCountValues((PCHAR)DOT3M, ',');
  366. if (numValues != 2) {
  367. // The periph gave me bad values. I'm not gonna read
  368. // them. I will set the defaults to the lowest
  369. // common denominator.
  370. DD((PCE)Pdx,DDT,"ParDot3ParseModes: Malformed 1284.3M field.\r\n");
  371. Pdx->P12843DL.FwdSkipMask = (USHORT) PAR_FWD_MODE_SKIP_MASK;
  372. Pdx->P12843DL.RevSkipMask = (USHORT) PAR_REV_MODE_SKIP_MASK;
  373. return;
  374. }
  375. // Only use the first channel.
  376. if (!String2Num(&DOT3M, ',', &fwd)) {
  377. fwd = (USHORT) PAR_FWD_MODE_SKIP_MASK;
  378. DD((PCE)Pdx,DDT,"ParDot3ParseModes: Couldn't read fwd of 1284.3M.\r\n");
  379. }
  380. if (!String2Num(&DOT3M, ',', &rev)) {
  381. rev = (USHORT) PAR_REV_MODE_SKIP_MASK;
  382. DD((PCE)Pdx,DDT,"ParDot3ParseModes: Couldn't read rev of 1284.3M.\r\n");
  383. }
  384. }
  385. Pdx->P12843DL.FwdSkipMask = (USHORT) fwd;
  386. Pdx->P12843DL.RevSkipMask = (USHORT) rev;
  387. }
  388. NTSTATUS
  389. ParDot3Read(
  390. IN PPDO_EXTENSION Pdx,
  391. IN PVOID Buffer,
  392. IN ULONG BufferSize,
  393. OUT PULONG BytesTransferred
  394. )
  395. {
  396. NTSTATUS Status;
  397. UCHAR ucScrap1;
  398. UCHAR ucScrap2[2];
  399. USHORT usScrap1;
  400. ULONG bytesToRead;
  401. ULONG bytesTransferred;
  402. USHORT Dot3CheckSum;
  403. USHORT Dot3DataLen;
  404. // ================================== Read the first byte of SOF
  405. bytesToRead = 1;
  406. bytesTransferred = 0;
  407. do
  408. {
  409. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap1, bytesToRead, &bytesTransferred);
  410. }
  411. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  412. // ================================== Check the first byte of SOF
  413. if (!NT_SUCCESS(Status) || ucScrap1 != Dot3_StartOfFrame1)
  414. {
  415. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  416. *BytesTransferred = 0;
  417. return(Status);
  418. }
  419. // ================================== Read the second byte of SOF
  420. bytesToRead = 1;
  421. bytesTransferred = 0;
  422. do
  423. {
  424. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap1, bytesToRead, &bytesTransferred);
  425. }
  426. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  427. // ================================== Check the second byte of SOF
  428. if (!NT_SUCCESS(Status) || ucScrap1 != Dot3_StartOfFrame2)
  429. {
  430. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  431. *BytesTransferred = 0;
  432. return(Status);
  433. }
  434. // ================================== Read the PID (Should be in Big Endian)
  435. bytesToRead = 2;
  436. bytesTransferred = 0;
  437. do
  438. {
  439. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &usScrap1, bytesToRead, &bytesTransferred);
  440. }
  441. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  442. // ================================== Check the PID
  443. if (!NT_SUCCESS(Status) || usScrap1 != Pdx->P12843DL.CurrentPID)
  444. {
  445. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  446. *BytesTransferred = 0;
  447. return(Status);
  448. }
  449. // ================================== Read the DataLen
  450. bytesToRead = 2;
  451. bytesTransferred = 0;
  452. do
  453. {
  454. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap2[0], bytesToRead, &bytesTransferred);
  455. }
  456. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  457. Dot3DataLen = (USHORT)((USHORT)(ucScrap2[0]<<8 | ucScrap2[1]));
  458. // ================================== Check the DataLen
  459. if (!NT_SUCCESS(Status))
  460. {
  461. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  462. *BytesTransferred = 0;
  463. return(Status);
  464. }
  465. // ================================== Read the Checksum
  466. bytesToRead = 2;
  467. bytesTransferred = 0;
  468. do
  469. {
  470. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap2[0], bytesToRead, &bytesTransferred);
  471. }
  472. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  473. Dot3CheckSum = (USHORT)(ucScrap2[0]<<8 | ucScrap2[1]);
  474. // ================================== Check the DataLen
  475. if (!NT_SUCCESS(Status))
  476. {
  477. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  478. *BytesTransferred = 0;
  479. return(Status);
  480. }
  481. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, Buffer, BufferSize, BytesTransferred);
  482. if (!NT_SUCCESS(Status))
  483. {
  484. DD((PCE)Pdx,DDE,"ParDot3Read: Data Read Failed. We're Hosed!\n");
  485. return(Status);
  486. }
  487. // LengthOfData field from the Frame header is really the number of bytes of ClientData - 1
  488. if ( ((ULONG)Dot3DataLen + 1) > BufferSize)
  489. {
  490. // buffer overflow - abort operation
  491. DD((PCE)Pdx,DDE,"ParDot3Read: Bad 1284.3DL Data Len. Buffer overflow. We're Hosed!\n");
  492. return STATUS_BUFFER_OVERFLOW;
  493. }
  494. // Check Checksum
  495. {
  496. USHORT pid = Pdx->P12843DL.CurrentPID;
  497. USHORT checkSum;
  498. // 2's complement sum in 32 bit accumulator
  499. ULONG sum = pid + Dot3DataLen + Dot3CheckSum;
  500. // fold 32 bit sum into 16 bits
  501. while( sum >> 16 ) {
  502. sum = (sum & 0xffff) + (sum >> 16);
  503. }
  504. // take 1's complement of folded sum - this should be Zero if there were no errors
  505. checkSum = (USHORT)(0xffff & ~sum);
  506. if( checkSum != 0 ) {
  507. DD((PCE)Pdx,DDE,"ParDot3Read: Bad 1284.3DL Checksum. We're Hosed!\n");
  508. return STATUS_DEVICE_PROTOCOL_ERROR;
  509. }
  510. }
  511. // ================================== Read the first byte of EOF
  512. bytesToRead = 1;
  513. bytesTransferred = 0;
  514. do
  515. {
  516. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap1, bytesToRead, &bytesTransferred);
  517. }
  518. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  519. // ================================== Check the first byte of EOF
  520. if (!NT_SUCCESS(Status) || ucScrap1 != Dot3_EndOfFrame1)
  521. {
  522. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  523. *BytesTransferred = 0;
  524. return(Status);
  525. }
  526. // ================================== Read the second byte of EOF
  527. bytesToRead = 1;
  528. bytesTransferred = 0;
  529. do
  530. {
  531. Status = ((PPROTOCOL_READ_ROUTINE) Pdx->P12843DL.fnRead)(Pdx, &ucScrap1, bytesToRead, &bytesTransferred);
  532. }
  533. while(NT_SUCCESS(Status) && bytesTransferred != bytesToRead);
  534. // ================================== Check the second byte of EOF
  535. if (!NT_SUCCESS(Status) || ucScrap1 != Dot3_EndOfFrame2)
  536. {
  537. DD((PCE)Pdx,DDE,"ParDot3Read: Header Read Failed. We're Hosed!\n");
  538. *BytesTransferred = 0;
  539. return(Status);
  540. }
  541. return Status;
  542. }
  543. NTSTATUS
  544. ParDot3Write(
  545. IN PPDO_EXTENSION Pdx,
  546. IN PVOID Buffer,
  547. IN ULONG BufferSize,
  548. OUT PULONG BytesTransferred
  549. )
  550. {
  551. NTSTATUS Status;
  552. ULONG frameBytesTransferred;
  553. ULONG bytesToWrite;
  554. USHORT scrap1;
  555. USHORT scrap2;
  556. USHORT scrapHigh;
  557. USHORT scrapLow;
  558. PUCHAR p;
  559. // valid range for data payload per Frame is 1..64K
  560. if( (BufferSize < 1) || (BufferSize > 64*1024) ) {
  561. return STATUS_INVALID_PARAMETER;
  562. };
  563. // ========================= Write out first Byte of SOF
  564. bytesToWrite = 1;
  565. frameBytesTransferred = 0;
  566. do
  567. {
  568. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &Dot3_StartOfFrame1, bytesToWrite, &frameBytesTransferred);
  569. }
  570. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  571. // ========================= Check first Byte of SOF
  572. if (!NT_SUCCESS(Status))
  573. {
  574. *BytesTransferred = 0;
  575. return(Status);
  576. }
  577. // ========================= Write out second Byte of SOF
  578. bytesToWrite = 1;
  579. frameBytesTransferred = 0;
  580. do
  581. {
  582. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &Dot3_StartOfFrame2, bytesToWrite, &frameBytesTransferred);
  583. }
  584. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  585. // ========================= Check second Byte of SOF
  586. if (!NT_SUCCESS(Status))
  587. {
  588. *BytesTransferred = 0;
  589. return(Status);
  590. }
  591. // ========================= Write out PID (which should be in Big Endian already)
  592. bytesToWrite = 2;
  593. frameBytesTransferred = 0;
  594. do
  595. {
  596. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &Pdx->P12843DL.CurrentPID, bytesToWrite, &frameBytesTransferred);
  597. }
  598. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  599. // ========================= Check PID
  600. if (!NT_SUCCESS(Status))
  601. {
  602. *BytesTransferred = 0;
  603. return(Status);
  604. }
  605. // ========================= Write out Length of Data
  606. bytesToWrite = 2;
  607. frameBytesTransferred = 0;
  608. scrap1 = (USHORT) (BufferSize - 1);
  609. scrapLow = (UCHAR) (scrap1 & 0xff);
  610. scrapHigh = (UCHAR) (scrap1 >> 8);
  611. p = (PUCHAR)&scrap2;
  612. *p++ = (UCHAR)scrapHigh;
  613. *p = (UCHAR)scrapLow;
  614. do
  615. {
  616. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &scrap2, bytesToWrite, &frameBytesTransferred);
  617. }
  618. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  619. // ========================= Check Length of Data
  620. if (!NT_SUCCESS(Status))
  621. {
  622. *BytesTransferred = 0;
  623. return(Status);
  624. }
  625. // ========================= Write out Checksum
  626. bytesToWrite = 2;
  627. frameBytesTransferred = 0;
  628. {
  629. USHORT pid = Pdx->P12843DL.CurrentPID;
  630. USHORT dataLengthMinusOne = (USHORT)(BufferSize - 1);
  631. USHORT checkSum;
  632. // 2's complement sum in 32 bit accumulator
  633. ULONG sum = pid + dataLengthMinusOne;
  634. // fold 32 bit sum into 16 bits
  635. while( sum >> 16 ) {
  636. sum = (sum & 0xffff) + (sum >> 16);
  637. }
  638. // final checksum is 1's complement of folded sum
  639. checkSum = (USHORT)(0xffff & ~sum);
  640. scrap1 = checkSum;
  641. }
  642. // send checksum big-endian
  643. scrapLow = (UCHAR)(scrap1 & 0xff);
  644. scrapHigh = (UCHAR)(scrap1 >> 8);
  645. p = (PUCHAR)&scrap2;
  646. *p++ = (UCHAR)scrapHigh;
  647. *p = (UCHAR)scrapLow;
  648. do
  649. {
  650. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &scrap2, bytesToWrite, &frameBytesTransferred);
  651. }
  652. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  653. // ========================= Check Checksum
  654. if (!NT_SUCCESS(Status))
  655. {
  656. *BytesTransferred = 0;
  657. return(Status);
  658. }
  659. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, Buffer, BufferSize, BytesTransferred);
  660. if (NT_SUCCESS(Status))
  661. {
  662. // ========================= Write out first Byte of EOF
  663. bytesToWrite = 1;
  664. frameBytesTransferred = 0;
  665. do
  666. {
  667. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &Dot3_EndOfFrame1, bytesToWrite, &frameBytesTransferred);
  668. }
  669. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  670. // ========================= Check first Byte of EOF
  671. if (!NT_SUCCESS(Status))
  672. {
  673. *BytesTransferred = 0;
  674. return(Status);
  675. }
  676. // ========================= Write out second Byte of EOF
  677. bytesToWrite = 1;
  678. frameBytesTransferred = 0;
  679. do
  680. {
  681. Status = ((PPROTOCOL_WRITE_ROUTINE) Pdx->P12843DL.fnWrite)(Pdx, &Dot3_EndOfFrame2, bytesToWrite, &frameBytesTransferred);
  682. }
  683. while(NT_SUCCESS(Status) && frameBytesTransferred != bytesToWrite);
  684. // ========================= Check second Byte of EOF
  685. if (!NT_SUCCESS(Status))
  686. {
  687. *BytesTransferred = 0;
  688. return(Status);
  689. }
  690. }
  691. return Status;
  692. }
  693. NTSTATUS
  694. ParMLCCompatReset(
  695. IN PPDO_EXTENSION Pdx
  696. )
  697. {
  698. NTSTATUS Status = STATUS_SUCCESS;
  699. UCHAR Reset[256]; // Reset should not require more than 256 chars
  700. const ULONG ResetLen = Pdx->P12843DL.ResetByteCount;
  701. ULONG BytesWritten;
  702. DD((PCE)Pdx,DDT,"ParMLCCompatReset: Start\n");
  703. if (Pdx->P12843DL.DataLinkMode != P12843DL_MLC_DL &&
  704. Pdx->P12843DL.DataLinkMode != P12843DL_DOT4_DL)
  705. {
  706. DD((PCE)Pdx,DDT,"ParMLCCompatReset: not MLC.\n");
  707. return STATUS_SUCCESS;
  708. }
  709. ParTerminate(Pdx);
  710. // Sending NULLs for reset
  711. DD((PCE)Pdx,DDT,"ParMLCCompatReset: Zeroing Reset Bytes.\n");
  712. RtlFillMemory(Reset, ResetLen, Pdx->P12843DL.ResetByte);
  713. DD((PCE)Pdx,DDT,"ParMLCCompatReset: Sending Reset Bytes.\n");
  714. // Don't use the Dot3Write since we are in MLC Mode.
  715. Status = SppWrite(Pdx, Reset, ResetLen, &BytesWritten);
  716. if (!NT_SUCCESS(Status) || BytesWritten != ResetLen)
  717. {
  718. DD((PCE)Pdx,DDE,"ParMLCCompatReset: FAIL. Write Failed\n");
  719. return Status;
  720. }
  721. DD((PCE)Pdx,DDT,"ParMLCCompatReset: Reset Bytes were sent.\n");
  722. return Status;
  723. }
  724. NTSTATUS
  725. ParMLCECPReset(
  726. IN PPDO_EXTENSION Pdx
  727. )
  728. {
  729. NTSTATUS Status = STATUS_SUCCESS;
  730. UCHAR Reset[256]; // Reset should not require more than 256 chars
  731. const ULONG ResetLen = Pdx->P12843DL.ResetByteCount;
  732. ULONG BytesWritten;
  733. DD((PCE)Pdx,DDT,"ParMLCECPReset: Start\n");
  734. if (Pdx->P12843DL.DataLinkMode != P12843DL_MLC_DL &&
  735. Pdx->P12843DL.DataLinkMode != P12843DL_DOT4_DL)
  736. {
  737. DD((PCE)Pdx,DDT,"ParMLCECPReset: not MLC.\n");
  738. return STATUS_SUCCESS;
  739. }
  740. Status = ParReverseToForward(Pdx);
  741. Pdx->ForwardInterfaceAddress = Pdx->P12843DL.ResetChannel;
  742. Status = ParSetFwdAddress(Pdx);
  743. if (!NT_SUCCESS(Status)) {
  744. DD((PCE)Pdx,DDE,"ParMLCECPReset: FAIL. Couldn't Set Reset Channel\n");
  745. return Status;
  746. }
  747. // Sending NULLs for reset
  748. DD((PCE)Pdx,DDT,"ParMLCECPReset: Zeroing Reset Bytes.\n");
  749. RtlFillMemory(Reset, ResetLen, Pdx->P12843DL.ResetByte);
  750. DD((PCE)Pdx,DDT,"ParMLCECPReset: Sending Reset Bytes.\n");
  751. // Don't use the Dot3Write since we are in MLC Mode.
  752. Status = afpForward[Pdx->IdxForwardProtocol].fnWrite(Pdx, Reset, ResetLen, &BytesWritten);
  753. if (!NT_SUCCESS(Status) || BytesWritten != ResetLen) {
  754. DD((PCE)Pdx,DDE,"ParMLCECPReset: FAIL. Write Failed\n");
  755. return Status;
  756. }
  757. DD((PCE)Pdx,DDT,"ParMLCECPReset: Reset Bytes were sent.\n");
  758. Pdx->ForwardInterfaceAddress = Pdx->P12843DL.DataChannel;
  759. Status = ParSetFwdAddress(Pdx);
  760. if (!NT_SUCCESS(Status)) {
  761. DD((PCE)Pdx,DDE,"ParMLCECPReset: FAIL. Couldn't Set Data Channel\n");
  762. return Status;
  763. }
  764. return Status;
  765. }