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.

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