#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/agp_backend.h>
#include <asm/agp.h>
#include "agp.h"
};
-
-typedef struct _ati_page_map {
+struct ati_page_map {
unsigned long *real;
- unsigned long *remapped;
-} ati_page_map;
+ unsigned long __iomem *remapped;
+};
static struct _ati_generic_private {
- volatile u8 *registers;
- ati_page_map **gatt_pages;
+ volatile u8 __iomem *registers;
+ struct ati_page_map **gatt_pages;
int num_tables;
} ati_generic_private;
-static int ati_create_page_map(ati_page_map *page_map)
+static int ati_create_page_map(struct ati_page_map *page_map)
{
int i, err = 0;
SetPageReserved(virt_to_page(page_map->real));
err = map_page_into_agp(virt_to_page(page_map->real));
-
- /* CACHE_FLUSH(); */
- global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(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));
/*CACHE_FLUSH();*/
global_cache_flush();
- for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
- page_map->remapped[i] = agp_bridge->scratch_page;
+ 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 void ati_free_page_map(ati_page_map *page_map)
+static void ati_free_page_map(struct ati_page_map *page_map)
{
unmap_page_from_agp(virt_to_page(page_map->real));
iounmap(page_map->remapped);
static void ati_free_gatt_pages(void)
{
int i;
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
tables = ati_generic_private.gatt_pages;
- for(i = 0; i < ati_generic_private.num_tables; i++) {
+ for (i = 0; i < ati_generic_private.num_tables; i++) {
entry = tables[i];
if (entry != NULL) {
if (entry->real != NULL)
static int ati_create_gatt_pages(int nr_tables)
{
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
int retval = 0;
int i;
- tables = kmalloc((nr_tables + 1) * sizeof(ati_page_map *),
- GFP_KERNEL);
+ tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
- memset(tables, 0, sizeof(ati_page_map *) * (nr_tables + 1));
for (i = 0; i < nr_tables; i++) {
- entry = kmalloc(sizeof(ati_page_map), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
if (entry == NULL) {
- while (i>0) {
- kfree (tables[i-1]);
+ while (i > 0) {
+ kfree(tables[i-1]);
i--;
}
- kfree (tables);
+ kfree(tables);
retval = -ENOMEM;
break;
}
- memset(entry, 0, sizeof(ati_page_map));
tables[i] = entry;
retval = ati_create_page_map(entry);
- if (retval != 0) break;
+ if (retval != 0)
+ break;
}
ati_generic_private.num_tables = nr_tables;
ati_generic_private.gatt_pages = tables;
- if (retval != 0) ati_free_gatt_pages();
+ if (retval != 0)
+ ati_free_gatt_pages();
return retval;
}
static void ati_tlbflush(struct agp_memory * mem)
{
- OUTREG32(ati_generic_private.registers, ATI_GART_CACHE_CNTRL, 1);
+ writel(1, ati_generic_private.registers+ATI_GART_CACHE_CNTRL);
+ readl(ati_generic_private.registers+ATI_GART_CACHE_CNTRL); /* PCI Posting. */
}
static void ati_cleanup(void)
temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
}
- iounmap((void *) ati_generic_private.registers);
+ iounmap((volatile u8 __iomem *)ati_generic_private.registers);
}
/* Get the memory mapped registers */
pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp);
temp = (temp & 0xfffff000);
- ati_generic_private.registers = (volatile u8 *) ioremap(temp, 4096);
+ ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
if (is_r200())
- pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
+ pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
else
pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000);
/* address to map too */
- /*
+ /*
pci_read_config_dword(agp_bridge.dev, AGP_APBASE, &temp);
agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr);
- */
- OUTREG32(ati_generic_private.registers, ATI_GART_FEATURE_ID, 0x60000);
+ */
+ writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID);
+ readl(ati_generic_private.registers+ATI_GART_FEATURE_ID); /* PCI Posting.*/
/* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
pci_read_config_dword(agp_bridge->dev, 4, &temp);
pci_write_config_dword(agp_bridge->dev, 4, temp | (1<<14));
/* Write out the address of the gatt table */
- OUTREG32(ati_generic_private.registers, ATI_GART_BASE,
- agp_bridge->gatt_bus_addr);
+ writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE);
+ readl(ati_generic_private.registers+ATI_GART_BASE); /* PCI Posting. */
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ pci_save_state(dev);
+ pci_set_power_state(dev, 3);
return 0;
}
+static int agp_ati_resume(struct pci_dev *dev)
+{
+ pci_set_power_state(dev, 0);
+ pci_restore_state(dev);
+
+ return ati_configure();
+}
+#endif
/*
- *Since we don't need contigious memory we just try
+ *Since we don't need contiguous memory we just try
* to get the gatt table once
*/
off_t pg_start, int type)
{
int i, j, num_entries;
- unsigned long *cur_gatt;
+ unsigned long __iomem *cur_gatt;
unsigned long addr;
num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
while (j < (pg_start + mem->page_count)) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- if (!PGE_EMPTY(agp_bridge,cur_gatt[GET_GATT_OFF(addr)]))
+ if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))
return -EBUSY;
j++;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- cur_gatt[GET_GATT_OFF(addr)] =
- agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
agp_bridge->driver->tlb_flush(mem);
return 0;
int type)
{
int i;
- unsigned long *cur_gatt;
+ unsigned long __iomem *cur_gatt;
unsigned long addr;
- if (type != 0 || mem->type != 0) {
+ if (type != 0 || mem->type != 0)
return -EINVAL;
- }
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- cur_gatt[GET_GATT_OFF(addr)] =
- (unsigned long) agp_bridge->scratch_page;
+ writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
+ readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
agp_bridge->driver->tlb_flush(mem);
return 0;
}
-static int ati_create_gatt_table(void)
+static int ati_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
unsigned long addr;
int retval;
u32 temp;
}
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
- agp_bridge->gatt_table = (u32 *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_bus(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);
agp_bridge->gart_bus_addr = addr;
/* Calculate the agp offset */
- for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
- virt_to_bus(ati_generic_private.gatt_pages[i]->real);
- page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
+ 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 ati_free_gatt_table(void)
+static int ati_free_gatt_table(struct agp_bridge_data *bridge)
{
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
- page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+ page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
ati_free_gatt_pages();
ati_free_page_map(&page_dir);
return 0;
}
-struct agp_bridge_driver ati_generic_bridge = {
+static struct agp_bridge_driver ati_generic_bridge = {
.owner = THIS_MODULE,
.aperture_sizes = ati_generic_sizes,
.size_type = LVL2_APER_SIZE,
.device_id = PCI_DEVICE_ID_ATI_RS300_200,
.chipset_name = "IGP9100/M",
},
+ {
+ .device_id = PCI_DEVICE_ID_ATI_RS350_200,
+ .chipset_name = "IGP9100/M",
+ },
{ }, /* dummy final entry, always present */
};
bridge->dev = pdev;
bridge->capndx = cap_ptr;
-
- bridge->driver = &ati_generic_bridge;
+ bridge->driver = &ati_generic_bridge;
printk(KERN_INFO PFX "Detected Ati %s chipset\n",
devs[j].chipset_name);
.id_table = agp_ati_pci_table,
.probe = agp_ati_probe,
.remove = agp_ati_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_ati_suspend,
+ .resume = agp_ati_resume,
+#endif
};
static int __init agp_ati_init(void)
{
- return pci_module_init(&agp_ati_pci_driver);
+ if (agp_off)
+ return -EINVAL;
+ return pci_register_driver(&agp_ati_pci_driver);
}
static void __exit agp_ati_cleanup(void)