Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

378 lines
8.5 KiB

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