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; }
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; }
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; }
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; }
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; }
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; }
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; }