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.

940 lines
30 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1993 - 1999
  3. Module Name:
  4. ieee1284.c
  5. Abstract:
  6. This module contains the code to do ieee 1284 negotiation and termination.
  7. Author:
  8. Timothy T. Wells (v-timtw) 13 Mar 97
  9. Robbie Harris (Hewlett-Packard) 21 May 98. Added enough comments to the
  10. Negotation proc to keep any developer happy.
  11. Environment:
  12. Kernel mode
  13. Revision History :
  14. --*/
  15. #include "pch.h"
  16. #include "readwrit.h"
  17. VOID
  18. IeeeTerminate1284Mode(
  19. IN PDEVICE_EXTENSION Extension
  20. );
  21. NTSTATUS
  22. IeeeEnter1284Mode(
  23. IN PDEVICE_EXTENSION Extension,
  24. IN UCHAR Extensibility
  25. );
  26. //
  27. // Definition of the Forward and Reverse Protocol Arrays
  28. //
  29. extern FORWARD_PTCL afpForward[] = {
  30. //
  31. // Bounded ECP (Hardware)
  32. //
  33. ParIsBecpSupported,
  34. ParEnterBecpMode,
  35. ParTerminateBecpMode,
  36. ParEcpHwSetAddress,
  37. ParEcpEnterForwardPhase, // Enter Forward
  38. ParEcpHwExitForwardPhase, // Exit Forward
  39. ParEcpHwWrite,
  40. BOUNDED_ECP,
  41. FAMILY_BECP,
  42. //
  43. // ECP Hardware
  44. //
  45. ParIsEcpHwSupported, // This is resued for both read/write
  46. ParEnterEcpHwMode,
  47. ParTerminateHwEcpMode,
  48. ParEcpHwSetAddress,
  49. ParEcpEnterForwardPhase, // Enter Forward
  50. ParEcpHwExitForwardPhase, // Exit Forward
  51. ParEcpHwWrite,
  52. ECP_HW_NOIRQ,
  53. FAMILY_ECP,
  54. //
  55. // Epp Hardware
  56. //
  57. ParIsEppHwSupported,
  58. ParEnterEppHwMode,
  59. ParTerminateEppHwMode,
  60. ParEppSetAddress,
  61. NULL, // Enter Forward
  62. NULL, // Exit Forward
  63. ParEppHwWrite,
  64. EPP_HW,
  65. FAMILY_EPP,
  66. //
  67. // Epp Software
  68. //
  69. ParIsEppSwWriteSupported,
  70. ParEnterEppSwMode,
  71. ParTerminateEppSwMode,
  72. ParEppSetAddress,
  73. NULL, // Enter Forward
  74. NULL, // Exit Forward
  75. ParEppSwWrite,
  76. EPP_SW,
  77. FAMILY_EPP,
  78. //
  79. // Ecp Software
  80. //
  81. ParIsEcpSwWriteSupported,
  82. ParEnterEcpSwMode,
  83. ParTerminateEcpMode,
  84. ParEcpSetAddress,
  85. NULL, // Enter Forward
  86. NULL, // Exit Forward
  87. ParEcpSwWrite,
  88. ECP_SW,
  89. FAMILY_ECP,
  90. //
  91. // IEEE Centronics
  92. //
  93. NULL,
  94. ParEnterSppMode,
  95. ParTerminateSppMode,
  96. NULL,
  97. NULL, // Enter Forward
  98. NULL, // Exit Forward
  99. SppIeeeWrite,
  100. IEEE_COMPATIBILITY,
  101. FAMILY_NONE,
  102. //
  103. // Centronics
  104. //
  105. NULL,
  106. ParEnterSppMode,
  107. ParTerminateSppMode,
  108. NULL,
  109. NULL, // Enter Forward
  110. NULL, // Exit Forward
  111. SppWrite,
  112. CENTRONICS,
  113. FAMILY_NONE,
  114. //
  115. // None...
  116. //
  117. NULL,
  118. NULL,
  119. NULL,
  120. NULL,
  121. NULL, // Enter Forward
  122. NULL, // Exit Forward
  123. NULL,
  124. NONE,
  125. FAMILY_NONE
  126. };
  127. extern REVERSE_PTCL arpReverse[] = {
  128. //
  129. // Bounded Ecp Mode
  130. //
  131. ParIsBecpSupported,
  132. ParEnterBecpMode,
  133. ParTerminateBecpMode,
  134. NULL, // Violates IEEE 1284.3 to set Reverse address for BECP
  135. ParEcpHwEnterReversePhase, // Enter Reverse
  136. ParBecpExitReversePhase, // Exit Reverse
  137. ParEcpHwDrainShadowBuffer, // A read from Cached data
  138. ParEcpHwHaveReadData, // Quick peek to see if Periph has reverse data without flipping the bus
  139. // NOTE: This is crucial since it violates the 1284.3 BECP to flip
  140. // blindly into reverse if the peripheral doesn't have data.
  141. ParBecpRead,
  142. BOUNDED_ECP,
  143. FAMILY_BECP,
  144. //
  145. // Hardware Ecp Mode
  146. //
  147. ParIsEcpHwSupported, // This is resued for both read/write
  148. ParEnterEcpHwMode,
  149. ParTerminateHwEcpMode,
  150. ParEcpHwSetAddress, // Reuse the one in ecp.c
  151. ParEcpHwEnterReversePhase, // Enter Reverse
  152. ParEcpHwExitReversePhase, // Exit Reverse
  153. ParEcpHwDrainShadowBuffer, // A read from Cached data
  154. ParEcpHwHaveReadData, // Quick peek to see if Periph has reverse data without flipping the bus
  155. ParEcpHwRead,
  156. ECP_HW_NOIRQ,
  157. FAMILY_ECP,
  158. //
  159. // Epp Hardware
  160. //
  161. ParIsEppHwSupported, // This is resued for both read/write
  162. ParEnterEppHwMode,
  163. ParTerminateEppHwMode,
  164. ParEppSetAddress,
  165. NULL, // Enter Reverse
  166. NULL, // Exit Reverse
  167. NULL, // A read from Cached data
  168. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  169. ParEppHwRead,
  170. EPP_HW,
  171. FAMILY_EPP,
  172. //
  173. // Epp Software Mode
  174. //
  175. ParIsEppSwReadSupported,
  176. ParEnterEppSwMode,
  177. ParTerminateEppSwMode,
  178. ParEppSetAddress,
  179. NULL, // Enter Reverse
  180. NULL, // Exit Reverse
  181. NULL, // A read from Cached data
  182. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  183. ParEppSwRead,
  184. EPP_SW,
  185. FAMILY_EPP,
  186. //
  187. // Ecp Software Mode
  188. //
  189. ParIsEcpSwReadSupported,
  190. ParEnterEcpSwMode,
  191. ParTerminateEcpMode,
  192. ParEcpSetAddress,
  193. ParEcpForwardToReverse, // Enter Reverse
  194. ParEcpReverseToForward, // Exit Reverse
  195. NULL, // A read from Cached data
  196. ParEcpHaveReadData, // Quick peek to see if Periph has reverse data without flipping the bus
  197. ParEcpSwRead,
  198. ECP_SW,
  199. FAMILY_ECP,
  200. //
  201. // Byte Mode
  202. //
  203. ParIsByteSupported,
  204. ParEnterByteMode,
  205. ParTerminateByteMode,
  206. NULL,
  207. NULL, // Enter Reverse
  208. NULL, // Exit Reverse
  209. NULL, // A read from Cached data
  210. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  211. ParByteModeRead,
  212. BYTE_BIDIR,
  213. FAMILY_REVERSE_BYTE,
  214. //
  215. // Nibble Mode
  216. //
  217. ParIsNibbleSupported,
  218. ParEnterNibbleMode,
  219. ParTerminateNibbleMode,
  220. NULL,
  221. NULL, // Enter Reverse
  222. NULL, // Exit Reverse
  223. NULL, // A read from Cached data
  224. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  225. ParNibbleModeRead,
  226. NIBBLE,
  227. FAMILY_REVERSE_NIBBLE,
  228. //
  229. // Channelized Nibble Mode
  230. //
  231. ParIsChannelizedNibbleSupported,
  232. ParEnterChannelizedNibbleMode,
  233. ParTerminateNibbleMode,
  234. NULL,
  235. NULL, // Enter Reverse
  236. NULL, // Exit Reverse
  237. NULL, // A read from Cached data
  238. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  239. ParNibbleModeRead,
  240. CHANNEL_NIBBLE,
  241. FAMILY_REVERSE_NIBBLE,
  242. //
  243. // None...
  244. //
  245. NULL,
  246. NULL,
  247. NULL,
  248. NULL,
  249. NULL, // Enter Reverse
  250. NULL, // Exit Reverse
  251. NULL, // A read from Cached data
  252. NULL, // Quick peek to see if Periph has reverse data without flipping the bus
  253. NULL,
  254. NONE,
  255. FAMILY_NONE
  256. };
  257. VOID
  258. IeeeTerminate1284Mode(
  259. IN PDEVICE_EXTENSION Extension
  260. )
  261. /*++
  262. Routine Description:
  263. This routine terminates the interface back to compatibility mode.
  264. Arguments:
  265. Controller - Supplies the parallel port's controller address.
  266. Return Value:
  267. None.
  268. --*/
  269. {
  270. PUCHAR Controller;
  271. PUCHAR wPortDCR;
  272. UCHAR dcr, dsrMask, dsrValue;
  273. BOOLEAN bXFlag;
  274. BOOLEAN bUseXFlag = FALSE;
  275. Controller = Extension->Controller;
  276. wPortDCR = Controller + OFFSET_DCR;
  277. dcr = READ_PORT_UCHAR(wPortDCR);
  278. if ( PHASE_TERMINATE == Extension->CurrentPhase )
  279. {
  280. // We are already terminated. This will fail if we don't
  281. // just bypass this mess.
  282. goto Terminate_ExitLabel;
  283. }
  284. #if 0
  285. // Not ready for this yet. --dvrh
  286. if (!Extension->IsIeeeTerminateOk)
  287. goto Terminate_ExitLabel;
  288. #endif
  289. // Keep Negotiated XFLAG to use for termination.
  290. // xFlag, // Technically we should have
  291. // cached this value from state
  292. // 6 of nego. This peripheral's XFlag
  293. // at pre state 22 should be the
  294. // same as state 6.
  295. bXFlag = READ_PORT_UCHAR(Controller + OFFSET_DSR) & 0x10;
  296. // REVISIT: Do we need to ensure the preceeding state is a valid
  297. // state to terminate from. In other words, is there there
  298. // a black bar on the 1284 line for that state?
  299. ParDump2(PARENTRY,("IeeeTerminate1284Mode: Start Controller %x\n", Controller));
  300. // =============== Host State 22 Termination ===============8
  301. // DIR = Don't Care (Possibly Low)
  302. // IRQEN = Don't Care (Possibly Low)
  303. // 1284/SelectIn = Low (Signals state 22)
  304. // nReverseReq/**(ECP only) = Don't Care (High for ECP, otherwise unused)
  305. // HostAck/HostBusy/nAutoFeed = High
  306. // HostClk/nStrobe = High
  307. //
  308. Extension->CurrentEvent = 22;
  309. dcr = READ_PORT_UCHAR(wPortDCR);
  310. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, ACTIVE, ACTIVE);
  311. WRITE_PORT_UCHAR(wPortDCR, dcr);
  312. // Clear data lines so we don't have any random spew.
  313. WRITE_PORT_UCHAR(Controller + OFFSET_DATA, 0);
  314. // *************** Periph State 23/24 Termination ***************8
  315. // PeriphAck/PtrBusy = High (Signals state 23 for ECP
  316. // otherwise already high)
  317. // PeriphClk/PtrClk = Low (Signals state 24 for ecp
  318. // Signals state 23 for Nibble)
  319. // nAckRev/AckDataReq/PE = Don't Care
  320. // XFlag = Low (ECP and Byte) (State 24)
  321. // = High (Nibble) (State 24)
  322. // = Low (All DeviceID Requests including Nibble) (State 24)
  323. // = Undefined (EPP)
  324. // nPeriphReq/nDataAvail = High
  325. // Don't check nPeriphReq/nDataAvail
  326. // Since it was in a "Don't Care"
  327. // state (ie. Double bar in the spec)
  328. // until state 23 for ECP mode.
  329. if (Extension->CurrentPhase == PHASE_REVERSE_IDLE ||
  330. Extension->CurrentPhase == PHASE_REVERSE_XFER)
  331. {
  332. // We must be in Nibble Reverse. Let's double check!!!
  333. if (FAMILY_REVERSE_NIBBLE == arpReverse[Extension->IdxReverseProtocol].ProtocolFamily ||
  334. FAMILY_REVERSE_BYTE == arpReverse[Extension->IdxReverseProtocol].ProtocolFamily)
  335. bUseXFlag = TRUE; // We're in Nibble or Byte
  336. else
  337. bUseXFlag = FALSE; // Don't know what mode we are in?
  338. }
  339. else
  340. {
  341. if (FAMILY_BECP == afpForward[Extension->IdxForwardProtocol].ProtocolFamily ||
  342. FAMILY_ECP == afpForward[Extension->IdxForwardProtocol].ProtocolFamily)
  343. bUseXFlag = TRUE; // We're in an ECP Flavor
  344. else
  345. bUseXFlag = FALSE; // Don't know what mode we are in?
  346. }
  347. if (bUseXFlag)
  348. {
  349. dsrMask = DSR_TEST_MASK( DONT_CARE,
  350. INACTIVE,
  351. DONT_CARE,
  352. bXFlag ? INACTIVE : ACTIVE,
  353. DONT_CARE );
  354. dsrValue = DSR_TEST_VALUE( DONT_CARE,
  355. INACTIVE,
  356. DONT_CARE,
  357. bXFlag ? INACTIVE : ACTIVE,
  358. DONT_CARE );
  359. }
  360. else
  361. {
  362. dsrMask = DSR_TEST_MASK( DONT_CARE,
  363. INACTIVE,
  364. DONT_CARE,
  365. DONT_CARE,
  366. DONT_CARE );
  367. dsrValue = DSR_TEST_VALUE( DONT_CARE,
  368. INACTIVE,
  369. DONT_CARE,
  370. DONT_CARE,
  371. DONT_CARE );
  372. }
  373. Extension->CurrentEvent = 23;
  374. if (!CheckPort(Controller + OFFSET_DSR,
  375. dsrMask,
  376. dsrValue,
  377. IEEE_MAXTIME_TL))
  378. {
  379. // We couldn't negotiate back to compatibility mode.
  380. // just terminate.
  381. ParDump2(PARERRORS,("IeeeTerminate1284Mode:State 23/24 Failed: Controller %x dsr %x dcr %x\n",
  382. Controller,
  383. READ_PORT_UCHAR(Controller + OFFSET_DSR), dcr));
  384. goto Terminate_ExitLabel;
  385. }
  386. // =============== Host State 25 Termination ===============8
  387. // DIR = Don't Care (Possibly Low)
  388. // IRQEN = Don't Care (Possibly Low)
  389. // 1284/SelectIn = Low
  390. // nReverseReq/**(ECP only) = Don't Care (Possibly High)
  391. // HostAck/HostBusy/nAutoFeed = Low (Signals State 25)
  392. // HostClk/nStrobe = High
  393. //
  394. Extension->CurrentEvent = 25;
  395. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, INACTIVE, ACTIVE);
  396. WRITE_PORT_UCHAR(wPortDCR, dcr);
  397. // =============== State 26 Termination ===============8
  398. // Do nothing for state 26
  399. // =============== Periph State 27 Termination ===============8
  400. // PeriphAck/PtrBusy = High
  401. // PeriphClk/PtrClk = High (Signals State 27)
  402. // nAckRev/AckDataReq/PE = Don't Care (Invalid from State 23)
  403. // XFlag = Don't Care (All Modes) (Invlaid at State 27)
  404. // nPeriphReq/nDataAvial = Don't Care (Invalid from State 26)
  405. // dvrh 6/16/97
  406. Extension->CurrentEvent = 27;
  407. if (!CHECK_DSR(Controller,
  408. ACTIVE, ACTIVE, DONT_CARE, DONT_CARE, DONT_CARE,
  409. IEEE_MAXTIME_TL))
  410. {
  411. ParDump2(PARERRORS, ("IeeeTerminate1284Mode:State 27 Failed: Controller %x dsr %x dcr %x\n",
  412. Controller,
  413. READ_PORT_UCHAR(Controller + OFFSET_DSR), dcr));
  414. }
  415. // I'm really big into having one exit point in a
  416. // proc. 2/10/97 dvrh
  417. Terminate_ExitLabel:
  418. // =============== Host State 28 Termination ===============8
  419. // DIR = Don't Care (Possibly Low)
  420. // IRQEN = Don't Care (Possibly Low)
  421. // 1284/SelectIn = Low
  422. // nReverseReq/**(ECP only) = Don't Care (Possibly High)
  423. // HostAck/HostBusy/nAutoFeed = High (Signals State 28)
  424. // HostClk/nStrobe = High
  425. //
  426. Extension->CurrentEvent = 28;
  427. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, ACTIVE, ACTIVE);
  428. WRITE_PORT_UCHAR(wPortDCR, dcr);
  429. // We are now back in compatibility mode.
  430. ParDump2(PARECPTRACE,("IeeeTerminate1284Mode: Phase_Terminate\n"));
  431. Extension->CurrentPhase = PHASE_TERMINATE;
  432. Extension->Connected = FALSE;
  433. Extension->IsIeeeTerminateOk = FALSE;
  434. ParDump2(PAREXIT,("IeeeTerminate1284Mode: End dcr %x\n", dcr));
  435. return;
  436. }
  437. NTSTATUS
  438. IeeeEnter1284Mode(
  439. IN PDEVICE_EXTENSION Extension,
  440. IN UCHAR Extensibility
  441. )
  442. /*++
  443. Routine Description:
  444. This routine performs 1284 negotiation with the peripheral to the
  445. nibble mode protocol.
  446. Arguments:
  447. Controller - Supplies the port address.
  448. DeviceIdRequest - Supplies whether or not this is a request for a device
  449. id.
  450. Return Value:
  451. STATUS_SUCCESS - Successful negotiation.
  452. otherwise - Unsuccessful negotiation.
  453. --*/
  454. {
  455. PUCHAR wPortDCR;
  456. PUCHAR Controller;
  457. UCHAR dcr;
  458. // BOOLEAN xFlag;
  459. NTSTATUS Status = STATUS_SUCCESS;
  460. const USHORT sPeriphResponseTime = 35;
  461. Controller = Extension->Controller;
  462. wPortDCR = Controller + OFFSET_DCR;
  463. ParDump2(PARENTRY,("IeeeEnter1284Mode: Start Controller %x\n", Controller));
  464. /* =============== Host Prep for Pre State 0 ===============8
  465. Set the following just in case someone didn't
  466. put the port in compatibility mode before we got it.
  467. DIR = Don't Care
  468. IRQEN = Don't Care
  469. 1284/SelectIn = Low
  470. nReverseReq/ (ECP only)= High for ECP / Don't Care for Nibble
  471. I will do ahead and set it to high
  472. since Nibble doesn't care.
  473. HostAck/HostBusy = High
  474. HostClk/nStrobe = Don't Care
  475. ============================================================ */
  476. dcr = READ_PORT_UCHAR(wPortDCR); // Get content of DCR.
  477. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, ACTIVE, ACTIVE, DONT_CARE);
  478. WRITE_PORT_UCHAR(wPortDCR, dcr);
  479. KeStallExecutionProcessor(2);
  480. /* =============== Host Pre State 0 Negotiation ===============8
  481. DIR = Low ( Don't Care by spec )
  482. IRQEN = Low ( Don't Care by spec )
  483. 1284/SelectIn = Low
  484. nReverseReq/ (ECP only)= High ( Don't Care by spec )
  485. HostAck/HostBusy = High
  486. HostClk/nStrobe = High
  487. ============================================================ */
  488. dcr = UPDATE_DCR(dcr, INACTIVE, INACTIVE, INACTIVE, ACTIVE, ACTIVE, ACTIVE);
  489. WRITE_PORT_UCHAR(wPortDCR, dcr);
  490. KeStallExecutionProcessor(2);
  491. /* =============== Host State 0 Negotiation ===============8
  492. Place the extensibility request value on the data bus - state 0.
  493. ============================================================ */
  494. Extension->CurrentEvent = 0;
  495. WRITE_PORT_UCHAR(Controller + DATA_OFFSET, Extensibility);
  496. KeStallExecutionProcessor(2);
  497. /* =========== Host State 1 Negotiation Phase ===========8
  498. DIR = Don't Care
  499. IRQEN = Don't Care
  500. 1284/SelectIn = High (Signals State 1)
  501. nReverseReq/ (ECP only)= Don't Care
  502. HostAck/HostBusy = Low (Signals state 1)
  503. HostClk/nStrobe = High
  504. ============================================================ */
  505. Extension->CurrentEvent = 1;
  506. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, INACTIVE, ACTIVE);
  507. WRITE_PORT_UCHAR(wPortDCR, dcr);
  508. /* =============== Periph State 2 Negotiation ===============8
  509. PeriphAck/PtrBusy = Don't Care
  510. PeriphClk/PtrClk = low Signals State 2
  511. nAckReverse/AckDataReq = high Signals State 2
  512. XFlag = high Signals State 2
  513. **Note: It is high at state 2
  514. for both ecp and nibble
  515. nPeriphReq/nDataAvail = high Signals State 2
  516. ============================================================ */
  517. Extension->CurrentEvent = 2;
  518. if (!CHECK_DSR(Controller, DONT_CARE, INACTIVE, ACTIVE, ACTIVE, ACTIVE,
  519. sPeriphResponseTime)) {
  520. KeStallExecutionProcessor(2);
  521. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, ACTIVE, DONT_CARE);
  522. WRITE_PORT_UCHAR(wPortDCR, dcr);
  523. ParDump2(PARIEEE, ("IeeeEnter1284Mode: %x - Extensibility=%x, FAIL - TIMEOUT on Event 2\n",
  524. Extension->Controller, Extensibility) );
  525. Extension->CurrentPhase = PHASE_UNKNOWN;
  526. Extension->Connected = FALSE;
  527. Extension->IsIeeeTerminateOk = FALSE;
  528. return STATUS_INVALID_DEVICE_REQUEST;
  529. }
  530. /* =============== Host State 3 Negotiation ===============8
  531. DIR = Don't Care
  532. IRQEN = Don't Care
  533. 1284/SelectIn = High
  534. nReverseReq/ (ECP only)= Don't Care
  535. HostAck/HostBusy = Low
  536. HostClk/nStrobe = Low (signals State 3)
  537. NOTE: Strobe the Extensibility byte
  538. ============================================================ */
  539. Extension->CurrentEvent = 3;
  540. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, INACTIVE, INACTIVE);
  541. WRITE_PORT_UCHAR(wPortDCR, dcr);
  542. // HostClk must be help low for at least .5 microseconds.
  543. //
  544. KeStallExecutionProcessor(2);
  545. /* =============== Host State 4 Negotiation ===============8
  546. DIR = Don't Care
  547. IRQEN = Don't Care
  548. 1284/SelectIn = High
  549. nReverseReq/ (ECP only)= Don't Care
  550. HostAck/HostBusy = High (signals State 4)
  551. HostClk/nStrobe = High (signals State 4)
  552. NOTE: nReverseReq should be high in ECP, but this line is only
  553. valid for ECP. Since it isn't used for signaling
  554. anything in negotiation, let's just ignore it for now.
  555. ============================================================ */
  556. Extension->CurrentEvent = 4;
  557. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, ACTIVE, ACTIVE);
  558. WRITE_PORT_UCHAR(wPortDCR, dcr);
  559. /* ============== Periph State 5/6 Negotiation ===============
  560. PeriphAck/PtrBusy = Don't Care. low (ECP) / Don't Care (Nibble)
  561. Since this line differs based on Protocol
  562. Let's not check the line.
  563. PeriphClk/PtrClk = high (Signals State 6)
  564. nAckReverse/AckDataReq = Don't Care. low (ECP) / high (Nibble)
  565. Since this line differs based on Protocol
  566. Let's not check the line.
  567. XFlag = Don't Care. high (ECP) / low (Nibble)
  568. Since this line differs based on Protocol
  569. Let's not check the line.
  570. nPeriphReq/nDataAvail = Don't Care. high (ECP) / low (Nibble)
  571. Since this line differs based on Protocol
  572. Let's not check the line.
  573. ============== Periph State 5/6 Negotiation ==============8
  574. NOTES:
  575. - It's ok to lump states 5 and 6 together. In state 5 Nibble,
  576. the periph will set XFlag low and nPeriphReq/nDataAvail low.
  577. The periph will then hold for .5ms then set PeriphClk/PtrClk
  578. high. In ECP, state 5 is nAckReverse/AckDataReq going low and
  579. PeriphAck/PtrBusy going low. Followed by a .5ms pause.
  580. Followed by PeriphClk/PtrClk going high.
  581. ============================================================ */
  582. Extension->CurrentEvent = 5;
  583. if (!CHECK_DSR(Controller, DONT_CARE, ACTIVE, DONT_CARE, DONT_CARE, DONT_CARE,
  584. sPeriphResponseTime)) {
  585. dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE, DONT_CARE, DONT_CARE);
  586. WRITE_PORT_UCHAR(wPortDCR, dcr);
  587. ParDump2(PARIEEE, ("IeeeEnter1284Mode: %x - Extensibility=%x, FAIL - TIMEOUT on Events 5/6\n",
  588. Extension->Controller, Extensibility) );
  589. Extension->CurrentPhase = PHASE_UNKNOWN;
  590. Extension->Connected = FALSE;
  591. Extension->IsIeeeTerminateOk = FALSE;
  592. return STATUS_INVALID_DEVICE_REQUEST;
  593. }
  594. KeStallExecutionProcessor(2);
  595. ParDump2(PARENTRY,("IeeeEnter1284Mode: Phase Negotiated Controller %x\n", Controller));
  596. Extension->CurrentPhase = PHASE_NEGOTIATION;
  597. Extension->Connected = TRUE;
  598. return STATUS_SUCCESS;
  599. }
  600. VOID
  601. IeeeDetermineSupportedProtocols(
  602. IN PDEVICE_EXTENSION Extension
  603. )
  604. /*++
  605. Routine Description:
  606. This routine walks the list of all ieee1284 modes, and
  607. flags each of the ones the peripheral supports in
  608. Extension->ProtocolModesSupported. This proc is called from
  609. external IOCTL.
  610. Arguments:
  611. Extension - The parallel device extension
  612. Return Value:
  613. --*/
  614. {
  615. REVERSE_MODE rm;
  616. FORWARD_MODE fm;
  617. // Take CENTRONICS as a given since it is not a
  618. // mode we can neogitate to.
  619. //
  620. // n.b.
  621. // Let's go ahead and mark IEEE_COMPATIBILITY since we
  622. // cannot negotiate into it. But if the someone sets
  623. // IEEE_COMPATIBILITY and the peripheral does not support
  624. // IEEE 1284 compliant compatibility mode then we're gonna
  625. // create one very unhappy peripheral. -- dvrh
  626. Extension->ProtocolModesSupported = CENTRONICS | IEEE_COMPATIBILITY;
  627. //
  628. // Unlikely that we would be connected, but...
  629. //
  630. ParTerminate(Extension);
  631. for (fm = FORWARD_FASTEST; fm < FORWARD_NONE; fm++) {
  632. if (afpForward[fm].fnIsModeSupported)
  633. afpForward[fm].fnIsModeSupported(Extension);
  634. }
  635. for (rm = REVERSE_FASTEST; rm < REVERSE_NONE; rm++) {
  636. if (arpReverse[rm].fnIsModeSupported)
  637. arpReverse[rm].fnIsModeSupported(Extension);
  638. }
  639. return;
  640. }
  641. NTSTATUS
  642. IeeeNegotiateBestMode(
  643. IN PDEVICE_EXTENSION Extension,
  644. IN USHORT usReadMask,
  645. IN USHORT usWriteMask
  646. )
  647. /*++
  648. Routine Description:
  649. This routine walks the list of supported modes, looking for the best
  650. (fastest) mode. It will skip any mode(s) mask passed in.
  651. Arguments:
  652. Extension - The parallel device extension
  653. Return Value:
  654. STATUS_SUCCESS - Successful negotiation.
  655. otherwise - Unsuccessful negotiation.
  656. --*/
  657. {
  658. REVERSE_MODE rm;
  659. FORWARD_MODE fm;
  660. //
  661. // A USHORT is provided in the extension so that each of the protocols
  662. // can decide whether they need to negotiate each time we go through this
  663. // process...
  664. //
  665. //
  666. // Unlikely that we would be connected, but...
  667. //
  668. ParDump2(PARENTRY, ("IeeeNegotiateBestMode: Enter. Skipping Fwd [%lx] Rev [%lx]\n",
  669. usWriteMask, usReadMask));
  670. ParTerminate(Extension);
  671. Extension->IdxForwardProtocol = FORWARD_NONE;
  672. Extension->IdxReverseProtocol = REVERSE_NONE;
  673. for (fm = FORWARD_FASTEST; fm < FORWARD_NONE; fm++) {
  674. if (!(afpForward[fm].Protocol & usWriteMask)) {
  675. if (afpForward[fm].fnIsModeSupported) {
  676. ParDump2( PARINFO, ("IeeeNegotiateBestMode: Calling ForwardIsSupportedRoutine.\n"));
  677. if (afpForward[fm].fnIsModeSupported(Extension)) {
  678. Extension->IdxForwardProtocol = (USHORT)fm;
  679. break;
  680. }
  681. }
  682. }
  683. }
  684. for (rm = REVERSE_FASTEST; rm < REVERSE_NONE; rm++) {
  685. if (!(arpReverse[rm].Protocol & usReadMask)) {
  686. if (arpReverse[rm].fnIsModeSupported) {
  687. ParDump2( PARINFO, ("IeeeNegotiateBestMode: Calling ReverseIsSupportedRoutine.\n"));
  688. if (arpReverse[rm].fnIsModeSupported(Extension)) {
  689. Extension->IdxReverseProtocol = (USHORT)rm;
  690. break;
  691. }
  692. }
  693. }
  694. }
  695. #if (1 == DVRH_USE_CORRECT_PTRS)
  696. Extension->fnRead = arpReverse[Extension->IdxReverseProtocol].fnRead;
  697. Extension->fnWrite = afpForward[Extension->IdxForwardProtocol].fnWrite;
  698. #endif
  699. ParDump2( PAREXIT, ("IeeeNegotiateBestMode: Exit. Fwd [%x] Rev [%x]\n", fm, rm));
  700. return STATUS_SUCCESS;
  701. }
  702. NTSTATUS
  703. IeeeNegotiateMode(
  704. IN PDEVICE_EXTENSION Extension,
  705. IN USHORT usReadMask,
  706. IN USHORT usWriteMask
  707. )
  708. /*++
  709. Routine Description:
  710. This routine walks the list of supported modes, looking for the best
  711. (fastest) mode which is also in the mode mask passed in.
  712. Arguments:
  713. Extension - The parallel device extension
  714. Return Value:
  715. STATUS_SUCCESS - Successful negotiation.
  716. otherwise - Unsuccessful negotiation.
  717. --*/
  718. {
  719. REVERSE_MODE rm;
  720. FORWARD_MODE fm;
  721. //
  722. // A USHORT is provided in the extension so that each of the protocols
  723. // can decide whether they need to negotiate each time we go through this
  724. // process...
  725. //
  726. //
  727. // Unlikely that we would be connected, but...
  728. //
  729. ParDump2(PARENTRY, ("IeeeNegotiateMode: Enter\n"));
  730. ParTerminate(Extension);
  731. Extension->IdxForwardProtocol = FORWARD_NONE;
  732. Extension->IdxReverseProtocol = REVERSE_NONE;
  733. for (fm = FORWARD_FASTEST; fm < FORWARD_NONE; fm++) {
  734. if (afpForward[fm].Protocol & usWriteMask) {
  735. if (afpForward[fm].fnIsModeSupported) {
  736. ParDump2( PARINFO, ("IeeeNegotiateMode: Calling ForwardIsSupportedRoutine.\n"));
  737. if (afpForward[fm].fnIsModeSupported(Extension)) {
  738. Extension->IdxForwardProtocol = (USHORT)fm;
  739. break;
  740. }
  741. } else {
  742. ParDump2( PARINFO, ("IeeeNegotiateMode: No ForwardIsSupportedRoutine.\n"));
  743. Extension->IdxForwardProtocol = (USHORT)fm;
  744. break;
  745. }
  746. }
  747. }
  748. ParDump2( PARINFO, ("IeeeNegotiateMode: Extension->IdxForwardProtocol = %x.\n", fm));
  749. for (rm = REVERSE_FASTEST; rm < REVERSE_NONE; rm++) {
  750. if (arpReverse[rm].Protocol & usReadMask) {
  751. if (arpReverse[rm].fnIsModeSupported) {
  752. ParDump2( PARINFO, ("IeeeNegotiateMode: Calling ReverseIsSupportedRoutine.\n"));
  753. if (arpReverse[rm].fnIsModeSupported(Extension)) {
  754. Extension->IdxReverseProtocol = (USHORT)rm;
  755. break;
  756. }
  757. } else {
  758. ParDump2( PARINFO, ("IeeeNegotiateMode: No ReverseIsSupportedRoutine.\n"));
  759. Extension->IdxReverseProtocol = (USHORT)rm;
  760. break;
  761. }
  762. }
  763. }
  764. ParDump2( PARINFO, ("IeeeNegotiateMode: Extension->IdxReverseProtocol = %x.\n", rm));
  765. #if (1 == DVRH_USE_CORRECT_PTRS)
  766. Extension->fnRead = arpReverse[Extension->IdxReverseProtocol].fnRead;
  767. Extension->fnWrite = afpForward[Extension->IdxForwardProtocol].fnWrite;
  768. #endif
  769. ParDump2( PAREXIT, ("IeeeNegotiateMode: Exit\n"));
  770. return STATUS_SUCCESS;
  771. }