aperture.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * Firmware replacement code.
  3.  * 
  4.  * Work around broken BIOSes that don't set an aperture. 
  5.  * The IOMMU code needs an aperture even who no AGP is present in the system.
  6.  * Map the aperture over some low memory.  This is cheaper than doing bounce 
  7.  * buffering. The memory is lost. This is done at early boot because only
  8.  * the bootmem allocator can allocate 32+MB. 
  9.  * 
  10.  * Copyright 2002 Andi Kleen, SuSE Labs.
  11.  * $Id: aperture.c,v 1.2 2002/09/19 19:25:32 ak Exp $
  12.  */
  13. #include <linux/config.h>
  14. #include <linux/kernel.h>
  15. #include <linux/types.h>
  16. #include <linux/init.h>
  17. #include <linux/bootmem.h>
  18. #include <linux/mmzone.h>
  19. #include <linux/pci_ids.h>
  20. #include <asm/e820.h>
  21. #include <asm/io.h>
  22. #include <asm/proto.h>
  23. #include <asm/pci-direct.h>
  24. int fallback_aper_order __initdata = 1; /* 64MB */
  25. int fallback_aper_force __initdata = 0; 
  26. extern int no_iommu, force_mmu;
  27. /* This code runs before the PCI subsystem is initialized, so just 
  28.    access the northbridge directly. */
  29. #define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
  30. static u32 __init allocate_aperture(void) 
  31. {
  32. #ifdef CONFIG_DISCONTIGMEM
  33. pg_data_t *nd0 = NODE_DATA(0);
  34. #else
  35. pg_data_t *nd0 = &contig_page_data;
  36. #endif
  37. u32 aper_size;
  38. void *p; 
  39. if (fallback_aper_order > 7) 
  40. fallback_aper_order = 7; 
  41. aper_size = (32 * 1024 * 1024) << fallback_aper_order; 
  42. /* 
  43.          * Aperture has to be naturally aligned it seems. This means an
  44.  * 2GB aperture won't have much changes to succeed in the lower 4GB of 
  45.  * memory. Unfortunately we cannot move it up because that would make
  46.  * the IOMMU useless.
  47.  */
  48. p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0); 
  49. if (!p || __pa(p)+aper_size > 0xffffffff) {
  50. printk("Cannot allocate aperture memory hole (%p,%uK)n",
  51.        p, aper_size>>10);
  52. if (p)
  53. free_bootmem_generic((unsigned long)p, aper_size); 
  54. return 0;
  55. }
  56. printk("Mapping aperture over %d KB of RAM @ %lxn",  
  57.        aper_size >> 10, __pa(p)); 
  58. return (u32)__pa(p); 
  59. }
  60. void __init iommu_hole_init(void) 
  61. int fix, num; 
  62. u32 aper_size, aper_alloc, aper_order;
  63. u64 aper_base; 
  64. if (no_iommu)
  65. return;
  66. if (end_pfn < (0xffffffff>>PAGE_SHIFT) && !force_mmu) 
  67. return;
  68. printk("Checking aperture...n"); 
  69. fix = 0;
  70. for (num = 24; num < 32; num++) {
  71. if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
  72. continue;
  73. aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 
  74. aper_size = (32 * 1024 * 1024) << aper_order; 
  75. aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
  76. aper_base <<= 25; 
  77. printk("CPU %d: aperture @ %Lx size %u KBn", num-24, 
  78.        aper_base, aper_size>>10);
  79. if (!aper_base || aper_base + aper_size >= 0xffffffff) {
  80. fix = 1; 
  81. break; 
  82. if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {  
  83. printk("Aperture pointing to e820 RAM. Ignoring.n");
  84. fix = 1; 
  85. break; 
  86. if (!fix && !fallback_aper_force) 
  87. return; 
  88. printk("Your BIOS is broken and doesn't leave a aperture memory holen");
  89. aper_alloc = allocate_aperture(); 
  90. if (!aper_alloc) 
  91. return; 
  92. for (num = 24; num < 32; num++) { 
  93. if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
  94. continue;
  95. /* Don't enable translation yet. That is done later. 
  96.    Assume this BIOS didn't initialise the GART so 
  97.    just overwrite all previous bits */ 
  98. write_pci_config(0, num, 3, 0x90, fallback_aper_order<<1); 
  99. write_pci_config(0, num, 3, 0x94, aper_alloc>>25);