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.

667 lines
22 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. nibble.c
  5. Abstract:
  6. This module contains the code to do nibble mode reads.
  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. --*/
  14. #include "pch.h"
  15. BOOLEAN
  16. ParIsNibbleSupported(
  17. IN PDEVICE_EXTENSION Extension
  18. );
  19. BOOLEAN
  20. ParIsChannelizedNibbleSupported(
  21. IN PDEVICE_EXTENSION Extension
  22. );
  23. NTSTATUS
  24. ParEnterNibbleMode(
  25. IN PDEVICE_EXTENSION Extension,
  26. IN BOOLEAN DeviceIdRequest
  27. );
  28. NTSTATUS
  29. ParEnterChannelizedNibbleMode(
  30. IN PDEVICE_EXTENSION Extension,
  31. IN BOOLEAN DeviceIdRequest
  32. );
  33. VOID
  34. ParTerminateNibbleMode(
  35. IN PDEVICE_EXTENSION Extension
  36. );
  37. NTSTATUS
  38. ParNibbleModeRead(
  39. IN PDEVICE_EXTENSION Extension,
  40. IN PVOID Buffer,
  41. IN ULONG BufferSize,
  42. OUT PULONG BytesTransferred
  43. );
  44. BOOLEAN
  45. ParIsNibbleSupported(
  46. IN PDEVICE_EXTENSION Extension
  47. )
  48. /*++
  49. Routine Description:
  50. This routine determines whether or not nibble mode is suported
  51. by trying to negotiate when asked.
  52. Arguments:
  53. Extension - The device extension.
  54. Return Value:
  55. BOOLEAN.
  56. --*/
  57. {
  58. NTSTATUS Status;
  59. ParDump2(PARINFO, ("ParIsNibbleSupported: Start\n"));
  60. if (Extension->BadProtocolModes & NIBBLE) {
  61. ParDump2(PARINFO, ("ParIsNibbleSupported: BAD PROTOCOL Leaving\n"));
  62. return FALSE;
  63. }
  64. if (Extension->ProtocolModesSupported & NIBBLE) {
  65. ParDump2(PARINFO, ("ParIsNibbleSupported: Already Checked YES Leaving\n"));
  66. return TRUE;
  67. }
  68. Status = ParEnterNibbleMode (Extension, FALSE);
  69. ParTerminateNibbleMode (Extension);
  70. if (NT_SUCCESS(Status)) {
  71. ParDump2(PARINFO, ("ParIsNibbleSupported: SUCCESS Leaving\n"));
  72. Extension->ProtocolModesSupported |= NIBBLE;
  73. return TRUE;
  74. }
  75. ParDump2(PARINFO, ("ParIsNibbleSupported: UNSUCCESSFUL Leaving\n"));
  76. return FALSE;
  77. }
  78. BOOLEAN
  79. ParIsChannelizedNibbleSupported(
  80. IN PDEVICE_EXTENSION Extension
  81. )
  82. /*++
  83. Routine Description:
  84. This routine determines whether or not channelized nibble mode is suported (1284.3)
  85. by trying to negotiate when asked.
  86. Arguments:
  87. Extension - The device extension.
  88. Return Value:
  89. BOOLEAN.
  90. --*/
  91. {
  92. NTSTATUS Status;
  93. ParDump2(PARINFO, ("ParIsChannelizedNibbleSupported: Start\n"));
  94. if (Extension->BadProtocolModes & CHANNEL_NIBBLE) {
  95. ParDump2(PARINFO, ("ParIsChannelizedNibbleSupported: BAD PROTOCOL Leaving\n"));
  96. return FALSE;
  97. }
  98. if (Extension->ProtocolModesSupported & CHANNEL_NIBBLE) {
  99. ParDump2(PARINFO, ("ParIsChannelizedNibbleSupported: Already Checked YES Leaving\n"));
  100. return TRUE;
  101. }
  102. Status = ParEnterChannelizedNibbleMode (Extension, FALSE);
  103. ParTerminateNibbleMode (Extension);
  104. if (NT_SUCCESS(Status)) {
  105. ParDump2(PARINFO, ("ParIsChannelizedNibbleSupported: SUCCESS Leaving\n"));
  106. Extension->ProtocolModesSupported |= CHANNEL_NIBBLE;
  107. return TRUE;
  108. }
  109. ParDump2(PARINFO, ("ParIsChannelizedNibbleSupported: UNSUCCESSFUL Leaving\n"));
  110. return FALSE;
  111. }
  112. NTSTATUS
  113. ParEnterNibbleMode(
  114. IN PDEVICE_EXTENSION Extension,
  115. IN BOOLEAN DeviceIdRequest
  116. )
  117. /*++
  118. Routine Description:
  119. This routine performs 1284 negotiation with the peripheral to the
  120. nibble mode protocol.
  121. Arguments:
  122. Controller - Supplies the port address.
  123. DeviceIdRequest - Supplies whether or not this is a request for a device
  124. id.
  125. Return Value:
  126. STATUS_SUCCESS - Successful negotiation.
  127. otherwise - Unsuccessful negotiation.
  128. --*/
  129. {
  130. NTSTATUS Status = STATUS_SUCCESS;
  131. ParDump2(PARINFO, ("ParEnterNibbleMode: Start\n"));
  132. if ( Extension->ModeSafety == SAFE_MODE ) {
  133. if (DeviceIdRequest) {
  134. Status = IeeeEnter1284Mode (Extension, NIBBLE_EXTENSIBILITY | DEVICE_ID_REQ);
  135. } else {
  136. Status = IeeeEnter1284Mode (Extension, NIBBLE_EXTENSIBILITY);
  137. }
  138. } else {
  139. ParDump2(PARINFO, ("ParEnterNibbleMode: In UNSAFE_MODE.\n"));
  140. Extension->Connected = TRUE;
  141. }
  142. // dvdr
  143. if (NT_SUCCESS(Status)) {
  144. ParDump2(PARINFO, ("ParEnterNibbleMode: IeeeEnter1284Mode returned success\n"));
  145. Extension->CurrentEvent = 6;
  146. Extension->CurrentPhase = PHASE_NEGOTIATION;
  147. Extension->IsIeeeTerminateOk = TRUE;
  148. } else {
  149. ParDump2(PARINFO, ("ParEnterNibbleMode: IeeeEnter1284Mode returned unsuccessful\n"));
  150. ParTerminateNibbleMode ( Extension );
  151. Extension->CurrentPhase = PHASE_UNKNOWN;
  152. Extension->IsIeeeTerminateOk = FALSE;
  153. }
  154. ParDump2(PARINFO, ("ParEnterNibbleMode: Leaving with Status : %x \n", Status));
  155. return Status;
  156. }
  157. NTSTATUS
  158. ParEnterChannelizedNibbleMode(
  159. IN PDEVICE_EXTENSION Extension,
  160. IN BOOLEAN DeviceIdRequest
  161. )
  162. /*++
  163. Routine Description:
  164. This routine performs 1284 negotiation with the peripheral to the
  165. nibble mode protocol.
  166. Arguments:
  167. Controller - Supplies the port address.
  168. DeviceIdRequest - Supplies whether or not this is a request for a device
  169. id.
  170. Return Value:
  171. STATUS_SUCCESS - Successful negotiation.
  172. otherwise - Unsuccessful negotiation.
  173. --*/
  174. {
  175. NTSTATUS Status = STATUS_SUCCESS;
  176. ParDump2(PARINFO, ("ParEnterChannelizedNibbleMode: Start\n"));
  177. if ( Extension->ModeSafety == SAFE_MODE ) {
  178. if (DeviceIdRequest) {
  179. Status = IeeeEnter1284Mode (Extension, CHANNELIZED_EXTENSIBILITY | DEVICE_ID_REQ);
  180. } else {
  181. Status = IeeeEnter1284Mode (Extension, CHANNELIZED_EXTENSIBILITY);
  182. }
  183. } else {
  184. ParDump2(PARINFO, ("ParEnterChannelizedNibbleMode: In UNSAFE_MODE.\n"));
  185. Extension->Connected = TRUE;
  186. }
  187. // dvdr
  188. if (NT_SUCCESS(Status)) {
  189. ParDump2(PARINFO, ("ParEnterChannelizedNibbleMode: IeeeEnter1284Mode returned success\n"));
  190. Extension->CurrentEvent = 6;
  191. Extension->CurrentPhase = PHASE_NEGOTIATION;
  192. Extension->IsIeeeTerminateOk = TRUE;
  193. } else {
  194. ParDump2(PARINFO, ("ParEnterChannelizedNibbleMode: IeeeEnter1284Mode returned unsuccessful\n"));
  195. ParTerminateNibbleMode ( Extension );
  196. Extension->CurrentPhase = PHASE_UNKNOWN;
  197. Extension->IsIeeeTerminateOk = FALSE;
  198. }
  199. ParDump2(PARINFO, ("ParEnterChannelizedNibbleMode: Leaving with Status : %x \n", Status));
  200. return Status;
  201. }
  202. VOID
  203. ParTerminateNibbleMode(
  204. IN PDEVICE_EXTENSION Extension
  205. )
  206. /*++
  207. Routine Description:
  208. This routine terminates the interface back to compatibility mode.
  209. Arguments:
  210. Controller - Supplies the parallel port's controller address.
  211. Return Value:
  212. None.
  213. --*/
  214. {
  215. ParDump2(PARINFO, ("ParTerminateNibbleMode: Enter.\n"));
  216. if ( Extension->ModeSafety == SAFE_MODE ) {
  217. IeeeTerminate1284Mode (Extension);
  218. } else {
  219. ParDump2(PARINFO, ("ParTerminateNibbleMode: In UNSAFE_MODE.\n"));
  220. Extension->Connected = FALSE;
  221. }
  222. ParDump2(PARINFO, ("ParTerminateNibbleMode: Exit.\n"));
  223. }
  224. NTSTATUS
  225. ParNibbleModeRead(
  226. IN PDEVICE_EXTENSION Extension,
  227. IN PVOID Buffer,
  228. IN ULONG BufferSize,
  229. OUT PULONG BytesTransferred
  230. )
  231. /*++
  232. Routine Description:
  233. This routine performs a 1284 nibble mode read into the given
  234. buffer for no more than 'BufferSize' bytes.
  235. Arguments:
  236. Extension - Supplies the device extension.
  237. Buffer - Supplies the buffer to read into.
  238. BufferSize - Supplies the number of bytes in the buffer.
  239. BytesTransferred - Returns the number of bytes transferred.
  240. --*/
  241. {
  242. PUCHAR Controller;
  243. PUCHAR wPortDCR;
  244. PUCHAR wPortDSR;
  245. NTSTATUS Status = STATUS_SUCCESS;
  246. PUCHAR p = (PUCHAR)Buffer;
  247. UCHAR dsr, dcr;
  248. UCHAR nibble[2];
  249. ULONG i, j;
  250. Controller = Extension->Controller;
  251. wPortDCR = Controller + OFFSET_DCR;
  252. wPortDSR = Controller + OFFSET_DSR;
  253. // Read nibbles according to 1284 spec.
  254. ParDump2(PARENTRY,("ParNibbleModeRead: Start\n"));
  255. dcr = READ_PORT_UCHAR(wPortDCR);
  256. switch (Extension->CurrentPhase) {
  257. case PHASE_NEGOTIATION:
  258. ParDump2(PARINFO,("ParNibbleModeRead: PHASE_NEGOTIATION\n"));
  259. // Starting in state 6 - where do we go from here?
  260. // To Reverse Idle or Reverse Data Transfer Phase depending if
  261. // data is available.
  262. dsr = READ_PORT_UCHAR(wPortDSR);
  263. // =============== Periph State 6 ===============8
  264. // PeriphAck/PtrBusy = Don't Care
  265. // PeriphClk/PtrClk = Don't Care (should be high
  266. // and the nego. proc already
  267. // checked this)
  268. // nAckReverse/AckDataReq = Don't Care (should be high)
  269. // XFlag = Don't Care (should be low)
  270. // nPeriphReq/nDataAvail = High/Low (line status determines
  271. // which state we move to)
  272. Extension->CurrentEvent = 6;
  273. #if (0 == DVRH_USE_NIBBLE_MACROS)
  274. if (dsr & DSR_NOT_DATA_AVAIL)
  275. #else
  276. if (TEST_DSR(dsr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE ))
  277. #endif
  278. {
  279. // Data is NOT available - go to Reverse Idle
  280. ParDump2(PARINFO,("ParNibbleModeRead: PHASE_REVERSE_IDLE\n"));
  281. // Host enters state 7 - officially in Reverse Idle now
  282. // Must stall for at least .5 microseconds before this state.
  283. KeStallExecutionProcessor(1);
  284. /* =============== Host State 7 Nibble Reverse Idle ===============8
  285. DIR = Don't Care
  286. IRQEN = Don't Care
  287. 1284/SelectIn = High
  288. nReverseReq/ (ECP only)= Don't Care
  289. HostAck/HostBusy = Low (signals State 7)
  290. HostClk/nStrobe = High
  291. ============================================================ */
  292. Extension->CurrentEvent = 7;
  293. #if (0 == DVRH_USE_NIBBLE_MACROS)
  294. dcr |= DCR_NOT_HOST_BUSY;
  295. #else
  296. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, INACTIVE, ACTIVE);
  297. #endif
  298. WRITE_PORT_UCHAR(wPortDCR, dcr);
  299. Extension->CurrentPhase = PHASE_REVERSE_IDLE ;
  300. // FALL THRU TO reverse idle
  301. } else {
  302. // Data is available, go to Reverse Transfer Phase
  303. Extension->CurrentPhase = PHASE_REVERSE_XFER ;
  304. // DO NOT fall thru
  305. goto PhaseReverseXfer; // please save me from my sins!
  306. }
  307. case PHASE_REVERSE_IDLE:
  308. // Check to see if the peripheral has indicated Interrupt Phase and if so,
  309. // get us ready to reverse transfer.
  310. // See if data is available (looking for state 19)
  311. dsr = READ_PORT_UCHAR(Controller + OFFSET_DSR);
  312. if (!(dsr & DSR_NOT_DATA_AVAIL)) {
  313. dcr = READ_PORT_UCHAR(wPortDCR);
  314. // =========== Host State 20 Interrupt Phase ===========8
  315. // DIR = Don't Care
  316. // IRQEN = Don't Care
  317. // 1284/SelectIn = High
  318. // nReverseReq/ (ECP only) = Don't Care
  319. // HostAck/HostBusy = High (Signals state 20)
  320. // HostClk/nStrobe = High
  321. //
  322. // Data is available, get us to Reverse Transfer Phase
  323. Extension->CurrentEvent = 20;
  324. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, ACTIVE, ACTIVE);
  325. WRITE_PORT_UCHAR(wPortDCR, dcr);
  326. // =============== Periph State 21 HBDA ===============8
  327. // PeriphAck/PtrBusy = Don't Care
  328. // PeriphClk/PtrClk = Don't Care (should be high)
  329. // nAckReverse/AckDataReq = low (signals state 21)
  330. // XFlag = Don't Care (should be low)
  331. // nPeriphReq/nDataAvail = Don't Care (should be low)
  332. Extension->CurrentEvent = 21;
  333. if (CHECK_DSR(Controller,
  334. DONT_CARE, DONT_CARE, INACTIVE,
  335. DONT_CARE, DONT_CARE,
  336. IEEE_MAXTIME_TL)) {
  337. // Got state 21
  338. // Let's jump to Reverse Xfer and get the data
  339. Extension->CurrentPhase = PHASE_REVERSE_XFER;
  340. goto PhaseReverseXfer;
  341. } else {
  342. // Timeout on state 21
  343. Extension->IsIeeeTerminateOk = TRUE;
  344. Status = STATUS_IO_DEVICE_ERROR;
  345. Extension->CurrentPhase = PHASE_UNKNOWN;
  346. ParDump2(PARERRORS, ("ParNibbleModeRead:Failed State 21: Controller %x dcr %x\n",
  347. Controller, dcr));
  348. // NOTE: Don't ASSERT Here. An Assert here can bite you if you are in
  349. // Nibble Rev and you device is off/offline.
  350. // dvrh 2/25/97
  351. goto NibbleReadExit;
  352. }
  353. } else {
  354. // Data is NOT available - do nothing
  355. // The device doesn't report any data, it still looks like it is
  356. // in ReverseIdle. Just to make sure it hasn't powered off or somehow
  357. // jumped out of Nibble mode, test also for AckDataReq high and XFlag low
  358. // and nDataAvaul high.
  359. Extension->CurrentEvent = 18;
  360. dsr = READ_PORT_UCHAR(Controller + OFFSET_DSR);
  361. if(( dsr & DSR_NIBBLE_VALIDATION )== DSR_NIBBLE_TEST_RESULT ) {
  362. Extension->CurrentPhase = PHASE_REVERSE_IDLE ;
  363. } else {
  364. #if DVRH_BUS_RESET_ON_ERROR
  365. BusReset(wPortDCR); // Pass in the dcr address
  366. #endif
  367. // Appears we failed state 19.
  368. Extension->IsIeeeTerminateOk = TRUE;
  369. Status = STATUS_IO_DEVICE_ERROR;
  370. Extension->CurrentPhase = PHASE_UNKNOWN;
  371. ParDump2(PARERRORS, ("ParNibbleModeRead:Failed State 19: Controller %x dcr %x\n",
  372. Controller, dcr));
  373. }
  374. goto NibbleReadExit;
  375. }
  376. PhaseReverseXfer:
  377. case PHASE_REVERSE_XFER:
  378. ParDump2(PARINFO,("ParNibbleModeRead:PHASE_REVERSE_IDLE\n"));
  379. for (i = 0; i < BufferSize; i++) {
  380. for (j = 0; j < 2; j++) {
  381. // Host enters state 7 or 12 depending if nibble 1 or 2
  382. // StoreControl (Controller, HDReady);
  383. dcr |= DCR_NOT_HOST_BUSY;
  384. WRITE_PORT_UCHAR(wPortDCR, dcr);
  385. // =============== Periph State 9 ===============8
  386. // PeriphAck/PtrBusy = Don't Care (Bit 3 of Nibble)
  387. // PeriphClk/PtrClk = low (signals state 9)
  388. // nAckReverse/AckDataReq = Don't Care (Bit 2 of Nibble)
  389. // XFlag = Don't Care (Bit 1 of Nibble)
  390. // nPeriphReq/nDataAvail = Don't Care (Bit 0 of Nibble)
  391. Extension->CurrentEvent = 9;
  392. if (!CHECK_DSR(Controller,
  393. DONT_CARE, INACTIVE, DONT_CARE,
  394. DONT_CARE, DONT_CARE,
  395. IEEE_MAXTIME_TL)) {
  396. // Time out.
  397. // Bad things happened - timed out on this state,
  398. // Mark Status as bad and let our mgr kill current mode.
  399. Extension->IsIeeeTerminateOk = FALSE;
  400. Status = STATUS_IO_DEVICE_ERROR;
  401. ParDump2(PARERRORS, ("ParNibbleModeRead:Failed State 9: Controller %x dcr %x\n",
  402. Controller, dcr));
  403. Extension->CurrentPhase = PHASE_UNKNOWN;
  404. goto NibbleReadExit;
  405. }
  406. // Read Nibble
  407. nibble[j] = READ_PORT_UCHAR(wPortDSR);
  408. /* ============== Host State 10 Nibble Read ===============8
  409. DIR = Don't Care
  410. IRQEN = Don't Care
  411. 1284/SelectIn = High
  412. HostAck/HostBusy = High (signals State 10)
  413. HostClk/nStrobe = High
  414. ============================================================ */
  415. Extension->CurrentEvent = 10;
  416. dcr &= ~DCR_NOT_HOST_BUSY;
  417. WRITE_PORT_UCHAR(wPortDCR, dcr);
  418. // =============== Periph State 11 ===============8
  419. // PeriphAck/PtrBusy = Don't Care (Bit 3 of Nibble)
  420. // PeriphClk/PtrClk = High (signals state 11)
  421. // nAckReverse/AckDataReq = Don't Care (Bit 2 of Nibble)
  422. // XFlag = Don't Care (Bit 1 of Nibble)
  423. // nPeriphReq/nDataAvail = Don't Care (Bit 0 of Nibble)
  424. Extension->CurrentEvent = 11;
  425. if (!CHECK_DSR(Controller,
  426. DONT_CARE, ACTIVE, DONT_CARE,
  427. DONT_CARE, DONT_CARE,
  428. IEEE_MAXTIME_TL)) {
  429. // Time out.
  430. // Bad things happened - timed out on this state,
  431. // Mark Status as bad and let our mgr kill current mode.
  432. Status = STATUS_IO_DEVICE_ERROR;
  433. Extension->IsIeeeTerminateOk = FALSE;
  434. ParDump2(PARERRORS, ("ParNibbleModeRead:Failed State 11: Controller %x dcr %x\n",
  435. Controller, dcr));
  436. Extension->CurrentPhase = PHASE_UNKNOWN;
  437. goto NibbleReadExit;
  438. }
  439. }
  440. // Read two nibbles - make them into one byte.
  441. p[i] = (((nibble[0]&0x38)>>3)&0x07) |
  442. ((nibble[0]&0x80) ? 0x00 : 0x08);
  443. p[i] |= (((nibble[1]&0x38)<<1)&0x70) |
  444. ((nibble[1]&0x80) ? 0x00 : 0x80);
  445. ParDump2(PARINFO,("ParNibbleModeRead:%x:%c\n", p[i], p[i]));
  446. // At this point, we've either received the number of bytes we
  447. // were looking for, or the peripheral has no more data to
  448. // send, or there was an error of some sort (of course, in the
  449. // error case we shouldn't get to this comment). Set the
  450. // phase to indicate reverse idle if no data available or
  451. // reverse data transfer if there's some waiting for us
  452. // to get next time.
  453. dsr = READ_PORT_UCHAR(wPortDSR);
  454. if (dsr & DSR_NOT_DATA_AVAIL) {
  455. // Data is NOT available - go to Reverse Idle
  456. // Really we are going to HBDNA, but if we set
  457. // current phase to reverse idle, the next time
  458. // we get into this function all we have to do
  459. // is set hostbusy low to indicate idle and
  460. // we have infinite time to do that.
  461. // Break out of the loop so we don't try to read
  462. // data that isn't there.
  463. // NOTE - this is a successful case even if we
  464. // didn't read all that the caller requested
  465. Extension->CurrentPhase = PHASE_REVERSE_IDLE ;
  466. i++; // account for this last byte transferred
  467. break;
  468. } else {
  469. // Data is available, go to (remain in ) Reverse Transfer Phase
  470. Extension->CurrentPhase = PHASE_REVERSE_XFER ;
  471. }
  472. } // end for i loop
  473. *BytesTransferred = i;
  474. // DON'T FALL THRU THIS ONE
  475. break;
  476. default:
  477. // I'm gonna mark this as false. There is not a correct answer here.
  478. // The peripheral and the host are out of sync. I'm gonna reset myself
  479. // and the peripheral.
  480. Extension->IsIeeeTerminateOk = FALSE;
  481. Status = STATUS_IO_DEVICE_ERROR;
  482. Extension->CurrentPhase = PHASE_UNKNOWN ;
  483. ParDump2(PARERRORS, ("ParNibbleModeRead:Failed State 9: Unknown Phase. Controller %x dcr %x\n",
  484. Controller, dcr));
  485. ParDump2(PARERRORS, ( "ParNibbleModeRead: You're hosed man.\n" ));
  486. ParDump2(PARERRORS, ( "ParNibbleModeRead: If you are here, you've got a bug somewhere else.\n" ));
  487. ParDump2(PARERRORS, ( "ParNibbleModeRead: Go fix it!\n" ));
  488. goto NibbleReadExit;
  489. break;
  490. } // end switch
  491. NibbleReadExit:
  492. ParDump2(PARINFO,("ParNibbleModeRead:PHASE_REVERSE_IDLE\n"));
  493. if( Extension->CurrentPhase == PHASE_REVERSE_IDLE ) {
  494. // Host enters state 7 - officially in Reverse Idle now
  495. dcr |= DCR_NOT_HOST_BUSY;
  496. WRITE_PORT_UCHAR (wPortDCR, dcr);
  497. }
  498. ParDump2(PAREXIT,("ParNibbleModeRead:End [%d] bytes read = %d\n",
  499. NT_SUCCESS(Status), *BytesTransferred));
  500. Extension->log.NibbleReadCount += *BytesTransferred;
  501. return Status;
  502. }