/*
* Intel(R) 855GM/852GM and 865G support added by David Dawes
* <dawes@tungstengraphics.com>.
- *
- * Intel(R) 915G support added by Alan Hourihane
- * <alanh@tungstengraphics.com>.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include <linux/pagemap.h>
#include <linux/agp_backend.h>
#include "agp.h"
#define INTEL_I850_MCHCFG 0x50
#define INTEL_I850_ERRSTS 0xc8
-/* intel 915G registers */
-#define I915_GMADDR 0x18
-#define I915_MMADDR 0x10
-#define I915_PTEADDR 0x1C
-#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
-#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
-
-
/* Intel 7505 registers */
#define INTEL_I7505_APSIZE 0x74
#define INTEL_I7505_NCAPID 0x60
return;
}
-/* Exists to support ARGB cursors */
-static void *i8xx_alloc_pages(void)
-{
- struct page * page;
-
- page = alloc_pages(GFP_KERNEL, 2);
- if (page == NULL) {
- return 0;
- }
- if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
- __free_page(page);
- return 0;
- }
- get_page(page);
- SetPageLocked(page);
- atomic_inc(&agp_bridge->current_memory_agp);
- return page_address(page);
-}
-
-static void i8xx_destroy_pages(void *addr)
-{
- struct page *page;
-
- if (addr == NULL)
- return;
-
- page = virt_to_page(addr);
- change_page_attr(page, 4, PAGE_KERNEL);
- put_page(page);
- unlock_page(page);
- free_pages((unsigned long)addr, 2);
- atomic_dec(&agp_bridge->current_memory_agp);
-}
-
static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
int type)
{
struct agp_memory *new;
void *addr;
- if (pg_count != 1 && pg_count != 4)
+ if (pg_count != 1)
return NULL;
- switch (pg_count) {
- case 1: addr = agp_bridge->driver->agp_alloc_page();
- break;
- case 4:
- /* kludge to get 4 physical pages for ARGB cursor */
- addr = i8xx_alloc_pages();
- break;
- default:
- return NULL;
- }
-
+ addr = agp_bridge->driver->agp_alloc_page();
if (addr == NULL)
return NULL;
- new = agp_create_memory(pg_count);
+ new = agp_create_memory(1);
if (new == NULL)
return NULL;
- new->memory[0] = virt_to_phys(addr);
- if (pg_count == 4) {
- /* kludge to get 4 physical pages for ARGB cursor */
- new->memory[1] = new->memory[0] + PAGE_SIZE;
- new->memory[2] = new->memory[1] + PAGE_SIZE;
- new->memory[3] = new->memory[2] + PAGE_SIZE;
- }
- new->page_count = pg_count;
- new->num_scratch_pages = pg_count;
+ new->memory[0] = agp_bridge->driver->mask_memory(virt_to_phys(addr), type);
+ new->page_count = 1;
+ new->num_scratch_pages = 1;
new->type = AGP_PHYS_MEMORY;
new->physical = new->memory[0];
return new;
{
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
- if (curr->page_count == 4)
- i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
- else
- agp_bridge->driver->agp_destroy_page(
- phys_to_virt(curr->memory[0]));
+ agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
{
{128, 32768, 5},
/* The 64M mode still requires a 128k gatt */
- {64, 16384, 5},
- {256, 65536, 6},
+ {64, 16384, 5}
};
static struct _intel_i830_private {
struct pci_dev *i830_dev; /* device one */
volatile u8 *registers;
- volatile u32 *gtt; /* I915G */
int gtt_entries;
} intel_i830_private;
u8 rdct;
int local = 0;
static const int ddt[4] = { 0, 16, 32, 64 };
- int size;
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. */
- 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) {
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I830_GMCH_GMS_STOLEN_512:
- gtt_entries = KB(512) - KB(size);
+ gtt_entries = KB(512) - KB(132);
break;
case I830_GMCH_GMS_STOLEN_1024:
- gtt_entries = MB(1) - KB(size);
+ gtt_entries = MB(1) - KB(132);
break;
case I830_GMCH_GMS_STOLEN_8192:
- gtt_entries = MB(8) - KB(size);
+ gtt_entries = MB(8) - KB(132);
break;
case I830_GMCH_GMS_LOCAL:
rdct = INREG8(intel_i830_private.registers,
} else {
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
- gtt_entries = MB(1) - KB(size);
+ gtt_entries = MB(1) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_4M:
- gtt_entries = MB(4) - KB(size);
+ gtt_entries = MB(4) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_8M:
- gtt_entries = MB(8) - KB(size);
+ gtt_entries = MB(8) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_16M:
- gtt_entries = MB(16) - KB(size);
+ gtt_entries = MB(16) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_32M:
- gtt_entries = MB(32) - KB(size);
- break;
- case I915_GMCH_GMS_STOLEN_48M:
- /* Check it's really I915G */
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB)
- gtt_entries = MB(48) - KB(size);
- else
- gtt_entries = 0;
+ gtt_entries = MB(32) - KB(132);
break;
- case I915_GMCH_GMS_STOLEN_64M:
- /* Check it's really I915G */
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB)
- gtt_entries = MB(64) - KB(size);
- else
- gtt_entries = 0;
default:
gtt_entries = 0;
break;
agp_bridge->aperture_size_idx = 0;
return(values[0].size);
} else {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
+ agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
agp_bridge->aperture_size_idx = 1;
return(values[1].size);
}
return(NULL);
}
-static int intel_i915_configure(void)
-{
- struct aper_size_info_fixed *current_size;
- u32 temp;
- u16 gmch_ctrl;
- int i;
-
- current_size = A_SIZE_FIX(agp_bridge->current_size);
-
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
-
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- gmch_ctrl |= I830_GMCH_ENABLED;
- pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
-
- OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED);
- global_cache_flush();
-
- if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++)
- OUTREG32(intel_i830_private.gtt, i, agp_bridge->scratch_page);
- }
-
- return (0);
-}
-
-static void intel_i915_cleanup(void)
-{
- iounmap((void *) intel_i830_private.gtt);
- iounmap((void *) intel_i830_private.registers);
-}
-
-static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i,j,num_entries;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_FIX(temp)->num_entries;
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
-
- printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
- return (-EINVAL);
- }
-
- if ((pg_start + mem->page_count) > num_entries)
- return (-EINVAL);
-
- /* 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);
-
- global_cache_flush();
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
- OUTREG32(intel_i830_private.gtt, j, agp_bridge->driver->mask_memory(mem->memory[i], mem->type));
-
- global_cache_flush();
-
- agp_bridge->driver->tlb_flush(mem);
-
- return(0);
-}
-
-static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i;
-
- global_cache_flush();
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
- return (-EINVAL);
- }
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++)
- OUTREG32(intel_i830_private.gtt, i, agp_bridge->scratch_page);
-
- global_cache_flush();
-
- agp_bridge->driver->tlb_flush(mem);
-
- return (0);
-}
-
-static int intel_i915_fetch_size(void)
-{
- struct aper_size_info_fixed *values;
- u32 temp, offset = 0;
-
-#define I915_256MB_ADDRESS_MASK (1<<27)
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- 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);
-}
-
-/* The intel i915 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i915_create_gatt_table(void)
-{
- int page_order;
- struct aper_size_info_fixed *size;
- int num_entries;
- u32 temp, temp2;
-
- size = agp_bridge->current_size;
- page_order = size->page_order;
- num_entries = size->num_entries;
- agp_bridge->gatt_table_real = 0;
-
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
-
- intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024);
- if (!intel_i830_private.gtt)
- return (-ENOMEM);
-
- temp &= 0xfff80000;
-
- intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
- return (-ENOMEM);
-
- temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000;
- global_cache_flush();
-
- /* we have to call this as early as possible after the MMIO base address is known */
- intel_i830_init_gtt_entries();
-
- agp_bridge->gatt_table = NULL;
-
- agp_bridge->gatt_bus_addr = temp;
-
- return(0);
-}
-
static int intel_fetch_size(void)
{
int i;
.owner = THIS_MODULE,
.aperture_sizes = intel_i830_sizes,
.size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 3,
+ .num_aperture_sizes = 2,
.needs_scratch_page = TRUE,
.configure = intel_i830_configure,
.fetch_size = intel_i830_fetch_size,
.agp_destroy_page = agp_generic_destroy_page,
};
-static struct agp_bridge_driver intel_915_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_i830_sizes,
- .size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 3,
- .needs_scratch_page = TRUE,
- .configure = intel_i915_configure,
- .fetch_size = intel_i915_fetch_size,
- .cleanup = intel_i915_cleanup,
- .tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
- .masks = intel_i810_masks,
- .agp_enable = intel_i810_agp_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = intel_i915_create_gatt_table,
- .free_gatt_table = intel_i830_free_gatt_table,
- .insert_memory = intel_i915_insert_entries,
- .remove_memory = intel_i915_remove_entries,
- .alloc_by_type = intel_i830_alloc_by_type,
- .free_by_type = intel_i810_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-
static struct agp_bridge_driver intel_7505_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
bridge->driver = &intel_845_driver;
name = "i875";
break;
- case PCI_DEVICE_ID_INTEL_82915G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) {
- bridge->driver = &intel_915_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "915G";
- break;
case PCI_DEVICE_ID_INTEL_7505_0:
bridge->driver = &intel_7505_driver;
- name = "E7505";
+ name = "E7505";
break;
case PCI_DEVICE_ID_INTEL_7205_0:
bridge->driver = &intel_7505_driver;
intel_845_configure();
else if (bridge->driver == &intel_830mp_driver)
intel_830mp_configure();
- else if (bridge->driver == &intel_915_driver)
- intel_i915_configure();
return 0;
}