current_size = A_SIZE_FIX(agp_bridge->current_size);
- pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
- temp &= 0xfff80000;
-
- intel_i810_private.registers = ioremap(temp, 128 * 4096);
if (!intel_i810_private.registers) {
- printk(KERN_ERR PFX "Unable to remap memory.\n");
- return -ENOMEM;
+ pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+ temp &= 0xfff80000;
+
+ intel_i810_private.registers = ioremap(temp, 128 * 4096);
+ if (!intel_i810_private.registers) {
+ printk(KERN_ERR PFX "Unable to remap memory.\n");
+ return -ENOMEM;
+ }
}
if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
int i, j, num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
if (type != 0 || mem->type != 0) {
if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
/* special insert */
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
+
for (i = pg_start; i < (pg_start + mem->page_count); i++) {
writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
- global_cache_flush();
+ readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
+
agp_bridge->driver->tlb_flush(mem);
return 0;
}
}
insert:
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
+
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i810_private.registers+I810_PTE_BASE+(j*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
- global_cache_flush();
+ readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
agp_bridge->driver->tlb_flush(mem);
return 0;
{
int i;
+ if (mem->page_count == 0)
+ return 0;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
+ readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
struct pci_dev *i830_dev; /* device one */
volatile u8 __iomem *registers;
volatile u32 __iomem *gtt; /* I915G */
+ /* gtt_entries is the number of gtt entries that are already mapped
+ * to stolen memory. Stolen memory is larger than the memory mapped
+ * through gtt_entries, as it includes some reserved space for the BIOS
+ * popup and for the GTT.
+ */
int gtt_entries;
} intel_i830_private;
u8 rdct;
int local = 0;
static const int ddt[4] = { 0, 16, 32, 64 };
- int size;
+ int size; /* reserved space (in kb) at the top of stolen memory */
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- /* We obtain the size of the GTT, which is also stored (for some
- * reason) at the top of stolen memory. Then we add 4KB to that
- * for the video BIOS popup, which is also stored in there. */
+ if (IS_I965) {
+ u32 pgetbl_ctl;
+ pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL);
- if (IS_I965)
- size = 512 + 4;
- else
+ /* The 965 has a field telling us the size of the GTT,
+ * which may be larger than what is necessary to map the
+ * aperture.
+ */
+ switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+ case I965_PGETBL_SIZE_128KB:
+ size = 128;
+ break;
+ case I965_PGETBL_SIZE_256KB:
+ size = 256;
+ break;
+ case I965_PGETBL_SIZE_512KB:
+ size = 512;
+ break;
+ default:
+ printk(KERN_INFO PFX "Unknown page table size, "
+ "assuming 512KB\n");
+ size = 512;
+ }
+ size += 4; /* add in BIOS popup space */
+ } else {
+ /* On previous hardware, the GTT size was just what was
+ * required to map the aperture.
+ */
size = agp_bridge->driver->fetch_size() + 4;
+ }
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
int i,j,num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;
- global_cache_flush(); /* FIXME: Necessary ?*/
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i830_private.registers+I810_PTE_BASE+(j*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
+ readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
{
int i;
- global_cache_flush();
+ if (mem->page_count == 0)
+ return 0;
if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
+ readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
int i,j,num_entries;
void *temp;
+ if (mem->page_count == 0)
+ return 0;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;
- global_cache_flush();
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = TRUE;
+ }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type), intel_i830_private.gtt+j);
- readl(intel_i830_private.gtt+j); /* PCI Posting. */
}
+ readl(intel_i830_private.gtt+j-1);
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
{
int i;
- global_cache_flush();
+ if (mem->page_count == 0)
+ return 0;
if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i);
}
+ readl(intel_i830_private.gtt+i-1);
- global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
-static int intel_i915_fetch_size(void)
+/* Return the aperture size by just checking the resource length. The effect
+ * described in the spec of the MSAC registers is just changing of the
+ * resource size.
+ */
+static int intel_i9xx_fetch_size(void)
{
- struct aper_size_info_fixed *values;
- u32 temp, offset;
+ int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
+ int aper_size; /* size in megabytes */
+ int i;
-#define I915_256MB_ADDRESS_MASK (1<<27)
+ aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
+ for (i = 0; i < num_sizes; i++) {
+ if (aper_size == intel_i830_sizes[i].size) {
+ agp_bridge->current_size = intel_i830_sizes + i;
+ agp_bridge->previous_size = agp_bridge->current_size;
+ return aper_size;
+ }
+ }
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
- if (temp & I915_256MB_ADDRESS_MASK)
- offset = 0; /* 128MB aperture */
- else
- offset = 2; /* 256MB aperture */
- agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
- return values[offset].size;
+ return 0;
}
/* The intel i915 automatically initializes the agp aperture during POST.
return 0;
}
-static int intel_i965_fetch_size(void)
-{
- struct aper_size_info_fixed *values;
- u32 offset = 0;
- u8 temp;
-
-#define I965_512MB_ADDRESS_MASK (3<<1)
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
- temp &= I965_512MB_ADDRESS_MASK;
- switch (temp) {
- case 0x00:
- offset = 0; /* 128MB */
- break;
- case 0x06:
- offset = 3; /* 512MB */
- break;
- default:
- case 0x02:
- offset = 2; /* 256MB */
- break;
- }
-
- agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
-
- return values[offset].size;
+
+/*
+ * The i965 supports 36-bit physical addresses, but to keep
+ * the format of the GTT the same, the bits that don't fit
+ * in a 32-bit word are shifted down to bits 4..7.
+ *
+ * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
+ * is always zero on 32-bit architectures, so no need to make
+ * this conditional.
+ */
+static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
+{
+ /* Shift high bits down */
+ addr |= (addr >> 28) & 0xf0;
+
+ /* Type checking must be done elsewhere */
+ return addr | bridge->driver->masks[type].mask;
}
/* The intel i965 automatically initializes the agp aperture during POST.
-+ * Use the memory already set aside for in the GTT.
-+ */
+ * Use the memory already set aside for in the GTT.
+ */
static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
.num_aperture_sizes = 4,
.needs_scratch_page = TRUE,
.configure = intel_i915_configure,
- .fetch_size = intel_i915_fetch_size,
+ .fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.tlb_flush = intel_i810_tlbflush,
.mask_memory = intel_i810_mask_memory,
.num_aperture_sizes = 4,
.needs_scratch_page = TRUE,
.configure = intel_i915_configure,
- .fetch_size = intel_i965_fetch_size,
+ .fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
+ .mask_memory = intel_i965_mask_memory,
.masks = intel_i810_masks,
.agp_enable = intel_i810_agp_enable,
.cache_flush = global_cache_flush,
pci_restore_state(pdev);
+ /* We should restore our graphics device's config space,
+ * as host bridge (00:00) resumes before graphics device (02:00),
+ * then our access to its pci space can work right.
+ */
+ if (intel_i810_private.i810_dev)
+ pci_restore_state(intel_i810_private.i810_dev);
+ if (intel_i830_private.i830_dev)
+ pci_restore_state(intel_i830_private.i830_dev);
+
if (bridge->driver == &intel_generic_driver)
intel_configure();
else if (bridge->driver == &intel_850_driver)