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.

362 lines
12 KiB

  1. #include "pch.h"
  2. // Register Definitions for National ChipSets
  3. #define REG_CR0 0x00
  4. #define REG_CR1 0x01
  5. #define REG_CR2 0x02
  6. #define REG_CR3 0x03
  7. #define REG_CR4 0x04
  8. #define REG_CR5 0x05
  9. #define REG_CR6 0x06
  10. #define REG_CR7 0x07
  11. #define REG_CR8 0x08
  12. // National Chip ID's
  13. #define PC87303 0x30
  14. #define PC87306 0x70
  15. #define PC87307 0xC0
  16. #define PC87308 0xA0
  17. #define PC87323 0x20
  18. #define PC87332 0x10
  19. #define PC87334 0x50
  20. #define PC87336 0x90
  21. #define PC87338 0xB0
  22. #define PC873xx 0x60
  23. // Additional definitions for National PC87307 and PC87308
  24. #define PC873_LOGICAL_DEV_REG 0x07
  25. #define PC873_PP_LDN 0x04
  26. #define PC873_DEVICE_ID 0x20
  27. #define PC873_PP_MODE_REG 0xF0
  28. #define PC873_ECP_MODE 0xF2
  29. #define PC873_EPP_MODE 0x62
  30. #define PC873_SPP_MODE 0x92
  31. #define PC873_BASE_IO_ADD_MSB 0x60
  32. #define PC873_BASE_IO_ADD_LSB 0x61
  33. NTSTATUS
  34. PptFindNatChip(
  35. IN PFDO_EXTENSION Fdx
  36. )
  37. /*++
  38. Routine Description:
  39. This routine finds out if there is a National Semiconductor IO chip on
  40. this machine. If it finds a National chip it then determines if this
  41. instance of Parport is using this chips paralle port IO address.
  42. Arguments:
  43. Fdx - Supplies the device extension.
  44. Return Value:
  45. STATUS_SUCCESS - if we were able to check for the parallel chip.
  46. STATUS_UNSUCCESSFUL - if we were not able to check for the parallel chip.
  47. Updates:
  48. Fdx->
  49. NationalChecked
  50. NationalChipFound
  51. --*/
  52. {
  53. BOOLEAN found = FALSE; // return code, assumed value
  54. BOOLEAN OkToLook = FALSE;
  55. BOOLEAN Conflict;
  56. PUCHAR ChipAddr[4] = { (PUCHAR)0x398, (PUCHAR)0x26e, (PUCHAR)0x15c, (PUCHAR)0x2e }; // list of valid chip addresses
  57. PUCHAR AddrList[4] = { (PUCHAR)0x378, (PUCHAR)0x3bc, (PUCHAR)0x278, (PUCHAR)0x00 }; // List of valid Parallel Port addresses
  58. PUCHAR PortAddr; // Chip Port Address
  59. ULONG_PTR Port; // Chip Port Read Value
  60. UCHAR SaveIdx; // Save the index register value
  61. UCHAR cr; // config register value
  62. UCHAR ii; // loop index
  63. NTSTATUS Status; // Status of success
  64. ULONG ResourceDescriptorCount;
  65. ULONG ResourcesSize;
  66. PCM_RESOURCE_LIST Resources;
  67. ULONG NationalChecked = 0;
  68. ULONG NationalChipFound = 0;
  69. //
  70. // Quick exit if we already know the answer
  71. //
  72. if ( Fdx->NationalChecked == TRUE ) {
  73. return STATUS_SUCCESS;
  74. }
  75. //
  76. // Mark extension so that we can quick exit the next time we are asked this question
  77. //
  78. Fdx->NationalChecked = TRUE;
  79. //
  80. // Check the registry - we should only need to check this once per installation
  81. //
  82. PptRegGetDeviceParameterDword(Fdx->PhysicalDeviceObject, (PWSTR)L"NationalChecked", &NationalChecked);
  83. if( NationalChecked ) {
  84. //
  85. // We previously performed the NatSemi Check - extract result from registry
  86. //
  87. PptRegGetDeviceParameterDword(Fdx->PhysicalDeviceObject, (PWSTR)L"NationalChipFound", &NationalChipFound);
  88. if( NationalChipFound ) {
  89. Fdx->NationalChipFound = TRUE;
  90. } else {
  91. Fdx->NationalChipFound = FALSE;
  92. }
  93. return STATUS_SUCCESS;
  94. }
  95. //
  96. // This is our first, and hopefully last time that we need to make this check
  97. // for this installation
  98. //
  99. //
  100. // Allocate a block of memory for constructing a resource descriptor
  101. //
  102. // number of partial descriptors
  103. ResourceDescriptorCount = sizeof(ChipAddr)/sizeof(ULONG);
  104. // size of resource descriptor list + space for (n-1) more partial descriptors
  105. // (resource descriptor list includes one partial descriptor)
  106. ResourcesSize = sizeof(CM_RESOURCE_LIST) +
  107. (ResourceDescriptorCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  108. Resources = (PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, ResourcesSize);
  109. if (Resources == NULL) {
  110. // Error out
  111. return(STATUS_UNSUCCESSFUL);
  112. }
  113. // zero out memory block as a precaution
  114. RtlZeroMemory(Resources, ResourcesSize);
  115. //
  116. // Build the Resource List
  117. //
  118. Status = PptBuildResourceList( Fdx,
  119. sizeof(ChipAddr)/sizeof(ULONG),
  120. &ChipAddr[0],
  121. Resources
  122. );
  123. // Check to see if it was successful
  124. if ( !NT_SUCCESS( Status ) ) {
  125. ExFreePool( Resources );
  126. return ( Status );
  127. }
  128. //
  129. // check to see if we can use the io addresses where
  130. // national chipsets are located
  131. //
  132. Status = IoReportResourceUsage( NULL,
  133. Fdx->DriverObject,
  134. Resources,
  135. sizeof(Resources),
  136. Fdx->DeviceObject,
  137. NULL,
  138. 0,
  139. FALSE,
  140. &Conflict
  141. );
  142. // done with resource list
  143. ExFreePool( Resources );
  144. // Check to see if IoReportResourceUsage was successful
  145. if( !NT_SUCCESS( Status ) ) {
  146. return Status;
  147. }
  148. // Check to see if it was successful
  149. if ( Conflict ) {
  150. return STATUS_UNSUCCESSFUL;
  151. }
  152. // Was successful so now we check each of the addresses that we have
  153. // the resources for
  154. //
  155. // the following for loop is a state machine that checks modes and
  156. // port addresses.
  157. //
  158. // state 0: check for Pc873 at primary port address
  159. // state 1: check for Pc873 at secondary port address
  160. // state 2: check for Pc873 at Ter port address
  161. // state 3: check for Pc873 at Quad port address
  162. for ( ii = 0; !found && ii < 4; ii++ ) {
  163. PortAddr = (PUCHAR)ChipAddr[ii];
  164. // After power up the index register will read back an 0xAA one time only.
  165. // So we'll check for that first.
  166. // Then it should read back a 0 or a valid register number
  167. if(( P5ReadPortUchar( PortAddr ) == 0x88 )
  168. && ( P5ReadPortUchar( PortAddr ) < 0x20 )) {
  169. OkToLook = TRUE;
  170. } else {
  171. // Or it could read back a 0 or a valid register number
  172. P5ReadPortUchar( PortAddr ); // may read back 0 here
  173. cr = P5ReadPortUchar( PortAddr ); // valid register no.
  174. // is it really valid?
  175. // if( cr < 0x20 ) { - dvdr
  176. if( cr != 0xff ) {
  177. // does it read back the same?
  178. if( P5ReadPortUchar( PortAddr ) == cr)
  179. OkToLook = TRUE;
  180. }
  181. } // end else
  182. // take a closer look by writing to the chip
  183. if ( OkToLook ) {
  184. OkToLook = FALSE;
  185. // setup for ID reg
  186. P5WritePortUchar( PortAddr, REG_CR8 );
  187. // read it back
  188. cr = P5ReadPortUchar( PortAddr );
  189. // does it read back the same?
  190. if( cr == REG_CR8 ) {
  191. // get the ID number.
  192. cr = (UCHAR)( P5ReadPortUchar( PortAddr + 1 ) & 0xf0 );
  193. // if the up. nib. is 1,3,5,6,7,9,A,B,C
  194. if( cr == PC87332 || cr == PC87334 || cr == PC87306 || cr == PC87303 ||
  195. cr == PC87323 || cr == PC87336 || cr == PC87338 || cr == PC873xx ) {
  196. // we found a national chip
  197. found = TRUE;
  198. // setup for Address reg
  199. P5WritePortUchar( PortAddr, REG_CR1 );
  200. // read it back
  201. Port = P5ReadPortUchar( PortAddr + 1 ) & 0x03;
  202. // Check the base address
  203. if ( Fdx->PortInfo.Controller == (PUCHAR)AddrList[ Port ] ) {
  204. //
  205. // it is using the same address that Parport is using
  206. // so we set the flag to not use generic ECP and EPP
  207. //
  208. Fdx->NationalChipFound = TRUE;
  209. }
  210. }
  211. } // reads back ok
  212. } // end OkToLook
  213. // check to see if we found it
  214. if ( !found ) {
  215. // Check for the 307/308 chips
  216. SaveIdx = P5ReadPortUchar( PortAddr );
  217. // Setup for SID Register
  218. P5WritePortUchar( PortAddr, PC873_DEVICE_ID );
  219. // Zero the ID register to start and because it is read only it will
  220. // let us know whether it is this chip
  221. P5WritePortUchar( PortAddr + 1, REG_CR0 );
  222. // get the ID number.
  223. cr = (UCHAR)( P5ReadPortUchar( PortAddr + 1 ) & 0xf8 );
  224. if ( (cr == PC87307) || (cr == PC87308) ) {
  225. // we found a new national chip
  226. found = TRUE;
  227. // Set the logical device
  228. P5WritePortUchar( PortAddr, PC873_LOGICAL_DEV_REG );
  229. P5WritePortUchar( PortAddr+1, PC873_PP_LDN );
  230. // set up for the base address MSB register
  231. P5WritePortUchar( PortAddr, PC873_BASE_IO_ADD_MSB );
  232. // get the MSB of the base address
  233. Port = (ULONG_PTR)((P5ReadPortUchar( PortAddr + 1 ) << 8) & 0xff00);
  234. // Set up for the base address LSB register
  235. P5WritePortUchar( PortAddr, PC873_BASE_IO_ADD_LSB );
  236. // Get the LSBs of the base address
  237. Port |= P5ReadPortUchar( PortAddr + 1 );
  238. // Check the base address
  239. if ( Fdx->PortInfo.Controller == (PUCHAR)Port ) {
  240. //
  241. // it is using the same address that Parport is using
  242. // so we set the flag to not use generic ECP and EPP
  243. //
  244. Fdx->NationalChipFound = TRUE;
  245. }
  246. } else {
  247. P5WritePortUchar( PortAddr, SaveIdx );
  248. }
  249. }
  250. } // end of for ii...
  251. //
  252. // Check for NatSemi chip is complete - save results in registry so that we never
  253. // have to make this check again for this port
  254. //
  255. {
  256. PDEVICE_OBJECT pdo = Fdx->PhysicalDeviceObject;
  257. NationalChecked = 1;
  258. NationalChipFound = Fdx->NationalChipFound ? 1 : 0;
  259. // we ignore status here because there is nothing we can do if the calls fail
  260. PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChecked", &NationalChecked);
  261. PptRegSetDeviceParameterDword(pdo, (PWSTR)L"NationalChipFound", &NationalChipFound);
  262. }
  263. //
  264. // release the io addresses where we checked for the national chipsets
  265. // we do this by calling IoReportResourceUsage with all NULL parameters
  266. //
  267. Status = IoReportResourceUsage( NULL,
  268. Fdx->DriverObject,
  269. NULL,
  270. 0,
  271. Fdx->DeviceObject,
  272. NULL,
  273. 0,
  274. FALSE,
  275. &Conflict
  276. );
  277. DD((PCE)Fdx,DDT,"ParMode::PptFindNatChip: return isFound [%x]\n",Fdx->NationalChipFound);
  278. return ( Status );
  279. } // end of ParFindNat()