Commit da090c71 authored by Dave Jones's avatar Dave Jones

Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart

into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart-new
parents 467d43e7 3716cffb
......@@ -31,7 +31,7 @@ config AGP_GART
config AGP_INTEL
tristate "Intel 440LX/BX/GX, I8xx and E7x05 support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
help
This option gives you AGP support for the GLX component of the
XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860
......@@ -44,7 +44,7 @@ config AGP_INTEL
#config AGP_I810
# tristate "Intel I810/I815/I830M (on-board) support"
# depends on AGP && !X86_64
# depends on AGP && X86 && !X86_64
# help
# This option gives you AGP support for the Xserver on the Intel 810
# 815 and 830m chipset boards for their on-board integrated graphics. This
......@@ -52,7 +52,7 @@ config AGP_INTEL
config AGP_VIA
tristate "VIA chipset support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
help
This option gives you AGP support for the GLX component of the
XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
......@@ -62,7 +62,7 @@ config AGP_VIA
config AGP_AMD
tristate "AMD Irongate, 761, and 762 support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
help
This option gives you AGP support for the GLX component of the
XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
......@@ -72,7 +72,7 @@ config AGP_AMD
config AGP_SIS
tristate "Generic SiS support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
help
This option gives you AGP support for the GLX component of the "soon
to be released" XFree86 4.x on Silicon Integrated Systems [SiS]
......@@ -85,7 +85,7 @@ config AGP_SIS
config AGP_ALI
tristate "ALI chipset support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
---help---
This option gives you AGP support for the GLX component of the
XFree86 4.x on the following ALi chipsets. The supported chipsets
......@@ -103,14 +103,22 @@ config AGP_ALI
config AGP_SWORKS
tristate "Serverworks LE/HE support"
depends on AGP && !X86_64
depends on AGP && X86 && !X86_64
help
Say Y here to support the Serverworks AGP card. See
<http://www.serverworks.com/> for product descriptions and images.
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
depends on AGP && X86 && !X86_64
help
This option gives you AGP support for the GLX component of the
XFree86 4.x on the following NVIDIA chipsets. The supported chipsets
include nForce and nForce2
config AGP_AMD_8151
tristate "AMD 8151 support"
depends on AGP
depends on AGP && X86
default GART_IOMMU
help
Say Y here to support the AMD 8151 AGP bridge and the builtin
......
#
# Makefile for the agpgart device driver. This driver adds a user
# space ioctl interface to use agp memory. It also adds a kernel interface
# that other drivers could use to manipulate agp memory.
agpgart-y := backend.o frontend.o generic.o generic-3.0.o
agpgart-objs := $(agpgart-y)
obj-$(CONFIG_AGP) += agpgart.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_VIA) += via-agp.o
obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
obj-$(CONFIG_AGP) += agpgart.o
obj-$(CONFIG_AGP_ALI) += ali-agp.o
obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o
obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o
obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o
obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o
obj-$(CONFIG_AGP_VIA) += via-agp.o
......@@ -34,24 +34,6 @@ extern struct agp_bridge_data *agp_bridge;
#define PFX "agpgart: "
#ifdef CONFIG_SMP
static void ipi_handler(void *null)
{
flush_agp_cache();
}
static void __attribute__((unused)) global_cache_flush(void)
{
if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)
panic(PFX "timed out waiting for the other CPUs!\n");
}
#else
static void global_cache_flush(void)
{
flush_agp_cache();
}
#endif /* !CONFIG_SMP */
enum aper_size_type {
U8_APER_SIZE,
U16_APER_SIZE,
......@@ -101,14 +83,41 @@ struct aper_size_info_fixed {
int page_order;
};
struct agp_bridge_driver {
struct module *owner;
void *aperture_sizes;
int num_aperture_sizes;
enum aper_size_type size_type;
int cant_use_aperture;
int needs_scratch_page;
struct gatt_mask *masks;
int (*fetch_size)(void);
int (*configure)(void);
void (*agp_enable)(u32);
void (*cleanup)(void);
void (*tlb_flush)(agp_memory *);
unsigned long (*mask_memory)(unsigned long, int);
void (*cache_flush)(void);
int (*create_gatt_table)(void);
int (*free_gatt_table)(void);
int (*insert_memory)(agp_memory *, off_t, int);
int (*remove_memory)(agp_memory *, off_t, int);
agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type)(agp_memory *);
void *(*agp_alloc_page)(void);
void (*agp_destroy_page)(void *);
int (*suspend)(void);
void (*resume)(void);
};
struct agp_bridge_data {
struct agp_version *version;
void *aperture_sizes;
struct agp_bridge_driver *driver;
struct vm_operations_struct *vm_ops;
void *previous_size;
void *current_size;
void *dev_private_data;
struct pci_dev *dev;
struct gatt_mask *masks;
u32 *gatt_table;
u32 *gatt_table_real;
unsigned long scratch_page;
......@@ -117,38 +126,12 @@ struct agp_bridge_data {
unsigned long gatt_bus_addr;
u32 mode;
enum chipset_type type;
enum aper_size_type size_type;
unsigned long *key_list;
atomic_t current_memory_agp;
atomic_t agp_in_use;
int max_memory_agp; /* in number of pages */
int needs_scratch_page;
int aperture_size_idx;
int num_aperture_sizes;
int capndx;
int cant_use_aperture;
struct vm_operations_struct *vm_ops;
/* Links to driver specific functions */
int (*fetch_size) (void);
int (*configure) (void);
void (*agp_enable) (u32);
void (*cleanup) (void);
void (*tlb_flush) (agp_memory *);
unsigned long (*mask_memory) (unsigned long, int);
void (*cache_flush) (void);
int (*create_gatt_table) (void);
int (*free_gatt_table) (void);
int (*insert_memory) (agp_memory *, off_t, int);
int (*remove_memory) (agp_memory *, off_t, int);
agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type) (agp_memory *);
void *(*agp_alloc_page) (void);
void (*agp_destroy_page) (void *);
int (*suspend)(void);
void (*resume)(void);
};
#define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr))
......@@ -165,20 +148,17 @@ struct agp_bridge_data {
#define MB(x) (KB (KB (x)))
#define GB(x) (MB (KB (x)))
#define CACHE_FLUSH agp_bridge->cache_flush
#define A_SIZE_8(x) ((struct aper_size_info_8 *) x)
#define A_SIZE_16(x) ((struct aper_size_info_16 *) x)
#define A_SIZE_32(x) ((struct aper_size_info_32 *) x)
#define A_SIZE_LVL2(x) ((struct aper_size_info_lvl2 *) x)
#define A_SIZE_FIX(x) ((struct aper_size_info_fixed *) x)
#define A_IDX8() (A_SIZE_8(agp_bridge->aperture_sizes) + i)
#define A_IDX16() (A_SIZE_16(agp_bridge->aperture_sizes) + i)
#define A_IDX32() (A_SIZE_32(agp_bridge->aperture_sizes) + i)
#define A_IDXLVL2() (A_SIZE_LVL2(agp_bridge->aperture_sizes) + i)
#define A_IDXFIX() (A_SIZE_FIX(agp_bridge->aperture_sizes) + i)
#define A_IDX8(bridge) (A_SIZE_8((bridge)->driver->aperture_sizes) + i)
#define A_IDX16(bridge) (A_SIZE_16((bridge)->driver->aperture_sizes) + i)
#define A_IDX32(bridge) (A_SIZE_32((bridge)->driver->aperture_sizes) + i)
#define MAXKEY (4096 * 32)
#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge->scratch_page)
#define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page)
/* intel register */
#define INTEL_APBASE 0x10
......@@ -374,11 +354,15 @@ struct agp_device_ids {
int (*chipset_setup) (struct pci_dev *pdev); /* used to override generic */
};
struct agp_driver {
struct module *owner;
struct pci_dev *dev;
};
/* Driver registration */
struct agp_bridge_data *agp_alloc_bridge(void);
void agp_put_bridge(struct agp_bridge_data *bridge);
int agp_add_bridge(struct agp_bridge_data *bridge);
void agp_remove_bridge(struct agp_bridge_data *bridge);
/* Frontend routines. */
int agp_frontend_initialize(void);
void agp_frontend_cleanup(void);
/* Generic routines. */
void agp_generic_enable(u32 mode);
......@@ -395,10 +379,29 @@ int agp_generic_suspend(void);
void agp_generic_resume(void);
void agp_free_key(int key);
int agp_num_entries(void);
int agp_register_driver (struct agp_driver *drv);
int agp_unregister_driver(struct agp_driver *drv);
u32 agp_collect_device_status(u32 mode, u32 command);
void agp_device_command(u32 command, int agp_v3);
int agp_3_0_node_enable(u32 mode, u32 minor);
int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor);
void global_cache_flush(void);
/* Standard agp registers */
#define AGPSTAT 0x4
#define AGPCMD 0x8
#define AGPNEPG 0x16
#define AGP_MAJOR_VERSION_SHIFT (20)
#define AGP_MINOR_VERSION_SHIFT (16)
#define AGPSTAT_RQ_DEPTH (0xff000000)
#define AGPSTAT_ARQSZ_SHIFT 13
#define AGPSTAT_AGP_ENABLE (1<<8)
#define AGPSTAT_SBA (1<<9)
#define AGPSTAT2_1X (1<<0)
#define AGPSTAT2_2X (1<<1)
#define AGPSTAT2_4X (1<<2)
#define AGPSTAT_FW (1<<4)
#endif /* _AGP_BACKEND_PRIV_H */
This diff is collapsed.
......@@ -81,7 +81,7 @@ static void alpha_core_agp_tlbflush(agp_memory *mem)
static unsigned long alpha_core_agp_mask_memory(unsigned long addr, int type)
{
/* Memory type is ignored */
return addr | agp_bridge->masks[0].mask;
return addr | agp_bridge->driver->masks[0].mask;
}
static void alpha_core_agp_enable(u32 mode)
......@@ -109,7 +109,7 @@ static int alpha_core_agp_insert_memory(agp_memory *mem, off_t pg_start,
status = agp->ops->bind(agp, pg_start, mem);
mb();
agp_bridge->tlb_flush(mem);
alpha_core_agp_tlbflush(mem);
return status;
}
......@@ -121,29 +121,57 @@ static int alpha_core_agp_remove_memory(agp_memory *mem, off_t pg_start,
int status;
status = agp->ops->unbind(agp, pg_start, mem);
agp_bridge->tlb_flush(mem);
alpha_core_agp_tlbflush(mem);
return status;
}
static struct agp_driver alpha_core_agp_driver = {
struct agp_bridge_driver alpha_core_agp_driver = {
.owner = THIS_MODULE,
.masks = alpha_core_agp_masks,
.aperture_sizes = aper_size,
.current_size = aper_size, /* only one entry */
.size_type = FIXED_APER_SIZE,
.num_aperture_sizes = 1,
.configure = alpha_core_agp_configure,
.fetch_size = alpha_core_agp_fetch_size,
.cleanup = alpha_core_agp_cleanup,
.tlb_flush = alpha_core_agp_tlbflush,
.mask_memory = alpha_core_agp_mask_memory,
.agp_enable = alpha_core_agp_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = alpha_core_agp_nop,
.free_gatt_table = alpha_core_agp_nop,
.insert_memory = alpha_core_agp_insert_memory,
.remove_memory = alpha_core_agp_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
.mode = agp->capability.lw,
.cant_use_aperture = 1,
.vm_ops = &alpha_core_agp_vm_ops,
};
struct agp_bridge_data *alpha_bridge;
int __init
alpha_core_agp_setup(void)
{
alpha_agp_info *agp = alpha_mv.agp_info();
struct pci_dev *pdev; /* faked */
struct aper_size_info_fixed *aper_size;
if (!agp) return -ENODEV;
if (agp->ops->setup(agp)) return -ENODEV;
if (!agp)
return -ENODEV;
if (agp->ops->setup(agp))
return -ENODEV;
/*
* Build the aperture size descriptor
*/
aper_size = alpha_core_agp_sizes;
if (!aper_size) return -ENOMEM;
if (!aper_size)
return -ENOMEM;
aper_size->size = agp->aperture.size / (1024 * 1024);
aper_size->num_entries = agp->aperture.size / PAGE_SIZE;
aper_size->page_order = ffs(aper_size->num_entries / 1024) - 1;
......@@ -151,63 +179,40 @@ alpha_core_agp_setup(void)
/*
* Build a fake pci_dev struct
*/
if (!(agp_bridge->dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL))) {
pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!pdev)
return -ENOMEM;
}
agp_bridge->dev->vendor = 0xffff;
agp_bridge->dev->device = 0xffff;
agp_bridge->dev->sysdata = agp->hose;
pdev->vendor = 0xffff;
pdev->device = 0xffff;
pdev->sysdata = agp->hose;
alpha_bridge = agp_alloc_bridge();
if (!alpha_bridge)
goto fail;
alpha_bridge->driver = &alpha_core_agp_driver;
alpha_bridge->dev_private_data = agp;
alpha_bridge->dev = pdev;
/*
* Fill in the rest of the agp_bridge struct
*/
agp_bridge->masks = alpha_core_agp_masks;
agp_bridge->aperture_sizes = aper_size;
agp_bridge->current_size = aper_size; /* only one entry */
agp_bridge->size_type = FIXED_APER_SIZE;
agp_bridge->num_aperture_sizes = 1;
agp_bridge->dev_private_data = agp;
agp_bridge->needs_scratch_page = FALSE;
agp_bridge->configure = alpha_core_agp_configure;
agp_bridge->fetch_size = alpha_core_agp_fetch_size;
agp_bridge->cleanup = alpha_core_agp_cleanup;
agp_bridge->tlb_flush = alpha_core_agp_tlbflush;
agp_bridge->mask_memory = alpha_core_agp_mask_memory;
agp_bridge->agp_enable = alpha_core_agp_enable;
agp_bridge->cache_flush = global_cache_flush;
agp_bridge->create_gatt_table = alpha_core_agp_nop;
agp_bridge->free_gatt_table = alpha_core_agp_nop;
agp_bridge->insert_memory = alpha_core_agp_insert_memory;
agp_bridge->remove_memory = alpha_core_agp_remove_memory;
agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
agp_bridge->free_by_type = agp_generic_free_by_type;
agp_bridge->agp_alloc_page = agp_generic_alloc_page;
agp_bridge->agp_destroy_page = agp_generic_destroy_page;
agp_bridge->mode = agp->capability.lw;
agp_bridge->cant_use_aperture = 1;
agp_bridge->vm_ops = &alpha_core_agp_vm_ops;
alpha_core_agp_driver.dev = agp_bridge->dev;
agp_register_driver(&alpha_core_agp_driver);
printk(KERN_INFO "Detected AGP on hose %d\n", agp->hose->index);
return 0;
return agp_add_bridge(alpha_bridge);
fail:
kfree(pdev);
return -ENOMEM;
}
static int __init agp_alpha_core_init(void)
{
int ret_val = -ENODEV;
if (alpha_mv.agp_info) {
agp_bridge->type = ALPHA_CORE_AGP;
ret_val = alpha_core_agp_setup();
}
return ret_val;
if (alpha_mv.agp_info)
return alpha_core_agp_setup();
return -ENODEV;
}
static void __exit agp_alpha_core_cleanup(void)
{
agp_unregister_driver(&alpha_core_agp_driver);
/* no pci driver for core */
agp_remove_bridge(alpha_bridge);
agp_put_bridge(alpha_bridge);
}
module_init(agp_alpha_core_init);
......
......@@ -33,7 +33,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
return -ENOMEM;
}
SetPageReserved(virt_to_page(page_map->real));
CACHE_FLUSH();
global_cache_flush();
page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
......@@ -42,7 +42,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
page_map->real = NULL;
return -ENOMEM;
}
CACHE_FLUSH();
global_cache_flush();
for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
page_map->remapped[i] = agp_bridge->scratch_page;
......@@ -75,6 +75,7 @@ static void amd_free_gatt_pages(void)
}
}
kfree(tables);
amd_irongate_private.gatt_pages = NULL;
}
static int amd_create_gatt_pages(int nr_tables)
......@@ -184,8 +185,8 @@ static int amd_irongate_fetch_size(void)
pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp);
temp = (temp & 0x0000000e);
values = A_SIZE_LVL2(agp_bridge->aperture_sizes);
for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
if (temp == values[i].size_value) {
agp_bridge->previous_size =
agp_bridge->current_size = (void *) (values + i);
......@@ -274,7 +275,7 @@ static unsigned long amd_irongate_mask_memory(unsigned long addr, int type)
{
/* Only type 0 is supported by the irongate */
return addr | agp_bridge->masks[0].mask;
return addr | agp_bridge->driver->masks[0].mask;
}
static int amd_insert_memory(agp_memory * mem,
......@@ -297,14 +298,13 @@ static int amd_insert_memory(agp_memory * mem,
while (j < (pg_start + mem->page_count)) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) {
if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)]))
return -EBUSY;
}
j++;
}
if (mem->is_flushed == FALSE) {
CACHE_FLUSH();
global_cache_flush();
mem->is_flushed = TRUE;
}
......@@ -312,9 +312,9 @@ static int amd_insert_memory(agp_memory * mem,
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
cur_gatt[GET_GATT_OFF(addr)] =
agp_bridge->mask_memory(mem->memory[i], mem->type);
amd_irongate_mask_memory(mem->memory[i], mem->type);
}
agp_bridge->tlb_flush(mem);
amd_irongate_tlbflush(mem);
return 0;
}
......@@ -335,7 +335,7 @@ static int amd_remove_memory(agp_memory * mem, off_t pg_start,
(unsigned long) agp_bridge->scratch_page;
}
agp_bridge->tlb_flush(mem);
amd_irongate_tlbflush(mem);
return 0;
}
......@@ -355,115 +355,104 @@ static struct gatt_mask amd_irongate_masks[] =
{.mask = 0x00000001, .type = 0}
};
static int __init amd_irongate_setup (struct pci_dev *pdev)
{
agp_bridge->masks = amd_irongate_masks;
agp_bridge->aperture_sizes = (void *) amd_irongate_sizes;
agp_bridge->size_type = LVL2_APER_SIZE;
agp_bridge->num_aperture_sizes = 7;
agp_bridge->dev_private_data = (void *) &amd_irongate_private;
agp_bridge->needs_scratch_page = FALSE;
agp_bridge->configure = amd_irongate_configure;
agp_bridge->fetch_size = amd_irongate_fetch_size;
agp_bridge->cleanup = amd_irongate_cleanup;
agp_bridge->tlb_flush = amd_irongate_tlbflush;
agp_bridge->mask_memory = amd_irongate_mask_memory;
agp_bridge->agp_enable = agp_generic_enable;
agp_bridge->cache_flush = global_cache_flush;
agp_bridge->create_gatt_table = amd_create_gatt_table;
agp_bridge->free_gatt_table = amd_free_gatt_table;
agp_bridge->insert_memory = amd_insert_memory;
agp_bridge->remove_memory = amd_remove_memory;
agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
agp_bridge->free_by_type = agp_generic_free_by_type;
agp_bridge->agp_alloc_page = agp_generic_alloc_page;
agp_bridge->agp_destroy_page = agp_generic_destroy_page;
agp_bridge->suspend = agp_generic_suspend;
agp_bridge->resume = agp_generic_resume;
agp_bridge->cant_use_aperture = 0;
return 0;
}
struct agp_bridge_driver amd_irongate_driver = {
.owner = THIS_MODULE,
.masks = amd_irongate_masks,
.aperture_sizes = amd_irongate_sizes,
.size_type = LVL2_APER_SIZE,
.num_aperture_sizes = 7,
.configure = amd_irongate_configure,
.fetch_size = amd_irongate_fetch_size,
.cleanup = amd_irongate_cleanup,
.tlb_flush = amd_irongate_tlbflush,
.mask_memory = amd_irongate_mask_memory,
.agp_enable = agp_generic_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = amd_create_gatt_table,
.free_gatt_table = amd_free_gatt_table,
.insert_memory = amd_insert_memory,
.remove_memory = amd_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
.suspend = agp_generic_suspend,
.resume = agp_generic_resume,
};
struct agp_device_ids amd_agp_device_ids[] __initdata =
{
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006,
.chipset = AMD_IRONGATE,
.chipset_name = "Irongate",
},
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_700E,
.chipset = AMD_761,
.chipset_name = "761",
},
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_700C,
.chipset = AMD_762,
.chipset_name = "760MP",
},
{ }, /* dummy final entry, always present */
};
/* scan table above for supported devices */
static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
static int __init agp_amdk7_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int j=0;
struct agp_device_ids *devs;
struct agp_device_ids *devs = amd_agp_device_ids;
struct agp_bridge_data *bridge;
u8 cap_ptr;
int j;
devs = amd_agp_device_ids;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
while (devs[j].chipset_name != NULL) {
for (j = 0; devs[j].chipset_name; j++) {
if (pdev->device == devs[j].device_id) {
printk (KERN_INFO PFX "Detected AMD %s chipset\n", devs[j].chipset_name);
agp_bridge->type = devs[j].chipset;
if (devs[j].chipset_setup != NULL)
return devs[j].chipset_setup(pdev);
else
return amd_irongate_setup(pdev);
printk (KERN_INFO PFX "Detected AMD %s chipset\n",
devs[j].chipset_name);
goto found;
}
j++;
}
/* try init anyway, if user requests it */
if (agp_try_unsupported) {
if (!agp_try_unsupported) {
printk(KERN_ERR PFX
"Unsupported AMD chipset (device id: %04x),"
" you might want to try agp_try_unsupported=1.\n",
pdev->device);
return -ENODEV;
}
printk(KERN_WARNING PFX "Trying generic AMD routines"
" for device id: %04x\n", pdev->device);
agp_bridge->type = AMD_GENERIC;
return amd_irongate_setup(pdev);
}
printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x),"
" you might want to try agp_try_unsupported=1.\n", pdev->device);
return -ENODEV;
}
found:
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
bridge->driver = &amd_irongate_driver;
bridge->dev_private_data = &amd_irongate_private,
bridge->dev = pdev;
bridge->capndx = cap_ptr;
static struct agp_driver amd_k7_agp_driver = {
.owner = THIS_MODULE,
};
/* Fill in the mode register */
pci_read_config_dword(pdev,
bridge->capndx+PCI_AGP_STATUS,
&bridge->mode);
/* Supported Device Scanning routine */
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
static int __init agp_amdk7_probe (struct pci_dev *dev, const struct pci_device_id *ent)
static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
{
u8 cap_ptr = 0;
cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
if (cap_ptr == 0)
return -ENODEV;
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
if (agp_lookup_host_bridge(dev) != -ENODEV) {
agp_bridge->dev = dev;
agp_bridge->capndx = cap_ptr;
/* Fill in the mode register */
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
amd_k7_agp_driver.dev = dev;
agp_register_driver(&amd_k7_agp_driver);
return 0;
}
return -ENODEV;
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
}
static struct pci_device_id agp_amdk7_pci_table[] __initdata = {
......@@ -484,22 +473,16 @@ static struct __initdata pci_driver agp_amdk7_pci_driver = {
.name = "agpgart-amdk7",
.id_table = agp_amdk7_pci_table,
.probe = agp_amdk7_probe,
.remove = agp_amdk7_remove,
};
static int __init agp_amdk7_init(void)
{
int ret_val;
ret_val = pci_module_init(&agp_amdk7_pci_driver);
if (ret_val)
agp_bridge->type = NOT_SUPPORTED;
return ret_val;
return pci_module_init(&agp_amdk7_pci_driver);
}
static void __exit agp_amdk7_cleanup(void)
{
agp_unregister_driver(&amd_k7_agp_driver);
pci_unregister_driver(&agp_amdk7_pci_driver);
}
......@@ -508,4 +491,3 @@ module_exit(agp_amdk7_cleanup);
MODULE_PARM(agp_try_unsupported, "1i");
MODULE_LICENSE("GPL and additional rights");
......@@ -29,6 +29,21 @@ static struct pci_dev * hammers[MAX_HAMMER_GARTS];
static int gart_iterator;
#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
static void flush_x86_64_tlb(struct pci_dev *dev)
{
u32 tmp;
pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp);
tmp |= 1<<0;
pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp);
}
static void amd_x86_64_tlbflush(agp_memory *temp)
{
for_each_nb()
flush_x86_64_tlb(hammers[gart_iterator]);
}
static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
{
int i, j, num_entries;
......@@ -50,18 +65,18 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
/* gatt table should be empty. */
while (j < (pg_start + mem->page_count)) {
if (!PGE_EMPTY(agp_bridge->gatt_table[j]))
if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
return -EBUSY;
j++;
}
if (mem->is_flushed == FALSE) {
CACHE_FLUSH();
global_cache_flush();
mem->is_flushed = TRUE;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = agp_bridge->mask_memory(mem->memory[i], mem->type);
addr = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
tmp = addr;
BUG_ON(tmp & 0xffffff0000000ffc);
......@@ -71,7 +86,7 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
agp_bridge->gatt_table[j] = pte;
}
agp_bridge->tlb_flush(mem);
amd_x86_64_tlbflush(mem);
return 0;
}
......@@ -113,7 +128,7 @@ static int amd_x86_64_fetch_size(void)
temp = (temp & 0xe);
values = A_SIZE_32(x86_64_aperture_sizes);
for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
if (temp == values[i].size_value) {
agp_bridge->previous_size =
agp_bridge->current_size = (void *) (values + i);
......@@ -125,25 +140,6 @@ static int amd_x86_64_fetch_size(void)
return 0;
}
static void flush_x86_64_tlb(struct pci_dev *dev)
{
u32 tmp;
pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp);
tmp |= 1<<0;
pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp);
}
static void amd_x86_64_tlbflush(agp_memory * temp)
{
for_each_nb() {
flush_x86_64_tlb (hammers[gart_iterator]);
}
}
/*
* In a multiprocessor x86-64 system, this function gets
* called once for each CPU.
......@@ -218,7 +214,7 @@ static void amd_8151_cleanup(void)
static unsigned long amd_8151_mask_memory(unsigned long addr, int type)
{
return addr | agp_bridge->masks[0].mask;
return addr | agp_bridge->driver->masks[0].mask;
}
......@@ -227,130 +223,84 @@ static struct gatt_mask amd_8151_masks[] =
{.mask = 0x00000001, .type = 0}
};
struct agp_bridge_driver amd_8151_driver = {
.owner = THIS_MODULE,
.masks = amd_8151_masks,
.aperture_sizes = amd_8151_sizes,
.size_type = U32_APER_SIZE,
.num_aperture_sizes = 7,
.configure = amd_8151_configure,
.fetch_size = amd_x86_64_fetch_size,
.cleanup = amd_8151_cleanup,
.tlb_flush = amd_x86_64_tlbflush,
.mask_memory = amd_8151_mask_memory,
.agp_enable = agp_generic_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = agp_generic_create_gatt_table,
.free_gatt_table = agp_generic_free_gatt_table,
.insert_memory = x86_64_insert_memory,
.remove_memory = agp_generic_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
.suspend = agp_generic_suspend,
.resume = agp_generic_resume,
};
/*
* Try to configure an AGP v3 capable setup.
* If we fail (typically because we don't have an AGP v3
* card in the system) we fall back to the generic AGP v2
* routines.
*/
static void agp_x86_64_agp_enable(u32 mode)
static int __init agp_amdk8_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct pci_dev *device = NULL;
u32 command, scratch;
struct agp_bridge_data *bridge;
struct pci_dev *loop_dev;
u8 cap_ptr;
u8 v3_devs=0;
/* FIXME: If 'mode' is x1/x2/x4 should we call the AGPv2 routines directly ?
* Messy, as some AGPv3 cards can only do x4 as a minimum.
*/
/* PASS1: Count # of devs capable of AGPv3 mode. */
pci_for_each_dev(device) {
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
if (cap_ptr != 0x00) {
pci_read_config_dword(device, cap_ptr, &scratch);
scratch &= (1<<20|1<<21|1<<22|1<<23);
scratch = scratch>>20;
/* AGP v3 capable ? */
if (scratch>=3) {
v3_devs++;
printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n",
device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn));
} else {
printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch);
}
}
}
/* If not enough, go to AGP v2 setup */
if (v3_devs<2) {
printk (KERN_INFO "AGP: Only %d devices found, not enough, trying AGPv2\n", v3_devs);
return agp_generic_enable(mode);
} else {
printk (KERN_INFO "AGP: Enough AGPv3 devices found, setting up...\n");
}
int i = 0;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &command);
command = agp_collect_device_status(mode, command);
command |= 0x100;
pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_COMMAND, command);
agp_device_command(command, 1);
}
printk(KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n");
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
static int __init amd_8151_setup (struct pci_dev *pdev)
{
struct pci_dev *dev;
int i=0;
agp_bridge->masks = amd_8151_masks;
agp_bridge->aperture_sizes = (void *) amd_8151_sizes;
agp_bridge->size_type = U32_APER_SIZE;
agp_bridge->num_aperture_sizes = 7;
agp_bridge->dev_private_data = NULL;
agp_bridge->needs_scratch_page = FALSE;
agp_bridge->configure = amd_8151_configure;
agp_bridge->fetch_size = amd_x86_64_fetch_size;
agp_bridge->cleanup = amd_8151_cleanup;
agp_bridge->tlb_flush = amd_x86_64_tlbflush;
agp_bridge->mask_memory = amd_8151_mask_memory;
agp_bridge->agp_enable = agp_x86_64_agp_enable;
agp_bridge->cache_flush = global_cache_flush;
agp_bridge->create_gatt_table = agp_generic_create_gatt_table;
agp_bridge->free_gatt_table = agp_generic_free_gatt_table;
agp_bridge->insert_memory = x86_64_insert_memory;
agp_bridge->remove_memory = agp_generic_remove_memory;
agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
agp_bridge->free_by_type = agp_generic_free_by_type;
agp_bridge->agp_alloc_page = agp_generic_alloc_page;
agp_bridge->agp_destroy_page = agp_generic_destroy_page;
agp_bridge->suspend = agp_generic_suspend;
agp_bridge->resume = agp_generic_resume;
agp_bridge->cant_use_aperture = 0;
bridge->driver = &amd_8151_driver;
bridge->dev = pdev;
bridge->capndx = cap_ptr;
/* Fill in the mode register */
pci_read_config_dword(pdev,
bridge->capndx+PCI_AGP_STATUS,
&bridge->mode);
/* cache pci_devs of northbridges. */
pci_for_each_dev(dev) {
if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 &&
(PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) {
hammers[i++] = dev;
pci_for_each_dev(loop_dev) {
if (loop_dev->bus->number == 0 &&
PCI_FUNC(loop_dev->devfn) == 3 &&
PCI_SLOT(loop_dev->devfn) >=24 &&
PCI_SLOT(loop_dev->devfn) <=31) {
hammers[i++] = loop_dev;
nr_garts = i;
if (i==MAX_HAMMER_GARTS)
return 0;
if (i == MAX_HAMMER_GARTS)
goto out_free;
}
}
return 0;
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
out_free:
agp_put_bridge(bridge);
return -ENOMEM;
}
static struct agp_driver amd_k8_agp_driver = {
.owner = THIS_MODULE,
};
static int __init agp_amdk8_probe (struct pci_dev *dev, const struct pci_device_id *ent)
static void __devexit agp_amdk8_remove(struct pci_dev *pdev)
{
u8 cap_ptr = 0;
cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
if (cap_ptr == 0)
return -ENODEV;
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
printk (KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n");
agp_bridge->dev = dev;
agp_bridge->capndx = cap_ptr;
/* Fill in the mode register */
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode);
amd_8151_setup(dev);
amd_k8_agp_driver.dev = dev;
agp_register_driver(&amd_k8_agp_driver);
return 0;
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
}
static struct pci_device_id agp_amdk8_pci_table[] __initdata = {
......@@ -371,25 +321,17 @@ static struct __initdata pci_driver agp_amdk8_pci_driver = {
.name = "agpgart-amd-k8",
.id_table = agp_amdk8_pci_table,
.probe = agp_amdk8_probe,
.remove = agp_amdk8_remove,
};
/* Not static due to IOMMU code calling it early. */
int __init agp_amdk8_init(void)
{
int ret_val;
ret_val = pci_module_init(&agp_amdk8_pci_driver);
if (ret_val)
agp_bridge->type = NOT_SUPPORTED;
agp_bridge->type = AMD_8151;
return ret_val;
return pci_module_init(&agp_amdk8_pci_driver);
}
static void __exit agp_amdk8_cleanup(void)
{
agp_unregister_driver(&amd_k8_agp_driver);
pci_unregister_driver(&agp_amdk8_pci_driver);
}
......
......@@ -43,37 +43,54 @@
* past 0.99 at all due to some boolean logic error. */
#define AGPGART_VERSION_MAJOR 0
#define AGPGART_VERSION_MINOR 100
static struct agp_version agp_current_version =
{
.major = AGPGART_VERSION_MAJOR,
.minor = AGPGART_VERSION_MINOR,
};
static int agp_count=0;
struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED };
struct agp_bridge_data *agp_bridge = &agp_bridge_dummy;
EXPORT_SYMBOL(agp_bridge);
/**
* agp_backend_acquire - attempt to acquire the agp backend.
*
* returns -EBUSY if agp is in use,
* returns 0 if the caller owns the agp backend
*/
int agp_backend_acquire(void)
{
if (agp_bridge->type == NOT_SUPPORTED)
return -EINVAL;
if (atomic_read(&agp_bridge->agp_in_use) != 0)
if (atomic_read(&agp_bridge->agp_in_use))
return -EBUSY;
atomic_inc(&agp_bridge->agp_in_use);
return 0;
}
EXPORT_SYMBOL(agp_backend_acquire);
/**
* agp_backend_release - release the lock on the agp backend.
*
* The caller must insure that the graphics aperture translation table
* is read for use by another entity.
*
* (Ensure that all memory it bound is unbound.)
*/
void agp_backend_release(void)
{
if (agp_bridge->type == NOT_SUPPORTED)
return;
if (agp_bridge->type != NOT_SUPPORTED)
atomic_dec(&agp_bridge->agp_in_use);
}
EXPORT_SYMBOL(agp_backend_release);
struct agp_max_table {
int mem;
int agp;
};
static struct agp_max_table maxes_table[9] =
{
struct { int mem, agp; } maxes_table[] = {
{0, 0},
{32, 4},
{64, 28},
......@@ -85,7 +102,7 @@ static struct agp_max_table maxes_table[9] =
{4096, 3932}
};
static int agp_find_max (void)
static int agp_find_max(void)
{
long memory, index, result;
......@@ -105,48 +122,43 @@ static int agp_find_max (void)
return result;
}
static struct agp_version agp_current_version =
{
.major = AGPGART_VERSION_MAJOR,
.minor = AGPGART_VERSION_MINOR,
};
static int agp_backend_initialize(struct pci_dev *dev)
static int agp_backend_initialize(struct agp_bridge_data *bridge)
{
int size_value, rc, got_gatt=0, got_keylist=0;
agp_bridge->max_memory_agp = agp_find_max();
agp_bridge->version = &agp_current_version;
bridge->max_memory_agp = agp_find_max();
bridge->version = &agp_current_version;
if (agp_bridge->needs_scratch_page == TRUE) {
void *addr;
addr = agp_bridge->agp_alloc_page();
if (bridge->driver->needs_scratch_page) {
void *addr = bridge->driver->agp_alloc_page();
if (addr == NULL) {
if (!addr) {
printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
return -ENOMEM;
}
agp_bridge->scratch_page_real = virt_to_phys(addr);
agp_bridge->scratch_page =
agp_bridge->mask_memory(agp_bridge->scratch_page_real, 0);
}
size_value = agp_bridge->fetch_size();
bridge->scratch_page_real = virt_to_phys(addr);
bridge->scratch_page =
bridge->driver->mask_memory(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 (agp_bridge->create_gatt_table()) {
printk(KERN_ERR PFX "unable to get memory for graphics translation table.\n");
if (bridge->driver->create_gatt_table()) {
printk(KERN_ERR PFX
"unable to get memory for graphics translation table.\n");
rc = -ENOMEM;
goto err_out;
}
got_gatt = 1;
agp_bridge->key_list = vmalloc(PAGE_SIZE * 4);
if (agp_bridge->key_list == NULL) {
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;
......@@ -154,61 +166,62 @@ static int agp_backend_initialize(struct pci_dev *dev)
got_keylist = 1;
/* FIXME vmalloc'd memory not guaranteed contiguous */
memset(agp_bridge->key_list, 0, PAGE_SIZE * 4);
memset(bridge->key_list, 0, PAGE_SIZE * 4);
if (agp_bridge->configure()) {
if (bridge->driver->configure()) {
printk(KERN_ERR PFX "error configuring host chipset.\n");
rc = -EINVAL;
goto err_out;
}
printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
size_value, agp_bridge->gart_bus_addr);
size_value, bridge->gart_bus_addr);
return 0;
err_out:
if (agp_bridge->needs_scratch_page == TRUE) {
agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real));
}
if (bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
phys_to_virt(bridge->scratch_page_real));
if (got_gatt)
agp_bridge->free_gatt_table();
if (got_keylist)
vfree(agp_bridge->key_list);
bridge->driver->free_gatt_table();
if (got_keylist) {
vfree(bridge->key_list);
bridge->key_list = NULL;
}
return rc;
}
/* cannot be __exit b/c as it could be called from __init code */
static void agp_backend_cleanup(void)
static void agp_backend_cleanup(struct agp_bridge_data *bridge)
{
if (agp_bridge->cleanup != NULL)
agp_bridge->cleanup();
if (agp_bridge->free_gatt_table != NULL)
agp_bridge->free_gatt_table();
if (agp_bridge->key_list)
vfree(agp_bridge->key_list);
if ((agp_bridge->agp_destroy_page!=NULL) &&
(agp_bridge->needs_scratch_page == TRUE))
agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real));
if (bridge->driver->cleanup)
bridge->driver->cleanup();
if (bridge->driver->free_gatt_table)
bridge->driver->free_gatt_table();
if (bridge->key_list) {
vfree(bridge->key_list);
bridge->key_list = NULL;
}
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
phys_to_virt(bridge->scratch_page_real));
}
static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data)
{
switch(rq)
{
switch(rq) {
case PM_SUSPEND:
return agp_bridge->suspend();
return agp_bridge->driver->suspend();
case PM_RESUME:
agp_bridge->resume();
agp_bridge->driver->resume();
return 0;
}
return 0;
}
extern int agp_frontend_initialize(void);
extern void agp_frontend_cleanup(void);
static const drm_agp_t drm_agp = {
&agp_free_memory,
......@@ -221,78 +234,81 @@ static const drm_agp_t drm_agp = {
&agp_copy_info
};
static int agp_count=0;
/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */
struct agp_bridge_data *agp_alloc_bridge(void)
{
return agp_bridge;
}
EXPORT_SYMBOL(agp_alloc_bridge);
int agp_register_driver (struct agp_driver *drv)
void agp_put_bridge(struct agp_bridge_data *bridge)
{
int ret_val;
}
EXPORT_SYMBOL(agp_put_bridge);
if (drv->dev == NULL) {
printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
int agp_add_bridge(struct agp_bridge_data *bridge)
{
int error;
if (!bridge->dev) {
printk(KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
return -EINVAL;
}
if (agp_count==1) {
printk (KERN_DEBUG PFX "Only one agpgart device currently supported.\n");
if (agp_count) {
printk(KERN_DEBUG PFX
"Only one agpgart device currently supported.\n");
return -ENODEV;
}
/* Grab reference on the chipset driver. */
if (!try_module_get(drv->owner))
if (!try_module_get(bridge->driver->owner))
return -EINVAL;
ret_val = agp_backend_initialize(drv->dev);
if (ret_val)
bridge->type = SUPPORTED;
error = agp_backend_initialize(agp_bridge);
if (error)
goto err_out;
ret_val = agp_frontend_initialize();
if (ret_val)
error = agp_frontend_initialize();
if (error)
goto frontend_err;
/* FIXME: What to do with this? */
inter_module_register("drm_agp", THIS_MODULE, &drm_agp);
pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge->dev), agp_power);
pm_register(PM_PCI_DEV, PM_PCI_ID(bridge->dev), agp_power);
agp_count++;
return 0;
frontend_err:
agp_backend_cleanup();
agp_backend_cleanup(agp_bridge);
err_out:
agp_bridge->type = NOT_SUPPORTED;
module_put(drv->owner);
drv->dev = NULL;
return ret_val;
bridge->type = NOT_SUPPORTED;
module_put(bridge->driver->owner);
return error;
}
EXPORT_SYMBOL_GPL(agp_add_bridge);
int agp_unregister_driver(struct agp_driver *drv)
{
if (drv->dev==NULL)
return -ENODEV;
agp_bridge->type = NOT_SUPPORTED;
void agp_remove_bridge(struct agp_bridge_data *bridge)
{
bridge->type = NOT_SUPPORTED;
pm_unregister_all(agp_power);
agp_frontend_cleanup();
agp_backend_cleanup();
agp_backend_cleanup(bridge);
inter_module_unregister("drm_agp");
agp_count--;
module_put(drv->owner);
return 0;
module_put(bridge->driver->owner);
}
EXPORT_SYMBOL_GPL(agp_remove_bridge);
int __init agp_init(void)
static int __init agp_init(void)
{
static int already_initialised=0;
if (already_initialised!=0)
return 0;
already_initialised = 1;
memset(agp_bridge, 0, sizeof(struct agp_bridge_data));
agp_bridge->type = NOT_SUPPORTED;
printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
return 0;
......@@ -300,19 +316,13 @@ int __init agp_init(void)
void __exit agp_exit(void)
{
if (agp_count!=0)
BUG();
}
#ifndef CONFIG_GART_IOMMU
module_init(agp_init);
module_exit(agp_exit);
#endif
EXPORT_SYMBOL(agp_backend_acquire);
EXPORT_SYMBOL(agp_backend_release);
EXPORT_SYMBOL_GPL(agp_register_driver);
EXPORT_SYMBOL_GPL(agp_unregister_driver);
MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
MODULE_DESCRIPTION("AGP GART driver");
MODULE_LICENSE("GPL and additional rights");
module_init(agp_init);
module_exit(agp_exit);
......@@ -40,6 +40,14 @@
#include <asm/pgtable.h>
#include "agp.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(x,y...) printk (KERN_DEBUG "agpgart: %s: " x "\n", __FUNCTION__ , ## y)
#else
#define DBG(x,y...) do { } while (0)
#endif
static struct agp_front_data agp_fe;
static agp_memory *agp_find_mem_by_key(int key)
......@@ -53,11 +61,12 @@ static agp_memory *agp_find_mem_by_key(int key)
while (curr != NULL) {
if (curr->key == key)
return curr;
break;
curr = curr->next;
}
return NULL;
DBG("key=%d -> mem=%p", key, curr);
return curr;
}
static void agp_remove_from_pool(agp_memory * temp)
......@@ -67,6 +76,7 @@ static void agp_remove_from_pool(agp_memory * temp)
/* Check to see if this is even in the memory pool */
DBG("mem=%p", temp);
if (agp_find_mem_by_key(temp->key) != NULL) {
next = temp->next;
prev = temp->prev;
......@@ -119,10 +129,16 @@ static agp_segment_priv *agp_find_seg_in_client(const agp_client * client,
static void agp_remove_seg_from_client(agp_client * client)
{
DBG("client=%p", client);
if (client->segments != NULL) {
if (*(client->segments) != NULL)
if (*(client->segments) != NULL) {
DBG("Freeing %p from client", *(client->segments), client);
kfree(*(client->segments));
}
DBG("Freeing %p from client %p", client->segments, client);
kfree(client->segments);
client->segments = NULL;
}
}
......@@ -136,6 +152,7 @@ static void agp_add_seg_to_client(agp_client * client,
if (prev_seg != NULL)
agp_remove_seg_from_client(client);
DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
client->num_segments = num_segments;
client->segments = seg;
}
......@@ -181,6 +198,7 @@ static int agp_create_segment(agp_client * client, agp_region * region)
seg = kmalloc((sizeof(agp_segment_priv) * region->seg_count), GFP_KERNEL);
if (seg == NULL) {
kfree(region->seg_list);
region->seg_list = NULL;
return -ENOMEM;
}
memset(seg, 0, (sizeof(agp_segment_priv) * region->seg_count));
......@@ -191,14 +209,15 @@ static int agp_create_segment(agp_client * client, agp_region * region)
seg[i].pg_count = user_seg[i].pg_count;
seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
}
kfree(region->seg_list);
region->seg_list = NULL;
ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
if (ret_seg == NULL) {
kfree(region->seg_list);
kfree(seg);
return -ENOMEM;
}
*ret_seg = seg;
kfree(region->seg_list);
agp_add_seg_to_client(client, ret_seg, region->seg_count);
return 0;
}
......@@ -586,7 +605,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
agp_file_private *priv = (agp_file_private *) file->private_data;
agp_kern_info kerninfo;
AGP_LOCK();
down(&(agp_fe.agp_mutex));
if (agp_fe.backend_acquired != TRUE)
goto out_eperm;
......@@ -599,6 +618,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
current_size = kerninfo.aper_size;
current_size = current_size * 0x100000;
offset = vma->vm_pgoff << PAGE_SHIFT;
DBG("%lx:%lx", offset, offset+size);
if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
if ((size + offset) > current_size)
......@@ -612,6 +632,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
goto out_inval;
DBG("client vm_ops=%p", kerninfo.vm_ops);
if (kerninfo.vm_ops) {
vma->vm_ops = kerninfo.vm_ops;
} else if (remap_page_range(vma, vma->vm_start,
......@@ -619,7 +640,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
size, vma->vm_page_prot)) {
goto out_again;
}
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return 0;
}
......@@ -627,6 +648,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (size != current_size)
goto out_inval;
DBG("controller vm_ops=%p", kerninfo.vm_ops);
if (kerninfo.vm_ops) {
vma->vm_ops = kerninfo.vm_ops;
} else if (remap_page_range(vma, vma->vm_start,
......@@ -634,20 +656,20 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
size, vma->vm_page_prot)) {
goto out_again;
}
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return 0;
}
out_eperm:
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return -EPERM;
out_inval:
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return -EINVAL;
out_again:
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return -EAGAIN;
}
......@@ -655,7 +677,9 @@ static int agp_release(struct inode *inode, struct file *file)
{
agp_file_private *priv = (agp_file_private *) file->private_data;
AGP_LOCK();
down(&(agp_fe.agp_mutex));
DBG("priv=%p", priv);
if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
agp_controller *controller;
......@@ -668,14 +692,17 @@ static int agp_release(struct inode *inode, struct file *file)
priv);
}
agp_remove_controller(controller);
controller = NULL;
}
}
if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
agp_remove_client(priv->my_pid);
}
agp_remove_file_private(priv);
kfree(priv);
AGP_UNLOCK();
(agp_file_private *) file->private_data = NULL;
up(&(agp_fe.agp_mutex));
return 0;
}
......@@ -686,7 +713,7 @@ static int agp_open(struct inode *inode, struct file *file)
agp_client *client;
int rc = -ENXIO;
AGP_LOCK();
down(&(agp_fe.agp_mutex));
if (minor != AGPGART_MINOR)
goto err_out;
......@@ -711,13 +738,14 @@ static int agp_open(struct inode *inode, struct file *file)
}
file->private_data = (void *) priv;
agp_insert_file_private(priv);
AGP_UNLOCK();
DBG("private=%p, client=%p", priv, client);
up(&(agp_fe.agp_mutex));
return 0;
err_out_nomem:
rc = -ENOMEM;
err_out:
AGP_UNLOCK();
up(&(agp_fe.agp_mutex));
return rc;
}
......@@ -760,8 +788,10 @@ static int agpioc_info_wrap(agp_file_private * priv, unsigned long arg)
static int agpioc_acquire_wrap(agp_file_private * priv, unsigned long arg)
{
int ret;
agp_controller *controller;
DBG("");
if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
return -EPERM;
......@@ -797,6 +827,7 @@ static int agpioc_acquire_wrap(agp_file_private * priv, unsigned long arg)
static int agpioc_release_wrap(agp_file_private * priv, unsigned long arg)
{
DBG("");
agp_controller_release_current(agp_fe.current_controller, priv);
return 0;
}
......@@ -805,9 +836,10 @@ static int agpioc_setup_wrap(agp_file_private * priv, unsigned long arg)
{
agp_setup mode;
if (copy_from_user(&mode, (void *) arg, sizeof(agp_setup))) {
DBG("");
if (copy_from_user(&mode, (void *) arg, sizeof(agp_setup)))
return -EFAULT;
}
agp_enable(mode.agp_mode);
return 0;
}
......@@ -818,6 +850,7 @@ static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg)
agp_client *client;
agp_file_private *client_priv;
DBG("");
if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region)))
return -EFAULT;
......@@ -831,10 +864,8 @@ static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg)
client_priv = agp_find_private(reserve.pid);
if (client_priv != NULL) {
set_bit(AGP_FF_IS_CLIENT,
&client_priv->access_flags);
set_bit(AGP_FF_IS_VALID,
&client_priv->access_flags);
set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
}
if (client == NULL) {
/* client is already removed */
......@@ -871,15 +902,11 @@ static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg)
client_priv = agp_find_private(reserve.pid);
if (client_priv != NULL) {
set_bit(AGP_FF_IS_CLIENT,
&client_priv->access_flags);
set_bit(AGP_FF_IS_VALID,
&client_priv->access_flags);
set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
}
return agp_create_segment(client, &reserve);
} else {
return agp_create_segment(client, &reserve);
}
return agp_create_segment(client, &reserve);
}
/* Will never really happen */
return -EINVAL;
......@@ -887,6 +914,7 @@ static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg)
static int agpioc_protect_wrap(agp_file_private * priv, unsigned long arg)
{
DBG("");
/* This function is not currently implemented */
return -EINVAL;
}
......@@ -896,6 +924,7 @@ static int agpioc_allocate_wrap(agp_file_private * priv, unsigned long arg)
agp_memory *memory;
agp_allocate alloc;
DBG("");
if (copy_from_user(&alloc, (void *) arg, sizeof(agp_allocate)))
return -EFAULT;
......@@ -918,6 +947,7 @@ static int agpioc_deallocate_wrap(agp_file_private * priv, unsigned long arg)
{
agp_memory *memory;
DBG("");
memory = agp_find_mem_by_key((int) arg);
if (memory == NULL)
......@@ -932,6 +962,7 @@ static int agpioc_bind_wrap(agp_file_private * priv, unsigned long arg)
agp_bind bind_info;
agp_memory *memory;
DBG("");
if (copy_from_user(&bind_info, (void *) arg, sizeof(agp_bind)))
return -EFAULT;
......@@ -948,6 +979,7 @@ static int agpioc_unbind_wrap(agp_file_private * priv, unsigned long arg)
agp_memory *memory;
agp_unbind unbind;
DBG("");
if (copy_from_user(&unbind, (void *) arg, sizeof(agp_unbind)))
return -EFAULT;
......@@ -965,7 +997,8 @@ static int agp_ioctl(struct inode *inode, struct file *file,
agp_file_private *curr_priv = (agp_file_private *) file->private_data;
int ret_val = -ENOTTY;
AGP_LOCK();
DBG("priv=%p, cmd=%x", curr_priv, cmd);
down(&(agp_fe.agp_mutex));
if ((agp_fe.current_controller == NULL) &&
(cmd != AGPIOC_ACQUIRE)) {
......@@ -1034,7 +1067,8 @@ static int agp_ioctl(struct inode *inode, struct file *file,
}
ioctl_out:
AGP_UNLOCK();
DBG("ioctl returns %d\n", ret_val);
up(&(agp_fe.agp_mutex));
return ret_val;
}
......@@ -1060,7 +1094,7 @@ static struct miscdevice agp_miscdev =
int agp_frontend_initialize(void)
{
memset(&agp_fe, 0, sizeof(struct agp_front_data));
AGP_LOCK_INIT();
sema_init(&(agp_fe.agp_mutex), 1);
if (misc_register(&agp_miscdev)) {
printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
......
......@@ -18,7 +18,7 @@ struct agp_3_0_dev {
struct pci_dev *dev;
};
static int agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new)
static void agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new)
{
struct agp_3_0_dev *cur, *n = list_entry(new, struct agp_3_0_dev, list);
struct list_head *pos;
......@@ -29,11 +29,9 @@ static int agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new
break;
}
list_add_tail(new, pos);
return 0;
}
static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
static void agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
{
struct agp_3_0_dev *cur;
struct pci_dev *dev;
......@@ -53,7 +51,6 @@ static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
pos = pos->next;
agp_3_0_dev_list_insert(head, tmp);
}
return 0;
}
/*
......@@ -62,7 +59,8 @@ static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs)
* lying behind it...)
*/
static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs)
static int agp_3_0_isochronous_node_enable(struct agp_bridge_data *bridge,
struct agp_3_0_dev *dev_list, unsigned int ndevs)
{
/*
* Convenience structure to make the calculations clearer
......@@ -77,7 +75,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
struct agp_3_0_dev *dev;
};
struct pci_dev *td = agp_bridge->dev, *dev;
struct pci_dev *td = bridge->dev, *dev;
struct list_head *head = &dev_list->list, *pos;
struct agp_3_0_dev *cur;
struct isoch_data *master, target;
......@@ -114,11 +112,10 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
* transfers are enabled and consequently whether maxbw will mean
* anything.
*/
if((ret = agp_3_0_dev_list_sort(dev_list, ndevs)) != 0)
goto free_and_exit;
agp_3_0_dev_list_sort(dev_list, ndevs);
pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat);
pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus);
pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat);
pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus);
/* Extract power-on defaults from the target */
target.maxbw = (tnistat >> 16) & 0xff;
......@@ -170,13 +167,13 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
* in the target's NISTAT register, so we need to do this now
* to get an accurate value for ISOCH_N later.
*/
pci_read_config_word(td, agp_bridge->capndx + 0x20, &tnicmd);
pci_read_config_word(td, bridge->capndx + 0x20, &tnicmd);
tnicmd &= ~(0x3 << 6);
tnicmd |= target.y << 6;
pci_write_config_word(td, agp_bridge->capndx + 0x20, tnicmd);
pci_write_config_word(td, bridge->capndx + 0x20, tnicmd);
/* Reread the target's ISOCH_N */
pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat);
pci_read_config_dword(td, bridge->capndx + 0x0c, &tnistat);
target.n = (tnistat >> 8) & 0xff;
/* Calculate the minimum ISOCH_N needed by each master */
......@@ -260,7 +257,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
? (rem_async + rem_isoch) : step;
pci_read_config_word(dev, cur->capndx + 0x20, &mnicmd);
pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd);
pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd);
mnicmd &= ~(0xff << 8);
mnicmd &= ~(0x3 << 6);
......@@ -270,7 +267,7 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
mnicmd |= master[cdev].y << 6;
mcmd |= master[cdev].rq << 24;
pci_write_config_dword(dev, cur->capndx + 0x08, mcmd);
pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd);
pci_write_config_word(dev, cur->capndx + 0x20, mnicmd);
}
......@@ -288,7 +285,8 @@ static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigne
* target by ndevs. Distribute this many slots to each AGP 3.0 device,
* giving any left over slots to the last device in dev_list.
*/
static int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs)
static void agp_3_0_nonisochronous_node_enable(struct agp_bridge_data *bridge,
struct agp_3_0_dev *dev_list, unsigned int ndevs)
{
struct agp_3_0_dev *cur;
struct list_head *head = &dev_list->list, *pos;
......@@ -296,7 +294,7 @@ static int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsi
u32 trq, mrq, rem;
unsigned int cdev = 0;
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x04, &tstatus);
pci_read_config_dword(bridge->dev, bridge->capndx + 0x04, &tstatus);
trq = (tstatus >> 24) & 0xff;
mrq = trq / ndevs;
......@@ -306,22 +304,20 @@ static int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsi
for(pos = head->next; cdev < ndevs; cdev++, pos = pos->next) {
cur = list_entry(pos, struct agp_3_0_dev, list);
pci_read_config_dword(cur->dev, cur->capndx + 0x08, &mcmd);
pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd);
mcmd &= ~(0xff << 24);
mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24;
pci_write_config_dword(cur->dev, cur->capndx + 0x08, mcmd);
pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd);
}
return 0;
}
/*
* Fully configure and enable an AGP 3.0 host bridge and all the devices
* lying behind it.
*/
int agp_3_0_node_enable(u32 mode, u32 minor)
int agp_3_0_node_enable(struct agp_bridge_data *bridge, u32 mode, u32 minor)
{
struct pci_dev *td = agp_bridge->dev, *dev;
struct pci_dev *td = bridge->dev, *dev;
u8 mcapndx;
u32 isoch, arqsz, cal_cycle, tmp, rate;
u32 tstatus, tcmd, mcmd, mstatus, ncapid;
......@@ -345,12 +341,22 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
/* Find all AGP devices, and add them to dev_list. */
pci_for_each_dev(dev) {
mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP);
switch ((dev->class >>8) & 0xff00) {
case 0x0600: /* Bridge */
/* Skip bridges. We should call this function for each one. */
continue;
case 0x0001: /* Unclassified device */
/* Don't know what this is, but log it for investigation. */
if (mcapndx != 0) {
printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n",
dev->vendor, dev->device);
}
continue;
case 0x0300: /* Display controller */
case 0x0400: /* Multimedia controller */
case 0x0600: /* Bridge */
mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP);
if (mcapndx == 0)
continue;
......@@ -371,7 +377,7 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
}
/* Extract some power-on defaults from the target */
pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus);
pci_read_config_dword(td, bridge->capndx + 0x04, &tstatus);
isoch = (tstatus >> 17) & 0x1;
arqsz = (tstatus >> 13) & 0x7;
cal_cycle = (tstatus >> 10) & 0x7;
......@@ -409,8 +415,8 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
goto free_and_exit;
}
mmajor = (ncapid >> 20) & 0xf;
mminor = (ncapid >> 16) & 0xf;
mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
mminor = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
if(mmajor < 3) {
printk(KERN_ERR PFX "woah! AGP 2.0 device "
......@@ -463,13 +469,15 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
* masters. This process is dramatically different depending on
* whether isochronous transfers are supported.
*/
if(isoch != 0) {
if((ret = agp_3_0_isochronous_node_enable(dev_list, ndevs)) != 0)
goto free_and_exit;
} else {
if((ret = agp_3_0_nonisochronous_node_enable(dev_list,ndevs)) != 0)
goto free_and_exit;
if (isoch) {
ret = agp_3_0_isochronous_node_enable(bridge, dev_list, ndevs);
if (ret) {
printk(KERN_INFO PFX "Something bad happened setting "
"up isochronous xfers. Falling back to "
"non-isochronous xfer mode.\n");
}
}
agp_3_0_nonisochronous_node_enable(bridge, dev_list, ndevs);
/*
* Set the calculated minimum supported cal_cycle and minimum
......@@ -477,7 +485,7 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
* Also set the AGP_ENABLE bit, effectively 'turning on' the
* target (this has to be done _before_ turning on the masters).
*/
pci_read_config_dword(td, agp_bridge->capndx + 0x08, &tcmd);
pci_read_config_dword(td, bridge->capndx+AGPCMD, &tcmd);
tcmd &= ~(0x7 << 10);
tcmd &= ~0x7;
......@@ -486,7 +494,7 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
tcmd |= 0x1 << 8;
tcmd |= rate;
pci_write_config_dword(td, agp_bridge->capndx + 0x08, tcmd);
pci_write_config_dword(td, bridge->capndx+AGPCMD, tcmd);
/*
* Set the target's advertised arqsz value, the minimum supported
......@@ -499,16 +507,16 @@ int agp_3_0_node_enable(u32 mode, u32 minor)
mcapndx = cur->capndx;
pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd);
pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd);
mcmd &= ~(0x7 << 13);
mcmd &= ~(0x7 << AGPSTAT_ARQSZ_SHIFT);
mcmd &= ~0x7;
mcmd |= arqsz << 13;
mcmd |= 0x1 << 8;
mcmd |= AGPSTAT_AGP_ENABLE;
mcmd |= rate;
pci_write_config_dword(dev, cur->capndx + 0x08, mcmd);
pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd);
}
free_and_exit:
......
This diff is collapsed.
......@@ -285,7 +285,7 @@ static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type)
}
if (mem->is_flushed == FALSE) {
CACHE_FLUSH();
global_cache_flush();
mem->is_flushed = TRUE;
}
......@@ -296,11 +296,11 @@ static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type)
for (k = 0;
k < hp->io_pages_per_kpage;
k++, j++, paddr += hp->io_page_size) {
hp->gatt[j] = agp_bridge->mask_memory(paddr, type);
hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type);
}
}
agp_bridge->tlb_flush(mem);
agp_bridge->driver->tlb_flush(mem);
return 0;
}
......@@ -319,7 +319,7 @@ static int hp_zx1_remove_memory(agp_memory * mem, off_t pg_start, int type)
hp->gatt[i] = agp_bridge->scratch_page;
}
agp_bridge->tlb_flush(mem);
agp_bridge->driver->tlb_flush(mem);
return 0;
}
......@@ -328,58 +328,62 @@ static unsigned long hp_zx1_mask_memory(unsigned long addr, int type)
return HP_ZX1_PDIR_VALID_BIT | addr;
}
static int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused)))
{
agp_bridge->masks = hp_zx1_masks;
agp_bridge->dev_private_data = NULL;
agp_bridge->size_type = FIXED_APER_SIZE;
agp_bridge->needs_scratch_page = FALSE;
agp_bridge->configure = hp_zx1_configure;
agp_bridge->fetch_size = hp_zx1_fetch_size;
agp_bridge->cleanup = hp_zx1_cleanup;
agp_bridge->tlb_flush = hp_zx1_tlbflush;
agp_bridge->mask_memory = hp_zx1_mask_memory;
agp_bridge->agp_enable = agp_generic_enable;
agp_bridge->cache_flush = global_cache_flush;
agp_bridge->create_gatt_table = hp_zx1_create_gatt_table;
agp_bridge->free_gatt_table = hp_zx1_free_gatt_table;
agp_bridge->insert_memory = hp_zx1_insert_memory;
agp_bridge->remove_memory = hp_zx1_remove_memory;
agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
agp_bridge->free_by_type = agp_generic_free_by_type;
agp_bridge->agp_alloc_page = agp_generic_alloc_page;
agp_bridge->agp_destroy_page = agp_generic_destroy_page;
agp_bridge->cant_use_aperture = 1;
return hp_zx1_ioc_init();
}
struct agp_bridge_driver hp_zx1_driver = {
.owner = THIS_MODULE,
.masks = hp_zx1_masks,
.size_type = FIXED_APER_SIZE,
.configure = hp_zx1_configure,
.fetch_size = hp_zx1_fetch_size,
.cleanup = hp_zx1_cleanup,
.tlb_flush = hp_zx1_tlbflush,
.mask_memory = hp_zx1_mask_memory,
.agp_enable = agp_generic_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = hp_zx1_create_gatt_table,
.free_gatt_table = hp_zx1_free_gatt_table,
.insert_memory = hp_zx1_insert_memory,
.remove_memory = hp_zx1_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
.cant_use_aperture = 1,
};
static int __init agp_find_supported_device(struct pci_dev *dev)
static int __init agp_hp_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
agp_bridge->dev = dev;
struct agp_bridge_data *bridge;
int error;
/* ZX1 LBAs can be either PCI or AGP bridges */
if (pci_find_capability(dev, PCI_CAP_ID_AGP)) {
printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n",
dev->slot_name);
agp_bridge->type = HP_ZX1;
agp_bridge->dev = dev;
return hp_zx1_setup(dev);
}
if (!pci_find_capability(pdev, PCI_CAP_ID_AGP))
return -ENODEV;
}
static struct agp_driver hp_agp_driver = {
.owner = THIS_MODULE,
};
printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n",
pdev->slot_name);
error = hp_zx1_ioc_init();
if (error)
return error;
static int __init agp_hp_probe (struct pci_dev *dev, const struct pci_device_id *ent)
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
bridge->driver = &hp_zx1_driver;
bridge->dev = pdev;
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
static void __devexit agp_hp_remove(struct pci_dev *pdev)
{
if (agp_find_supported_device(dev) == 0) {
hp_agp_driver.dev = dev;
agp_register_driver(&hp_agp_driver);
return 0;
}
return -ENODEV;
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
}
static struct pci_device_id agp_hp_pci_table[] __initdata = {
......@@ -400,22 +404,16 @@ static struct __initdata pci_driver agp_hp_pci_driver = {
.name = "agpgart-hp",
.id_table = agp_hp_pci_table,
.probe = agp_hp_probe,
.remove = agp_hp_remove,
};
static int __init agp_hp_init(void)
{
int ret_val;
ret_val = pci_module_init(&agp_hp_pci_driver);
if (ret_val)
agp_bridge->type = NOT_SUPPORTED;
return ret_val;
return pci_module_init(&agp_hp_pci_driver);
}
static void __exit agp_hp_cleanup(void)
{
agp_unregister_driver(&hp_agp_driver);
pci_unregister_driver(&agp_hp_pci_driver);
}
......
......@@ -69,7 +69,7 @@ static struct {
} *lp_desc;
} i460;
static const struct aper_size_info_8 i460_sizes[3] =
static struct aper_size_info_8 i460_sizes[3] =
{
/*
* The 32GB aperture is only available with a 4M GART page size. Due to the
......@@ -107,7 +107,7 @@ static int i460_fetch_size (void)
return 0;
}
values = A_SIZE_8(agp_bridge->aperture_sizes);
values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp);
......@@ -130,7 +130,7 @@ static int i460_fetch_size (void)
else
i460.dynamic_apbase = INTEL_I460_APBASE;
for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
/*
* Dynamically calculate the proper num_entries and page_order values for
* the define aperture sizes. Take care not to shift off the end of
......@@ -140,7 +140,7 @@ static int i460_fetch_size (void)
values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
}
for (i = 0; i < agp_bridge->num_aperture_sizes; i++) {
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
/* Neglect control bits when matching up size_value */
if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) {
agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
......@@ -294,7 +294,7 @@ static int i460_insert_memory_small_io_page (agp_memory *mem, off_t pg_start, in
j = io_pg_start;
while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) {
if (!PGE_EMPTY(RD_GATT(j))) {
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;
......@@ -306,7 +306,7 @@ static int i460_insert_memory_small_io_page (agp_memory *mem, off_t pg_start, in
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->mask_memory(paddr, mem->type));
WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type));
}
WR_FLUSH_GATT(j - 1);
return 0;
......@@ -417,7 +417,7 @@ static int i460_insert_memory_large_io_page (agp_memory * mem, off_t pg_start, i
if (i460_alloc_large_page(lp) < 0)
return -ENOMEM;
pg = lp - i460.lp_desc;
WR_GATT(pg, agp_bridge->mask_memory(lp->paddr, 0));
WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0));
WR_FLUSH_GATT(pg);
}
......@@ -439,7 +439,7 @@ static int i460_remove_memory_large_io_page (agp_memory * mem, off_t pg_start, i
struct lp_desc *start, *end, *lp;
void *temp;
temp = agp_bridge->current_size;
temp = agp_bridge->driver->current_size;
num_entries = A_SIZE_8(temp)->num_entries;
/* Figure out what pg_start means in terms of our large GART pages */
......@@ -519,64 +519,71 @@ static void i460_destroy_page (void *page)
static unsigned long i460_mask_memory (unsigned long addr, int type)
{
/* Make sure the returned address is a valid GATT entry */
return (agp_bridge->masks[0].mask
return (agp_bridge->driver->masks[0].mask
| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12));
}
static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused)))
{
agp_bridge->masks = i460_masks;
agp_bridge->aperture_sizes = (void *) i460_sizes;
agp_bridge->size_type = U8_APER_SIZE;
agp_bridge->num_aperture_sizes = 3;
agp_bridge->dev_private_data = NULL;
agp_bridge->needs_scratch_page = FALSE;
agp_bridge->configure = i460_configure;
agp_bridge->fetch_size = i460_fetch_size;
agp_bridge->cleanup = i460_cleanup;
agp_bridge->tlb_flush = i460_tlb_flush;
agp_bridge->mask_memory = i460_mask_memory;
agp_bridge->agp_enable = agp_generic_enable;
agp_bridge->cache_flush = global_cache_flush;
agp_bridge->create_gatt_table = i460_create_gatt_table;
agp_bridge->free_gatt_table = i460_free_gatt_table;
struct agp_bridge_driver intel_i460_driver = {
.owner = THIS_MODULE,
.masks = i460_masks,
.aperture_sizes = i460_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 3,
.configure = i460_configure,
.fetch_size = i460_fetch_size,
.cleanup = i460_cleanup,
.tlb_flush = i460_tlb_flush,
.mask_memory = i460_mask_memory,
.agp_enable = agp_generic_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = i460_create_gatt_table,
.free_gatt_table = i460_free_gatt_table,
#if I460_LARGE_IO_PAGES
agp_bridge->insert_memory = i460_insert_memory;
agp_bridge->remove_memory = i460_remove_memory;
agp_bridge->agp_alloc_page = i460_alloc_page;
agp_bridge->agp_destroy_page = i460_destroy_page;
.insert_memory = i460_insert_memory,
.remove_memory = i460_remove_memory,
.agp_alloc_page = i460_alloc_page,
.agp_destroy_page = i460_destroy_page,
#else
agp_bridge->insert_memory = i460_insert_memory_small_io_page;
agp_bridge->remove_memory = i460_remove_memory_small_io_page;
agp_bridge->agp_alloc_page = agp_generic_alloc_page;
agp_bridge->agp_destroy_page = agp_generic_destroy_page;
.insert_memory = i460_insert_memory_small_io_page,
.remove_memory = i460_remove_memory_small_io_page,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
#endif
agp_bridge->alloc_by_type = agp_generic_alloc_by_type;
agp_bridge->free_by_type = agp_generic_free_by_type;
agp_bridge->suspend = agp_generic_suspend;
agp_bridge->resume = agp_generic_resume;
agp_bridge->cant_use_aperture = 1;
return 0;
}
static struct agp_driver i460_agp_driver = {
.owner = THIS_MODULE,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.suspend = agp_generic_suspend,
.resume = agp_generic_resume,
.cant_use_aperture = 1,
};
static int __init agp_intel_i460_probe (struct pci_dev *dev, const struct pci_device_id *ent)
static int __init agp_intel_i460_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u8 cap_ptr = 0;
struct agp_bridge_data *bridge;
u8 cap_ptr;
cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
if (cap_ptr == 0)
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
agp_bridge->dev = dev;
agp_bridge->capndx = cap_ptr;
intel_i460_setup(dev);
i460_agp_driver.dev = dev;
agp_register_driver(&i460_agp_driver);
return 0;
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
bridge->driver = &intel_i460_driver;
bridge->dev = pdev;
bridge->capndx = cap_ptr;
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
}
static struct pci_device_id agp_intel_i460_pci_table[] __initdata = {
......@@ -597,22 +604,16 @@ static struct __initdata pci_driver agp_intel_i460_pci_driver = {
.name = "agpgart-intel-i460",
.id_table = agp_intel_i460_pci_table,
.probe = agp_intel_i460_probe,
.remove = agp_intel_i460_remove,
};
static int __init agp_intel_i460_init(void)
{
int ret_val;
ret_val = pci_module_init(&agp_intel_i460_pci_driver);
if (ret_val)
agp_bridge->type = NOT_SUPPORTED;
return ret_val;
return pci_module_init(&agp_intel_i460_pci_driver);
}
static void __exit agp_intel_i460_cleanup(void)
{
agp_unregister_driver(&i460_agp_driver);
pci_unregister_driver(&agp_intel_i460_pci_driver);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -112,10 +112,6 @@ typedef struct _agp_unbind {
#define AGPGART_MINOR 175
#define AGP_UNLOCK() up(&(agp_fe.agp_mutex));
#define AGP_LOCK() down(&(agp_fe.agp_mutex));
#define AGP_LOCK_INIT() sema_init(&(agp_fe.agp_mutex), 1)
#ifndef _AGP_BACKEND_H
struct _agp_version {
u16 major;
......
......@@ -1007,7 +1007,9 @@
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C
#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0
#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4
#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE 0x01bc
#define PCI_DEVICE_ID_NVIDIA_NFORCE2 0x01e0
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3 0x0200
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202
......@@ -1902,10 +1904,11 @@
#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562
#define PCI_DEVICE_ID_INTEL_82865_HB 0x2570
#define PCI_DEVICE_ID_INTEL_82865_IG 0x2572
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
#define PCI_DEVICE_ID_INTEL_82855_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855_IG 0x3582
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment