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.

726 lines
14 KiB

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