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.

299 lines
7.7 KiB

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