|
@@ -24,6 +24,9 @@
|
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)
|
|
|
|
|
|
|
|
|
+extern int agp_memory_reserved;
|
|
|
+
|
|
|
+
|
|
|
/* Intel 815 register */
|
|
|
#define INTEL_815_APCONT 0x51
|
|
|
#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
|
|
@@ -68,12 +71,15 @@ static struct aper_size_info_fixed intel_i810_sizes[] =
|
|
|
|
|
|
#define AGP_DCACHE_MEMORY 1
|
|
|
#define AGP_PHYS_MEMORY 2
|
|
|
+#define INTEL_AGP_CACHED_MEMORY 3
|
|
|
|
|
|
static struct gatt_mask intel_i810_masks[] =
|
|
|
{
|
|
|
{.mask = I810_PTE_VALID, .type = 0},
|
|
|
{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
|
|
|
- {.mask = I810_PTE_VALID, .type = 0}
|
|
|
+ {.mask = I810_PTE_VALID, .type = 0},
|
|
|
+ {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
|
|
|
+ .type = INTEL_AGP_CACHED_MEMORY}
|
|
|
};
|
|
|
|
|
|
static struct _intel_i810_private {
|
|
@@ -82,6 +88,7 @@ static struct _intel_i810_private {
|
|
|
int num_dcache_entries;
|
|
|
} intel_i810_private;
|
|
|
|
|
|
+
|
|
|
static int intel_i810_fetch_size(void)
|
|
|
{
|
|
|
u32 smram_miscc;
|
|
@@ -201,62 +208,79 @@ static void i8xx_destroy_pages(void *addr)
|
|
|
atomic_dec(&agp_bridge->current_memory_agp);
|
|
|
}
|
|
|
|
|
|
+static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
|
|
|
+ int type)
|
|
|
+{
|
|
|
+ if (type < AGP_USER_TYPES)
|
|
|
+ return type;
|
|
|
+ else if (type == AGP_USER_CACHED_MEMORY)
|
|
|
+ return INTEL_AGP_CACHED_MEMORY;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
|
|
|
int type)
|
|
|
{
|
|
|
int i, j, num_entries;
|
|
|
void *temp;
|
|
|
+ int ret = -EINVAL;
|
|
|
+ int mask_type;
|
|
|
|
|
|
if (mem->page_count == 0)
|
|
|
- return 0;
|
|
|
+ goto out;
|
|
|
|
|
|
temp = agp_bridge->current_size;
|
|
|
num_entries = A_SIZE_FIX(temp)->num_entries;
|
|
|
|
|
|
if ((pg_start + mem->page_count) > num_entries)
|
|
|
- return -EINVAL;
|
|
|
+ goto out_err;
|
|
|
|
|
|
- for (j = pg_start; j < (pg_start + mem->page_count); j++) {
|
|
|
- if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
|
|
|
- if (type != 0 || mem->type != 0) {
|
|
|
- if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
|
|
|
- /* special insert */
|
|
|
- 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-1)*4)); /* PCI Posting. */
|
|
|
-
|
|
|
- agp_bridge->driver->tlb_flush(mem);
|
|
|
- return 0;
|
|
|
+ for (j = pg_start; j < (pg_start + mem->page_count); j++) {
|
|
|
+ if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
|
|
|
+ ret = -EBUSY;
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
- if ((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
|
|
|
- goto insert;
|
|
|
- return -EINVAL;
|
|
|
}
|
|
|
|
|
|
-insert:
|
|
|
- if (!mem->is_flushed) {
|
|
|
- global_cache_flush();
|
|
|
- mem->is_flushed = TRUE;
|
|
|
- }
|
|
|
+ if (type != mem->type)
|
|
|
+ goto out_err;
|
|
|
|
|
|
- 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));
|
|
|
+ mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
|
|
|
+
|
|
|
+ switch (mask_type) {
|
|
|
+ case AGP_DCACHE_MEMORY:
|
|
|
+ if (!mem->is_flushed)
|
|
|
+ global_cache_flush();
|
|
|
+ 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-1)*4));
|
|
|
+ break;
|
|
|
+ case AGP_PHYS_MEMORY:
|
|
|
+ case AGP_NORMAL_MEMORY:
|
|
|
+ if (!mem->is_flushed)
|
|
|
+ global_cache_flush();
|
|
|
+ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
|
|
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
|
|
|
+ mem->memory[i],
|
|
|
+ mask_type),
|
|
|
+ intel_i810_private.registers+I810_PTE_BASE+(j*4));
|
|
|
+ }
|
|
|
+ readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
- readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
|
|
|
|
|
|
agp_bridge->driver->tlb_flush(mem);
|
|
|
- return 0;
|
|
|
+out:
|
|
|
+ ret = 0;
|
|
|
+out_err:
|
|
|
+ mem->is_flushed = 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
|
|
@@ -337,12 +361,11 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
|
|
|
new->type = AGP_DCACHE_MEMORY;
|
|
|
new->page_count = pg_count;
|
|
|
new->num_scratch_pages = 0;
|
|
|
- vfree(new->memory);
|
|
|
+ agp_free_page_array(new);
|
|
|
return new;
|
|
|
}
|
|
|
if (type == AGP_PHYS_MEMORY)
|
|
|
return alloc_agpphysmem_i8xx(pg_count, type);
|
|
|
-
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
@@ -357,7 +380,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
|
|
|
gart_to_virt(curr->memory[0]));
|
|
|
global_flush_tlb();
|
|
|
}
|
|
|
- vfree(curr->memory);
|
|
|
+ agp_free_page_array(curr);
|
|
|
}
|
|
|
kfree(curr);
|
|
|
}
|
|
@@ -619,9 +642,11 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
|
|
|
{
|
|
|
int i,j,num_entries;
|
|
|
void *temp;
|
|
|
+ int ret = -EINVAL;
|
|
|
+ int mask_type;
|
|
|
|
|
|
if (mem->page_count == 0)
|
|
|
- return 0;
|
|
|
+ goto out;
|
|
|
|
|
|
temp = agp_bridge->current_size;
|
|
|
num_entries = A_SIZE_FIX(temp)->num_entries;
|
|
@@ -631,34 +656,41 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
|
|
|
pg_start,intel_i830_private.gtt_entries);
|
|
|
|
|
|
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
|
|
|
- return -EINVAL;
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
|
|
|
if ((pg_start + mem->page_count) > num_entries)
|
|
|
- return -EINVAL;
|
|
|
+ goto out_err;
|
|
|
|
|
|
/* The i830 can't check the GTT for entries since its read only,
|
|
|
* depend on the caller to make the correct offset decisions.
|
|
|
*/
|
|
|
|
|
|
- if ((type != 0 && type != AGP_PHYS_MEMORY) ||
|
|
|
- (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
|
|
|
- return -EINVAL;
|
|
|
+ if (type != mem->type)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
|
|
|
|
|
|
- if (!mem->is_flushed) {
|
|
|
+ if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
|
|
|
+ mask_type != INTEL_AGP_CACHED_MEMORY)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ 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));
|
|
|
+ mem->memory[i], mask_type),
|
|
|
+ intel_i830_private.registers+I810_PTE_BASE+(j*4));
|
|
|
}
|
|
|
readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
|
|
|
-
|
|
|
agp_bridge->driver->tlb_flush(mem);
|
|
|
- return 0;
|
|
|
+
|
|
|
+out:
|
|
|
+ ret = 0;
|
|
|
+out_err:
|
|
|
+ mem->is_flushed = 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
|
|
@@ -687,7 +719,6 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
|
|
|
{
|
|
|
if (type == AGP_PHYS_MEMORY)
|
|
|
return alloc_agpphysmem_i8xx(pg_count, type);
|
|
|
-
|
|
|
/* always return NULL for other allocation types for now */
|
|
|
return NULL;
|
|
|
}
|
|
@@ -734,9 +765,11 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
|
|
|
{
|
|
|
int i,j,num_entries;
|
|
|
void *temp;
|
|
|
+ int ret = -EINVAL;
|
|
|
+ int mask_type;
|
|
|
|
|
|
if (mem->page_count == 0)
|
|
|
- return 0;
|
|
|
+ goto out;
|
|
|
|
|
|
temp = agp_bridge->current_size;
|
|
|
num_entries = A_SIZE_FIX(temp)->num_entries;
|
|
@@ -746,33 +779,41 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
|
|
|
pg_start,intel_i830_private.gtt_entries);
|
|
|
|
|
|
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
|
|
|
- return -EINVAL;
|
|
|
+ goto out_err;
|
|
|
}
|
|
|
|
|
|
if ((pg_start + mem->page_count) > num_entries)
|
|
|
- return -EINVAL;
|
|
|
+ goto out_err;
|
|
|
|
|
|
- /* The i830 can't check the GTT for entries since its read only,
|
|
|
+ /* The i915 can't check the GTT for entries since its read only,
|
|
|
* depend on the caller to make the correct offset decisions.
|
|
|
*/
|
|
|
|
|
|
- if ((type != 0 && type != AGP_PHYS_MEMORY) ||
|
|
|
- (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
|
|
|
- return -EINVAL;
|
|
|
+ if (type != mem->type)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
|
|
|
|
|
|
- if (!mem->is_flushed) {
|
|
|
+ if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
|
|
|
+ mask_type != INTEL_AGP_CACHED_MEMORY)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ mem->memory[i], mask_type), intel_i830_private.gtt+j);
|
|
|
}
|
|
|
- readl(intel_i830_private.gtt+j-1);
|
|
|
|
|
|
+ readl(intel_i830_private.gtt+j-1);
|
|
|
agp_bridge->driver->tlb_flush(mem);
|
|
|
- return 0;
|
|
|
+
|
|
|
+ out:
|
|
|
+ ret = 0;
|
|
|
+ out_err:
|
|
|
+ mem->is_flushed = 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
|
|
@@ -1384,6 +1425,7 @@ static struct agp_bridge_driver intel_generic_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_810_driver = {
|
|
@@ -1408,6 +1450,7 @@ static struct agp_bridge_driver intel_810_driver = {
|
|
|
.free_by_type = intel_i810_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_815_driver = {
|
|
@@ -1431,6 +1474,7 @@ static struct agp_bridge_driver intel_815_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_830_driver = {
|
|
@@ -1455,6 +1499,7 @@ static struct agp_bridge_driver intel_830_driver = {
|
|
|
.free_by_type = intel_i810_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_820_driver = {
|
|
@@ -1478,6 +1523,7 @@ static struct agp_bridge_driver intel_820_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_830mp_driver = {
|
|
@@ -1501,6 +1547,7 @@ static struct agp_bridge_driver intel_830mp_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_840_driver = {
|
|
@@ -1524,6 +1571,7 @@ static struct agp_bridge_driver intel_840_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_845_driver = {
|
|
@@ -1547,6 +1595,7 @@ static struct agp_bridge_driver intel_845_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_850_driver = {
|
|
@@ -1570,6 +1619,7 @@ static struct agp_bridge_driver intel_850_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_860_driver = {
|
|
@@ -1593,6 +1643,7 @@ static struct agp_bridge_driver intel_860_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_915_driver = {
|
|
@@ -1617,6 +1668,7 @@ static struct agp_bridge_driver intel_915_driver = {
|
|
|
.free_by_type = intel_i810_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_i965_driver = {
|
|
@@ -1641,6 +1693,7 @@ static struct agp_bridge_driver intel_i965_driver = {
|
|
|
.free_by_type = intel_i810_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static struct agp_bridge_driver intel_7505_driver = {
|
|
@@ -1664,6 +1717,7 @@ static struct agp_bridge_driver intel_7505_driver = {
|
|
|
.free_by_type = agp_generic_free_by_type,
|
|
|
.agp_alloc_page = agp_generic_alloc_page,
|
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
|
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
|
};
|
|
|
|
|
|
static int find_i810(u16 device)
|