static int ati_create_gatt_table(struct agp_bridge_data *bridge) { struct aper_size_info_lvl2 *value; ati_page_map page_dir; unsigned long addr; int retval; u32 temp; int i; struct aper_size_info_lvl2 *current_size; value = A_SIZE_LVL2(agp_bridge->current_size); retval = ati_create_page_map(&page_dir); if (retval != 0) return retval; retval = ati_create_gatt_pages(value->num_entries / 1024); if (retval != 0) { ati_free_page_map(&page_dir); return retval; } agp_bridge->gatt_table_real = (u32 *)page_dir.real; agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Write out the size register */ current_size = A_SIZE_LVL2(agp_bridge->current_size); if (is_r200()) { pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); temp = (((temp & ~(0x0000000e)) | current_size->size_value) | 0x00000001); pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp); pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); } else { pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); temp = (((temp & ~(0x0000000e)) | current_size->size_value) | 0x00000001); pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp); pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); } /* * Get the address for the gart region. * This is a bus address even on the alpha, b/c its * used to program the agp master not the cpu */ pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); agp_bridge->gart_bus_addr = addr; /* Calculate the agp offset */ for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1, page_dir.remapped+GET_PAGE_DIR_OFF(addr)); readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ } return 0; }
static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) { struct aper_size_info_lvl2 *value; struct serverworks_page_map page_dir; int retval; u32 temp; int i; value = A_SIZE_LVL2(agp_bridge->current_size); retval = serverworks_create_page_map(&page_dir); if (retval != 0) { return retval; } retval = serverworks_create_page_map(&serverworks_private.scratch_dir); if (retval != 0) { serverworks_free_page_map(&page_dir); return retval; } /* Create a fake scratch directory */ for(i = 0; i < 1024; i++) { writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); } retval = serverworks_create_gatt_pages(value->num_entries / 1024); if (retval != 0) { serverworks_free_page_map(&page_dir); serverworks_free_page_map(&serverworks_private.scratch_dir); return retval; } agp_bridge->gatt_table_real = (u32 *)page_dir.real; agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Get the address for the gart region. * This is a bus address even on the alpha, b/c its * used to program the agp master not the cpu */ pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp); agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); /* Calculate the agp offset */ for(i = 0; i < value->num_entries / 1024; i++) writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; }
static int amd_create_page_map(struct amd_page_map *page_map) { int i; page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); if (page_map->real == NULL) return -ENOMEM; #ifndef CONFIG_X86 SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); free_page((unsigned long) page_map->real); page_map->real = NULL; return -ENOMEM; } global_cache_flush(); #else set_memory_uc((unsigned long)page_map->real, 1); page_map->remapped = page_map->real; #endif for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); readl(page_map->remapped+i); /* PCI Posting. */ } return 0; }
static int serverworks_create_page_map(struct serverworks_page_map *page_map) { int i; page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); if (page_map->real == NULL) { return -ENOMEM; } SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); free_page((unsigned long) page_map->real); page_map->real = NULL; return -ENOMEM; } global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) writel(agp_bridge->scratch_page, page_map->remapped+i); return 0; }
static int ati_create_page_map(ati_page_map *page_map) { int i, err = 0; page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); if (page_map->real == NULL) return -ENOMEM; SetPageReserved(virt_to_page(page_map->real)); err = map_page_into_agp(virt_to_page(page_map->real)); page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL || err) { ClearPageReserved(virt_to_page(page_map->real)); free_page((unsigned long) page_map->real); page_map->real = NULL; return -ENOMEM; } /*CACHE_FLUSH();*/ global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); readl(page_map->remapped+i); /* PCI Posting. */ } return 0; }
static int i460_alloc_large_page (struct lp_desc *lp) { unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT; size_t map_size; void *lpage; lpage = (void *) __get_free_pages(GFP_KERNEL, order); if (!lpage) { printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); return -ENOMEM; } map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8; lp->alloced_map = kzalloc(map_size, GFP_KERNEL); if (!lp->alloced_map) { free_pages((unsigned long) lpage, order); printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); return -ENOMEM; } lp->paddr = virt_to_gart(lpage); lp->refcount = 0; atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); return 0; }
static int amd_8151_configure(void) { unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); int i; /* Configure AGP regs in each x86-64 host bridge. */ for (i = 0; i < num_k8_northbridges; i++) { agp_bridge->gart_bus_addr = amd64_configure(k8_northbridges[i], gatt_bus); } k8_flush_garts(); return 0; }
static int hp_zx1_configure (void) { struct _hp_private *hp = &hp_private; agp_bridge->gart_bus_addr = hp->gart_base; agp_bridge->capndx = hp->lba_cap_offset; agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); if (hp->io_pdir_owner) { writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); readl(hp->ioc_regs+HP_ZX1_TCNFG); writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); readl(hp->ioc_regs+HP_ZX1_IMASK); writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); readl(hp->ioc_regs+HP_ZX1_IBASE); writel(hp->iova_base|ilog2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM); readl(hp->ioc_regs+HP_ZX1_PCOM); } return 0; }
static int agp_backend_initialize(struct agp_bridge_data *bridge) { int size_value, rc, got_gatt=0, got_keylist=0; bridge->max_memory_agp = agp_find_max(); bridge->version = &agp_current_version; if (bridge->driver->needs_scratch_page) { void *addr = bridge->driver->agp_alloc_page(bridge); if (!addr) { printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); return -ENOMEM; } bridge->scratch_page_real = virt_to_gart(addr); bridge->scratch_page = bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0); } size_value = bridge->driver->fetch_size(); if (size_value == 0) { printk(KERN_ERR PFX "unable to determine aperture size.\n"); rc = -EINVAL; goto err_out; } if (bridge->driver->create_gatt_table(bridge)) { printk(KERN_ERR PFX "unable to get memory for graphics translation table.\n"); rc = -ENOMEM; goto err_out; } got_gatt = 1; bridge->key_list = vmalloc(PAGE_SIZE * 4); if (bridge->key_list == NULL) { printk(KERN_ERR PFX "error allocating memory for key lists.\n"); rc = -ENOMEM; goto err_out; } got_keylist = 1; /* FIXME vmalloc'd memory not guaranteed contiguous */ memset(bridge->key_list, 0, PAGE_SIZE * 4); if (bridge->driver->configure()) { printk(KERN_ERR PFX "error configuring host chipset.\n"); rc = -EINVAL; goto err_out; } return 0; err_out: if (bridge->driver->needs_scratch_page) bridge->driver->agp_destroy_page( gart_to_virt(bridge->scratch_page_real)); if (got_gatt) bridge->driver->free_gatt_table(bridge); if (got_keylist) { vfree(bridge->key_list); bridge->key_list = NULL; } return rc; }