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.

291 lines
7.3 KiB

  1. /*
  2. * OPTIVIP.C - OPTi Viper-M PCI chipset routines.
  3. *
  4. * Notes:
  5. * Algorithms from OPTi Viper-M 82C556M/82C557M/82C558M doc,
  6. * 82C558M spec.
  7. *
  8. */
  9. #include "local.h"
  10. // IRQ = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  11. const UCHAR rgbIRQToBig[16] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 4, 5, 0, 6, 7 };
  12. const UCHAR rgbIRQToSmall[16] = { 0, 0, 0, 1, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 };
  13. const UCHAR rgbBigToIRQ[8] = { 0, 5, 9, 10, 11, 12, 14, 15 };
  14. const UCHAR rgbSmallToIRQ[8] = { 0, 3, 4, 7 };
  15. /****************************************************************************
  16. *
  17. * OptiViperSetIRQ - Set a OptiViper PCI link to a specific IRQ
  18. *
  19. * Exported.
  20. *
  21. * ENTRY: bIRQNumber is the new IRQ to be used.
  22. *
  23. * bLink is the Link to be set.
  24. *
  25. * EXIT: Standard PCIMP return value.
  26. *
  27. ***************************************************************************/
  28. PCIMPRET CDECL
  29. OptiViperSetIRQ(UCHAR bIRQNumber, UCHAR bLink)
  30. {
  31. ULONG ulIRQRegister;
  32. //
  33. // If not an OPTi IRQ, bail.
  34. //
  35. if (bIRQNumber && (!rgbIRQToBig[bIRQNumber] &&
  36. !rgbIRQToSmall[bIRQNumber]))
  37. {
  38. return(PCIMP_INVALID_IRQ);
  39. }
  40. //
  41. // Make link number 0 based, and validate.
  42. //
  43. bLink--;
  44. if (bLink > 3) {
  45. return(PCIMP_INVALID_LINK);
  46. }
  47. //
  48. // Read in the big IRQ Register,
  49. // clear the old IRQ index for the link,
  50. // set the new IRQ index,
  51. // and write it back.
  52. //
  53. ulIRQRegister=ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x40);
  54. ulIRQRegister &= ~(0x7 << (3 * bLink));
  55. ulIRQRegister |= rgbIRQToBig[bIRQNumber] << (3 * bLink);
  56. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x40, ulIRQRegister);
  57. //
  58. // Read in the small IRQ register,
  59. // clear the old IRQ index for the link,
  60. // set the new IRQ index,
  61. // and write it back.
  62. //
  63. ulIRQRegister=ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x50);
  64. ulIRQRegister &= ~(0x3 << (2 * bLink));
  65. ulIRQRegister |= rgbIRQToSmall[bIRQNumber] << (2 * bLink);
  66. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x50, ulIRQRegister);
  67. return(PCIMP_SUCCESS);
  68. }
  69. /****************************************************************************
  70. *
  71. * OptiViperGetIRQ - Get the IRQ of a OptiViper PCI link
  72. *
  73. * Exported.
  74. *
  75. * ENTRY: pbIRQNumber is the buffer to fill.
  76. *
  77. * bLink is the Link to be read.
  78. *
  79. * EXIT: Standard PCIMP return value.
  80. *
  81. ***************************************************************************/
  82. PCIMPRET CDECL
  83. OptiViperGetIRQ(PUCHAR pbIRQNumber, UCHAR bLink)
  84. {
  85. ULONG ulIRQRegister;
  86. ULONG ulIndex;
  87. //
  88. // Make link number 0 based, and validate.
  89. //
  90. bLink--;
  91. if (bLink > 3) {
  92. return(PCIMP_INVALID_LINK);
  93. }
  94. //
  95. // Read in the big IRQ Register.
  96. //
  97. ulIRQRegister=ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x40);
  98. //
  99. // If we have a big IRQ, we're done.
  100. //
  101. ulIndex = (ulIRQRegister >> (bLink * 3)) & 0x7;
  102. if ((*pbIRQNumber = rgbBigToIRQ[ulIndex]) != 0)
  103. {
  104. return(PCIMP_SUCCESS);
  105. }
  106. //
  107. // Read in the small IRQ register.
  108. //
  109. ulIRQRegister=ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x50);
  110. //
  111. // Set the buffer to the small IRQ's value.
  112. //
  113. ulIndex = (ulIRQRegister >> (bLink * 2)) & 0x3;
  114. *pbIRQNumber = rgbSmallToIRQ[ulIndex];
  115. return(PCIMP_SUCCESS);
  116. }
  117. /****************************************************************************
  118. *
  119. * OptiViperSetTrigger - Set the IRQ triggering values for the OptiViper
  120. *
  121. * Exported.
  122. *
  123. * ENTRY: ulTrigger has bits set for Level triggered IRQs.
  124. *
  125. * EXIT: Standard PCIMP return value.
  126. *
  127. ***************************************************************************/
  128. PCIMPRET CDECL
  129. OptiViperSetTrigger(ULONG ulTrigger)
  130. {
  131. ULONG ulBigIRQRegister;
  132. ULONG ulSmallIRQRegister;
  133. ULONG i;
  134. //
  135. // Read in the big & small IRQ registers,
  136. // setting all IRQs to edge.
  137. //
  138. ulBigIRQRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x40) & ~0x00FE0000;
  139. ulSmallIRQRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x50) & ~0x00000700;
  140. //
  141. // For each IRQ...
  142. //
  143. for (i=0; i<16; i++)
  144. {
  145. //
  146. // If we want this to be level triggered...
  147. //
  148. if (ulTrigger & (1 << i))
  149. {
  150. if (rgbIRQToBig[i])
  151. {
  152. //
  153. // If it's a big IRQ, set the
  154. // corresponding bit in the
  155. // big register.
  156. //
  157. ulBigIRQRegister |= 1 << (16 + rgbIRQToBig[i]);
  158. }
  159. else if (rgbIRQToSmall[i])
  160. {
  161. //
  162. // If it's a small IRQ, set the
  163. // corresponding bit in the
  164. // small register.
  165. //
  166. ulSmallIRQRegister |= 1 << (11 - rgbIRQToSmall[i]);
  167. }
  168. else
  169. {
  170. //
  171. // Trying to level set an unsupported IRQ.
  172. //
  173. return(PCIMP_INVALID_IRQ);
  174. }
  175. }
  176. }
  177. //
  178. // Write the new IRQ register values.
  179. //
  180. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x40, ulBigIRQRegister);
  181. WriteConfigUlong(bBusPIC, bDevFuncPIC, 0x50, ulSmallIRQRegister);
  182. return(PCIMP_SUCCESS);
  183. }
  184. /****************************************************************************
  185. *
  186. * OptiViperGetTrigger - Get the IRQ triggering values for the OptiViper
  187. *
  188. * Exported.
  189. *
  190. * ENTRY: pulTrigger will have bits set for Level triggered IRQs.
  191. *
  192. * EXIT: Standard PCIMP return value.
  193. *
  194. ***************************************************************************/
  195. PCIMPRET CDECL
  196. OptiViperGetTrigger(PULONG pulTrigger)
  197. {
  198. ULONG ulBigIRQRegister;
  199. ULONG ulSmallIRQRegister;
  200. ULONG i;
  201. //
  202. // Assume all edge.
  203. //
  204. *pulTrigger = 0;
  205. //
  206. // Read in the big&small IRQ registers.
  207. //
  208. ulBigIRQRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x40);
  209. ulSmallIRQRegister = ReadConfigUlong(bBusPIC, bDevFuncPIC, 0x50);
  210. //
  211. // For each IRQ...
  212. //
  213. for (i=0; i<16; i++)
  214. {
  215. //
  216. // If it's a big IRQ and it's level triggered,
  217. // or if it's a small IRQ and it's level triggered,
  218. // set the corresponding bit in pulTrigger.
  219. //
  220. if ( ((rgbIRQToBig[i]) &&
  221. (ulBigIRQRegister & (1 << (16 + rgbIRQToBig[i])))) ||
  222. ((rgbIRQToSmall[i]) &&
  223. (ulSmallIRQRegister & (1 << (11 - rgbIRQToSmall[i])))))
  224. {
  225. *pulTrigger |= 1 << i;
  226. }
  227. }
  228. return(PCIMP_SUCCESS);
  229. }
  230. /****************************************************************************
  231. *
  232. * OptiViperValidateTable - Validate an IRQ table
  233. *
  234. * Exported.
  235. *
  236. * ENTRY: piihIRQInfoHeader points to an IRQInfoHeader followed
  237. * by an IRQ Routing Table.
  238. *
  239. * ulFlags are PCIMP_VALIDATE flags.
  240. *
  241. * EXIT: Standard PCIMP return value.
  242. *
  243. ***************************************************************************/
  244. #ifdef ALLOC_PRAGMA
  245. PCIMPRET CDECL
  246. OptiViperValidateTable(PIRQINFOHEADER piihIRQInfoHeader, ULONG ulFlags);
  247. #pragma alloc_text(PAGE, OptiViperValidateTable)
  248. #endif //ALLOC_PRAGMA
  249. PCIMPRET CDECL
  250. OptiViperValidateTable(PIRQINFOHEADER piihIRQInfoHeader, ULONG ulFlags)
  251. {
  252. PAGED_CODE();
  253. if (GetMaxLink(piihIRQInfoHeader)>0x04) {
  254. return(PCIMP_FAILURE);
  255. }
  256. return(PCIMP_SUCCESS);
  257. }