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.

311 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. eisac.c
  5. Abstract:
  6. This module implements routines to get EISA configuration information.
  7. Author:
  8. Shie-Lin Tzong (shielint) 18-Jan-1992
  9. Environment:
  10. 16-bit real mode.
  11. Revision History:
  12. --*/
  13. #include "hwdetect.h"
  14. #include "string.h"
  15. #if defined(NEC_98)
  16. #else // PC98
  17. typedef EISA_PORT_CONFIGURATION far *FPEISA_PORT_CONFIGURATION;
  18. extern CM_EISA_FUNCTION_INFORMATION FunctionInformation;
  19. VOID
  20. GetEisaConfigurationData (
  21. FPVOID Buffer,
  22. FPULONG Size
  23. )
  24. /*++
  25. Routine Description:
  26. This routine collects all the eisa slot information, function
  27. information and stores it in the caller supplied Buffer and
  28. returns the size of the data.
  29. Arguments:
  30. Buffer - A pointer to a PVOID to recieve the address of configuration
  31. data.
  32. Size - a pointer to a ULONG to receive the size of the configuration
  33. data.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. UCHAR Slot=0;
  39. UCHAR Function=0, SlotFunctions = 0, ReturnCode;
  40. EISA_SLOT_INFORMATION SlotInformation;
  41. FPUCHAR ConfigurationData, CurrentData;
  42. FPEISA_SLOT_INFORMATION FarSlotInformation;
  43. ULONG TotalSize = DATA_HEADER_SIZE;
  44. BOOLEAN Overflowed = FALSE;
  45. HwGetEisaSlotInformation(&SlotInformation, Slot);
  46. TotalSize += sizeof(EISA_SLOT_INFORMATION);
  47. ConfigurationData = (FPVOID)HwAllocateHeap(TotalSize, FALSE);
  48. CurrentData = ConfigurationData + DATA_HEADER_SIZE;
  49. _fmemcpy(CurrentData, (FPVOID)&SlotInformation, sizeof(EISA_SLOT_INFORMATION));
  50. FarSlotInformation = (FPEISA_SLOT_INFORMATION)CurrentData;
  51. while (SlotInformation.ReturnCode != EISA_INVALID_SLOT) {
  52. //
  53. // Ensure that the slot is not empty and collect all the function
  54. // information for the slot.
  55. //
  56. if (SlotInformation.ReturnCode != EISA_EMPTY_SLOT) {
  57. while (SlotInformation.NumberFunctions > Function) {
  58. ReturnCode = HwGetEisaFunctionInformation(
  59. &FunctionInformation, Slot, Function);
  60. Function++;
  61. //
  62. // if function call succeeds and the function contains usefull
  63. // information or this is the last function for the slot and
  64. // there is no function information collected for the slot, we
  65. // will save this function information to our heap.
  66. //
  67. if (!ReturnCode) {
  68. if (((FunctionInformation.FunctionFlags & 0x7f) != 0) ||
  69. (SlotInformation.NumberFunctions == Function &&
  70. SlotFunctions == 0)) {
  71. CurrentData = (FPVOID)HwAllocateHeap(
  72. sizeof(EISA_FUNCTION_INFORMATION), FALSE);
  73. if (CurrentData == NULL) {
  74. Overflowed = TRUE;
  75. break;
  76. }
  77. SlotFunctions++;
  78. TotalSize += sizeof(EISA_FUNCTION_INFORMATION);
  79. _fmemcpy(CurrentData,
  80. (FPVOID)&FunctionInformation,
  81. sizeof(EISA_FUNCTION_INFORMATION));
  82. }
  83. }
  84. }
  85. FarSlotInformation->NumberFunctions = SlotFunctions;
  86. }
  87. if (Overflowed) {
  88. break;
  89. }
  90. Slot++;
  91. Function = 0;
  92. HwGetEisaSlotInformation(&SlotInformation, Slot);
  93. CurrentData = (FPVOID)HwAllocateHeap(
  94. sizeof(EISA_SLOT_INFORMATION), FALSE);
  95. if (CurrentData == NULL) {
  96. Overflowed = TRUE;
  97. break;
  98. }
  99. TotalSize += sizeof(EISA_SLOT_INFORMATION);
  100. _fmemcpy(CurrentData,
  101. (FPVOID)&SlotInformation,
  102. sizeof(EISA_SLOT_INFORMATION));
  103. FarSlotInformation = (FPEISA_SLOT_INFORMATION)CurrentData;
  104. SlotFunctions = 0;
  105. }
  106. //
  107. // Free the last EISA_SLOT_INFORMATION space which contains the slot
  108. // information for IVALID SLOT
  109. //
  110. if (Overflowed != TRUE) {
  111. HwFreeHeap(sizeof(EISA_SLOT_INFORMATION));
  112. TotalSize -= sizeof(EISA_SLOT_INFORMATION);
  113. }
  114. //
  115. // Check if we got any EISA information. If nothing, we release
  116. // the space for data header and return.
  117. //
  118. if (TotalSize == DATA_HEADER_SIZE) {
  119. HwFreeHeap(DATA_HEADER_SIZE);
  120. *(FPULONG)Buffer = (ULONG)0;
  121. *Size = (ULONG)0;
  122. } else {
  123. HwSetUpFreeFormDataHeader((FPHWRESOURCE_DESCRIPTOR_LIST)ConfigurationData,
  124. 0,
  125. 0,
  126. 0,
  127. TotalSize - DATA_HEADER_SIZE
  128. );
  129. *(FPULONG)Buffer = (ULONG)ConfigurationData;
  130. *Size = TotalSize;
  131. }
  132. }
  133. BOOLEAN
  134. HwEisaGetIrqFromPort (
  135. USHORT Port,
  136. PUCHAR Irq,
  137. PUCHAR TriggerMethod
  138. )
  139. /*++
  140. Routine Description:
  141. This routine scans EISA configuration data to match the I/O port address.
  142. The IRQ information is returned from the matched EISA function information.
  143. Arguments:
  144. Port - The I/O port address to scan for.
  145. Irq - Supplies a pointer to a variable to receive the irq information.
  146. TriggerMethod - Supplies a pointer to a variable to receive the
  147. EISA interrupt trigger method.
  148. Return Value:
  149. TRUE - if the Irq information is found. Otherwise a value of FALSE is
  150. returned.
  151. --*/
  152. {
  153. UCHAR Function, i, j;
  154. FPEISA_SLOT_INFORMATION SlotInformation;
  155. FPEISA_FUNCTION_INFORMATION Buffer;
  156. UCHAR FunctionFlags;
  157. ULONG SizeToScan = 0L;
  158. EISA_PORT_CONFIGURATION PortConfig;
  159. EISA_IRQ_DESCRIPTOR IrqConfig;
  160. SlotInformation = (FPEISA_SLOT_INFORMATION)HwEisaConfigurationData;
  161. //
  162. // Scan through all the EISA configuration data.
  163. //
  164. while (SizeToScan < HwEisaConfigurationSize) {
  165. if (SlotInformation->ReturnCode != EISA_EMPTY_SLOT) {
  166. //
  167. // Make sure this slot contains PORT_RANGE and IRQ information.
  168. //
  169. if ((SlotInformation->FunctionInformation & EISA_HAS_PORT_RANGE) &&
  170. (SlotInformation->FunctionInformation & EISA_HAS_IRQ_ENTRY)) {
  171. Buffer = (FPEISA_FUNCTION_INFORMATION)(SlotInformation + 1);
  172. //
  173. // For each function of the slot, if it contains both the IRQ
  174. // and PORT information, we then check for its PORT address.
  175. //
  176. for (Function = 0; Function < SlotInformation->NumberFunctions; Function++) {
  177. FunctionFlags = Buffer->FunctionFlags;
  178. if ((FunctionFlags & EISA_HAS_IRQ_ENTRY) &&
  179. (FunctionFlags & EISA_HAS_PORT_RANGE)) {
  180. for (i = 0; i < 20 ; i++ ) {
  181. PortConfig = Buffer->EisaPort[i];
  182. if ((Port >= PortConfig.PortAddress) &&
  183. (Port <= (PortConfig.PortAddress +
  184. PortConfig.Configuration.NumberPorts))) {
  185. //
  186. // If there is only one IRQ entry, that's the
  187. // one we want. (This is the normal case and
  188. // correct usage of EISA function data.) Otherwise,
  189. // we try to get the irq from the same index
  190. // number as port entry. (This is ALR's incorrect
  191. // way of packing functions into one function
  192. // data.)
  193. //
  194. IrqConfig = Buffer->EisaIrq[0].ConfigurationByte;
  195. if (IrqConfig.MoreEntries == 0) {
  196. *Irq = IrqConfig.Interrupt;
  197. *TriggerMethod = IrqConfig.LevelTriggered;
  198. return(TRUE);
  199. } else if (i >= 7) {
  200. return(FALSE);
  201. }
  202. for (j = 0; j <= i; j++) {
  203. if (j == i) {
  204. *Irq = IrqConfig.Interrupt;
  205. *TriggerMethod = IrqConfig.LevelTriggered;
  206. return(TRUE);
  207. }
  208. if (!IrqConfig.MoreEntries) {
  209. return(FALSE);
  210. }
  211. IrqConfig =
  212. Buffer->EisaIrq[j+1].ConfigurationByte;
  213. }
  214. return(FALSE);
  215. }
  216. if (!PortConfig.Configuration.MoreEntries) {
  217. break;
  218. }
  219. }
  220. }
  221. Buffer++;
  222. }
  223. }
  224. //
  225. // Move on to next slot
  226. //
  227. SizeToScan += sizeof(EISA_SLOT_INFORMATION) +
  228. sizeof(EISA_FUNCTION_INFORMATION) *
  229. SlotInformation->NumberFunctions;
  230. SlotInformation = (FPEISA_SLOT_INFORMATION)(HwEisaConfigurationData +
  231. SizeToScan);
  232. } else {
  233. //
  234. // This is a empty slot. We simply skip it.
  235. //
  236. SizeToScan += sizeof(EISA_SLOT_INFORMATION);
  237. SlotInformation++;
  238. }
  239. }
  240. return(FALSE);
  241. }
  242. #endif // PC98