示例#1
0
static int i460_insert_memory_large_io_page (struct agp_memory *mem,
				off_t pg_start, int type)
{
	int i, start_offset, end_offset, idx, pg, num_entries;
	struct lp_desc *start, *end, *lp;
	void *temp;

	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
		return -EINVAL;

	temp = agp_bridge->current_size;
	num_entries = A_SIZE_8(temp)->num_entries;

	/* Figure out what pg_start means in terms of our large GART pages */
	start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
	end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
	start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
	end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;

	if (end > i460.lp_desc + num_entries) {
		printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
		return -EINVAL;
	}

	/* Check if the requested region of the aperture is free */
	for (lp = start; lp <= end; ++lp) {
		if (!lp->alloced_map)
			continue;	/* OK, the entire large page is available... */

		for (idx = ((lp == start) ? start_offset : 0);
		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
		     idx++)
		{
			if (test_bit(idx, lp->alloced_map))
				return -EBUSY;
		}
	}

	for (lp = start, i = 0; lp <= end; ++lp) {
		if (!lp->alloced_map) {
			/* Allocate new GART pages... */
			if (i460_alloc_large_page(lp) < 0)
				return -ENOMEM;
			pg = lp - i460.lp_desc;
			WR_GATT(pg, i460_mask_memory(agp_bridge,
						     lp->paddr, 0));
			WR_FLUSH_GATT(pg);
		}

		for (idx = ((lp == start) ? start_offset : 0);
		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
		     idx++, i++)
		{
			mem->pages[i] = lp->page;
			__set_bit(idx, lp->alloced_map);
			++lp->refcount;
		}
	}
	return 0;
}
示例#2
0
static int i460_create_gatt_table (struct agp_bridge_data *bridge)
{
	int page_order, num_entries, i;
	void *temp;

	/*
	 * Load up the fixed address of the GART SRAMS which hold our GATT table.
	 */
	temp = agp_bridge->current_size;
	page_order = A_SIZE_8(temp)->page_order;
	num_entries = A_SIZE_8(temp)->num_entries;

	i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
	if (!i460.gatt) {
		printk(KERN_ERR PFX "ioremap failed\n");
		return -ENOMEM;
	}

	/* These are no good, the should be removed from the agp_bridge strucure... */
	agp_bridge->gatt_table_real = NULL;
	agp_bridge->gatt_table = NULL;
	agp_bridge->gatt_bus_addr = 0;

	for (i = 0; i < num_entries; ++i)
		WR_GATT(i, 0);
	WR_FLUSH_GATT(i - 1);
	return 0;
}
示例#3
0
static int i460_create_gatt_table (struct agp_bridge_data *bridge)
{
	int page_order, num_entries, i;
	void *temp;

	
	temp = agp_bridge->current_size;
	page_order = A_SIZE_8(temp)->page_order;
	num_entries = A_SIZE_8(temp)->num_entries;

	i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
	if (!i460.gatt) {
		printk(KERN_ERR PFX "ioremap failed\n");
		return -ENOMEM;
	}

	
	agp_bridge->gatt_table_real = NULL;
	agp_bridge->gatt_table = NULL;
	agp_bridge->gatt_bus_addr = 0;

	for (i = 0; i < num_entries; ++i)
		WR_GATT(i, 0);
	WR_FLUSH_GATT(i - 1);
	return 0;
}
示例#4
0
static int i460_remove_memory_small_io_page(struct agp_memory *mem,
				off_t pg_start, int type)
{
	int i;

	pr_debug("i460_remove_memory_small_io_page(mem=%p, pg_start=%ld, type=%d)\n",
		 mem, pg_start, type);

	pg_start = I460_IOPAGES_PER_KPAGE * pg_start;

	for (i = pg_start; i < (pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count); i++)
		WR_GATT(i, 0);
	WR_FLUSH_GATT(i - 1);
	return 0;
}
示例#5
0
static int i460_free_gatt_table (struct agp_bridge_data *bridge)
{
	int num_entries, i;
	void *temp;

	temp = agp_bridge->current_size;

	num_entries = A_SIZE_8(temp)->num_entries;

	for (i = 0; i < num_entries; ++i)
		WR_GATT(i, 0);
	WR_FLUSH_GATT(num_entries - 1);

	iounmap(i460.gatt);
	return 0;
}
示例#6
0
static int i460_insert_memory_small_io_page (struct agp_memory *mem,
				off_t pg_start, int type)
{
	unsigned long paddr, io_pg_start, io_page_size;
	int i, j, k, num_entries;
	void *temp;

	pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
		 mem, pg_start, type, mem->memory[0]);

	if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
		return -EINVAL;

	io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;

	temp = agp_bridge->current_size;
	num_entries = A_SIZE_8(temp)->num_entries;

	if ((io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count) > num_entries) {
		printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
		return -EINVAL;
	}

	j = io_pg_start;
	while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) {
		if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) {
			pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n",
				 j, RD_GATT(j));
			return -EBUSY;
		}
		j++;
	}

	io_page_size = 1UL << I460_IO_PAGE_SHIFT;
	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
		paddr = mem->memory[i];
		for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
			WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
				paddr, mem->type));
	}
	WR_FLUSH_GATT(j - 1);
	return 0;
}
示例#7
0
static int i460_remove_memory_large_io_page (struct agp_memory *mem,
				off_t pg_start, int type)
{
	int i, pg, start_offset, end_offset, idx, num_entries;
	struct lp_desc *start, *end, *lp;
	void *temp;

	temp = agp_bridge->current_size;
	num_entries = A_SIZE_8(temp)->num_entries;

	/* Figure out what pg_start means in terms of our large GART pages */
	start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
	end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
	start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
	end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;

	for (i = 0, lp = start; lp <= end; ++lp) {
		for (idx = ((lp == start) ? start_offset : 0);
		     idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
		     idx++, i++)
		{
			mem->pages[i] = NULL;
			__clear_bit(idx, lp->alloced_map);
			--lp->refcount;
		}

		/* Free GART pages if they are unused */
		if (lp->refcount == 0) {
			pg = lp - i460.lp_desc;
			WR_GATT(pg, 0);
			WR_FLUSH_GATT(pg);
			i460_free_large_page(lp);
		}
	}
	return 0;
}