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.

2647 lines
76 KiB

  1. /*++
  2. Copyright (C) SCM Micro Systems.
  3. Module Name:
  4. parstl.c
  5. Abstract:
  6. This is the module that generates unique device id
  7. for shuttle adapters, that do not have the capability
  8. to do so, by themselves.
  9. Author:
  10. Devanathan NR 21-Jun-1999
  11. Sudheendran TL
  12. Environment:
  13. Kernel mode
  14. Revision History :
  15. --*/
  16. #include "pch.h"
  17. #include "parstl.h"
  18. BOOLEAN
  19. ParStlCheckIfStl(
  20. IN PDEVICE_EXTENSION Extension,
  21. IN ULONG ulDaisyIndex
  22. )
  23. /*++
  24. Routine Description:
  25. This function checks whether the indicated device
  26. is a shuttle device or not.
  27. Arguments:
  28. Extension - Device extension structure.
  29. ulDaisyIndex - The daisy index on which to do the check.
  30. Return Value:
  31. TRUE - Yes, it was a Shuttle device.
  32. FALSE - No, not a shuttle.
  33. --*/
  34. {
  35. NTSTATUS status ;
  36. BOOLEAN bStlNon1284_3Found = FALSE ;
  37. Extension->Ieee1284Flags &= ( ~ ( 1 << ulDaisyIndex ) ) ;
  38. bStlNon1284_3Found = ParStlCheckIfNon1284_3Present( Extension ) ;
  39. if ( TRUE == ParStlCheckIfStl1284_3 ( Extension, ulDaisyIndex, bStlNon1284_3Found ) ) {
  40. // this adapter is a Shuttle 1284_3 adapter
  41. Extension->Ieee1284Flags |= ( 1 << ulDaisyIndex ) ;
  42. return TRUE ;
  43. }
  44. if ( TRUE == bStlNon1284_3Found ) {
  45. if ( TRUE == ParStlCheckIfStlProductId ( Extension, ulDaisyIndex ) ) {
  46. // this adapter is Shuttle non-1284_3 adapter
  47. Extension->Ieee1284Flags |= ( 1 << ulDaisyIndex ) ;
  48. return TRUE ;
  49. }
  50. }
  51. return FALSE ;
  52. }
  53. BOOLEAN
  54. ParStlCheckIfNon1284_3Present(
  55. IN PDEVICE_EXTENSION Extension
  56. )
  57. /*++
  58. Routine Description:
  59. Indicates whether one of the devices of the earlier
  60. specification is present in the chain.
  61. Arguments:
  62. Extension - Device Extension structure
  63. Return Value:
  64. TRUE : Atleast one of the adapters are of earlier spec.
  65. FALSE : None of the adapters of the earlier spec.
  66. --*/
  67. {
  68. BOOLEAN bReturnValue = FALSE ;
  69. UCHAR i, value, newvalue, status;
  70. ULONG Delay = 3;
  71. PUCHAR CurrentPort, CurrentStatus, CurrentControl;
  72. UCHAR ucAckStatus ;
  73. CurrentPort = Extension->Controller;
  74. CurrentStatus = CurrentPort + 1;
  75. CurrentControl = CurrentPort + 2;
  76. // get current ctl reg
  77. value = READ_PORT_UCHAR( CurrentControl );
  78. // make sure 1284.3 devices do not get reseted
  79. newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
  80. // make sure we can write
  81. newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION);
  82. WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
  83. // bring nStrobe high
  84. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  85. // send first four bytes of the 1284.3 mode qualifier sequence out
  86. for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) {
  87. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] );
  88. KeStallExecutionProcessor( Delay );
  89. }
  90. // check for correct status
  91. status = READ_PORT_UCHAR( CurrentStatus );
  92. if ( (status & (UCHAR)0xb8 )
  93. == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
  94. ucAckStatus = status & 0x40 ;
  95. // continue with fifth byte of mode qualifier
  96. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] );
  97. KeStallExecutionProcessor( Delay );
  98. // check for correct status
  99. status = READ_PORT_UCHAR( CurrentStatus );
  100. // note busy is high too but is opposite so we see it as a low
  101. if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
  102. if ( ucAckStatus != ( status & 0x40 ) ) {
  103. // save current ack status
  104. ucAckStatus = status & 0x40 ;
  105. // continue with sixth byte
  106. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] );
  107. KeStallExecutionProcessor( Delay );
  108. // check for correct status
  109. status = READ_PORT_UCHAR( CurrentStatus );
  110. // if status is valid there is a device out there responding
  111. if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
  112. bReturnValue = TRUE ;
  113. } // Third status
  114. } // ack of earlier adapters not seen
  115. // last byte
  116. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
  117. } // Second status
  118. } // First status
  119. WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
  120. return bReturnValue ;
  121. } // ParStlCheckIfNon1284_3Present
  122. BOOLEAN
  123. ParStlCheckIfStl1284_3(
  124. IN PDEVICE_EXTENSION Extension,
  125. IN ULONG ulDaisyIndex,
  126. IN BOOLEAN bNoStrobe
  127. )
  128. /*++
  129. Routine Description:
  130. This function checks to see whether the device indicated
  131. is a Shuttle 1284_3 type of device.
  132. Arguments:
  133. Extension - Device extension structure.
  134. ulDaisyIndex - The daisy chain id of the device that
  135. this function will check on.
  136. bNoStrobe - If set, indicates that the query
  137. Ep1284 command issued by this function
  138. need not assert strobe to latch the
  139. command.
  140. Return Value:
  141. TRUE - Yes. Device is Shuttle 1284_3 type of device.
  142. FALSE - No. This may mean that this device is either
  143. non-shuttle or Shuttle non-1284_3 type of
  144. device.
  145. --*/
  146. {
  147. BOOLEAN bReturnValue = FALSE ;
  148. UCHAR i, value, newvalue, status;
  149. ULONG Delay = 3;
  150. UCHAR ucExpectedPattern ;
  151. UCHAR ucReadValue, ucReadPattern;
  152. PUCHAR CurrentPort, CurrentStatus, CurrentControl;
  153. CurrentPort = Extension->Controller;
  154. CurrentStatus = CurrentPort + 1;
  155. CurrentControl = CurrentPort + 2;
  156. // get current ctl reg
  157. value = READ_PORT_UCHAR( CurrentControl );
  158. // make sure 1284.3 devices do not get reseted
  159. newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
  160. // make sure we can write
  161. newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION);
  162. WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
  163. // bring nStrobe high
  164. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  165. // send first four bytes of the 1284.3 mode qualifier sequence out
  166. for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) {
  167. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] );
  168. KeStallExecutionProcessor( Delay );
  169. }
  170. // check for correct status
  171. status = READ_PORT_UCHAR( CurrentStatus );
  172. if ( (status & (UCHAR)0xb8 )
  173. == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
  174. // continue with fifth byte of mode qualifier
  175. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] );
  176. KeStallExecutionProcessor( Delay );
  177. // check for correct status
  178. status = READ_PORT_UCHAR( CurrentStatus );
  179. // note busy is high too but is opposite so we see it as a low
  180. if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
  181. // continue with sixth byte
  182. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] );
  183. KeStallExecutionProcessor( Delay );
  184. // check for correct status
  185. status = READ_PORT_UCHAR( CurrentStatus );
  186. // if status is valid there is a device out there responding
  187. if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
  188. // Device is out there
  189. KeStallExecutionProcessor( Delay );
  190. // issue shuttle specific CPP command
  191. WRITE_PORT_UCHAR( CurrentPort, (UCHAR) ( 0x88 | ulDaisyIndex ) );
  192. KeStallExecutionProcessor( Delay ); // wait a bit
  193. if ( ulDaisyIndex && ( bNoStrobe == FALSE ) ) {
  194. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  195. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
  196. KeStallExecutionProcessor( Delay ); // wait a bit
  197. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  198. KeStallExecutionProcessor( Delay ); // wait a bit
  199. }
  200. ucExpectedPattern = 0xF0 ;
  201. bReturnValue = TRUE ;
  202. while ( ucExpectedPattern ) {
  203. KeStallExecutionProcessor( Delay ); // wait a bit
  204. WRITE_PORT_UCHAR( CurrentPort, (UCHAR) (0x80 | ulDaisyIndex )) ;
  205. KeStallExecutionProcessor( Delay ); // wait a bit
  206. WRITE_PORT_UCHAR( CurrentPort, (UCHAR) (0x88 | ulDaisyIndex )) ;
  207. KeStallExecutionProcessor( Delay ); // wait a bit
  208. ucReadValue = READ_PORT_UCHAR( CurrentStatus ) ;
  209. ucReadPattern = ( ucReadValue << 1 ) & 0x70 ;
  210. ucReadPattern |= ( ucReadValue & 0x80 ) ;
  211. if ( ucReadPattern != ucExpectedPattern ) {
  212. // not Shuttle 1284_3 behaviour
  213. bReturnValue = FALSE ;
  214. break ;
  215. }
  216. ucExpectedPattern -= 0x10 ;
  217. }
  218. // last byte
  219. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
  220. } // Third status
  221. } // Second status
  222. } // First status
  223. WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
  224. return bReturnValue ;
  225. } // end ParStlCheckIfStl1284_3()
  226. BOOLEAN
  227. ParStlCheckIfStlProductId(
  228. IN PDEVICE_EXTENSION Extension,
  229. IN ULONG ulDaisyIndex
  230. )
  231. /*++
  232. Routine Description:
  233. This function checks to see whether the device indicated
  234. is a Shuttle non-1284_3 type of device.
  235. Arguments:
  236. Extension - Device extension structure.
  237. ulDaisyIndex - The daisy chain id of the device that
  238. this function will check on.
  239. Return Value:
  240. TRUE - Yes. Device is Shuttle non-1284_3 type of device.
  241. FALSE - No. This may mean that this device is
  242. non-shuttle.
  243. --*/
  244. {
  245. BOOLEAN bReturnValue = FALSE ;
  246. UCHAR i, value, newvalue, status;
  247. ULONG Delay = 3;
  248. UCHAR ucProdIdHiByteHiNibble, ucProdIdHiByteLoNibble ;
  249. UCHAR ucProdIdLoByteHiNibble, ucProdIdLoByteLoNibble ;
  250. UCHAR ucProdIdHiByte, ucProdIdLoByte ;
  251. USHORT usProdId ;
  252. PUCHAR CurrentPort, CurrentStatus, CurrentControl;
  253. CurrentPort = Extension->Controller;
  254. CurrentStatus = CurrentPort + 1;
  255. CurrentControl = CurrentPort + 2;
  256. // get current ctl reg
  257. value = READ_PORT_UCHAR( CurrentControl );
  258. // make sure 1284.3 devices do not get reseted
  259. newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
  260. // make sure we can write
  261. newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION);
  262. WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
  263. // bring nStrobe high
  264. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  265. // send first four bytes of the 1284.3 mode qualifier sequence out
  266. for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) {
  267. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] );
  268. KeStallExecutionProcessor( Delay );
  269. }
  270. // check for correct status
  271. status = READ_PORT_UCHAR( CurrentStatus );
  272. if ( (status & (UCHAR)0xb8 )
  273. == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
  274. // continue with fifth byte of mode qualifier
  275. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] );
  276. KeStallExecutionProcessor( Delay );
  277. // check for correct status
  278. status = READ_PORT_UCHAR( CurrentStatus );
  279. // note busy is high too but is opposite so we see it as a low
  280. if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
  281. // continue with sixth byte
  282. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] );
  283. KeStallExecutionProcessor( Delay );
  284. // check for correct status
  285. status = READ_PORT_UCHAR( CurrentStatus );
  286. // if status is valid there is a device out there responding
  287. if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
  288. WRITE_PORT_UCHAR ( CurrentPort, (UCHAR) (CPP_QUERY_PRODID | ulDaisyIndex )) ;
  289. KeStallExecutionProcessor( Delay );
  290. // Device is out there
  291. KeStallExecutionProcessor( Delay );
  292. ucProdIdLoByteHiNibble = READ_PORT_UCHAR( CurrentStatus ) ;
  293. ucProdIdLoByteHiNibble &= 0xF0 ;
  294. KeStallExecutionProcessor( Delay );
  295. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  296. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
  297. KeStallExecutionProcessor( Delay ); // wait a bit
  298. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  299. KeStallExecutionProcessor( Delay ); // wait a bit
  300. ucProdIdLoByteLoNibble = READ_PORT_UCHAR( CurrentStatus ) ;
  301. ucProdIdLoByteLoNibble >>= 4 ;
  302. ucProdIdLoByte = ucProdIdLoByteHiNibble | ucProdIdLoByteLoNibble ;
  303. KeStallExecutionProcessor( Delay );
  304. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  305. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
  306. KeStallExecutionProcessor( Delay ); // wait a bit
  307. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  308. KeStallExecutionProcessor( Delay ); // wait a bit
  309. ucProdIdHiByteHiNibble = READ_PORT_UCHAR( CurrentStatus ) ;
  310. ucProdIdHiByteHiNibble &= 0xF0 ;
  311. KeStallExecutionProcessor( Delay );
  312. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  313. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
  314. KeStallExecutionProcessor( Delay ); // wait a bit
  315. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  316. KeStallExecutionProcessor( Delay ); // wait a bit
  317. ucProdIdHiByteLoNibble = READ_PORT_UCHAR( CurrentStatus ) ;
  318. ucProdIdHiByteLoNibble >>= 4 ;
  319. ucProdIdHiByte = ucProdIdHiByteHiNibble | ucProdIdHiByteLoNibble ;
  320. // last strobe
  321. KeStallExecutionProcessor( Delay );
  322. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
  323. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
  324. KeStallExecutionProcessor( Delay ); // wait a bit
  325. WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
  326. KeStallExecutionProcessor( Delay ); // wait a bit
  327. usProdId = ( ucProdIdHiByte << 8 ) | ucProdIdLoByte ;
  328. if ( ( SHTL_EPAT_PRODID == usProdId ) ||\
  329. ( SHTL_EPST_PRODID == usProdId ) ) {
  330. // one of the devices that conform to the earlier
  331. // draft is found
  332. bReturnValue = TRUE ;
  333. }
  334. // last byte
  335. WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
  336. } // Third status
  337. } // Second status
  338. } // First status
  339. WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
  340. return bReturnValue ;
  341. } // end ParStlCheckIfStlProductId()
  342. PCHAR
  343. ParStlQueryStlDeviceId(
  344. IN PDEVICE_EXTENSION Extension,
  345. OUT PCHAR CallerDeviceIdBuffer,
  346. IN ULONG CallerBufferSize,
  347. OUT PULONG DeviceIdSize,
  348. IN BOOLEAN bReturnRawString
  349. )
  350. /*++
  351. Routine Description:
  352. This routine retrieves/constructs the unique device id
  353. string from the selected shuttle device on the chain
  354. and updates the caller's buffer with the same.
  355. Arguments:
  356. IN Extension : The device extension
  357. OUT CallerDeviceIdBuffer : Caller's buffer
  358. IN CallerBufferSize : Size of caller's buffer
  359. OUT DeviceIdSize : Updated device id's size
  360. IN bReturnRawString : Whether to return raw
  361. string with the first two
  362. bytes or not.
  363. Return Value:
  364. Pointer to the read device ID string, if successful.
  365. NULL otherwise.
  366. --*/
  367. {
  368. PUCHAR Controller = Extension->Controller;
  369. NTSTATUS Status;
  370. UCHAR idSizeBuffer[2];
  371. ULONG bytesToRead;
  372. ULONG bytesRead = 0;
  373. USHORT deviceIdSize;
  374. USHORT deviceIdBufferSize;
  375. PCHAR deviceIdBuffer;
  376. PCHAR readPtr;
  377. *DeviceIdSize = 0;
  378. // assert idle state, to recover from undefined state,
  379. // just in case it gets into
  380. ParStlAssertIdleState ( Extension ) ;
  381. //
  382. // If we are currently connected to the peripheral via any 1284 mode
  383. // other than Compatibility/Spp mode (which does not require an IEEE
  384. // negotiation), we must first terminate the current mode/connection.
  385. //
  386. // dvdf - RMT - what if we are connected in a reverse mode?
  387. //
  388. if( (Extension->Connected) && (afpForward[Extension->IdxForwardProtocol].fnDisconnect) ) {
  389. afpForward[Extension->IdxForwardProtocol].fnDisconnect (Extension);
  390. }
  391. do {
  392. //
  393. // Negotiate the peripheral into nibble device id mode.
  394. //
  395. Status = ParEnterNibbleMode(Extension, REQUEST_DEVICE_ID);
  396. if( !NT_SUCCESS(Status) ) {
  397. ParTerminateNibbleMode(Extension);
  398. break ;
  399. }
  400. //
  401. // Read first two bytes to get the total (including the 2 size bytes) size
  402. // of the Device Id string.
  403. //
  404. bytesToRead = 2;
  405. Status = ParNibbleModeRead(Extension, idSizeBuffer, bytesToRead, &bytesRead);
  406. if( !NT_SUCCESS( Status ) || ( bytesRead != bytesToRead ) ) {
  407. break ;
  408. }
  409. //
  410. // Compute size of DeviceId string (including the 2 byte size prefix)
  411. //
  412. deviceIdSize = (USHORT)( idSizeBuffer[0]*0x100 + idSizeBuffer[1] );
  413. //
  414. // Allocate a buffer to hold the DeviceId string and read the DeviceId into it.
  415. //
  416. if( bReturnRawString ) {
  417. //
  418. // Caller wants the raw string including the 2 size bytes
  419. //
  420. *DeviceIdSize = deviceIdSize;
  421. deviceIdBufferSize = (USHORT)(deviceIdSize + sizeof(CHAR)); // ID size + ID + terminating NULL
  422. } else {
  423. //
  424. // Caller does not want the 2 byte size prefix
  425. //
  426. *DeviceIdSize = deviceIdSize - 2*sizeof(CHAR);
  427. deviceIdBufferSize = (USHORT)(deviceIdSize - 2*sizeof(CHAR) + sizeof(CHAR)); // ID + terminating NULL
  428. }
  429. deviceIdBuffer = (PCHAR)ExAllocatePool(PagedPool, deviceIdBufferSize);
  430. if( !deviceIdBuffer ) {
  431. break;
  432. }
  433. //
  434. // NULL out the ID buffer to be safe
  435. //
  436. RtlZeroMemory( deviceIdBuffer, deviceIdBufferSize );
  437. //
  438. // Does the caller want the 2 byte size prefix?
  439. //
  440. if( bReturnRawString ) {
  441. //
  442. // Yes, caller wants the size prefix. Copy prefix to buffer to return.
  443. //
  444. *(deviceIdBuffer+0) = idSizeBuffer[0];
  445. *(deviceIdBuffer+1) = idSizeBuffer[1];
  446. readPtr = deviceIdBuffer + 2;
  447. } else {
  448. //
  449. // No, discard size prefix
  450. //
  451. readPtr = deviceIdBuffer;
  452. }
  453. //
  454. // Read remainder of DeviceId from device
  455. //
  456. bytesToRead = deviceIdSize - 2; // already have the 2 size bytes
  457. Status = ParNibbleModeRead(Extension, readPtr, bytesToRead, &bytesRead);
  458. ParTerminateNibbleMode( Extension );
  459. if( !NT_SUCCESS(Status) || (bytesRead < 1) ) {
  460. ExFreePool( deviceIdBuffer );
  461. break ;
  462. }
  463. if ( strstr ( readPtr, "MFG:" ) == 0 ) {
  464. ExFreePool( deviceIdBuffer ) ;
  465. break ;
  466. }
  467. deviceIdSize = (USHORT) strlen(deviceIdBuffer);
  468. *DeviceIdSize = deviceIdSize;
  469. if( (NULL != CallerDeviceIdBuffer) && (CallerBufferSize >= deviceIdSize) ) {
  470. // caller supplied buffer is large enough, use it
  471. RtlZeroMemory( CallerDeviceIdBuffer, CallerBufferSize );
  472. RtlCopyMemory( CallerDeviceIdBuffer, deviceIdBuffer, deviceIdSize );
  473. ExFreePool( deviceIdBuffer );
  474. return CallerDeviceIdBuffer;
  475. }
  476. return deviceIdBuffer;
  477. } while ( FALSE ) ;
  478. // Builds later than 2080 fail to terminate in Compatibility mode.
  479. //IEEETerminate1284Mode fails after Event 23 (Extension->CurrentEvent equals 23)
  480. // with earlier 1284 draft.
  481. //So, we terminate the adapter ourselves, in some cases may be redundant.
  482. WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT);
  483. KeStallExecutionProcessor( 5 );
  484. WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT | DCR_AUTOFEED);
  485. KeStallExecutionProcessor( 5 );
  486. WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT);
  487. ParStlAssertIdleState ( Extension ) ;
  488. deviceIdBuffer = ParBuildStlDeviceId(Extension);
  489. if( !deviceIdBuffer ) {
  490. return NULL;
  491. }
  492. deviceIdSize = (USHORT) strlen(deviceIdBuffer);
  493. *DeviceIdSize = deviceIdSize;
  494. if( (NULL != CallerDeviceIdBuffer) && (CallerBufferSize >= deviceIdSize) ) {
  495. // caller supplied buffer is large enough, use it
  496. RtlZeroMemory( CallerDeviceIdBuffer, CallerBufferSize );
  497. RtlCopyMemory( CallerDeviceIdBuffer, deviceIdBuffer, deviceIdSize );
  498. ExFreePool( deviceIdBuffer );
  499. return CallerDeviceIdBuffer;
  500. }
  501. return deviceIdBuffer;
  502. }
  503. PCHAR
  504. ParBuildStlDeviceId(
  505. IN PDEVICE_EXTENSION Extension
  506. )
  507. /*++
  508. Routine Description:
  509. This function detects the type of shuttle adapter and
  510. builds an appropriate device id string and returns it
  511. back.
  512. It is assumed that the device is already in the
  513. selected state.
  514. Arguments:
  515. Nil.
  516. Return Value:
  517. Pointer to the read/built device ID string, if successful.
  518. NULL otherwise.
  519. --*/
  520. {
  521. ULONG size = 0x80 ;
  522. PCHAR id ;
  523. STL_DEVICE_TYPE dtDeviceType ;
  524. CHAR szDeviceIdString[0x80] ;
  525. CHAR szVidPidString[] = "MFG:VID_04E6;CLS:SCSIADAPTER;MDL:PID_" ;
  526. CHAR szVidPidStringScan[] = "MFG:VID_04E6;CLS:IMAGE;MDL:PID_" ;
  527. RtlZeroMemory(szDeviceIdString, sizeof(szDeviceIdString));
  528. // identify the shuttle adapter type by calling
  529. // Devtype routines here and build an unique id
  530. // string here.
  531. dtDeviceType = ParStlGetDeviceType(Extension, DEVICE_TYPE_AUTO_DETECT);
  532. switch ( dtDeviceType ) {
  533. case DEVICE_TYPE_NONE :
  534. return NULL;
  535. case DEVICE_TYPE_EPP_DEVICE :
  536. dtDeviceType |= 0x80000000 ;
  537. sprintf(szDeviceIdString, "%s%08X;", szVidPidStringScan, dtDeviceType);
  538. break;
  539. default :
  540. dtDeviceType |= 0x80000000 ;
  541. sprintf(szDeviceIdString, "%s%08X;", szVidPidString, dtDeviceType);
  542. break;
  543. }
  544. id = ExAllocatePool(PagedPool, size);
  545. if( id ) {
  546. RtlZeroMemory( id, size );
  547. RtlCopyMemory( id, szDeviceIdString, size - sizeof(NULL) );
  548. return id;
  549. }
  550. return NULL;
  551. }
  552. STL_DEVICE_TYPE __cdecl
  553. ParStlGetDeviceType (
  554. IN PDEVICE_EXTENSION Extension,
  555. IN int nPreferredDeviceType
  556. )
  557. {
  558. STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ;
  559. int nLocalPreferredDeviceType = nPreferredDeviceType ;
  560. ATAPIPARAMS atapiParams ;
  561. int i;
  562. for ( i=0 ; i<ATAPI_MAX_DRIVES ; i++){
  563. atapiParams.dsDeviceState[i] = DEVICE_STATE_INVALID ;
  564. }
  565. do
  566. {
  567. if ( TRUE == ParStlCheckIfScsiDevice(Extension))
  568. {
  569. // SCSI Device identified.
  570. dtDeviceType |= DEVICE_TYPE_SCSI_BIT ;
  571. break ;
  572. }
  573. if ( TRUE == NeedToEnableIoPads () )
  574. {
  575. // in some adapters, the IO pads need to be enabled, before
  576. // doing the device detection
  577. ParStlWriteReg( Extension, CONFIG_INDEX_REGISTER, EP1284_POWER_CONTROL_REG );
  578. ParStlWriteReg( Extension, CONFIG_DATA_REGISTER, ENABLE_IOPADS );
  579. }
  580. if ( TRUE == IsImpactSPresent() )
  581. {
  582. // as impact-s has been identified, the device type identification
  583. // can be done through personality configuration info
  584. dtDeviceType |= ParStlGetImpactSDeviceType( Extension, &atapiParams, nPreferredDeviceType );
  585. break;
  586. }
  587. if ( TRUE == IsImpactPresent() )
  588. {
  589. // as impact has been identified, the device type identification
  590. // can be done through personality configuration info
  591. dtDeviceType |= ParStlGetImpactDeviceType( Extension, &atapiParams, nPreferredDeviceType );
  592. break;
  593. }
  594. if (TRUE == ParStlCheckIfEppDevice(Extension))
  595. {
  596. // epp device identified
  597. if ( TRUE == ParStlCheckUMAXScannerPresence(Extension) ) {
  598. // umax identified
  599. dtDeviceType |= DEVICE_TYPE_UMAX_BIT;
  600. break;
  601. }
  602. if ( TRUE == ParStlCheckAvisionScannerPresence(Extension) ) {
  603. // avision identified
  604. dtDeviceType |= DEVICE_TYPE_AVISION_BIT;
  605. break;
  606. }
  607. // generice scanner peripheral detected
  608. dtDeviceType |= DEVICE_TYPE_EPP_DEVICE_BIT;
  609. break;
  610. }
  611. if (TRUE == ParStlCheckIfSSFDC(Extension))
  612. {
  613. // SSFDC identified
  614. dtDeviceType |= DEVICE_TYPE_SSFDC_BIT;
  615. break;
  616. }
  617. if (TRUE == ParStlCheckIfMMC(Extension,&atapiParams))
  618. {
  619. // MMC device identified
  620. dtDeviceType |= DEVICE_TYPE_MMC_BIT;
  621. break;
  622. }
  623. // set the 16 bit mode of the adapter
  624. ParStlSet16BitOperation(Extension) ;
  625. if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension, &atapiParams))
  626. {
  627. // necessary but not sufficient condition has passed
  628. // proceed for sufficency checks
  629. if (TRUE == ParStlCheckIfAtapiDevice(Extension, &atapiParams))
  630. {
  631. // sub-classify between HiFD and LS-120.
  632. if ( TRUE == ParStlCheckIfLS120(Extension))
  633. {
  634. // LS Engine is found.
  635. dtDeviceType |= DEVICE_TYPE_LS120_BIT ;
  636. break ;
  637. }
  638. // Check for HiFD.
  639. if (TRUE == ParStlCheckIfHiFD(Extension))
  640. {
  641. // HiFD device identified.
  642. dtDeviceType |= DEVICE_TYPE_HIFD_BIT ;
  643. break ;
  644. }
  645. // OtherWise, it is a generic ATAPI device.
  646. dtDeviceType |= DEVICE_TYPE_ATAPI_BIT;
  647. break ;
  648. }
  649. if (TRUE == ParStlCheckIfAtaDevice(Extension, &atapiParams))
  650. {
  651. // ata identified
  652. dtDeviceType |= DEVICE_TYPE_ATA_BIT;
  653. break;
  654. }
  655. }
  656. if (TRUE == ParStlCheckIfDazzle(Extension))
  657. {
  658. // dazzle identified
  659. dtDeviceType |= DEVICE_TYPE_DAZZLE_BIT;
  660. break;
  661. }
  662. if (TRUE == ParStlCheckIfFlash(Extension))
  663. {
  664. // flash identified
  665. dtDeviceType |= DEVICE_TYPE_FLASH_BIT;
  666. break;
  667. }
  668. }
  669. while ( FALSE ) ;
  670. return dtDeviceType & nPreferredDeviceType ;
  671. }
  672. VOID
  673. ParStlWaitForMicroSeconds (
  674. int nMicroSecondsToWait
  675. ) {
  676. KeStallExecutionProcessor ( nMicroSecondsToWait ) ;
  677. }
  678. BOOLEAN
  679. ParStlCheckCardInsertionStatus (
  680. IN PDEVICE_EXTENSION Extension
  681. )
  682. {
  683. BOOLEAN bReturnValue = FALSE ;
  684. UCHAR byPowerRegData ;
  685. do
  686. {
  687. if ( FALSE == IsEp1284Present() )
  688. {
  689. break ;
  690. }
  691. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , 0x0F ) ;
  692. byPowerRegData = (UCHAR) ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ;
  693. if ( byPowerRegData & SHTL_CARD_INSERTED_STATUS )
  694. {
  695. // as the card not inserted status is reported, it is ATA / ATAPI
  696. // possibly, not flash. hence, we break here.
  697. break ;
  698. }
  699. bReturnValue = TRUE ;
  700. }
  701. while ( FALSE ) ;
  702. return ( bReturnValue ) ;
  703. }
  704. BOOLEAN
  705. ParStlSelectAdapterSocket (
  706. IN PDEVICE_EXTENSION Extension,
  707. IN int nSocketNumber
  708. )
  709. {
  710. BOOLEAN bReturnValue = FALSE ;
  711. UCHAR bySCRControlReg , byISAControlReg ;
  712. do
  713. {
  714. if ( ( nSocketNumber != SOCKET_0 ) &&
  715. ( nSocketNumber != SOCKET_1 ) )
  716. {
  717. // as an invalid socket number is provided, we
  718. // break here with error.
  719. break ;
  720. }
  721. ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ;
  722. bySCRControlReg = (UCHAR) ParStlReadReg (Extension, CONFIG_DATA_REGISTER ) ;
  723. ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , ISA_CONTROL_REGISTER ) ;
  724. byISAControlReg = (UCHAR) ParStlReadReg (Extension, CONFIG_DATA_REGISTER ) ;
  725. if ( SOCKET_1 == nSocketNumber )
  726. {
  727. bySCRControlReg |= (UCHAR)SOCKET_1 ;
  728. bySCRControlReg |= (UCHAR)PERIPHERAL_RESET_1 ;
  729. byISAControlReg &= ~(UCHAR)ISA_IO_SWAP ;
  730. }
  731. else
  732. {
  733. bySCRControlReg &= ~(UCHAR)SOCKET_1 ;
  734. bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_0 ;
  735. }
  736. ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , ISA_CONTROL_REGISTER ) ;
  737. ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , byISAControlReg ) ;
  738. ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ;
  739. ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
  740. if ( SOCKET_1 == nSocketNumber )
  741. {
  742. // Wait for a few milliseconds to provide an optimal puse width
  743. // for reset.
  744. ParStlWaitForMicroSeconds(1000);
  745. bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_1 ;
  746. }
  747. else
  748. {
  749. bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_0 ;
  750. }
  751. ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
  752. bReturnValue = TRUE ;
  753. }
  754. while ( FALSE ) ;
  755. return bReturnValue ;
  756. }
  757. BOOLEAN
  758. ParStlCheckIfAtaAtapiDevice (
  759. IN PDEVICE_EXTENSION Extension,
  760. IN OUT PATAPIPARAMS atapiParams
  761. )
  762. {
  763. BOOLEAN bReturnValue = FALSE;
  764. do
  765. {
  766. if ( TRUE == ParStlCheckCardInsertionStatus(Extension) )
  767. {
  768. // as the card insertion status is valid, its probably
  769. // a flash
  770. break ;
  771. }
  772. if ( FALSE == ParStlCheckDrivePresent(Extension, atapiParams) )
  773. {
  774. // as the ATA/ATAPI controller is not present, it cant be
  775. // an ATA/ATAPI device
  776. break ;
  777. }
  778. bReturnValue = TRUE;
  779. }
  780. while ( FALSE ) ;
  781. return bReturnValue ;
  782. }
  783. BOOLEAN
  784. ParStlCheckIfAtapiDevice (
  785. IN PDEVICE_EXTENSION Extension,
  786. IN OUT PATAPIPARAMS atapiParams
  787. )
  788. {
  789. BOOLEAN bReturnValue = FALSE;
  790. do
  791. {
  792. // return whatever ATAPI initialization module says
  793. bReturnValue = ParStlAtapiInitialize(Extension, atapiParams) ;
  794. }
  795. while ( FALSE ) ;
  796. return bReturnValue ;
  797. }
  798. BOOLEAN
  799. ParStlCheckIfAtaDevice (
  800. IN PDEVICE_EXTENSION Extension,
  801. IN OUT PATAPIPARAMS atapiParams
  802. )
  803. {
  804. BOOLEAN bReturnValue = FALSE;
  805. do
  806. {
  807. // return whatever ATA initialization module says
  808. bReturnValue = ParStlAtaInitialize(Extension, atapiParams) ;
  809. }
  810. while ( FALSE ) ;
  811. return bReturnValue ;
  812. }
  813. BOOLEAN
  814. ParStlCheckDrivePresent (
  815. IN PDEVICE_EXTENSION Extension,
  816. IN OUT PATAPIPARAMS atapiParams
  817. )
  818. {
  819. BOOLEAN bReturnValue = FALSE ;
  820. UCHAR byOrgCylHigh, byOrgCylLow ;
  821. int nCurrentDrive = 0 , i ;
  822. UCHAR nDrvHdArray[]={ATAPI_MASTER, ATAPI_SLAVE};
  823. do
  824. {
  825. if ( atapiParams->dsDeviceState[nCurrentDrive] == DEVICE_STATE_VALID )
  826. {
  827. // this means that the MMC module had detected the presence
  828. // of an ATA/ATAPI device. So, we make use of that and break out
  829. bReturnValue = TRUE ;
  830. break ;
  831. }
  832. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, nDrvHdArray[nCurrentDrive]);
  833. // The Atapi Fuji MO drive is found to de-assert BSY and still
  834. // does not respond to reg. r/w when configured as slave with no media.
  835. // However, after a delay, it works ok.
  836. if ( nCurrentDrive )
  837. {
  838. ParStlWaitForMicroSeconds ( DELAY_1SECOND ) ;
  839. }
  840. // this dummy write of 0 is to zero out a possible
  841. // floating bus
  842. for ( i = 0 ; i < 16 ; i++ )
  843. {
  844. ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER, i) ;
  845. if ( !( ParStlReadIoPort (Extension, ATA_TASK_STAT_REG ) & ATA_ST_BUSY ) )
  846. {
  847. break ;
  848. }
  849. }
  850. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  851. {
  852. // as the busy has been found permanently set, we check
  853. // for the slave also
  854. continue;
  855. }
  856. // as the drive head setup might have been performed in a busy state,
  857. // we set it up again after busy clears.
  858. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, nDrvHdArray[nCurrentDrive]);
  859. if ( ( ParStlReadIoPort(Extension, ATA_DRVHD_REG) & ATAPI_SLAVE ) != nDrvHdArray[nCurrentDrive] )
  860. {
  861. continue ;
  862. }
  863. // read original contents of the cyl ATA high/low registers
  864. byOrgCylLow = (UCHAR) ParStlReadIoPort(Extension, ATA_CYLLOW_REG);
  865. byOrgCylHigh = (UCHAR) ParStlReadIoPort(Extension, ATA_CYLHIGH_REG);
  866. // write a test pattern in the cyl ATA high/low registers
  867. ParStlWriteIoPort(Extension, ATA_CYLLOW_REG, TEST_PATTERN_1);
  868. ParStlWriteIoPort(Extension, ATA_CYLHIGH_REG, TEST_PATTERN_2);
  869. // read the test pattern in the cyl ATA high/low registers
  870. if ( ( TEST_PATTERN_1 != ParStlReadIoPort(Extension, ATA_CYLLOW_REG) ) ||\
  871. ( TEST_PATTERN_2 != ParStlReadIoPort(Extension, ATA_CYLHIGH_REG) ) )
  872. {
  873. // as we were not able to read back the written values
  874. // we break out here, indicating the absence of the device
  875. continue ;
  876. }
  877. // write back original contents in the cyl ATA high/low registers
  878. ParStlWriteIoPort(Extension, ATA_CYLLOW_REG, byOrgCylLow);
  879. ParStlWriteIoPort(Extension, ATA_CYLHIGH_REG, byOrgCylHigh);
  880. bReturnValue = TRUE ;
  881. atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_VALID ;
  882. }
  883. while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
  884. // reset back to master state, as check drive present
  885. // will be called successively
  886. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
  887. return bReturnValue ;
  888. }
  889. BOOLEAN
  890. ParStlAtapiInitialize (
  891. IN PDEVICE_EXTENSION Extension,
  892. IN OUT PATAPIPARAMS atapiParams
  893. )
  894. {
  895. BOOLEAN bReturnValue = FALSE ;
  896. int nCurrentDrive = 0, i ;
  897. UCHAR byTempValue ;
  898. UCHAR chAtapiIdentifyBuffer [ ATAPI_IDENTIFY_LENGTH ] ;
  899. do
  900. {
  901. if ( DEVICE_STATE_VALID != atapiParams->dsDeviceState[nCurrentDrive] )
  902. {
  903. // the device is absent
  904. continue ;
  905. }
  906. if ( nCurrentDrive )
  907. {
  908. // as it is the next drive, choose the slave
  909. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_SLAVE);
  910. }
  911. else
  912. {
  913. // choose the master
  914. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
  915. }
  916. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  917. {
  918. // as busy has permanently set after master/slave, we fail
  919. // the detection process
  920. continue ;
  921. }
  922. // check if the ATAPI signature is present in the cyl hi/lo
  923. // registers. If present, it is definitely an ATAPI device
  924. if ( ( ParStlReadIoPort(Extension, ATA_CYLLOW_REG) == ATAPI_SIGN_LOW ) &&\
  925. ( ParStlReadIoPort(Extension, ATA_CYLHIGH_REG) == ATAPI_SIGN_HI ) )
  926. {
  927. // as ATAPI signature is present, it is ATAPI type
  928. bReturnValue = TRUE ;
  929. // set this flag so that, ATA initialize will skip this
  930. // target
  931. atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_ATAPI ;
  932. // for Impact, since Ls120 engine is always present,
  933. // issuing ATAPI_IDENTIFY is mandatory.
  934. if ( !IsImpactPresent())
  935. {
  936. continue ;
  937. }
  938. }
  939. // issue the ata nop command
  940. ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATA_NOP_COMMAND) ;
  941. if ( FALSE == ParStlWaitForIrq(Extension) )
  942. {
  943. // ATAPI devices are expected to give interrrupt on NOP command
  944. // mandatorily.
  945. continue ;
  946. }
  947. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  948. {
  949. // as busy has permanently set, we proceed with the next
  950. // drive
  951. continue ;
  952. }
  953. // issue the atapi packet command
  954. ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATAPI_IDENTIFY) ;
  955. if ( FALSE == ParStlWaitForIrq(Extension) )
  956. {
  957. // ATAPI devices are expected to give interrrupt on 0xA1 command
  958. // mandatorily.
  959. continue ;
  960. }
  961. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  962. {
  963. // as busy has permanently set, we proceed with the next
  964. // drive
  965. continue ;
  966. }
  967. byTempValue = (UCHAR) ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) ;
  968. if ( ! ( byTempValue & ATA_ST_ERROR ) )
  969. {
  970. // as the drive has passed the packet command, this is an atapi
  971. // drive
  972. // Wait for DRQ to be sit, as some drives are known
  973. // to remove busy too early and set DRQ after some time.
  974. if ( FALSE == ParStlWaitForDrq(Extension) )
  975. {
  976. // as there was no DRQ set, we proceed with the next
  977. // drive
  978. continue ;
  979. }
  980. bReturnValue = TRUE ;
  981. // as the DRQ is still asserted, quell it, as certain ATA/ATAPI-4
  982. // spec. dictates it so
  983. // There is a need to check the device identifier returned in the
  984. // ATAPI Identify cmd. to determine the presence of Ls-120.
  985. ParStlReceiveData ( Extension, chAtapiIdentifyBuffer , SKIP_MEMORY_ADDRESS , ATAPI_IDENTIFY_LENGTH ) ;
  986. for ( i = 0 ; i < ATAPI_NAME_LENGTH ; i++ )
  987. {
  988. atapiParams->szAtapiNameString[i] = chAtapiIdentifyBuffer[ ATAPI_NAME_OFFSET + i ] ;
  989. }
  990. // set this flag so that, ATA initialize will skip this
  991. // target
  992. atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_ATAPI ;
  993. }
  994. }
  995. while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
  996. // reset back to master state, as check drive present
  997. // will be called successively
  998. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
  999. return ( bReturnValue ) ;
  1000. }
  1001. BOOLEAN
  1002. ParStlAtaInitialize (
  1003. IN PDEVICE_EXTENSION Extension,
  1004. IN OUT PATAPIPARAMS atapiParams
  1005. )
  1006. {
  1007. BOOLEAN bReturnValue = FALSE ;
  1008. UCHAR byTempValue ;
  1009. int nCurrentDrive = 0 ;
  1010. do
  1011. {
  1012. if ( DEVICE_STATE_VALID != atapiParams->dsDeviceState[nCurrentDrive] )
  1013. {
  1014. // atapi module has marked its presence or the device is absent
  1015. continue ;
  1016. }
  1017. // select the possibly present device
  1018. if ( nCurrentDrive )
  1019. {
  1020. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_SLAVE ) ;
  1021. }
  1022. else
  1023. {
  1024. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER ) ;
  1025. }
  1026. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  1027. {
  1028. // as busy has permanently set after master/slave, we fail the
  1029. // detection process
  1030. continue ;
  1031. }
  1032. // issue the ata NOP command
  1033. ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATA_NOP_COMMAND) ;
  1034. if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) )
  1035. {
  1036. // as busy has permanently set, we fail the detection process
  1037. continue ;
  1038. }
  1039. byTempValue = (UCHAR) ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) ;
  1040. if ( ( byTempValue != BUS_LINES_IN_HIGH_IMPEDANCE ) &&\
  1041. ( byTempValue & ATA_ST_ERROR ) )
  1042. {
  1043. // as the bus is not reading 0xFF and the status register
  1044. // indicates an error, this is likely to be an ATA device
  1045. if ( ATA_ERROR_ABORTED_COMMAND == ( (UCHAR) ParStlReadIoPort ( Extension, ATA_ERROR_REG ) & 0x0F ) )
  1046. {
  1047. // as the error register, contains the ata aborted error
  1048. // in response to our ATA NOP command, we conclude that
  1049. // it is ATA! as it is already known that it is not ATAPI
  1050. bReturnValue = TRUE ;
  1051. break;
  1052. }
  1053. }
  1054. }
  1055. while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
  1056. // reset back to master state, as check drive present
  1057. // will be called successively
  1058. ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
  1059. return ( bReturnValue ) ;
  1060. }
  1061. BOOLEAN
  1062. ParStlWaitForBusyToClear (
  1063. IN PDEVICE_EXTENSION Extension,
  1064. IN int nRegisterToWaitOn
  1065. )
  1066. {
  1067. // The default timeout increased to 10secs as Fujitsu MO is found to set
  1068. // BUSY for >5secs for 0xA1 command.
  1069. int nMaxRetrials = MAX_RETRIES_FOR_10_SECS ;
  1070. BOOLEAN bRetVal = FALSE ;
  1071. while ( nMaxRetrials-- )
  1072. {
  1073. // the following service will be implemented by the caller
  1074. // the driver can use the STLMPORT service.
  1075. ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ;
  1076. if ( ! ( ParStlReadIoPort ( Extension, nRegisterToWaitOn ) & ATA_ST_BUSY ) )
  1077. {
  1078. // as busy has cleared, we return clear here
  1079. bRetVal = TRUE ;
  1080. break ;
  1081. }
  1082. }
  1083. return bRetVal ;
  1084. }
  1085. BOOLEAN
  1086. ParStlWaitForDrq (
  1087. IN PDEVICE_EXTENSION Extension
  1088. )
  1089. {
  1090. int nMaxRetrials = MAX_RETRIES_FOR_5_SECS ;
  1091. BOOLEAN bRetVal = FALSE ;
  1092. while ( nMaxRetrials-- )
  1093. {
  1094. if ( ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) & ATA_ST_DRQ )
  1095. {
  1096. // as busy has cleared, we return clear here
  1097. bRetVal = TRUE ;
  1098. break ;
  1099. }
  1100. // the following service will be implemented by the caller
  1101. // the driver can use the STLMPORT service.
  1102. ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ;
  1103. }
  1104. return bRetVal ;
  1105. }
  1106. BOOLEAN
  1107. ParStlWaitForIrq (
  1108. IN PDEVICE_EXTENSION Extension
  1109. )
  1110. {
  1111. int nMaxRetrials = MAX_RETRIES_FOR_10_SECS ;
  1112. BOOLEAN bRetVal = FALSE ;
  1113. while ( nMaxRetrials-- )
  1114. {
  1115. if ( ParStlReadReg ( Extension, EP1284_TRANSFER_CONTROL_REG ) & XFER_IRQ_BIT )
  1116. {
  1117. // as Irq has asserted, we return true here
  1118. bRetVal = TRUE ;
  1119. break ;
  1120. }
  1121. ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ;
  1122. }
  1123. return bRetVal ;
  1124. }
  1125. VOID
  1126. ParStlSet16BitOperation (
  1127. IN PDEVICE_EXTENSION Extension
  1128. )
  1129. {
  1130. int nModeReg ;
  1131. nModeReg = ParStlReadReg ( Extension, EP1284_MODE_REGISTER ) ;
  1132. if ( 0 == ( nModeReg & EP1284_ENABLE_16BIT ) )
  1133. {
  1134. // as the bit is not already set, this needs to be set now
  1135. ParStlWriteReg ( Extension, EP1284_MODE_REGISTER, nModeReg | EP1284_ENABLE_16BIT ) ;
  1136. }
  1137. }
  1138. BOOLEAN
  1139. ParStlCheckIfEppDevice (
  1140. IN PDEVICE_EXTENSION Extension
  1141. )
  1142. {
  1143. BOOLEAN bReturnValue = FALSE;
  1144. do
  1145. {
  1146. if ( FALSE == IsEp1284Present() )
  1147. {
  1148. // as EPPDEVs live only on EP1284 we break here
  1149. break;
  1150. }
  1151. bReturnValue = ParStlCheckPersonalityForEppDevice(Extension) ;
  1152. }
  1153. while ( FALSE ) ;
  1154. return bReturnValue ;
  1155. }
  1156. BOOLEAN
  1157. ParStlCheckPersonalityForEppDevice (
  1158. IN PDEVICE_EXTENSION Extension
  1159. )
  1160. {
  1161. BOOLEAN bReturnValue = FALSE ;
  1162. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, EP1284_PERSONALITY_REG ) ;
  1163. if ( EPPDEV_SIGN == ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & PERSONALITY_MASK ) )
  1164. {
  1165. // as the EPPDEV sign is found in the personality
  1166. // we break with success here
  1167. bReturnValue = TRUE ;
  1168. }
  1169. return bReturnValue ;
  1170. }
  1171. BOOLEAN
  1172. ParStlCheckIfFlash (
  1173. IN PDEVICE_EXTENSION Extension
  1174. )
  1175. {
  1176. BOOLEAN bReturnValue = FALSE ;
  1177. do
  1178. {
  1179. if ( !IsEp1284Present() && !IsImpactPresent() && !IsEpatPlusPresent() )
  1180. {
  1181. // Check the sign-on version checks for the existence of Shuttle
  1182. // adapter. If nothing is found, we break here.
  1183. break ;
  1184. }
  1185. // Perform a ATA-16bit check just in case, it turns out to be something else
  1186. bReturnValue = ParStlCheckFlashPersonality(Extension) ;
  1187. }
  1188. while ( FALSE ) ;
  1189. return bReturnValue ;
  1190. }
  1191. BOOLEAN
  1192. ParStlCheckFlashPersonality (
  1193. IN PDEVICE_EXTENSION Extension
  1194. )
  1195. {
  1196. BOOLEAN bReturnValue = FALSE ;
  1197. if ( IsEp1284Present() )
  1198. {
  1199. // as the personality configuration check only works for
  1200. // Ep1284, confim its presence before the actual check.
  1201. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, EP1284_PERSONALITY_REG ) ;
  1202. if ( FLASH_SIGN == ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & FLASH_PERSONALITY_MASK ) )
  1203. {
  1204. // as the flash sign ATA-16bit device is found in the personality
  1205. // we break with success here
  1206. bReturnValue = TRUE ;
  1207. }
  1208. }
  1209. else
  1210. {
  1211. // always return true, if a shuttle adapter other than ep1284 is
  1212. // identified and assume it might be flash!
  1213. bReturnValue = TRUE ;
  1214. }
  1215. return bReturnValue ;
  1216. }
  1217. BOOLEAN
  1218. ParStlCheckIfDazzle (
  1219. IN PDEVICE_EXTENSION Extension
  1220. )
  1221. {
  1222. BOOLEAN bReturnValue = FALSE ;
  1223. UCHAR ucSignature ;
  1224. do
  1225. {
  1226. if ( !IsEp1284Present() )
  1227. {
  1228. // Check for EP1284 presence, as Dazzle is ONLY on EP1284
  1229. // adapters. If the adapter is not EP1284, we break.
  1230. break ;
  1231. }
  1232. // Check whether any card insertion is detected, to eliminate
  1233. // possible flash adapters with the card in
  1234. if ( TRUE == ParStlCheckCardInsertionStatus( Extension ) ) {
  1235. break ;
  1236. }
  1237. // code to read the pulled up pattern present on dazzle
  1238. // adapters.
  1239. ParStlWriteReg( Extension, DAZ_SELECT_BLK, DAZ_BLK0 ) ;
  1240. ucSignature = (UCHAR) ParStlReadReg( Extension, DAZ_REG1 ) ;
  1241. if ( ( ucSignature == DAZ_CONFIGURED ) ||\
  1242. ( ucSignature == DAZ_NOT_CONFIGURED ) ) {
  1243. // the pulled up pattern generally found ONLY
  1244. // on the DAZZLE adapter is found. So, we
  1245. // conclude that it is a Dazzle adapter
  1246. bReturnValue = TRUE ;
  1247. }
  1248. }
  1249. while ( FALSE ) ;
  1250. return bReturnValue ;
  1251. }
  1252. BOOLEAN
  1253. ParStlCheckIfHiFD (
  1254. IN PDEVICE_EXTENSION Extension
  1255. )
  1256. {
  1257. BOOLEAN bReturnValue = FALSE;
  1258. do
  1259. {
  1260. if ( FALSE == ParStlSelectAdapterSocket(Extension, SOCKET_1) )
  1261. {
  1262. // as the socket 1 selection failed,
  1263. // we break out here.
  1264. break ;
  1265. }
  1266. // check for the ready status of the floppy controller,
  1267. // after clearing the reset bit of the floppy controller.
  1268. if ( FALSE == ParStlHIFDCheckIfControllerReady(Extension) )
  1269. {
  1270. // since the controller didnot wake up after the
  1271. // reset pin was asserted, we break here.
  1272. break ;
  1273. }
  1274. if ( FALSE == ParStlHIFDCheckSMCController(Extension) )
  1275. {
  1276. // as the SMC ID retrieval failed,
  1277. // we break out here.
  1278. break ;
  1279. }
  1280. bReturnValue = TRUE ;
  1281. }
  1282. while ( FALSE ) ;
  1283. // Reset the socket to zero.
  1284. ParStlSelectAdapterSocket(Extension, SOCKET_0);
  1285. return bReturnValue ;
  1286. }
  1287. BOOLEAN
  1288. ParStlHIFDCheckIfControllerReady (
  1289. IN PDEVICE_EXTENSION Extension
  1290. )
  1291. {
  1292. BOOLEAN bReturnValue = FALSE ;
  1293. UCHAR bySCRControlReg ;
  1294. do
  1295. {
  1296. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ;
  1297. bySCRControlReg = (UCHAR) ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ;
  1298. bySCRControlReg |= (UCHAR)PERIPHERAL_RESET_1 ;
  1299. ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
  1300. ParStlWaitForMicroSeconds ( HIFD_WAIT_10_MILLISEC ) ;
  1301. ParStlWriteIoPort ( Extension, HIFD_DIGITAL_OUTPUT_REGISTER ,
  1302. 0x00 ) ;
  1303. ParStlWaitForMicroSeconds ( HIFD_WAIT_1_MILLISEC ) ;
  1304. ParStlWriteIoPort ( Extension, HIFD_DIGITAL_OUTPUT_REGISTER ,
  1305. HIFD_DOR_RESET_BIT | HIFD_ENABLE_DMA_BIT ) ;
  1306. ParStlWaitForMicroSeconds ( HIFD_WAIT_10_MILLISEC ) ;
  1307. if ( HIFD_CONTROLLER_READY_STATUS == ParStlReadIoPort ( Extension, HIFD_MAIN_STATUS_REGISTER ) )
  1308. {
  1309. bReturnValue = TRUE ;
  1310. }
  1311. bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_1 ;
  1312. ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
  1313. }
  1314. while ( FALSE ) ;
  1315. return bReturnValue ;
  1316. }
  1317. BOOLEAN
  1318. ParStlHIFDCheckSMCController (
  1319. IN PDEVICE_EXTENSION Extension
  1320. )
  1321. {
  1322. BOOLEAN bReturnValue = FALSE ;
  1323. do
  1324. {
  1325. ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_COMMAND_TO_CONTROLLER ) ;
  1326. ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_COMMAND_TO_CONTROLLER ) ;
  1327. ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_CTL_REG_0D ) ;
  1328. if ( SMC_DEVICE_ID == ParStlReadIoPort ( Extension, HIFD_STATUS_REGISTER_B ) )
  1329. {
  1330. bReturnValue = TRUE ;
  1331. ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_CTL_REG_03 ) ;
  1332. ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_B , SMC_ENABLE_MODE2 ) ;
  1333. }
  1334. ParStlWriteReg ( Extension, HIFD_STATUS_REGISTER_A , HIFD_TERMINATE_SEQUENCE ) ;
  1335. }
  1336. while ( FALSE ) ;
  1337. return bReturnValue ;
  1338. }
  1339. STL_DEVICE_TYPE
  1340. ParStlGetImpactDeviceType (
  1341. IN PDEVICE_EXTENSION Extension,
  1342. IN OUT PATAPIPARAMS atapiParams,
  1343. IN int nPreferredDeviceType
  1344. )
  1345. {
  1346. IMPACT_DEVICE_TYPE idtImpactDeviceType ;
  1347. STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ;
  1348. int nLocalPreferredDeviceType = nPreferredDeviceType ;
  1349. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACT_PERSONALITY_REG ) ;
  1350. idtImpactDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) >> 4 ;
  1351. switch ( idtImpactDeviceType )
  1352. {
  1353. case IMPACT_DEVICE_TYPE_ATA_ATAPI:
  1354. // set the 16 bit mode of the adapter
  1355. ParStlSet16BitOperation(Extension) ;
  1356. if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension,atapiParams))
  1357. {
  1358. // necessary but not sufficient condition has passed
  1359. // proceed for sufficency checks
  1360. if (TRUE == ParStlCheckIfAtapiDevice(Extension,atapiParams))
  1361. {
  1362. // atapi identified
  1363. // Check for Impact LS-120 device
  1364. if ( TRUE == ParStlCheckIfImpactLS120(Extension, atapiParams))
  1365. {
  1366. dtDeviceType |= DEVICE_TYPE_LS120_BIT ;
  1367. break ;
  1368. }
  1369. dtDeviceType |= DEVICE_TYPE_ATAPI_BIT;
  1370. break ;
  1371. }
  1372. if (TRUE == ParStlCheckIfAtaDevice(Extension, atapiParams))
  1373. {
  1374. // ata identified
  1375. dtDeviceType |= DEVICE_TYPE_ATA_BIT;
  1376. break;
  1377. }
  1378. }
  1379. break ;
  1380. case IMPACT_DEVICE_TYPE_CF:
  1381. dtDeviceType |= DEVICE_TYPE_FLASH_BIT;
  1382. break ;
  1383. case IMPACT_DEVICE_TYPE_PCMCIA_CF:
  1384. dtDeviceType |= DEVICE_TYPE_PCMCIA_CF_BIT ;
  1385. break;
  1386. case IMPACT_DEVICE_TYPE_SSFDC:
  1387. dtDeviceType |= DEVICE_TYPE_SSFDC_BIT ;
  1388. break;
  1389. case IMPACT_DEVICE_TYPE_MMC:
  1390. dtDeviceType |= DEVICE_TYPE_MMC_BIT ;
  1391. break;
  1392. case IMPACT_DEVICE_TYPE_HIFD:
  1393. dtDeviceType |= DEVICE_TYPE_HIFD_BIT ;
  1394. break;
  1395. case IMPACT_DEVICE_TYPE_SOUND:
  1396. dtDeviceType |= DEVICE_TYPE_SOUND_BIT ;
  1397. break;
  1398. case IMPACT_DEVICE_TYPE_FLP_TAPE_DSK:
  1399. dtDeviceType |= DEVICE_TYPE_FLP_TAPE_DSK_BIT ;
  1400. break;
  1401. case IMPACT_DEVICE_TYPE_ATA_ATAPI_8BIT:
  1402. dtDeviceType |= DEVICE_TYPE_ATA_ATAPI_8BIT_BIT ;
  1403. break;
  1404. default:
  1405. break;
  1406. }
  1407. return dtDeviceType & nPreferredDeviceType ;
  1408. }
  1409. STL_DEVICE_TYPE
  1410. ParStlGetImpactSDeviceType (
  1411. IN PDEVICE_EXTENSION Extension,
  1412. IN OUT PATAPIPARAMS atapiParams,
  1413. IN int nPreferredDeviceType
  1414. )
  1415. {
  1416. IMPACT_DEVICE_TYPE idtImpactDeviceType ;
  1417. IMPACT_DEVICE_TYPE idtImpactSDeviceType ;
  1418. STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ;
  1419. int nLocalPreferredDeviceType = nPreferredDeviceType ;
  1420. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACT_PERSONALITY_REG ) ;
  1421. idtImpactDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) >> 4 ;
  1422. switch ( idtImpactDeviceType )
  1423. {
  1424. case IMPACT_DEVICE_TYPE_ATA_ATAPI:
  1425. // set the 16 bit mode of the adapter
  1426. ParStlSet16BitOperation(Extension) ;
  1427. if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension,atapiParams))
  1428. {
  1429. // necessary but not sufficient condition has passed
  1430. // proceed for sufficency checks
  1431. if (TRUE == ParStlCheckIfAtapiDevice(Extension,atapiParams))
  1432. {
  1433. // atapi identified
  1434. dtDeviceType |= DEVICE_TYPE_ATAPI_BIT;
  1435. break ;
  1436. }
  1437. if (TRUE == ParStlCheckIfAtaDevice(Extension,atapiParams))
  1438. {
  1439. // ata identified
  1440. dtDeviceType |= DEVICE_TYPE_ATA_BIT;
  1441. break;
  1442. }
  1443. }
  1444. break ;
  1445. case IMPACT_DEVICE_TYPE_CF:
  1446. dtDeviceType |= DEVICE_TYPE_FLASH_BIT;
  1447. break ;
  1448. case IMPACT_DEVICE_TYPE_PCMCIA_CF:
  1449. dtDeviceType |= DEVICE_TYPE_PCMCIA_CF_BIT ;
  1450. break;
  1451. case IMPACT_DEVICE_TYPE_SSFDC:
  1452. dtDeviceType |= DEVICE_TYPE_SSFDC_BIT ;
  1453. break;
  1454. case IMPACT_DEVICE_TYPE_MMC:
  1455. dtDeviceType |= DEVICE_TYPE_MMC_BIT ;
  1456. break;
  1457. case IMPACT_DEVICE_TYPE_HIFD:
  1458. dtDeviceType |= DEVICE_TYPE_HIFD_BIT ;
  1459. break;
  1460. case IMPACT_DEVICE_TYPE_SOUND:
  1461. dtDeviceType |= DEVICE_TYPE_SOUND_BIT ;
  1462. break;
  1463. case IMPACT_DEVICE_TYPE_FLP_TAPE_DSK:
  1464. dtDeviceType |= DEVICE_TYPE_FLP_TAPE_DSK_BIT ;
  1465. break;
  1466. case IMPACT_DEVICE_TYPE_ATA_ATAPI_8BIT:
  1467. dtDeviceType |= DEVICE_TYPE_ATA_ATAPI_8BIT_BIT ;
  1468. break;
  1469. case IMPACTS_EXT_PERSONALITY_PRESENT:
  1470. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACTS_EXT_PERSONALITY_XREG ) ;
  1471. idtImpactSDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ;
  1472. dtDeviceType = DEVICE_TYPE_EXT_HWDETECT ;
  1473. dtDeviceType |= idtImpactSDeviceType ;
  1474. break ;
  1475. default:
  1476. break;
  1477. }
  1478. return dtDeviceType & nPreferredDeviceType ;
  1479. }
  1480. BOOLEAN
  1481. ParStlCheckIfLS120 (
  1482. IN PDEVICE_EXTENSION Extension
  1483. )
  1484. {
  1485. BOOLEAN bReturnValue = FALSE;
  1486. do
  1487. {
  1488. if ( FALSE == ParStlSelectAdapterSocket(Extension, SOCKET_1) )
  1489. {
  1490. // as the socket 1 selection failed,
  1491. // we break out here.
  1492. break ;
  1493. }
  1494. // check for engine version.
  1495. if ( LS120_ENGINE_VERSION == ParStlReadIoPort( Extension, LS120_ENGINE_VERSION_REGISTER ) )
  1496. {
  1497. // if the ls120 engine version is correct, we have
  1498. // found LS120.
  1499. bReturnValue = TRUE ;
  1500. }
  1501. // Reset the socket to zero.
  1502. ParStlSelectAdapterSocket ( Extension, SOCKET_0 ) ;
  1503. }
  1504. while ( FALSE ) ;
  1505. return bReturnValue ;
  1506. }
  1507. BOOLEAN
  1508. ParStlCheckIfImpactLS120 (
  1509. IN PDEVICE_EXTENSION Extension,
  1510. IN OUT PATAPIPARAMS atapiParams
  1511. )
  1512. {
  1513. BOOLEAN bReturnValue = FALSE ;
  1514. BOOLEAN bLs120NameFound= TRUE ;
  1515. char chLs120Name[] = "HU DlFpoyp";
  1516. char *pszAtapiName = atapiParams->szAtapiNameString ;
  1517. int i , nMemoryOnBoard ;
  1518. do
  1519. {
  1520. for ( i = 0 ;i < sizeof(chLs120Name)-1 ; i++ )
  1521. {
  1522. if ( pszAtapiName[i] != chLs120Name[i] )
  1523. {
  1524. bLs120NameFound = FALSE ;
  1525. break ;
  1526. }
  1527. }
  1528. if ( TRUE != bLs120NameFound )
  1529. {
  1530. // as LS-120 name string is not found, we conclude that it is
  1531. // not LS-120
  1532. break ;
  1533. }
  1534. nMemoryOnBoard = ParStlGetMemorySize(Extension) ;
  1535. if ( ( !IsShtlError ( nMemoryOnBoard ) ) && \
  1536. ( nMemoryOnBoard ) )
  1537. {
  1538. // there is memory on-board.
  1539. // hence, we return ls120 here
  1540. bReturnValue = TRUE ;
  1541. break ;
  1542. }
  1543. }
  1544. while ( FALSE ) ;
  1545. return bReturnValue ;
  1546. }
  1547. BOOLEAN
  1548. ParStlCheckIfMMC (
  1549. IN PDEVICE_EXTENSION Extension,
  1550. IN OUT PATAPIPARAMS atapiParams
  1551. )
  1552. {
  1553. BOOLEAN bReturnValue = FALSE;
  1554. do
  1555. {
  1556. if ( FALSE == IsEpatPlusPresent() )
  1557. {
  1558. // as mmc device can exist only on EPAT Plus adapter only
  1559. // we break out of here
  1560. break;
  1561. }
  1562. if ( TRUE == ParStlCheckIfAtaAtapiDevice (Extension,atapiParams) )
  1563. {
  1564. // as an ATA/ATAPI device is probably present,
  1565. // we break out of here
  1566. break;
  1567. }
  1568. bReturnValue = ParStlIsMMCEnginePresent(Extension) ;
  1569. }
  1570. while ( FALSE ) ;
  1571. return bReturnValue ;
  1572. }
  1573. BOOLEAN
  1574. ParStlIsMMCEnginePresent(
  1575. IN PDEVICE_EXTENSION Extension
  1576. )
  1577. {
  1578. BOOLEAN bReturnValue = FALSE;
  1579. do
  1580. {
  1581. // check if the ATAPI signature is present in the cyl hi/lo
  1582. // registers. If present, it is definitely an ATAPI device
  1583. if ( ( ParStlReadIoPort(Extension, CYLLOW_REG) == ATAPI_SIGN_LOW ) &&\
  1584. ( ParStlReadIoPort(Extension, CYLHIGH_REG) == ATAPI_SIGN_HI ) )
  1585. {
  1586. // as ATAPI signature is present, it cant be MMC
  1587. break ;
  1588. }
  1589. // write a zero pattern ( which will be a NOP for ATA/ATAPI devices )
  1590. // in the block size / possible ATA/ATAPI command register
  1591. ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG);
  1592. ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_1);
  1593. if ( MMC_TEST_PATTERN_1 != ParStlReadReg(Extension, MMC_ENGINE_DATA) )
  1594. {
  1595. // as the written value is not available, it means device present
  1596. // has responded to the written value, in a way different from
  1597. // how an MMC would have.
  1598. break ;
  1599. }
  1600. // write a test pattern in the freq register
  1601. ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_FREQ_SELECT_REG);
  1602. ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_2);
  1603. // write another in the block size register
  1604. ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG);
  1605. ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_3);
  1606. ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_FREQ_SELECT_REG);
  1607. if ( MMC_TEST_PATTERN_2 != ParStlReadReg(Extension, MMC_ENGINE_DATA) )
  1608. {
  1609. // as we were not able to read back the written value
  1610. // we quit here
  1611. break;
  1612. }
  1613. ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG);
  1614. if ( MMC_TEST_PATTERN_3 != ParStlReadReg(Extension, MMC_ENGINE_DATA) )
  1615. {
  1616. // as we were not able to read back the written value
  1617. // we quit here
  1618. break;
  1619. }
  1620. // as all tests have passed, engine presence is confirmed
  1621. // here
  1622. bReturnValue = TRUE ;
  1623. }
  1624. while ( FALSE ) ;
  1625. return bReturnValue ;
  1626. }
  1627. BOOLEAN
  1628. ParStlCheckIfScsiDevice (
  1629. IN PDEVICE_EXTENSION Extension
  1630. )
  1631. {
  1632. BOOLEAN bReturnValue = FALSE;
  1633. do
  1634. {
  1635. if ( FALSE == IsEpstPresent() )
  1636. {
  1637. // as SCSI devices live only on EPST we break here
  1638. break;
  1639. }
  1640. bReturnValue = TRUE ;
  1641. }
  1642. while ( FALSE ) ;
  1643. return bReturnValue ;
  1644. }
  1645. BOOLEAN
  1646. ParStlCheckIfSSFDC (
  1647. IN PDEVICE_EXTENSION Extension
  1648. )
  1649. {
  1650. BOOLEAN bReturnValue = FALSE;
  1651. UCHAR byMakerCode = 0x00 , byDeviceCode = 0x00 ;
  1652. do
  1653. {
  1654. if ( FALSE == IsEp1284Present() )
  1655. {
  1656. // SSFDC lives on EP1284 alone, other than impact
  1657. // which is already taken care
  1658. break;
  1659. }
  1660. //check to see if the loop back of the EPCS and EPDO pins
  1661. //of the INDEX 00 register read the same. If so, it is
  1662. //SSFDC board characteristic
  1663. ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , 0x00 ) ;
  1664. ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x10 ) ;
  1665. ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x12 ) ;
  1666. if ( 0x1A == ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) )
  1667. {
  1668. ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x10 ) ;
  1669. if ( ! ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & 0x08 ) )
  1670. {
  1671. //as they are equal, SSFDC present
  1672. bReturnValue = TRUE ;
  1673. break ;
  1674. }
  1675. }
  1676. }
  1677. while ( FALSE ) ;
  1678. return bReturnValue ;
  1679. }
  1680. VOID
  1681. ParStlAssertIdleState (
  1682. IN PDEVICE_EXTENSION Extension
  1683. )
  1684. {
  1685. PUCHAR CurrentPort, CurrentControl ;
  1686. ULONG Delay = 5 ;
  1687. CurrentPort = Extension->Controller;
  1688. CurrentControl = CurrentPort + 2;
  1689. // place op-code for idle state in port base
  1690. WRITE_PORT_UCHAR ( CurrentPort, (UCHAR) 0x00 ) ;
  1691. KeStallExecutionProcessor( Delay );
  1692. // bring down DCR_INIT and DCR_STROBE
  1693. WRITE_PORT_UCHAR ( CurrentControl, (UCHAR) STB_INIT_LOW ) ;
  1694. KeStallExecutionProcessor( Delay );
  1695. // lift DCR_INIT and DCR_STROBE to high
  1696. WRITE_PORT_UCHAR ( CurrentControl, (UCHAR) STB_INIT_AFXT_HI ) ;
  1697. KeStallExecutionProcessor( Delay );
  1698. }
  1699. BOOLEAN
  1700. ParStlCheckAvisionScannerPresence(
  1701. IN PDEVICE_EXTENSION Extension
  1702. )
  1703. {
  1704. BOOLEAN bReturnValue = FALSE ;
  1705. UCHAR data;
  1706. do {
  1707. data = (UCHAR) ParStlReadReg( Extension, STATUSPORT);
  1708. if((data & 0x80) == 0) {
  1709. break ;
  1710. }
  1711. ParStlWriteReg( Extension, CONTROLPORT, 0x08 ) ;
  1712. ParStlWriteReg( Extension, CONTROLPORT, 0x08 ) ;
  1713. data = (UCHAR) ParStlReadReg( Extension, STATUSPORT);
  1714. if((data & 0x80) != 0) {
  1715. break ;
  1716. }
  1717. ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
  1718. ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
  1719. data = (UCHAR) ParStlReadReg( Extension, STATUSPORT);
  1720. if((data & 0x80) == 0) {
  1721. break ;
  1722. }
  1723. ParStlWriteReg( Extension, CONTROLPORT, 0x02 ) ;
  1724. ParStlWriteReg( Extension, CONTROLPORT, 0x02 ) ;
  1725. data = (UCHAR) ParStlReadReg( Extension, STATUSPORT);
  1726. if((data & 0x80) != 0) {
  1727. break ;
  1728. }
  1729. ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
  1730. ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
  1731. data = (UCHAR) ParStlReadReg( Extension, STATUSPORT);
  1732. if((data & 0x80) == 0) {
  1733. break ;
  1734. }
  1735. bReturnValue = TRUE ;
  1736. } while ( FALSE ) ;
  1737. return bReturnValue ;
  1738. }
  1739. BOOLEAN
  1740. ParStlCheckUMAXScannerPresence(
  1741. IN PDEVICE_EXTENSION Extension
  1742. )
  1743. {
  1744. UCHAR commandPacket_[6] = {0x55,0xaa,0,0,0,0} ;
  1745. PUCHAR commandPacket ;
  1746. USHORT status;
  1747. UCHAR idx;
  1748. PUCHAR saveCommandPacket;
  1749. ULONG dataLength;
  1750. ParStlWriteReg ( Extension, CONTROLPORT, 0 ) ; // scannner reset
  1751. KeStallExecutionProcessor ( 2000 ) ; // 2 m.secs delay
  1752. ParStlWriteReg ( Extension, CONTROLPORT, 0x0C ) ;
  1753. commandPacket = commandPacket_ ;
  1754. saveCommandPacket = commandPacket;
  1755. if ( TRUE == ParStlSetEPPMode(Extension) ) {
  1756. commandPacket+=2;
  1757. dataLength = *(ULONG*)commandPacket;
  1758. dataLength &= 0xffffff; //data bytes ordering (msb to lsb) will
  1759. // wrong .What we need here is whether the
  1760. // dataLength is 0 or not.
  1761. commandPacket = saveCommandPacket;
  1762. //Command phase
  1763. status = ParStlEPPWrite(Extension, *(commandPacket)++);
  1764. if((status & 0x700) != 0){
  1765. return FALSE; //TIMEOUT_ERROR);
  1766. }
  1767. status = ParStlEPPWrite(Extension, *(commandPacket)++);
  1768. if((status & 0x700 ) != 0){
  1769. return FALSE; //TIMEOUT_ERROR);
  1770. }
  1771. for(idx=0; idx<= 6 ;idx++){
  1772. if(status & 0x800){
  1773. break;
  1774. }
  1775. status = ParStlEPPRead(Extension);
  1776. }
  1777. if(idx == 7){
  1778. status = (status & 0xf800) | 0x100;
  1779. if ( status & 0x700 )
  1780. return FALSE;
  1781. }
  1782. status = ParStlEPPWrite(Extension, *(commandPacket)++);
  1783. if((status & 0x700 ) != 0){
  1784. return FALSE; //TIMEOUT_ERROR);
  1785. }
  1786. status = ParStlEPPWrite(Extension, *(commandPacket)++);
  1787. if((status & 0x700 ) != 0){
  1788. return FALSE; //TIMEOUT_ERROR);
  1789. }
  1790. status = ParStlEPPWrite(Extension, *(commandPacket)++);
  1791. if((status & 0x700 ) != 0){
  1792. return FALSE; //TIMEOUT_ERROR);
  1793. }
  1794. status = ParStlEPPWrite(Extension, *commandPacket);
  1795. if((status & 0x700 ) != 0){
  1796. return FALSE; //TIMEOUT_ERROR);
  1797. }
  1798. //Response phase
  1799. status = ParStlEPPRead(Extension);
  1800. commandPacket = saveCommandPacket;
  1801. if((status & 0x700) == 0){
  1802. if((commandPacket[5] == 0xc2)&& (dataLength == 0)){
  1803. status = ParStlEPPRead(Extension);
  1804. if((status & 0x0700) != 0){
  1805. return FALSE; //TIMEOUT_ERROR);
  1806. }
  1807. }
  1808. }
  1809. return TRUE;
  1810. }
  1811. return FALSE;
  1812. }
  1813. BOOLEAN
  1814. ParStlSetEPPMode(
  1815. IN PDEVICE_EXTENSION Extension
  1816. )
  1817. {
  1818. UCHAR idx;
  1819. BOOLEAN timeout = TRUE ;
  1820. ParStlWriteReg( Extension, CONTROLPORT, 0x0C ) ;
  1821. ParStlWriteReg( Extension, DATAPORT, 0x40 ) ;
  1822. ParStlWriteReg( Extension, CONTROLPORT, 0x06 ) ;
  1823. for(idx=0; idx<10; idx++){
  1824. if((ParStlReadReg(Extension, STATUSPORT) & 0x78) == 0x38){
  1825. timeout = FALSE;
  1826. break;
  1827. }
  1828. }
  1829. if(timeout == FALSE){
  1830. ParStlWriteReg( Extension, CONTROLPORT,0x7 );
  1831. timeout = TRUE;
  1832. for(idx=0; idx<10; idx++){
  1833. if((ParStlReadReg( Extension, STATUSPORT) & 0x78) == 0x38){
  1834. timeout = FALSE;
  1835. break;
  1836. }
  1837. }
  1838. if(timeout == FALSE){
  1839. ParStlWriteReg( Extension, CONTROLPORT,0x4 ) ;
  1840. timeout = TRUE;
  1841. for(idx=0; idx<10; idx++){
  1842. if((ParStlReadReg( Extension, STATUSPORT) & 0xf8) == 0xf8){
  1843. timeout = FALSE;
  1844. break;
  1845. }
  1846. }
  1847. if(timeout == FALSE){
  1848. timeout = TRUE;
  1849. ParStlWriteReg( Extension, CONTROLPORT, 0x5 );
  1850. for(idx=0; idx<10; idx++){
  1851. if( ParStlReadReg( Extension, CONTROLPORT ) == 0x5){
  1852. timeout = FALSE;
  1853. break;
  1854. }
  1855. }
  1856. if(timeout == FALSE){
  1857. ParStlWriteReg( Extension, CONTROLPORT, 0x84) ;
  1858. return TRUE ;
  1859. } // final check
  1860. } // third check
  1861. } // second check
  1862. } // first check
  1863. return(FALSE);
  1864. }
  1865. USHORT
  1866. ParStlEPPWrite(
  1867. IN PDEVICE_EXTENSION Extension,
  1868. IN UCHAR value
  1869. )
  1870. {
  1871. UCHAR idx;
  1872. USHORT statusData;
  1873. BOOLEAN timeout;
  1874. timeout = TRUE;
  1875. for(idx=0; idx<10; idx++){
  1876. if( !( (statusData = (USHORT)ParStlReadReg( Extension, STATUSPORT)) & BUSY)){
  1877. timeout = FALSE;
  1878. break;
  1879. }
  1880. }
  1881. if(timeout == TRUE){
  1882. return(((statusData<<8) & 0xf800)|0x100);
  1883. }
  1884. ParStlWriteReg( Extension, EPPDATA0PORT,value );
  1885. return(((statusData & 0xf8) << 8)|value);
  1886. }
  1887. USHORT
  1888. ParStlEPPRead(
  1889. IN PDEVICE_EXTENSION Extension
  1890. )
  1891. {
  1892. UCHAR idx;
  1893. USHORT statusData;
  1894. USHORT controlData;
  1895. UCHAR eppData;
  1896. BOOLEAN timeout = TRUE ;
  1897. for(idx=0; idx<10; idx++){
  1898. if(!( (statusData = (USHORT)ParStlReadReg( Extension, STATUSPORT)) & PE)){
  1899. timeout = FALSE;
  1900. break;
  1901. }
  1902. }
  1903. if(timeout == TRUE){
  1904. return(((statusData<<8) & 0xf800)|0x100);
  1905. }
  1906. eppData = (UCHAR)ParStlReadReg( Extension, EPPDATA0PORT) ;
  1907. return(((statusData & 0x00f8)<<8) | eppData );
  1908. }
  1909. int __cdecl
  1910. ParStlReadReg (
  1911. IN PDEVICE_EXTENSION Extension,
  1912. IN unsigned reg
  1913. )
  1914. {
  1915. UCHAR byReadNibble ;
  1916. PUCHAR CurrentPort, CurrentStatus, CurrentControl ;
  1917. ULONG Delay = 5 ;
  1918. CurrentPort = Extension->Controller;
  1919. CurrentStatus = CurrentPort + 1;
  1920. CurrentControl = CurrentPort + 2;
  1921. // select the register to read
  1922. WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)reg ) ;
  1923. KeStallExecutionProcessor( Delay );
  1924. // issue nibble ctl signals to read
  1925. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_LOW ) ;
  1926. KeStallExecutionProcessor( Delay );
  1927. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_LO ) ;
  1928. KeStallExecutionProcessor( Delay );
  1929. // read first nibble
  1930. byReadNibble = READ_PORT_UCHAR (CurrentStatus);
  1931. KeStallExecutionProcessor( Delay );
  1932. byReadNibble >>= 4 ;
  1933. // issue nibble ctl signals to read
  1934. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_HI ) ;
  1935. KeStallExecutionProcessor( Delay );
  1936. // read next nibble
  1937. byReadNibble |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ;
  1938. return (int)byReadNibble ;
  1939. }
  1940. int __cdecl
  1941. ParStlWriteReg (
  1942. IN PDEVICE_EXTENSION Extension,
  1943. IN unsigned reg,
  1944. IN int databyte
  1945. )
  1946. {
  1947. PUCHAR CurrentPort, CurrentStatus, CurrentControl ;
  1948. ULONG Delay = 5 ;
  1949. CurrentPort = Extension->Controller;
  1950. CurrentStatus = CurrentPort + 1;
  1951. CurrentControl = CurrentPort + 2;
  1952. // select the register to write
  1953. WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)( reg | 0x60 ) ) ;
  1954. KeStallExecutionProcessor( Delay );
  1955. // write to printer ctl port
  1956. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_LOW ) ;
  1957. KeStallExecutionProcessor( Delay );
  1958. // write the requested data
  1959. WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)databyte ) ;
  1960. KeStallExecutionProcessor( Delay );
  1961. // write to printer ctl port
  1962. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_HI ) ;
  1963. KeStallExecutionProcessor( Delay );
  1964. return SHTL_NO_ERROR ;
  1965. }
  1966. int __cdecl
  1967. ParStlReceiveData (
  1968. IN PDEVICE_EXTENSION Extension,
  1969. IN VOID *hostBufferPointer,
  1970. IN long shuttleMemoryAddress,
  1971. IN unsigned count
  1972. )
  1973. {
  1974. PCHAR pchDataBuffer = (PCHAR) hostBufferPointer ;
  1975. unsigned int i = 0 ;
  1976. PUCHAR CurrentPort, CurrentStatus, CurrentControl ;
  1977. ULONG Delay = 5 ;
  1978. CurrentPort = Extension->Controller;
  1979. CurrentStatus = CurrentPort + 1;
  1980. CurrentControl = CurrentPort + 2;
  1981. // set the block address register to ATA/ATAPI data register,
  1982. // as this function is currently used ONLY for ATA/ATAPI devices
  1983. // ATA/ATAPI data register 0x1F0 corresponds to 0x18 value
  1984. ParStlWriteReg ( Extension, EP1284_BLK_ADDR_REGISTER, 0x18 ) ;
  1985. // do the nibble block read sequence
  1986. // write the nibble block read op-code
  1987. WRITE_PORT_UCHAR ( CurrentPort, OP_NIBBLE_BLOCK_READ ) ;
  1988. KeStallExecutionProcessor( Delay );
  1989. // set control ports to correct signals.
  1990. WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_LO ) ;
  1991. KeStallExecutionProcessor( Delay );
  1992. // set data port to 0xFF
  1993. WRITE_PORT_UCHAR ( CurrentPort, 0xFF ) ;
  1994. KeStallExecutionProcessor( Delay );
  1995. WRITE_PORT_UCHAR ( CurrentControl, INIT_AFXT_HIGH ) ;
  1996. KeStallExecutionProcessor( Delay );
  1997. do
  1998. {
  1999. // low nibble is available in status after
  2000. // toggling sequences as in EP1284 manual
  2001. WRITE_PORT_UCHAR ( CurrentControl, AFXT_LO_STB_HI ) ;
  2002. KeStallExecutionProcessor( Delay );
  2003. pchDataBuffer[i] = READ_PORT_UCHAR( CurrentStatus ) >> 4 ;
  2004. KeStallExecutionProcessor( Delay );
  2005. // high nibble is available in status after
  2006. // toggling sequences as in EP1284 manual
  2007. WRITE_PORT_UCHAR ( CurrentControl, AFXT_HI_STB_HI ) ;
  2008. KeStallExecutionProcessor( Delay );
  2009. pchDataBuffer[i++] |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ;
  2010. KeStallExecutionProcessor( Delay );
  2011. if ( count - 1 == i )
  2012. {
  2013. // to read the last byte
  2014. WRITE_PORT_UCHAR ( CurrentPort, 0xFD ) ;
  2015. KeStallExecutionProcessor( Delay );
  2016. }
  2017. WRITE_PORT_UCHAR ( CurrentControl, AFXT_LO_STB_LO ) ;
  2018. KeStallExecutionProcessor( Delay );
  2019. pchDataBuffer[i] = READ_PORT_UCHAR ( CurrentStatus ) >> 4 ;
  2020. KeStallExecutionProcessor( Delay );
  2021. WRITE_PORT_UCHAR ( CurrentControl, AFXT_HI_STB_LO ) ;
  2022. KeStallExecutionProcessor( Delay );
  2023. pchDataBuffer[i++] |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ;
  2024. KeStallExecutionProcessor( Delay );
  2025. }
  2026. while ( i <= count ) ;
  2027. // clean up
  2028. WRITE_PORT_UCHAR ( CurrentPort, 0x00 ) ;
  2029. KeStallExecutionProcessor( Delay );
  2030. // done
  2031. return SHTL_NO_ERROR ;
  2032. }
  2033. int __cdecl
  2034. ParStlReadIoPort (
  2035. IN PDEVICE_EXTENSION Extension,
  2036. IN unsigned reg
  2037. )
  2038. {
  2039. switch ( reg )
  2040. {
  2041. case 0x08 :
  2042. reg = 0x16 ;
  2043. break ;
  2044. case 0x09 :
  2045. reg = 0x17 ;
  2046. break ;
  2047. default :
  2048. reg |= 0x18 ;
  2049. break;
  2050. }
  2051. return ParStlReadReg ( Extension, reg ) ;
  2052. }
  2053. int __cdecl
  2054. ParStlWriteIoPort (
  2055. IN PDEVICE_EXTENSION Extension,
  2056. IN unsigned reg,
  2057. IN int databyte
  2058. )
  2059. {
  2060. switch ( reg )
  2061. {
  2062. case 0x08 :
  2063. reg = 0x16 ;
  2064. break ;
  2065. case 0x09 :
  2066. reg = 0x17 ;
  2067. break ;
  2068. default :
  2069. reg |= 0x18 ;
  2070. break;
  2071. }
  2072. return ParStlWriteReg ( Extension, reg, databyte ) ;
  2073. }
  2074. int __cdecl
  2075. ParStlGetMemorySize (
  2076. IN PDEVICE_EXTENSION Extension
  2077. )
  2078. {
  2079. BOOLEAN bReturnValue = FALSE ;
  2080. UCHAR byTempValue ;
  2081. do
  2082. {
  2083. // Issue reset through control register
  2084. // first try on DRAM
  2085. byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ;
  2086. byTempValue |= ENABLE_MEM|SELECT_DRAM|RESET_PTR ;
  2087. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2088. byTempValue &= ~RESET_PTR ;
  2089. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2090. // write to the first location in the memory
  2091. ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_1 ) ;
  2092. // write to the next location in the memory
  2093. ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_2 ) ;
  2094. byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ;
  2095. byTempValue |= ENABLE_MEM|SELECT_DRAM|RESET_PTR ;
  2096. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2097. byTempValue &= ~RESET_PTR ;
  2098. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2099. // read from the first and next location in the memory
  2100. if ( ( TEST_PATTERN_1 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) &&\
  2101. ( TEST_PATTERN_2 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) )
  2102. {
  2103. bReturnValue = TRUE ;
  2104. break ;
  2105. }
  2106. if ( !IsImpactPresent () )
  2107. {
  2108. // as only DRAM can be present on non-impact adapters
  2109. break ;
  2110. }
  2111. // Issue reset through control register
  2112. // and next try on SRAM
  2113. byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ;
  2114. byTempValue |= ENABLE_MEM|RESET_PTR ;
  2115. byTempValue &= SELECT_SRAM ;
  2116. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2117. byTempValue &= ~RESET_PTR ;
  2118. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2119. // write to the first location in the memory
  2120. ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_1 ) ;
  2121. // write to the next location in the memory
  2122. ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_2 ) ;
  2123. byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ;
  2124. byTempValue |= ENABLE_MEM|RESET_PTR ;
  2125. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2126. byTempValue &= ~RESET_PTR ;
  2127. ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
  2128. // read from the first location in the memory
  2129. if ( ( TEST_PATTERN_1 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) &&\
  2130. ( TEST_PATTERN_2 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) )
  2131. {
  2132. bReturnValue = TRUE ;
  2133. break ;
  2134. }
  2135. }
  2136. while ( FALSE ) ;
  2137. return bReturnValue ;
  2138. }
  2139. // end of file