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.

370 lines
8.1 KiB

  1. /*
  2. * VLSI.C - VLSI Wildcat PCI chipset routines.
  3. *
  4. * Notes:
  5. * Algorithms from VLSI VL82C596/7 spec.
  6. *
  7. */
  8. #include "local.h"
  9. #define NUM_VLSI_IRQ (sizeof(rgbIndexToIRQ)/sizeof(rgbIndexToIRQ[0]))
  10. const UCHAR rgbIndexToIRQ[] = { 3, 5, 9, 10, 11, 12, 14, 15 };
  11. #define INDEX_UNUSED ((ULONG)-1)
  12. /****************************************************************************
  13. *
  14. * VLSISetIRQ - Set a VLSI PCI link to a specific IRQ
  15. *
  16. * Exported.
  17. *
  18. * ENTRY: bIRQNumber is the new IRQ to be used.
  19. *
  20. * bLink is the Link to be set.
  21. *
  22. * EXIT: Standard PCIMP return value.
  23. *
  24. ***************************************************************************/
  25. PCIMPRET CDECL
  26. VLSISetIRQ(UCHAR bIRQNumber, UCHAR bLink)
  27. {
  28. ULONG ulNewIRQIndex;
  29. ULONG rgbIRQSteering[NUM_IRQ_PINS];
  30. ULONG ulMask;
  31. ULONG ulUnusedIndex;
  32. ULONG ulVLSIRegister;
  33. ULONG ulIRQIndex;
  34. ULONG i;
  35. //
  36. // Make link number 0 based, and validate.
  37. //
  38. bLink--;
  39. if (bLink > 3) {
  40. return(PCIMP_INVALID_LINK);
  41. }
  42. //
  43. // Find the VLSI index of the new IRQ.
  44. //
  45. if (bIRQNumber) {
  46. //
  47. // Look through the list of valid indicies.
  48. //
  49. for (ulNewIRQIndex=0; ulNewIRQIndex<NUM_VLSI_IRQ; ulNewIRQIndex++)
  50. {
  51. if (rgbIndexToIRQ[ulNewIRQIndex] == bIRQNumber)
  52. break;
  53. }
  54. //
  55. // If there is no VLSI equivalent, bail.
  56. //
  57. if (ulNewIRQIndex==NUM_VLSI_IRQ) {
  58. return(PCIMP_INVALID_IRQ);
  59. }
  60. } else {
  61. //
  62. // Blowing away this interrupt.
  63. //
  64. ulNewIRQIndex = INDEX_UNUSED;
  65. }
  66. //
  67. // Read in the VLSI Interrupt Steering Register.
  68. //
  69. ulVLSIRegister=ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x74);
  70. //
  71. // Compute the complete IRQ mapping.
  72. //
  73. for (i=0, ulMask=0x07; i<NUM_IRQ_PINS; i++, ulMask<<=4)
  74. {
  75. ulIRQIndex = (ulVLSIRegister & ulMask) >> (i * 4);
  76. if ((ulVLSIRegister & (1 << (ulIRQIndex + 16))) != 0)
  77. {
  78. rgbIRQSteering[i] = ulIRQIndex;
  79. }
  80. else
  81. {
  82. rgbIRQSteering[i] = INDEX_UNUSED;
  83. }
  84. }
  85. //
  86. // Update the IRQ Mapping with the new IRQ.
  87. //
  88. rgbIRQSteering[bLink] = ulNewIRQIndex;
  89. //
  90. // Find an unused IRQ index.
  91. //
  92. for (ulUnusedIndex=0; ulUnusedIndex<NUM_VLSI_IRQ; ulUnusedIndex++)
  93. {
  94. for (i=0; i<NUM_IRQ_PINS; i++)
  95. {
  96. if (rgbIRQSteering[i] == ulUnusedIndex)
  97. break;
  98. }
  99. if (i == NUM_IRQ_PINS)
  100. break;
  101. }
  102. //
  103. // Compute the new VLSI Interrupt Steering Register.
  104. //
  105. ulVLSIRegister = 0x00000000;
  106. for (i=0; i<NUM_IRQ_PINS; i++)
  107. {
  108. if (rgbIRQSteering[i] == INDEX_UNUSED)
  109. {
  110. ulVLSIRegister |= ulUnusedIndex << (4*i);
  111. }
  112. else
  113. {
  114. ulVLSIRegister |= rgbIRQSteering[i] << (4*i);
  115. ulVLSIRegister |= 1 << (rgbIRQSteering[i] + 16);
  116. }
  117. }
  118. //
  119. // Write out the new VLSI Interrupt Steering Register.
  120. //
  121. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x74, ulVLSIRegister);
  122. return(PCIMP_SUCCESS);
  123. }
  124. /****************************************************************************
  125. *
  126. * VLSIGetIRQ - Get the IRQ of a VLSI PCI link
  127. *
  128. * Exported.
  129. *
  130. * ENTRY: pbIRQNumber is the buffer to fill.
  131. *
  132. * bLink is the Link to be read.
  133. *
  134. * EXIT: Standard PCIMP return value.
  135. *
  136. ***************************************************************************/
  137. PCIMPRET CDECL
  138. VLSIGetIRQ(PUCHAR pbIRQNumber, UCHAR bLink)
  139. {
  140. ULONG ulVLSIRegister;
  141. ULONG ulIndex;
  142. UCHAR bIRQ;
  143. //
  144. // Make link number 0 based, and validate.
  145. //
  146. bLink--;
  147. if (bLink > 3) {
  148. return(PCIMP_INVALID_LINK);
  149. }
  150. //
  151. // Read in the VLSI Interrupt Steering Register.
  152. //
  153. ulVLSIRegister=ReadConfigUchar(bBusPIC, bDevFuncPIC, 0x74);
  154. //
  155. // Find the link's IRQ value.
  156. //
  157. ulIndex = (ulVLSIRegister >> (bLink*4)) & 0x7;
  158. bIRQ = rgbIndexToIRQ[ulIndex];
  159. //
  160. // Make sure the IRQ is marked as in use.
  161. //
  162. if ((ulVLSIRegister & (1 << (ulIndex + 16))) == 0)
  163. {
  164. bIRQ = 0;
  165. }
  166. //
  167. // Set the return buffer.
  168. //
  169. *pbIRQNumber = bIRQ;
  170. return(PCIMP_SUCCESS);
  171. }
  172. /****************************************************************************
  173. *
  174. * VLSISetTrigger - Set the IRQ triggering values for the VLSI.
  175. *
  176. * Exported.
  177. *
  178. * ENTRY: ulTrigger has bits set for Level triggered IRQs.
  179. *
  180. * EXIT: Standard PCIMP return value.
  181. *
  182. ***************************************************************************/
  183. PCIMPRET CDECL
  184. VLSISetTrigger(ULONG ulTrigger)
  185. {
  186. ULONG ulAssertionRegister;
  187. ULONG ulPMAssertionRegister;
  188. ULONG i;
  189. //
  190. // Read in the Interrupt Assertion Level register.
  191. //
  192. ulAssertionRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x5C);
  193. //
  194. // Clear off the old edge/level settings.
  195. //
  196. ulAssertionRegister &= ~0xff;
  197. //
  198. // For each VLSI interrupt...
  199. //
  200. for (i=0; i<NUM_VLSI_IRQ; i++)
  201. {
  202. //
  203. // If the corresponding bit is set to level...
  204. //
  205. if (ulTrigger & (1 << rgbIndexToIRQ[i]))
  206. {
  207. //
  208. // Set the corresponding bit in the
  209. // Assertion Register.
  210. //
  211. ulAssertionRegister |= 1 << i;
  212. //
  213. // And clear the bit from ulTrigger.
  214. //
  215. ulTrigger &= ~(1 << rgbIndexToIRQ[i]);
  216. }
  217. }
  218. //
  219. // If the caller wanted some non-VLSI IRQs level, bail.
  220. //
  221. if (ulTrigger)
  222. {
  223. return(PCIMP_INVALID_IRQ);
  224. }
  225. //
  226. // Set the Assertion Register.
  227. //
  228. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x5C, ulAssertionRegister);
  229. //
  230. // Read in the Power Mgmt edge/level setting.
  231. //
  232. ulPMAssertionRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x78);
  233. //
  234. // Clear off the old edge/level settings.
  235. //
  236. ulPMAssertionRegister &= ~0xff;
  237. //
  238. // Copy the new edge/level settings.
  239. //
  240. ulPMAssertionRegister |= ulAssertionRegister & 0xff;
  241. //
  242. // Set the Power Mgmt Assertion Register.
  243. //
  244. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x78, ulPMAssertionRegister);
  245. return(PCIMP_SUCCESS);
  246. }
  247. /****************************************************************************
  248. *
  249. * VLSIGetTrigger - Get the IRQ triggering values for the VLSI.
  250. *
  251. * Exported.
  252. *
  253. * ENTRY: pulTrigger will have bits set for Level triggered IRQs.
  254. *
  255. * EXIT: TRUE if successful.
  256. *
  257. ***************************************************************************/
  258. PCIMPRET CDECL
  259. VLSIGetTrigger(PULONG pulTrigger)
  260. {
  261. ULONG ulAssertionRegister;
  262. ULONG i;
  263. //
  264. // Read in the Interrupt Assertion Level register.
  265. //
  266. ulAssertionRegister = ReadConfigUchar(bBusPIC, bDevFuncPIC, 0x5C);
  267. //
  268. // Clear the return buffer.
  269. //
  270. *pulTrigger = 0;
  271. //
  272. // For each VLSI interrupt...
  273. //
  274. for (i=0; i<NUM_VLSI_IRQ; i++)
  275. {
  276. //
  277. // If the corresponding bit is set to level...
  278. //
  279. if (ulAssertionRegister & (1 << i))
  280. {
  281. //
  282. // Set the corresponding bit in the
  283. // return buffer.
  284. //
  285. *pulTrigger |= 1 << rgbIndexToIRQ[i];
  286. }
  287. }
  288. return(PCIMP_SUCCESS);
  289. }
  290. /****************************************************************************
  291. *
  292. * VLSIValidateTable - Validate an IRQ table
  293. *
  294. * Exported.
  295. *
  296. * ENTRY: piihIRQInfoHeader points to an IRQInfoHeader followed
  297. * by an IRQ Routing Table.
  298. *
  299. * ulFlags are PCIMP_VALIDATE flags.
  300. *
  301. * EXIT: Standard PCIMP return value.
  302. *
  303. ***************************************************************************/
  304. #ifdef ALLOC_PRAGMA
  305. PCIMPRET CDECL
  306. VLSIValidateTable(PIRQINFOHEADER piihIRQInfoHeader, ULONG ulFlags);
  307. #pragma alloc_text(PAGE, VLSIValidateTable)
  308. #endif //ALLOC_PRAGMA
  309. PCIMPRET CDECL
  310. VLSIValidateTable(PIRQINFOHEADER piihIRQInfoHeader, ULONG ulFlags)
  311. {
  312. PAGED_CODE();
  313. if (GetMaxLink(piihIRQInfoHeader)>0x04) {
  314. return(PCIMP_FAILURE);
  315. }
  316. return(PCIMP_SUCCESS);
  317. }