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.

717 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. This contains the misc support functions used by the
  7. PCI IRQ Miniport library.
  8. Author:
  9. Santosh Jodh (santoshj) 09-June-1998
  10. Environment:
  11. kernel mode only
  12. Revision History:
  13. --*/
  14. #include "local.h"
  15. NTSTATUS
  16. EisaGetTrigger (
  17. OUT PULONG Trigger
  18. )
  19. /*++
  20. Routine Description:
  21. This routine gets the EISA Irq trigger mask (1 - Level, 0 - Edge).
  22. Parameters:
  23. Trigger - Trigger mask is returned in this argument.
  24. Return Value:
  25. PCIIRQMP_STATUS_SUCCESS.
  26. Notes:
  27. --*/
  28. {
  29. UCHAR LowPart;
  30. UCHAR HighPart;
  31. //
  32. // Read the edge\level mask for Irq 0-7.
  33. //
  34. LowPart = READ_PORT_UCHAR((PUCHAR)0x4D0);
  35. //
  36. // Allow delay before another I/O.
  37. //
  38. IO_Delay();
  39. //
  40. // Read the edge\level mask for Irq 8-15.
  41. //
  42. HighPart = READ_PORT_UCHAR((PUCHAR)0x4D1);
  43. //
  44. // Combine set the trigger to the mask for Irq 0-15.
  45. //
  46. *Trigger = (ULONG)((HighPart << 8) + LowPart) & 0xFFFF;
  47. return (PCIMP_SUCCESS);
  48. }
  49. NTSTATUS
  50. EisaSetTrigger (
  51. IN ULONG Trigger
  52. )
  53. /*++
  54. Routine Description:
  55. This routine sets the EISA Irq trigger mask (1 - Level, 0 - Edge).
  56. Parameters:
  57. Trigger - Trigger mask to be set.
  58. Return Value:
  59. PCIIRQMP_STATUS_SUCCESS.
  60. Notes:
  61. --*/
  62. {
  63. //
  64. // Program the EISA edge\level control for Irq 0-7.
  65. //
  66. WRITE_PORT_UCHAR((PUCHAR)0x4D0, (CHAR)Trigger);
  67. //
  68. // Allow delay before another I/O.
  69. //
  70. IO_Delay();
  71. //
  72. // Program the EISA edge\level control for Irq 8-15.
  73. //
  74. WRITE_PORT_UCHAR((PUCHAR)0x4D1, (CHAR)(Trigger >> 8));
  75. return (PCIMP_SUCCESS);
  76. }
  77. UCHAR
  78. ReadConfigUchar (
  79. IN ULONG BusNumber,
  80. IN ULONG DevFunc,
  81. IN UCHAR Offset
  82. )
  83. /*++
  84. Routine Description:
  85. This routine calls the HAL to read the Pci config space.
  86. Parameters:
  87. BusNumber - Bus number of the Pci device being read.
  88. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  89. Offset - Offset in the config space to be read.
  90. Return Value:
  91. Value read from the specified offset in the config space.
  92. Notes:
  93. --*/
  94. {
  95. UCHAR Data;
  96. ULONG slotNumber;
  97. slotNumber = (DevFunc >> 3) & 0x1F;
  98. slotNumber |= ((DevFunc & 0x07) << 5);
  99. //
  100. // Initialize data to invalid values.
  101. //
  102. Data = 0xFF;
  103. //
  104. // Call the HAL to do the actual reading.
  105. //
  106. HalGetBusDataByOffset( PCIConfiguration,
  107. BusNumber,
  108. slotNumber,
  109. &Data,
  110. Offset,
  111. sizeof(Data));
  112. //
  113. // Return data read to the caller.
  114. //
  115. return(Data);
  116. }
  117. USHORT
  118. ReadConfigUshort (
  119. IN ULONG BusNumber,
  120. IN ULONG DevFunc,
  121. IN UCHAR Offset
  122. )
  123. /*++
  124. Routine Description:
  125. This routine calls the HAL to read the Pci config space.
  126. Parameters:
  127. BusNumber - Bus number of the Pci device being read.
  128. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  129. Offset - Offset in the config space to be read.
  130. Return Value:
  131. Value read from the specified offset in the config space.
  132. Notes:
  133. --*/
  134. {
  135. USHORT Data;
  136. ULONG slotNumber;
  137. slotNumber = (DevFunc >> 3) & 0x1F;
  138. slotNumber |= ((DevFunc & 0x07) << 5);
  139. //
  140. // Initialize data to invalid values.
  141. //
  142. Data = 0xFFFF;
  143. //
  144. // Call the HAL to do the actual reading.
  145. //
  146. HalGetBusDataByOffset( PCIConfiguration,
  147. BusNumber,
  148. slotNumber,
  149. &Data,
  150. Offset,
  151. sizeof(Data));
  152. //
  153. // Return data read to the caller.
  154. //
  155. return(Data);
  156. }
  157. ULONG
  158. ReadConfigUlong (
  159. IN ULONG BusNumber,
  160. IN ULONG DevFunc,
  161. IN UCHAR Offset
  162. )
  163. /*++
  164. Routine Description:
  165. This routine calls the HAL to read the Pci config space.
  166. Parameters:
  167. BusNumber - Bus number of the Pci device being read.
  168. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  169. Offset - Offset in the config space to be read.
  170. Return Value:
  171. Value read from the specified offset in the config space.
  172. Notes:
  173. --*/
  174. {
  175. ULONG Data;
  176. ULONG slotNumber;
  177. slotNumber = (DevFunc >> 3) & 0x1F;
  178. slotNumber |= ((DevFunc & 0x07) << 5);
  179. //
  180. // Initialize data to invalid values.
  181. //
  182. Data = 0xFFFFFFFF;
  183. //
  184. // Call the HAL to do the actual reading.
  185. //
  186. HalGetBusDataByOffset( PCIConfiguration,
  187. BusNumber,
  188. slotNumber,
  189. &Data,
  190. Offset,
  191. sizeof(Data));
  192. //
  193. // Return data read to the caller.
  194. //
  195. return(Data);
  196. }
  197. VOID
  198. WriteConfigUchar (
  199. IN ULONG BusNumber,
  200. IN ULONG DevFunc,
  201. IN UCHAR Offset,
  202. IN UCHAR Data
  203. )
  204. /*++
  205. Routine Description:
  206. This routine calls the HAL to write to the Pci config space.
  207. Parameters:
  208. BusNumber - Bus number of the Pci device being written to.
  209. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  210. Offset - Offset in the config space to be written.
  211. Data - Value to be written.
  212. Return Value:
  213. None.
  214. Notes:
  215. --*/
  216. {
  217. ULONG slotNumber;
  218. slotNumber = (DevFunc >> 3) & 0x1F;
  219. slotNumber |= ((DevFunc & 0x07) << 5);
  220. //
  221. // Call the HAL to do the actual writing.
  222. //
  223. HalSetBusDataByOffset( PCIConfiguration,
  224. BusNumber,
  225. slotNumber,
  226. &Data,
  227. Offset,
  228. sizeof(Data));
  229. }
  230. VOID
  231. WriteConfigUshort (
  232. IN ULONG BusNumber,
  233. IN ULONG DevFunc,
  234. IN UCHAR Offset,
  235. IN USHORT Data
  236. )
  237. /*++
  238. Routine Description:
  239. This routine calls the HAL to write to the Pci config space.
  240. Parameters:
  241. BusNumber - Bus number of the Pci device being written to.
  242. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  243. Offset - Offset in the config space to be written.
  244. Data - Value to be written.
  245. Return Value:
  246. None.
  247. Notes:
  248. --*/
  249. {
  250. ULONG slotNumber;
  251. slotNumber = (DevFunc >> 3) & 0x1F;
  252. slotNumber |= ((DevFunc & 0x07) << 5);
  253. //
  254. // Call the HAL to do the actual writing.
  255. //
  256. HalSetBusDataByOffset( PCIConfiguration,
  257. BusNumber,
  258. slotNumber,
  259. &Data,
  260. Offset,
  261. sizeof(Data));
  262. }
  263. VOID
  264. WriteConfigUlong (
  265. IN ULONG BusNumber,
  266. IN ULONG DevFunc,
  267. IN UCHAR Offset,
  268. IN ULONG Data
  269. )
  270. /*++
  271. Routine Description:
  272. This routine calls the HAL to write to the Pci config space.
  273. Parameters:
  274. BusNumber - Bus number of the Pci device being written to.
  275. DevFunc - Slot number of the Pci device being read (Dev (7:3), Func(2:0)).
  276. Offset - Offset in the config space to be written.
  277. Data - Value to be written.
  278. Return Value:
  279. None.
  280. Notes:
  281. --*/
  282. {
  283. ULONG slotNumber;
  284. slotNumber = (DevFunc >> 3) & 0x1F;
  285. slotNumber |= ((DevFunc & 0x07) << 5);
  286. //
  287. // Call the HAL to do the actual writing.
  288. //
  289. HalSetBusDataByOffset( PCIConfiguration,
  290. BusNumber,
  291. slotNumber,
  292. &Data,
  293. Offset,
  294. sizeof(Data));
  295. }
  296. UCHAR
  297. GetMinLink (
  298. IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable
  299. )
  300. /*++
  301. Routine Description:
  302. This routine finds and returns the minimum link value in the
  303. given Pci Irq Routing Table.
  304. Parameters:
  305. PciIrqRoutingTable - Pci Irq Routing Table to be processed.
  306. Return Value:
  307. Minimum link value in the table.
  308. Notes:
  309. --*/
  310. {
  311. UCHAR MinLink;
  312. PPIN_INFO PinInfo;
  313. PPIN_INFO LastPin;
  314. PSLOT_INFO SlotInfo;
  315. PSLOT_INFO LastSlot;
  316. //
  317. // Start by setting the maximum link to the maximum possible value.
  318. //
  319. MinLink = 0xFF;
  320. //
  321. // Process all slots in this table.
  322. //
  323. SlotInfo = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + sizeof(PCI_IRQ_ROUTING_TABLE));
  324. LastSlot = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + PciIrqRoutingTable->TableSize);
  325. while (SlotInfo < LastSlot)
  326. {
  327. //
  328. // Process all pins for this slot.
  329. //
  330. PinInfo = &SlotInfo->PinInfo[0];
  331. LastPin = &SlotInfo->PinInfo[NUM_IRQ_PINS];
  332. while (PinInfo < LastPin)
  333. {
  334. //
  335. // Update the min link found so far if the current link is
  336. // valid and smaller.
  337. //
  338. if ( PinInfo->Link &&
  339. PinInfo->Link < MinLink)
  340. {
  341. MinLink = PinInfo->Link;
  342. }
  343. //
  344. // Next link.
  345. //
  346. PinInfo++;
  347. }
  348. //
  349. // Next slot.
  350. //
  351. SlotInfo++;
  352. }
  353. //
  354. // If we failed to find the minimum value, set the minimum to zero.
  355. //
  356. if (MinLink == 0xFF)
  357. MinLink = 0;
  358. //
  359. // Return the minimum link in the table to the caller.
  360. //
  361. return (MinLink);
  362. }
  363. UCHAR
  364. GetMaxLink (
  365. IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable
  366. )
  367. /*++
  368. Routine Description:
  369. This routine finds and returns the maximum link value in the
  370. given Pci Irq Routing Table.
  371. Parameters:
  372. PciIrqRoutingTable - Pci Irq Routing Table to be processed.
  373. Return Value:
  374. Maximum link value in the table.
  375. Notes:
  376. --*/
  377. {
  378. UCHAR MaxLink;
  379. PPIN_INFO PinInfo;
  380. PPIN_INFO LastPin;
  381. PSLOT_INFO SlotInfo;
  382. PSLOT_INFO LastSlot;
  383. //
  384. // Start by setting the maximum link to the smallest possible value.
  385. //
  386. MaxLink = 0;
  387. //
  388. // Process all slots in this table.
  389. //
  390. SlotInfo = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + sizeof(PCI_IRQ_ROUTING_TABLE));
  391. LastSlot = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + PciIrqRoutingTable->TableSize);
  392. while (SlotInfo < LastSlot)
  393. {
  394. //
  395. // Process all pins for this slot.
  396. //
  397. PinInfo = &SlotInfo->PinInfo[0];
  398. LastPin = &SlotInfo->PinInfo[NUM_IRQ_PINS];
  399. while (PinInfo < LastPin)
  400. {
  401. //
  402. // Update the max link found so far if the current link is
  403. // valid and larger.
  404. //
  405. if ( PinInfo->Link &&
  406. PinInfo->Link > MaxLink)
  407. {
  408. MaxLink = PinInfo->Link;
  409. }
  410. //
  411. // Next pin.
  412. //
  413. PinInfo++;
  414. }
  415. //
  416. // Next slot.
  417. //
  418. SlotInfo++;
  419. }
  420. //
  421. // Return the maximum link in the table to the caller.
  422. //
  423. return (MaxLink);
  424. }
  425. #ifdef ALLOC_PRAGMA
  426. #pragma alloc_text(PAGE, NormalizeLinks)
  427. #endif //ALLOC_PRAGMA
  428. VOID
  429. NormalizeLinks (
  430. IN PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable,
  431. IN UCHAR Adjustment
  432. )
  433. /*++
  434. Routine Description:
  435. This routine normalizes all link values in the Pci Irq Routing Table by
  436. adding the adjustment to all the links.
  437. Parameters:
  438. PciIrqRoutingTable - Pci Irq Routing Table to be normalized.
  439. Adjustment - Amount to be added to each link.
  440. Return Value:
  441. None.
  442. Notes:
  443. --*/
  444. {
  445. PPIN_INFO PinInfo;
  446. PPIN_INFO LastPin;
  447. PSLOT_INFO SlotInfo;
  448. PSLOT_INFO LastSlot;
  449. PAGED_CODE();
  450. //
  451. // Process all slots in this table.
  452. //
  453. SlotInfo = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + sizeof(PCI_IRQ_ROUTING_TABLE));
  454. LastSlot = (PSLOT_INFO)((PUCHAR)PciIrqRoutingTable + PciIrqRoutingTable->TableSize);
  455. while (SlotInfo < LastSlot)
  456. {
  457. //
  458. // Process all pins.
  459. //
  460. PinInfo = &SlotInfo->PinInfo[0];
  461. LastPin = &SlotInfo->PinInfo[NUM_IRQ_PINS];
  462. while (PinInfo < LastPin)
  463. {
  464. //
  465. // Only normalize valid link values.
  466. //
  467. if(PinInfo->Link)
  468. {
  469. PinInfo->Link += Adjustment;
  470. }
  471. //
  472. // Next pin.
  473. //
  474. PinInfo++;
  475. }
  476. //
  477. // Next slot.
  478. //
  479. SlotInfo++;
  480. }
  481. }