Commit fe2839b3 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-dj.bkbits.net/agpgart

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents e537d26b c0231af3
...@@ -802,7 +802,6 @@ CONFIG_AGP=y ...@@ -802,7 +802,6 @@ CONFIG_AGP=y
# CONFIG_AGP_AMD is not set # CONFIG_AGP_AMD is not set
# CONFIG_AGP_AMD64 is not set # CONFIG_AGP_AMD64 is not set
CONFIG_AGP_INTEL=y CONFIG_AGP_INTEL=y
CONFIG_AGP_INTEL_MCH=m
# CONFIG_AGP_NVIDIA is not set # CONFIG_AGP_NVIDIA is not set
# CONFIG_AGP_SIS is not set # CONFIG_AGP_SIS is not set
# CONFIG_AGP_SWORKS is not set # CONFIG_AGP_SWORKS is not set
......
...@@ -672,7 +672,6 @@ CONFIG_RTC=y ...@@ -672,7 +672,6 @@ CONFIG_RTC=y
# #
CONFIG_AGP=y CONFIG_AGP=y
CONFIG_AGP_AMD64=y CONFIG_AGP_AMD64=y
# CONFIG_AGP_INTEL_MCH is not set
# CONFIG_DRM is not set # CONFIG_DRM is not set
# CONFIG_MWAVE is not set # CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y CONFIG_RAW_DRIVER=y
......
...@@ -789,7 +789,7 @@ static int __init pci_iommu_init(void) ...@@ -789,7 +789,7 @@ static int __init pci_iommu_init(void)
/* Add other K8 AGP bridge drivers here */ /* Add other K8 AGP bridge drivers here */
no_agp = no_agp || no_agp = no_agp ||
(agp_amd64_init() < 0) || (agp_amd64_init() < 0) ||
(agp_copy_info(&info) < 0); (agp_copy_info(agp_bridge, &info) < 0);
#endif #endif
if (swiotlb) { if (swiotlb) {
......
...@@ -89,16 +89,6 @@ config AGP_INTEL ...@@ -89,16 +89,6 @@ config AGP_INTEL
use GLX or DRI, or if you have any Intel integrated graphics use GLX or DRI, or if you have any Intel integrated graphics
chipsets. If unsure, say Y. chipsets. If unsure, say Y.
config AGP_INTEL_MCH
tristate "Intel i865 chipset support"
depends on AGP && X86
help
This option gives you AGP support for the GLX component of XFree86 4.x
on Intel chipsets that support Intel EM64T processors.
You should say Y here if you use XFree86 3.3.6 or 4.x and want to
use GLX or DRI. If unsure, say Y.
config AGP_NVIDIA config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support" tristate "NVIDIA nForce/nForce2 chipset support"
depends on AGP && X86 && !X86_64 depends on AGP && X86 && !X86_64
......
...@@ -9,7 +9,6 @@ obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o ...@@ -9,7 +9,6 @@ obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o
obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o
obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL_MCH) += intel-mch-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o obj-$(CONFIG_AGP_SIS) += sis-agp.o
......
/* /*
* AGPGART * AGPGART
* Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2004 Dave Jones * Copyright (C) 2002-2004 Dave Jones
* Copyright (C) 1999 Jeff Hartmann * Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Precision Insight, Inc.
...@@ -100,18 +101,19 @@ struct agp_bridge_driver { ...@@ -100,18 +101,19 @@ struct agp_bridge_driver {
struct gatt_mask *masks; struct gatt_mask *masks;
int (*fetch_size)(void); int (*fetch_size)(void);
int (*configure)(void); int (*configure)(void);
void (*agp_enable)(u32); void (*agp_enable)(struct agp_bridge_data *, u32);
void (*cleanup)(void); void (*cleanup)(void);
void (*tlb_flush)(struct agp_memory *); void (*tlb_flush)(struct agp_memory *);
unsigned long (*mask_memory)(unsigned long, int); unsigned long (*mask_memory)(struct agp_bridge_data *,
unsigned long, int);
void (*cache_flush)(void); void (*cache_flush)(void);
int (*create_gatt_table)(void); int (*create_gatt_table)(struct agp_bridge_data *);
int (*free_gatt_table)(void); int (*free_gatt_table)(struct agp_bridge_data *);
int (*insert_memory)(struct agp_memory *, off_t, int); int (*insert_memory)(struct agp_memory *, off_t, int);
int (*remove_memory)(struct agp_memory *, off_t, int); int (*remove_memory)(struct agp_memory *, off_t, int);
struct agp_memory *(*alloc_by_type) (size_t, int); struct agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type)(struct agp_memory *); void (*free_by_type)(struct agp_memory *);
void *(*agp_alloc_page)(void); void *(*agp_alloc_page)(struct agp_bridge_data *);
void (*agp_destroy_page)(void *); void (*agp_destroy_page)(void *);
}; };
...@@ -137,8 +139,10 @@ struct agp_bridge_data { ...@@ -137,8 +139,10 @@ struct agp_bridge_data {
int max_memory_agp; /* in number of pages */ int max_memory_agp; /* in number of pages */
int aperture_size_idx; int aperture_size_idx;
int capndx; int capndx;
int flags;
char major_version; char major_version;
char minor_version; char minor_version;
struct list_head list;
}; };
#define KB(x) ((x) * 1024) #define KB(x) ((x) * 1024)
...@@ -243,24 +247,26 @@ int agp_frontend_initialize(void); ...@@ -243,24 +247,26 @@ int agp_frontend_initialize(void);
void agp_frontend_cleanup(void); void agp_frontend_cleanup(void);
/* Generic routines. */ /* Generic routines. */
void agp_generic_enable(u32 mode); void agp_generic_enable(struct agp_bridge_data *bridge, u32 mode);
int agp_generic_create_gatt_table(void); int agp_generic_create_gatt_table(struct agp_bridge_data *bridge);
int agp_generic_free_gatt_table(void); int agp_generic_free_gatt_table(struct agp_bridge_data *bridge);
struct agp_memory *agp_create_memory(int scratch_pages); struct agp_memory *agp_create_memory(int scratch_pages);
int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type); int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type);
int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type); int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
void agp_generic_free_by_type(struct agp_memory *curr); void agp_generic_free_by_type(struct agp_memory *curr);
void *agp_generic_alloc_page(void); void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
void agp_generic_destroy_page(void *addr); void agp_generic_destroy_page(void *addr);
void agp_free_key(int key); void agp_free_key(int key);
int agp_num_entries(void); int agp_num_entries(void);
u32 agp_collect_device_status(u32 mode, u32 command); u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
void agp_device_command(u32 command, int agp_v3); void agp_device_command(u32 command, int agp_v3);
int agp_3_5_enable(struct agp_bridge_data *bridge); int agp_3_5_enable(struct agp_bridge_data *bridge);
void global_cache_flush(void); void global_cache_flush(void);
void get_agp_version(struct agp_bridge_data *bridge); void get_agp_version(struct agp_bridge_data *bridge);
unsigned long agp_generic_mask_memory(unsigned long addr, int type); unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
unsigned long addr, int type);
struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
/* generic routines for agp>=3 */ /* generic routines for agp>=3 */
int agp3_generic_fetch_size(void); int agp3_generic_fetch_size(void);
...@@ -315,4 +321,11 @@ extern int agp_try_unsupported_boot; ...@@ -315,4 +321,11 @@ extern int agp_try_unsupported_boot;
#define AGPCTRL_APERENB (1<<8) #define AGPCTRL_APERENB (1<<8)
#define AGPCTRL_GTLBEN (1<<7) #define AGPCTRL_GTLBEN (1<<7)
#define AGP2_RESERVED_MASK 0x00fffcc8
#define AGP3_RESERVED_MASK 0x00ff00cc
#define AGP_ERRATA_FASTWRITES 1<<0
#define AGP_ERRATA_SBA 1<<1
#define AGP_ERRATA_1X 1<<2
#endif /* _AGP_BACKEND_PRIV_H */ #endif /* _AGP_BACKEND_PRIV_H */
...@@ -139,9 +139,9 @@ static void m1541_cache_flush(void) ...@@ -139,9 +139,9 @@ static void m1541_cache_flush(void)
} }
} }
static void *m1541_alloc_page(void) static void *m1541_alloc_page(struct agp_bridge_data *bridge)
{ {
void *addr = agp_generic_alloc_page(); void *addr = agp_generic_alloc_page(agp_bridge);
u32 temp; u32 temp;
if (!addr) if (!addr)
...@@ -398,7 +398,7 @@ static int __init agp_ali_init(void) ...@@ -398,7 +398,7 @@ static int __init agp_ali_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_ali_pci_driver); return pci_register_driver(&agp_ali_pci_driver);
} }
static void __exit agp_ali_cleanup(void) static void __exit agp_ali_cleanup(void)
......
...@@ -76,11 +76,12 @@ static void alpha_core_agp_tlbflush(struct agp_memory *mem) ...@@ -76,11 +76,12 @@ static void alpha_core_agp_tlbflush(struct agp_memory *mem)
alpha_mv.mv_pci_tbi(agp->hose, 0, -1); alpha_mv.mv_pci_tbi(agp->hose, 0, -1);
} }
static void alpha_core_agp_enable(u32 mode) static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
alpha_agp_info *agp = agp_bridge->dev_private_data; alpha_agp_info *agp = bridge->dev_private_data;
agp->mode.lw = agp_collect_device_status(mode, agp->capability.lw); agp->mode.lw = agp_collect_device_status(bridge, mode,
agp->capability.lw);
agp->mode.bits.enable = 1; agp->mode.bits.enable = 1;
agp->ops->configure(agp); agp->ops->configure(agp);
......
...@@ -132,7 +132,7 @@ static int amd_create_gatt_pages(int nr_tables) ...@@ -132,7 +132,7 @@ static int amd_create_gatt_pages(int nr_tables)
#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\ #define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped) GET_PAGE_DIR_IDX(addr)]->remapped)
static int amd_create_gatt_table(void) static int amd_create_gatt_table(struct agp_bridge_data *bridge)
{ {
struct aper_size_info_lvl2 *value; struct aper_size_info_lvl2 *value;
struct amd_page_map page_dir; struct amd_page_map page_dir;
...@@ -175,7 +175,7 @@ static int amd_create_gatt_table(void) ...@@ -175,7 +175,7 @@ static int amd_create_gatt_table(void)
return 0; return 0;
} }
static int amd_free_gatt_table(void) static int amd_free_gatt_table(struct agp_bridge_data *bridge)
{ {
struct amd_page_map page_dir; struct amd_page_map page_dir;
...@@ -314,7 +314,8 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) ...@@ -314,7 +314,8 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr); cur_gatt = GET_GATT(addr);
writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); writel(agp_generic_mask_memory(agp_bridge,
mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
} }
amd_irongate_tlbflush(mem); amd_irongate_tlbflush(mem);
...@@ -421,6 +422,53 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, ...@@ -421,6 +422,53 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
bridge->dev = pdev; bridge->dev = pdev;
bridge->capndx = cap_ptr; bridge->capndx = cap_ptr;
/* 751 Errata (22564_B-1.PDF)
erratum 20: strobe glitch with Nvidia NV10 GeForce cards.
system controller may experience noise due to strong drive strengths
*/
if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
u8 cap_ptr=0;
struct pci_dev *gfxcard=NULL;
while (!cap_ptr) {
gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
if (!gfxcard) {
printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
return -ENODEV;
}
cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
if (!cap_ptr) {
pci_dev_put(gfxcard);
continue;
}
}
/* With so many variants of NVidia cards, it's simpler just
to blacklist them all, and then whitelist them as needed
(if necessary at all). */
if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) {
agp_bridge->flags |= AGP_ERRATA_1X;
printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n");
}
pci_dev_put(gfxcard);
}
/* 761 Errata (23613_F.pdf)
* Revisions B0/B1 were a disaster.
* erratum 44: SYSCLK/AGPCLK skew causes 2X failures -- Force mode to 1X
* erratum 45: Timing problem prevents fast writes -- Disable fast write.
* erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
* With this lot disabled, we should prevent lockups. */
if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
u8 revision=0;
pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
if (revision == 0x10 || revision == 0x11) {
agp_bridge->flags = AGP_ERRATA_FASTWRITES;
agp_bridge->flags |= AGP_ERRATA_SBA;
agp_bridge->flags |= AGP_ERRATA_1X;
printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n");
}
}
/* Fill in the mode register */ /* Fill in the mode register */
pci_read_config_dword(pdev, pci_read_config_dword(pdev,
bridge->capndx+PCI_AGP_STATUS, bridge->capndx+PCI_AGP_STATUS,
...@@ -480,7 +528,7 @@ static int __init agp_amdk7_init(void) ...@@ -480,7 +528,7 @@ static int __init agp_amdk7_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_amdk7_pci_driver); return pci_register_driver(&agp_amdk7_pci_driver);
} }
static void __exit agp_amdk7_cleanup(void) static void __exit agp_amdk7_cleanup(void)
......
...@@ -106,7 +106,8 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) ...@@ -106,7 +106,8 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
} }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type); tmp = agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type);
BUG_ON(tmp & 0xffffff0000000ffcULL); BUG_ON(tmp & 0xffffff0000000ffcULL);
pte = (tmp & 0x000000ff00000000ULL) >> 28; pte = (tmp & 0x000000ff00000000ULL) >> 28;
...@@ -709,7 +710,7 @@ int __init agp_amd64_init(void) ...@@ -709,7 +710,7 @@ int __init agp_amd64_init(void)
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
if (pci_module_init(&agp_amd64_pci_driver) > 0) { if (pci_register_driver(&agp_amd64_pci_driver) > 0) {
struct pci_dev *dev; struct pci_dev *dev;
if (!agp_try_unsupported && !agp_try_unsupported_boot) { if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n"); printk(KERN_INFO PFX "No supported AGP bridge found.\n");
......
...@@ -291,7 +291,8 @@ static int ati_insert_memory(struct agp_memory * mem, ...@@ -291,7 +291,8 @@ static int ati_insert_memory(struct agp_memory * mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr); cur_gatt = GET_GATT(addr);
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); 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. */ readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
} }
agp_bridge->driver->tlb_flush(mem); agp_bridge->driver->tlb_flush(mem);
...@@ -319,7 +320,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, ...@@ -319,7 +320,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
return 0; 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; struct aper_size_info_lvl2 *value;
ati_page_map page_dir; ati_page_map page_dir;
...@@ -380,7 +381,7 @@ static int ati_create_gatt_table(void) ...@@ -380,7 +381,7 @@ static int ati_create_gatt_table(void)
return 0; 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; ati_page_map page_dir;
...@@ -531,7 +532,7 @@ static int __init agp_ati_init(void) ...@@ -531,7 +532,7 @@ static int __init agp_ati_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_ati_pci_driver); return pci_register_driver(&agp_ati_pci_driver);
} }
static void __exit agp_ati_cleanup(void) static void __exit agp_ati_cleanup(void)
......
/* /*
* AGPGART driver backend routines. * AGPGART driver backend routines.
* Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones. * Copyright (C) 2002-2003 Dave Jones.
* Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Jeff Hartmann.
* Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Precision Insight, Inc.
...@@ -42,34 +43,38 @@ ...@@ -42,34 +43,38 @@
* fix some real stupidity. It's only by chance we can bump * fix some real stupidity. It's only by chance we can bump
* past 0.99 at all due to some boolean logic error. */ * past 0.99 at all due to some boolean logic error. */
#define AGPGART_VERSION_MAJOR 0 #define AGPGART_VERSION_MAJOR 0
#define AGPGART_VERSION_MINOR 100 #define AGPGART_VERSION_MINOR 101
static struct agp_version agp_current_version = static struct agp_version agp_current_version =
{ {
.major = AGPGART_VERSION_MAJOR, .major = AGPGART_VERSION_MAJOR,
.minor = AGPGART_VERSION_MINOR, .minor = AGPGART_VERSION_MINOR,
}; };
static int agp_count=0; struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *) =
&agp_generic_find_bridge;
struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED }; struct agp_bridge_data *agp_bridge;
struct agp_bridge_data *agp_bridge = &agp_bridge_dummy; LIST_HEAD(agp_bridges);
EXPORT_SYMBOL(agp_bridge); EXPORT_SYMBOL(agp_bridge);
EXPORT_SYMBOL(agp_bridges);
/** /**
* agp_backend_acquire - attempt to acquire the agp backend. * agp_backend_acquire - attempt to acquire an agp backend.
* *
* returns -EBUSY if agp is in use,
* returns 0 if the caller owns the agp backend
*/ */
int agp_backend_acquire(void) struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
{ {
if (agp_bridge->type == NOT_SUPPORTED) struct agp_bridge_data *bridge;
return -EINVAL;
if (atomic_read(&agp_bridge->agp_in_use)) bridge = agp_find_bridge(pdev);
return -EBUSY;
atomic_inc(&agp_bridge->agp_in_use); if (!bridge)
return 0; return NULL;
if (atomic_read(&bridge->agp_in_use))
return NULL;
atomic_inc(&bridge->agp_in_use);
return bridge;
} }
EXPORT_SYMBOL(agp_backend_acquire); EXPORT_SYMBOL(agp_backend_acquire);
...@@ -82,10 +87,11 @@ EXPORT_SYMBOL(agp_backend_acquire); ...@@ -82,10 +87,11 @@ EXPORT_SYMBOL(agp_backend_acquire);
* *
* (Ensure that all memory it bound is unbound.) * (Ensure that all memory it bound is unbound.)
*/ */
void agp_backend_release(void) void agp_backend_release(struct agp_bridge_data *bridge)
{ {
if (agp_bridge->type != NOT_SUPPORTED)
atomic_dec(&agp_bridge->agp_in_use); if (bridge)
atomic_dec(&bridge->agp_in_use);
} }
EXPORT_SYMBOL(agp_backend_release); EXPORT_SYMBOL(agp_backend_release);
...@@ -121,7 +127,6 @@ static int agp_find_max(void) ...@@ -121,7 +127,6 @@ static int agp_find_max(void)
(maxes_table[index].agp - maxes_table[index - 1].agp)) / (maxes_table[index].agp - maxes_table[index - 1].agp)) /
(maxes_table[index].mem - maxes_table[index - 1].mem); (maxes_table[index].mem - maxes_table[index - 1].mem);
printk(KERN_INFO PFX "Maximum main memory to use for agp memory: %ldM\n", result);
result = result << (20 - PAGE_SHIFT); result = result << (20 - PAGE_SHIFT);
return result; return result;
} }
...@@ -135,7 +140,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -135,7 +140,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->version = &agp_current_version; bridge->version = &agp_current_version;
if (bridge->driver->needs_scratch_page) { if (bridge->driver->needs_scratch_page) {
void *addr = bridge->driver->agp_alloc_page(); void *addr = bridge->driver->agp_alloc_page(bridge);
if (!addr) { if (!addr) {
printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
...@@ -144,7 +149,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -144,7 +149,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->scratch_page_real = virt_to_phys(addr); bridge->scratch_page_real = virt_to_phys(addr);
bridge->scratch_page = bridge->scratch_page =
bridge->driver->mask_memory(bridge->scratch_page_real, 0); bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
} }
size_value = bridge->driver->fetch_size(); size_value = bridge->driver->fetch_size();
...@@ -153,7 +158,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -153,7 +158,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
rc = -EINVAL; rc = -EINVAL;
goto err_out; goto err_out;
} }
if (bridge->driver->create_gatt_table()) { if (bridge->driver->create_gatt_table(bridge)) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"unable to get memory for graphics translation table.\n"); "unable to get memory for graphics translation table.\n");
rc = -ENOMEM; rc = -ENOMEM;
...@@ -178,9 +183,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -178,9 +183,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
goto err_out; goto err_out;
} }
printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
size_value, bridge->gart_bus_addr);
return 0; return 0;
err_out: err_out:
...@@ -188,7 +190,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -188,7 +190,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->driver->agp_destroy_page( bridge->driver->agp_destroy_page(
phys_to_virt(bridge->scratch_page_real)); phys_to_virt(bridge->scratch_page_real));
if (got_gatt) if (got_gatt)
bridge->driver->free_gatt_table(); bridge->driver->free_gatt_table(bridge);
if (got_keylist) { if (got_keylist) {
vfree(bridge->key_list); vfree(bridge->key_list);
bridge->key_list = NULL; bridge->key_list = NULL;
...@@ -202,7 +204,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) ...@@ -202,7 +204,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->cleanup) if (bridge->driver->cleanup)
bridge->driver->cleanup(); bridge->driver->cleanup();
if (bridge->driver->free_gatt_table) if (bridge->driver->free_gatt_table)
bridge->driver->free_gatt_table(); bridge->driver->free_gatt_table(bridge);
if (bridge->key_list) { if (bridge->key_list) {
vfree(bridge->key_list); vfree(bridge->key_list);
bridge->key_list = NULL; bridge->key_list = NULL;
...@@ -214,16 +216,35 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) ...@@ -214,16 +216,35 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
phys_to_virt(bridge->scratch_page_real)); phys_to_virt(bridge->scratch_page_real));
} }
/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */ /* When we remove the global variable agp_bridge from all drivers
* then agp_alloc_bridge and agp_generic_find_bridge need to be updated
*/
struct agp_bridge_data *agp_alloc_bridge(void) struct agp_bridge_data *agp_alloc_bridge(void)
{ {
return agp_bridge; struct agp_bridge_data *bridge = kmalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return NULL;
memset(bridge, 0, sizeof(*bridge));
atomic_set(&bridge->agp_in_use, 0);
atomic_set(&bridge->current_memory_agp, 0);
if (list_empty(&agp_bridges))
agp_bridge = bridge;
return bridge;
} }
EXPORT_SYMBOL(agp_alloc_bridge); EXPORT_SYMBOL(agp_alloc_bridge);
void agp_put_bridge(struct agp_bridge_data *bridge) void agp_put_bridge(struct agp_bridge_data *bridge)
{ {
kfree(bridge);
if (list_empty(&agp_bridges))
agp_bridge = NULL;
} }
EXPORT_SYMBOL(agp_put_bridge); EXPORT_SYMBOL(agp_put_bridge);
...@@ -240,40 +261,38 @@ int agp_add_bridge(struct agp_bridge_data *bridge) ...@@ -240,40 +261,38 @@ int agp_add_bridge(struct agp_bridge_data *bridge)
return -EINVAL; return -EINVAL;
} }
if (agp_count) {
printk (KERN_INFO PFX
"Only one agpgart device currently supported.\n");
return -ENODEV;
}
/* Grab reference on the chipset driver. */ /* Grab reference on the chipset driver. */
if (!try_module_get(bridge->driver->owner)) { if (!try_module_get(bridge->driver->owner)) {
printk (KERN_INFO PFX "Couldn't lock chipset driver.\n"); printk (KERN_INFO PFX "Couldn't lock chipset driver.\n");
return -EINVAL; return -EINVAL;
} }
bridge->type = SUPPORTED; error = agp_backend_initialize(bridge);
error = agp_backend_initialize(agp_bridge);
if (error) { if (error) {
printk (KERN_INFO PFX "agp_backend_initialize() failed.\n"); printk (KERN_INFO PFX "agp_backend_initialize() failed.\n");
goto err_out; goto err_out;
} }
if (list_empty(&agp_bridges)) {
error = agp_frontend_initialize(); error = agp_frontend_initialize();
if (error) { if (error) {
printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n"); printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
goto frontend_err; goto frontend_err;
} }
agp_count++; printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
bridge->driver->fetch_size(), bridge->gart_bus_addr);
}
list_add(&bridge->list, &agp_bridges);
return 0; return 0;
frontend_err: frontend_err:
agp_backend_cleanup(agp_bridge); agp_backend_cleanup(bridge);
err_out: err_out:
bridge->type = NOT_SUPPORTED;
module_put(bridge->driver->owner); module_put(bridge->driver->owner);
agp_put_bridge(bridge);
return error; return error;
} }
EXPORT_SYMBOL_GPL(agp_add_bridge); EXPORT_SYMBOL_GPL(agp_add_bridge);
...@@ -281,10 +300,10 @@ EXPORT_SYMBOL_GPL(agp_add_bridge); ...@@ -281,10 +300,10 @@ EXPORT_SYMBOL_GPL(agp_add_bridge);
void agp_remove_bridge(struct agp_bridge_data *bridge) void agp_remove_bridge(struct agp_bridge_data *bridge)
{ {
bridge->type = NOT_SUPPORTED;
agp_frontend_cleanup();
agp_backend_cleanup(bridge); agp_backend_cleanup(bridge);
agp_count--; list_del(&bridge->list);
if (list_empty(&agp_bridges))
agp_frontend_cleanup();
module_put(bridge->driver->owner); module_put(bridge->driver->owner);
} }
EXPORT_SYMBOL_GPL(agp_remove_bridge); EXPORT_SYMBOL_GPL(agp_remove_bridge);
......
...@@ -148,7 +148,7 @@ static int efficeon_configure(void) ...@@ -148,7 +148,7 @@ static int efficeon_configure(void)
return 0; return 0;
} }
static int efficeon_free_gatt_table(void) static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
{ {
int index, freed = 0; int index, freed = 0;
...@@ -183,7 +183,7 @@ static int efficeon_free_gatt_table(void) ...@@ -183,7 +183,7 @@ static int efficeon_free_gatt_table(void)
#define GET_GATT(addr) (efficeon_private.gatt_pages[\ #define GET_GATT(addr) (efficeon_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped) GET_PAGE_DIR_IDX(addr)]->remapped)
static int efficeon_create_gatt_table(void) static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
{ {
int index; int index;
const int pati = EFFICEON_PATI; const int pati = EFFICEON_PATI;
...@@ -209,7 +209,7 @@ static int efficeon_create_gatt_table(void) ...@@ -209,7 +209,7 @@ static int efficeon_create_gatt_table(void)
page = get_zeroed_page(GFP_KERNEL); page = get_zeroed_page(GFP_KERNEL);
if (!page) { if (!page) {
efficeon_free_gatt_table(); efficeon_free_gatt_table(agp_bridge);
return -ENOMEM; return -ENOMEM;
} }
SetPageReserved(virt_to_page((char *)page)); SetPageReserved(virt_to_page((char *)page));
...@@ -448,7 +448,7 @@ static int __init agp_efficeon_init(void) ...@@ -448,7 +448,7 @@ static int __init agp_efficeon_init(void)
return 0; return 0;
agp_initialised=1; agp_initialised=1;
return pci_module_init(&agp_efficeon_pci_driver); return pci_register_driver(&agp_efficeon_pci_driver);
} }
static void __exit agp_efficeon_cleanup(void) static void __exit agp_efficeon_cleanup(void)
......
/* /*
* AGPGART driver frontend * AGPGART driver frontend
* Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones * Copyright (C) 2002-2003 Dave Jones
* Copyright (C) 1999 Jeff Hartmann * Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Precision Insight, Inc.
...@@ -299,7 +300,7 @@ static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) ...@@ -299,7 +300,7 @@ static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
{ {
struct agp_memory *memory; struct agp_memory *memory;
memory = agp_allocate_memory(pg_count, type); memory = agp_allocate_memory(agp_bridge, pg_count, type);
if (memory == NULL) if (memory == NULL)
return NULL; return NULL;
...@@ -420,7 +421,7 @@ static int agp_remove_controller(struct agp_controller *controller) ...@@ -420,7 +421,7 @@ static int agp_remove_controller(struct agp_controller *controller)
if (agp_fe.current_controller == controller) { if (agp_fe.current_controller == controller) {
agp_fe.current_controller = NULL; agp_fe.current_controller = NULL;
agp_fe.backend_acquired = FALSE; agp_fe.backend_acquired = FALSE;
agp_backend_release(); agp_backend_release(agp_bridge);
} }
kfree(controller); kfree(controller);
return 0; return 0;
...@@ -468,7 +469,7 @@ static void agp_controller_release_current(struct agp_controller *controller, ...@@ -468,7 +469,7 @@ static void agp_controller_release_current(struct agp_controller *controller,
agp_fe.current_controller = NULL; agp_fe.current_controller = NULL;
agp_fe.used_by_controller = FALSE; agp_fe.used_by_controller = FALSE;
agp_backend_release(); agp_backend_release(agp_bridge);
} }
/* /*
...@@ -605,7 +606,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -605,7 +606,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
goto out_eperm; goto out_eperm;
agp_copy_info(&kerninfo); agp_copy_info(agp_bridge, &kerninfo);
size = vma->vm_end - vma->vm_start; size = vma->vm_end - vma->vm_start;
current_size = kerninfo.aper_size; current_size = kerninfo.aper_size;
current_size = current_size * 0x100000; current_size = current_size * 0x100000;
...@@ -757,7 +758,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) ...@@ -757,7 +758,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
struct agp_info userinfo; struct agp_info userinfo;
struct agp_kern_info kerninfo; struct agp_kern_info kerninfo;
agp_copy_info(&kerninfo); agp_copy_info(agp_bridge, &kerninfo);
userinfo.version.major = kerninfo.version.major; userinfo.version.major = kerninfo.version.major;
userinfo.version.minor = kerninfo.version.minor; userinfo.version.minor = kerninfo.version.minor;
...@@ -777,7 +778,6 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) ...@@ -777,7 +778,6 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
static int agpioc_acquire_wrap(struct agp_file_private *priv) static int agpioc_acquire_wrap(struct agp_file_private *priv)
{ {
int ret;
struct agp_controller *controller; struct agp_controller *controller;
DBG(""); DBG("");
...@@ -788,11 +788,15 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv) ...@@ -788,11 +788,15 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (agp_fe.current_controller != NULL) if (agp_fe.current_controller != NULL)
return -EBUSY; return -EBUSY;
ret = agp_backend_acquire(); if(!agp_bridge)
if (ret == 0) return -ENODEV;
if (atomic_read(&agp_bridge->agp_in_use))
return -EBUSY;
atomic_inc(&agp_bridge->agp_in_use);
agp_fe.backend_acquired = TRUE; agp_fe.backend_acquired = TRUE;
else
return ret;
controller = agp_find_controller_by_pid(priv->my_pid); controller = agp_find_controller_by_pid(priv->my_pid);
...@@ -803,7 +807,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv) ...@@ -803,7 +807,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (controller == NULL) { if (controller == NULL) {
agp_fe.backend_acquired = FALSE; agp_fe.backend_acquired = FALSE;
agp_backend_release(); agp_backend_release(agp_bridge);
return -ENOMEM; return -ENOMEM;
} }
agp_insert_controller(controller); agp_insert_controller(controller);
...@@ -830,7 +834,7 @@ static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) ...@@ -830,7 +834,7 @@ static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
if (copy_from_user(&mode, arg, sizeof(struct agp_setup))) if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
return -EFAULT; return -EFAULT;
agp_enable(mode.agp_mode); agp_enable(agp_bridge, mode.agp_mode);
return 0; return 0;
} }
......
/* /*
* AGPGART driver. * AGPGART driver.
* Copyright (C) 2002-2004 Dave Jones. * Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2005 Dave Jones.
* Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Jeff Hartmann.
* Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Precision Insight, Inc.
* Copyright (C) 1999 Xi Graphics, Inc. * Copyright (C) 1999 Xi Graphics, Inc.
...@@ -139,19 +140,19 @@ void agp_free_memory(struct agp_memory *curr) ...@@ -139,19 +140,19 @@ void agp_free_memory(struct agp_memory *curr)
{ {
size_t i; size_t i;
if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL)) if (curr == NULL)
return; return;
if (curr->is_bound == TRUE) if (curr->is_bound == TRUE)
agp_unbind_memory(curr); agp_unbind_memory(curr);
if (curr->type != 0) { if (curr->type != 0) {
agp_bridge->driver->free_by_type(curr); curr->bridge->driver->free_by_type(curr);
return; return;
} }
if (curr->page_count != 0) { if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) { for (i = 0; i < curr->page_count; i++) {
agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
} }
} }
agp_free_key(curr->key); agp_free_key(curr->key);
...@@ -173,20 +174,23 @@ EXPORT_SYMBOL(agp_free_memory); ...@@ -173,20 +174,23 @@ EXPORT_SYMBOL(agp_free_memory);
* *
* It returns NULL whenever memory is unavailable. * It returns NULL whenever memory is unavailable.
*/ */
struct agp_memory *agp_allocate_memory(size_t page_count, u32 type) struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
size_t page_count, u32 type)
{ {
int scratch_pages; int scratch_pages;
struct agp_memory *new; struct agp_memory *new;
size_t i; size_t i;
if (agp_bridge->type == NOT_SUPPORTED) if (!bridge)
return NULL; return NULL;
if ((atomic_read(&agp_bridge->current_memory_agp) + page_count) > agp_bridge->max_memory_agp) if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
return NULL; return NULL;
if (type != 0) { if (type != 0) {
new = agp_bridge->driver->alloc_by_type(page_count, type); new = bridge->driver->alloc_by_type(page_count, type);
if (new)
new->bridge = bridge;
return new; return new;
} }
...@@ -198,7 +202,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type) ...@@ -198,7 +202,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
return NULL; return NULL;
for (i = 0; i < page_count; i++) { for (i = 0; i < page_count; i++) {
void *addr = agp_bridge->driver->agp_alloc_page(); void *addr = bridge->driver->agp_alloc_page(bridge);
if (addr == NULL) { if (addr == NULL) {
agp_free_memory(new); agp_free_memory(new);
...@@ -207,6 +211,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type) ...@@ -207,6 +211,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
new->memory[i] = virt_to_phys(addr); new->memory[i] = virt_to_phys(addr);
new->page_count++; new->page_count++;
} }
new->bridge = bridge;
flush_agp_mappings(); flush_agp_mappings();
...@@ -289,6 +294,19 @@ int agp_num_entries(void) ...@@ -289,6 +294,19 @@ int agp_num_entries(void)
EXPORT_SYMBOL_GPL(agp_num_entries); EXPORT_SYMBOL_GPL(agp_num_entries);
static int check_bridge_mode(struct pci_dev *dev)
{
u32 agp3;
u8 cap_ptr;
cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
if (agp3 & AGPSTAT_MODE_3_0)
return 1;
return 0;
}
/** /**
* agp_copy_info - copy bridge state information * agp_copy_info - copy bridge state information
* *
...@@ -297,35 +315,36 @@ EXPORT_SYMBOL_GPL(agp_num_entries); ...@@ -297,35 +315,36 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
* This function copies information about the agp bridge device and the state of * This function copies information about the agp bridge device and the state of
* the agp backend into an agp_kern_info pointer. * the agp backend into an agp_kern_info pointer.
*/ */
int agp_copy_info(struct agp_kern_info *info) int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
{ {
memset(info, 0, sizeof(struct agp_kern_info)); memset(info, 0, sizeof(struct agp_kern_info));
if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED || if (!bridge) {
!agp_bridge->version) {
info->chipset = NOT_SUPPORTED; info->chipset = NOT_SUPPORTED;
return -EIO; return -EIO;
} }
info->version.major = agp_bridge->version->major; info->version.major = bridge->version->major;
info->version.minor = agp_bridge->version->minor; info->version.minor = bridge->version->minor;
info->chipset = agp_bridge->type; info->chipset = SUPPORTED;
info->device = agp_bridge->dev; info->device = bridge->dev;
info->mode = agp_bridge->mode; if (check_bridge_mode(bridge->dev))
info->aper_base = agp_bridge->gart_bus_addr; info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
info->mode = bridge->mode;
info->aper_base = bridge->gart_bus_addr;
info->aper_size = agp_return_size(); info->aper_size = agp_return_size();
info->max_memory = agp_bridge->max_memory_agp; info->max_memory = bridge->max_memory_agp;
info->current_memory = atomic_read(&agp_bridge->current_memory_agp); info->current_memory = atomic_read(&bridge->current_memory_agp);
info->cant_use_aperture = agp_bridge->driver->cant_use_aperture; info->cant_use_aperture = bridge->driver->cant_use_aperture;
info->vm_ops = agp_bridge->vm_ops; info->vm_ops = bridge->vm_ops;
info->page_mask = ~0UL; info->page_mask = ~0UL;
return 0; return 0;
} }
EXPORT_SYMBOL(agp_copy_info); EXPORT_SYMBOL(agp_copy_info);
/* End - Routine to copy over information structure */ /* End - Routine to copy over information structure */
/* /*
* Routines for handling swapping of agp_memory into the GATT - * Routines for handling swapping of agp_memory into the GATT -
* These routines take agp_memory and insert them into the GATT. * These routines take agp_memory and insert them into the GATT.
...@@ -345,7 +364,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) ...@@ -345,7 +364,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
{ {
int ret_val; int ret_val;
if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL)) if (curr == NULL)
return -EINVAL; return -EINVAL;
if (curr->is_bound == TRUE) { if (curr->is_bound == TRUE) {
...@@ -353,10 +372,10 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) ...@@ -353,10 +372,10 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
return -EINVAL; return -EINVAL;
} }
if (curr->is_flushed == FALSE) { if (curr->is_flushed == FALSE) {
agp_bridge->driver->cache_flush(); curr->bridge->driver->cache_flush();
curr->is_flushed = TRUE; curr->is_flushed = TRUE;
} }
ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type); ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
...@@ -380,7 +399,7 @@ int agp_unbind_memory(struct agp_memory *curr) ...@@ -380,7 +399,7 @@ int agp_unbind_memory(struct agp_memory *curr)
{ {
int ret_val; int ret_val;
if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL)) if (curr == NULL)
return -EINVAL; return -EINVAL;
if (curr->is_bound != TRUE) { if (curr->is_bound != TRUE) {
...@@ -388,7 +407,7 @@ int agp_unbind_memory(struct agp_memory *curr) ...@@ -388,7 +407,7 @@ int agp_unbind_memory(struct agp_memory *curr)
return -EINVAL; return -EINVAL;
} }
ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type); ret_val = curr->bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
...@@ -403,71 +422,137 @@ EXPORT_SYMBOL(agp_unbind_memory); ...@@ -403,71 +422,137 @@ EXPORT_SYMBOL(agp_unbind_memory);
/* Generic Agp routines - Start */ /* Generic Agp routines - Start */
static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp) static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
{ {
u32 tmp;
if (*requested_mode & AGP2_RESERVED_MASK) {
printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP2_RESERVED_MASK;
}
/* Check the speed bits make sense. Only one should be set. */
tmp = *requested_mode & 7;
switch (tmp) {
case 0:
printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
*requested_mode |= AGPSTAT2_1X;
break;
case 1:
case 2:
break;
case 3:
*requested_mode &= ~(AGPSTAT2_1X); /* rate=2 */
break;
case 4:
break;
case 5:
case 6:
case 7:
*requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/
break;
}
/* disable SBA if it's not supported */ /* disable SBA if it's not supported */
if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA))) if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
*cmd &= ~AGPSTAT_SBA; *bridge_agpstat &= ~AGPSTAT_SBA;
/* Set speed */ /* Set rate */
if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X))) if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
*cmd &= ~AGPSTAT2_4X; *bridge_agpstat &= ~AGPSTAT2_4X;
if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X))) if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X)))
*cmd &= ~AGPSTAT2_2X; *bridge_agpstat &= ~AGPSTAT2_2X;
if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X))) if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X)))
*cmd &= ~AGPSTAT2_1X; *bridge_agpstat &= ~AGPSTAT2_1X;
/* Now we know what mode it should be, clear out the unwanted bits. */ /* Now we know what mode it should be, clear out the unwanted bits. */
if (*cmd & AGPSTAT2_4X) if (*bridge_agpstat & AGPSTAT2_4X)
*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */
if (*cmd & AGPSTAT2_2X) if (*bridge_agpstat & AGPSTAT2_2X)
*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */
if (*cmd & AGPSTAT2_1X) if (*bridge_agpstat & AGPSTAT2_1X)
*cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */ *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */
/* Apply any errata. */
if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
*bridge_agpstat &= ~AGPSTAT_FW;
if (agp_bridge->flags & AGP_ERRATA_SBA)
*bridge_agpstat &= ~AGPSTAT_SBA;
if (agp_bridge->flags & AGP_ERRATA_1X) {
*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
*bridge_agpstat |= AGPSTAT2_1X;
}
/* If we've dropped down to 1X, disable fast writes. */
if (*bridge_agpstat & AGPSTAT2_1X)
*bridge_agpstat &= ~AGPSTAT_FW;
} }
/* /*
* mode = requested mode. * requested_mode = Mode requested by (typically) X.
* cmd = PCI_AGP_STATUS from agp bridge. * bridge_agpstat = PCI_AGP_STATUS from agp bridge.
* tmp = PCI_AGP_STATUS from graphic card. * vga_agpstat = PCI_AGP_STATUS from graphic card.
*/ */
static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
{ {
u32 origcmd=*cmd, origtmp=*tmp; u32 origbridge=*bridge_agpstat, origvga=*vga_agpstat;
u32 tmp;
if (*requested_mode & AGP3_RESERVED_MASK) {
printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
*requested_mode &= ~AGP3_RESERVED_MASK;
}
/* Check the speed bits make sense. */
tmp = *requested_mode & 7;
if (tmp == 0) {
printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
*requested_mode |= AGPSTAT3_4X;
}
if (tmp == 3) {
printk (KERN_INFO PFX "%s tried to set rate=x3. Setting to AGP3 x4 mode.\n", current->comm);
*requested_mode |= AGPSTAT3_4X;
}
if (tmp >3) {
printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp);
*requested_mode |= AGPSTAT3_8X;
}
/* ARQSZ - Set the value to the maximum one. /* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values. */ * Don't allow the mode register to override values. */
*cmd = ((*cmd & ~AGPSTAT_ARQSZ) | *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ))); max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
/* Calibration cycle. /* Calibration cycle.
* Don't allow the mode register to override values. */ * Don't allow the mode register to override values. */
*cmd = ((*cmd & ~AGPSTAT_CAL_MASK) | *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) |
min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK))); min_t(u32,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK)));
/* SBA *must* be supported for AGP v3 */ /* SBA *must* be supported for AGP v3 */
*cmd |= AGPSTAT_SBA; *bridge_agpstat |= AGPSTAT_SBA;
/* /*
* Set speed. * Set speed.
* Check for invalid speeds. This can happen when applications * Check for invalid speeds. This can happen when applications
* written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
*/ */
if (*mode & AGPSTAT_MODE_3_0) { if (*requested_mode & AGPSTAT_MODE_3_0) {
/* /*
* Caller hasn't a clue what its doing. We are in 3.0 mode, * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode,
* have been passed a 3.0 mode, but with 2.x speed bits set. * have been passed a 3.0 mode, but with 2.x speed bits set.
* AGP2.x 4x -> AGP3.0 4x. * AGP2.x 4x -> AGP3.0 4x.
*/ */
if (*mode & AGPSTAT2_4X) { if (*requested_mode & AGPSTAT2_4X) {
printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n", printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
current->comm, *mode); current->comm, *requested_mode);
*mode &= ~AGPSTAT2_4X; *requested_mode &= ~AGPSTAT2_4X;
*mode |= AGPSTAT3_4X; *requested_mode |= AGPSTAT3_4X;
} }
} else { } else {
/* /*
...@@ -476,27 +561,27 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) ...@@ -476,27 +561,27 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
* Convert AGP 1x,2x,4x -> AGP 3.0 4x. * Convert AGP 1x,2x,4x -> AGP 3.0 4x.
*/ */
printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n", printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
current->comm, *mode); current->comm, *requested_mode);
*mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X); *requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
*mode |= AGPSTAT3_4X; *requested_mode |= AGPSTAT3_4X;
} }
if (*mode & AGPSTAT3_8X) { if (*requested_mode & AGPSTAT3_8X) {
if (!(*cmd & AGPSTAT3_8X)) { if (!(*bridge_agpstat & AGPSTAT3_8X)) {
*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*cmd |= AGPSTAT3_4X; *bridge_agpstat |= AGPSTAT3_4X;
printk ("%s requested AGPx8 but bridge not capable.\n", current->comm); printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
return; return;
} }
if (!(*tmp & AGPSTAT3_8X)) { if (!(*vga_agpstat & AGPSTAT3_8X)) {
*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*cmd |= AGPSTAT3_4X; *bridge_agpstat |= AGPSTAT3_4X;
printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm); printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
return; return;
} }
/* All set, bridge & device can do AGP x8*/ /* All set, bridge & device can do AGP x8*/
*cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
return; goto done;
} else { } else {
...@@ -505,71 +590,105 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) ...@@ -505,71 +590,105 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
* If the hardware can't do x4, we're up shit creek, and never * If the hardware can't do x4, we're up shit creek, and never
* should have got this far. * should have got this far.
*/ */
*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
if ((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X)) if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
*cmd |= AGPSTAT3_4X; *bridge_agpstat |= AGPSTAT3_4X;
else { else {
printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. " printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
"[cmd:%x tmp:%x fell back to:- cmd:%x tmp:%x]\n", "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
origcmd, origtmp, *cmd, *tmp); origbridge, origvga, *bridge_agpstat, *vga_agpstat);
if (!(*cmd & AGPSTAT3_4X)) if (!(*bridge_agpstat & AGPSTAT3_4X))
printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
if (!(*tmp & AGPSTAT3_4X)) if (!(*vga_agpstat & AGPSTAT3_4X))
printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
return;
} }
} }
done:
/* Apply any errata. */
if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
*bridge_agpstat &= ~AGPSTAT_FW;
if (agp_bridge->flags & AGP_ERRATA_SBA)
*bridge_agpstat &= ~AGPSTAT_SBA;
if (agp_bridge->flags & AGP_ERRATA_1X) {
*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
*bridge_agpstat |= AGPSTAT2_1X;
}
} }
//FIXME: This doesn't smell right.
//We need a function we pass an agp_device to. /**
u32 agp_collect_device_status(u32 mode, u32 cmd) * agp_collect_device_status - determine correct agp_cmd from various agp_stat's
* @bridge: an agp_bridge_data struct allocated for the AGP host bridge.
* @requested_mode: requested agp_stat from userspace (Typically from X)
* @bridge_agpstat: current agp_stat from AGP bridge.
*
* This function will hunt for an AGP graphics card, and try to match
* the requested mode to the capabilities of both the bridge and the card.
*/
u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat)
{ {
struct pci_dev *device = NULL; struct pci_dev *device = NULL;
u8 cap_ptr; u8 cap_ptr = 0;
u32 tmp; u32 vga_agpstat;
u32 agp3;
for_each_pci_dev(device) { while (!cap_ptr) {
device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
if (!device) {
printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
return 0;
}
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
if (!cap_ptr) if (!cap_ptr) {
pci_dev_put(device);
continue;
}
if ((device->bus->self->vendor != bridge->dev->vendor) &&
(device->bus->self->device != bridge->dev->device)) {
pci_dev_put(device);
cap_ptr = 0;
continue; continue;
}
}
//FIXME: We should probably skip anything here that
// isn't an AGP graphic card.
/* /*
* Ok, here we have a AGP device. Disable impossible * Ok, here we have a AGP device. Disable impossible
* settings, and adjust the readqueue to the minimum. * settings, and adjust the readqueue to the minimum.
*/ */
pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp); pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat);
/* adjust RQ depth */ /* adjust RQ depth */
cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) | bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) |
min_t(u32, (mode & AGPSTAT_RQ_DEPTH), min_t(u32, (requested_mode & AGPSTAT_RQ_DEPTH),
min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH)))); min_t(u32, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH))));
/* disable FW if it's not supported */ /* disable FW if it's not supported */
if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW))) if (!((bridge_agpstat & AGPSTAT_FW) &&
cmd &= ~AGPSTAT_FW; (vga_agpstat & AGPSTAT_FW) &&
(requested_mode & AGPSTAT_FW)))
bridge_agpstat &= ~AGPSTAT_FW;
/* Check to see if we are operating in 3.0 mode */ /* Check to see if we are operating in 3.0 mode */
pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3); if (check_bridge_mode(agp_bridge->dev))
if (agp3 & AGPSTAT_MODE_3_0) { agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
agp_v3_parse_one(&mode, &cmd, &tmp); else
} else { agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
agp_v2_parse_one(&mode, &cmd, &tmp);
} pci_dev_put(device);
} return bridge_agpstat;
return cmd;
} }
EXPORT_SYMBOL(agp_collect_device_status); EXPORT_SYMBOL(agp_collect_device_status);
void agp_device_command(u32 command, int agp_v3) void agp_device_command(u32 bridge_agpstat, int agp_v3)
{ {
struct pci_dev *device = NULL; struct pci_dev *device = NULL;
int mode; int mode;
mode = command & 0x7; mode = bridge_agpstat & 0x7;
if (agp_v3) if (agp_v3)
mode *= 4; mode *= 4;
...@@ -580,7 +699,7 @@ void agp_device_command(u32 command, int agp_v3) ...@@ -580,7 +699,7 @@ void agp_device_command(u32 command, int agp_v3)
printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n", printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",
agp_v3 ? 3 : 2, pci_name(device), mode); agp_v3 ? 3 : 2, pci_name(device), mode);
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
} }
} }
EXPORT_SYMBOL(agp_device_command); EXPORT_SYMBOL(agp_device_command);
...@@ -591,20 +710,19 @@ void get_agp_version(struct agp_bridge_data *bridge) ...@@ -591,20 +710,19 @@ void get_agp_version(struct agp_bridge_data *bridge)
u32 ncapid; u32 ncapid;
/* Exit early if already set by errata workarounds. */ /* Exit early if already set by errata workarounds. */
if (agp_bridge->major_version != 0) if (bridge->major_version != 0)
return; return;
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid); pci_read_config_dword(bridge->dev, bridge->capndx, &ncapid);
agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
} }
EXPORT_SYMBOL(get_agp_version); EXPORT_SYMBOL(get_agp_version);
void agp_generic_enable(u32 mode) void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
{ {
u32 command, temp; u32 bridge_agpstat, temp;
u32 agp3;
get_agp_version(agp_bridge); get_agp_version(agp_bridge);
...@@ -614,29 +732,31 @@ void agp_generic_enable(u32 mode) ...@@ -614,29 +732,31 @@ void agp_generic_enable(u32 mode)
pci_name(agp_bridge->dev)); pci_name(agp_bridge->dev));
pci_read_config_dword(agp_bridge->dev, pci_read_config_dword(agp_bridge->dev,
agp_bridge->capndx + PCI_AGP_STATUS, &command); agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat);
command = agp_collect_device_status(mode, command); bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat);
command |= AGPSTAT_AGP_ENABLE; if (bridge_agpstat == 0)
/* Something bad happened. FIXME: Return error code? */
return;
/* Do AGP version specific frobbing. */ bridge_agpstat |= AGPSTAT_AGP_ENABLE;
if(agp_bridge->major_version >= 3) {
pci_read_config_dword(agp_bridge->dev,
agp_bridge->capndx+AGPSTAT, &agp3);
/* Check to see if we are operating in 3.0 mode */ /* Do AGP version specific frobbing. */
if (agp3 & AGPSTAT_MODE_3_0) { if (bridge->major_version >= 3) {
if (check_bridge_mode(bridge->dev)) {
/* If we have 3.5, we can do the isoch stuff. */ /* If we have 3.5, we can do the isoch stuff. */
if (agp_bridge->minor_version >= 5) if (bridge->minor_version >= 5)
agp_3_5_enable(agp_bridge); agp_3_5_enable(bridge);
agp_device_command(command, TRUE); agp_device_command(bridge_agpstat, TRUE);
return; return;
} else { } else {
/* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/ /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
command &= ~(7<<10) ; bridge_agpstat &= ~(7<<10) ;
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp); pci_read_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, &temp);
temp |= (1<<9); temp |= (1<<9);
pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp); pci_write_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, temp);
printk (KERN_INFO PFX "Device is in legacy mode," printk (KERN_INFO PFX "Device is in legacy mode,"
" falling back to 2.x\n"); " falling back to 2.x\n");
...@@ -644,12 +764,12 @@ void agp_generic_enable(u32 mode) ...@@ -644,12 +764,12 @@ void agp_generic_enable(u32 mode)
} }
/* AGP v<3 */ /* AGP v<3 */
agp_device_command(command, FALSE); agp_device_command(bridge_agpstat, FALSE);
} }
EXPORT_SYMBOL(agp_generic_enable); EXPORT_SYMBOL(agp_generic_enable);
int agp_generic_create_gatt_table(void) int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
{ {
char *table; char *table;
char *table_end; char *table_end;
...@@ -661,17 +781,17 @@ int agp_generic_create_gatt_table(void) ...@@ -661,17 +781,17 @@ int agp_generic_create_gatt_table(void)
struct page *page; struct page *page;
/* The generic routines can't handle 2 level gatt's */ /* The generic routines can't handle 2 level gatt's */
if (agp_bridge->driver->size_type == LVL2_APER_SIZE) if (bridge->driver->size_type == LVL2_APER_SIZE)
return -EINVAL; return -EINVAL;
table = NULL; table = NULL;
i = agp_bridge->aperture_size_idx; i = bridge->aperture_size_idx;
temp = agp_bridge->current_size; temp = bridge->current_size;
size = page_order = num_entries = 0; size = page_order = num_entries = 0;
if (agp_bridge->driver->size_type != FIXED_APER_SIZE) { if (bridge->driver->size_type != FIXED_APER_SIZE) {
do { do {
switch (agp_bridge->driver->size_type) { switch (bridge->driver->size_type) {
case U8_APER_SIZE: case U8_APER_SIZE:
size = A_SIZE_8(temp)->size; size = A_SIZE_8(temp)->size;
page_order = page_order =
...@@ -702,29 +822,29 @@ int agp_generic_create_gatt_table(void) ...@@ -702,29 +822,29 @@ int agp_generic_create_gatt_table(void)
if (table == NULL) { if (table == NULL) {
i++; i++;
switch (agp_bridge->driver->size_type) { switch (bridge->driver->size_type) {
case U8_APER_SIZE: case U8_APER_SIZE:
agp_bridge->current_size = A_IDX8(agp_bridge); bridge->current_size = A_IDX8(bridge);
break; break;
case U16_APER_SIZE: case U16_APER_SIZE:
agp_bridge->current_size = A_IDX16(agp_bridge); bridge->current_size = A_IDX16(bridge);
break; break;
case U32_APER_SIZE: case U32_APER_SIZE:
agp_bridge->current_size = A_IDX32(agp_bridge); bridge->current_size = A_IDX32(bridge);
break; break;
/* This case will never really happen. */ /* This case will never really happen. */
case FIXED_APER_SIZE: case FIXED_APER_SIZE:
case LVL2_APER_SIZE: case LVL2_APER_SIZE:
default: default:
agp_bridge->current_size = bridge->current_size =
agp_bridge->current_size; bridge->current_size;
break; break;
} }
temp = agp_bridge->current_size; temp = bridge->current_size;
} else { } else {
agp_bridge->aperture_size_idx = i; bridge->aperture_size_idx = i;
} }
} while (!table && (i < agp_bridge->driver->num_aperture_sizes)); } while (!table && (i < bridge->driver->num_aperture_sizes));
} else { } else {
size = ((struct aper_size_info_fixed *) temp)->size; size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order; page_order = ((struct aper_size_info_fixed *) temp)->page_order;
...@@ -740,15 +860,15 @@ int agp_generic_create_gatt_table(void) ...@@ -740,15 +860,15 @@ int agp_generic_create_gatt_table(void)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page); SetPageReserved(page);
agp_bridge->gatt_table_real = (u32 *) table; bridge->gatt_table_real = (u32 *) table;
agp_gatt_table = (void *)table; agp_gatt_table = (void *)table;
agp_bridge->driver->cache_flush(); bridge->driver->cache_flush();
agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table), bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
(PAGE_SIZE * (1 << page_order))); (PAGE_SIZE * (1 << page_order)));
agp_bridge->driver->cache_flush(); bridge->driver->cache_flush();
if (agp_bridge->gatt_table == NULL) { if (bridge->gatt_table == NULL) {
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page); ClearPageReserved(page);
...@@ -756,28 +876,28 @@ int agp_generic_create_gatt_table(void) ...@@ -756,28 +876,28 @@ int agp_generic_create_gatt_table(void)
return -ENOMEM; return -ENOMEM;
} }
agp_bridge->gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real); bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */ /* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) { for (i = 0; i < num_entries; i++) {
writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i); writel(bridge->scratch_page, bridge->gatt_table+i);
readl(agp_bridge->gatt_table+i); /* PCI Posting. */ readl(bridge->gatt_table+i); /* PCI Posting. */
} }
return 0; return 0;
} }
EXPORT_SYMBOL(agp_generic_create_gatt_table); EXPORT_SYMBOL(agp_generic_create_gatt_table);
int agp_generic_free_gatt_table(void) int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
{ {
int page_order; int page_order;
char *table, *table_end; char *table, *table_end;
void *temp; void *temp;
struct page *page; struct page *page;
temp = agp_bridge->current_size; temp = bridge->current_size;
switch (agp_bridge->driver->size_type) { switch (bridge->driver->size_type) {
case U8_APER_SIZE: case U8_APER_SIZE:
page_order = A_SIZE_8(temp)->page_order; page_order = A_SIZE_8(temp)->page_order;
break; break;
...@@ -803,19 +923,19 @@ int agp_generic_free_gatt_table(void) ...@@ -803,19 +923,19 @@ int agp_generic_free_gatt_table(void)
* called, then all agp memory is deallocated and removed * called, then all agp memory is deallocated and removed
* from the table. */ * from the table. */
iounmap(agp_bridge->gatt_table); iounmap(bridge->gatt_table);
table = (char *) agp_bridge->gatt_table_real; table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page); ClearPageReserved(page);
free_pages((unsigned long) agp_bridge->gatt_table_real, page_order); free_pages((unsigned long) bridge->gatt_table_real, page_order);
agp_gatt_table = NULL; agp_gatt_table = NULL;
agp_bridge->gatt_table = NULL; bridge->gatt_table = NULL;
agp_bridge->gatt_table_real = NULL; bridge->gatt_table_real = NULL;
agp_bridge->gatt_bus_addr = 0; bridge->gatt_bus_addr = 0;
return 0; return 0;
} }
...@@ -828,10 +948,15 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) ...@@ -828,10 +948,15 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
size_t i; size_t i;
off_t j; off_t j;
void *temp; void *temp;
struct agp_bridge_data *bridge;
temp = agp_bridge->current_size; bridge = mem->bridge;
if (!bridge)
return -EINVAL;
switch (agp_bridge->driver->size_type) { temp = bridge->current_size;
switch (bridge->driver->size_type) {
case U8_APER_SIZE: case U8_APER_SIZE:
num_entries = A_SIZE_8(temp)->num_entries; num_entries = A_SIZE_8(temp)->num_entries;
break; break;
...@@ -868,22 +993,22 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) ...@@ -868,22 +993,22 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
j = pg_start; j = pg_start;
while (j < (pg_start + mem->page_count)) { while (j < (pg_start + mem->page_count)) {
if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) if (!PGE_EMPTY(bridge, readl(bridge->gatt_table+j)))
return -EBUSY; return -EBUSY;
j++; j++;
} }
if (mem->is_flushed == FALSE) { if (mem->is_flushed == FALSE) {
agp_bridge->driver->cache_flush(); bridge->driver->cache_flush();
mem->is_flushed = TRUE; mem->is_flushed = TRUE;
} }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j); writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
readl(agp_bridge->gatt_table+j); /* PCI Posting. */ readl(bridge->gatt_table+j); /* PCI Posting. */
} }
agp_bridge->driver->tlb_flush(mem); bridge->driver->tlb_flush(mem);
return 0; return 0;
} }
EXPORT_SYMBOL(agp_generic_insert_memory); EXPORT_SYMBOL(agp_generic_insert_memory);
...@@ -892,6 +1017,11 @@ EXPORT_SYMBOL(agp_generic_insert_memory); ...@@ -892,6 +1017,11 @@ EXPORT_SYMBOL(agp_generic_insert_memory);
int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{ {
size_t i; size_t i;
struct agp_bridge_data *bridge;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
if (type != 0 || mem->type != 0) { if (type != 0 || mem->type != 0) {
/* The generic routines know nothing of memory types */ /* The generic routines know nothing of memory types */
...@@ -900,12 +1030,12 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) ...@@ -900,12 +1030,12 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
/* AK: bogus, should encode addresses > 4GB */ /* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) { for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i); writel(bridge->scratch_page, bridge->gatt_table+i);
readl(agp_bridge->gatt_table+i); /* PCI Posting. */ readl(bridge->gatt_table+i); /* PCI Posting. */
} }
global_cache_flush(); global_cache_flush();
agp_bridge->driver->tlb_flush(mem); bridge->driver->tlb_flush(mem);
return 0; return 0;
} }
EXPORT_SYMBOL(agp_generic_remove_memory); EXPORT_SYMBOL(agp_generic_remove_memory);
...@@ -920,9 +1050,7 @@ EXPORT_SYMBOL(agp_generic_alloc_by_type); ...@@ -920,9 +1050,7 @@ EXPORT_SYMBOL(agp_generic_alloc_by_type);
void agp_generic_free_by_type(struct agp_memory *curr) void agp_generic_free_by_type(struct agp_memory *curr)
{ {
if (curr->memory != NULL)
vfree(curr->memory); vfree(curr->memory);
agp_free_key(curr->key); agp_free_key(curr->key);
kfree(curr); kfree(curr);
} }
...@@ -936,7 +1064,7 @@ EXPORT_SYMBOL(agp_generic_free_by_type); ...@@ -936,7 +1064,7 @@ EXPORT_SYMBOL(agp_generic_free_by_type);
* against a maximum value. * against a maximum value.
*/ */
void *agp_generic_alloc_page(void) void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{ {
struct page * page; struct page * page;
...@@ -978,14 +1106,25 @@ EXPORT_SYMBOL(agp_generic_destroy_page); ...@@ -978,14 +1106,25 @@ EXPORT_SYMBOL(agp_generic_destroy_page);
* *
* @mode: agp mode register value to configure with. * @mode: agp mode register value to configure with.
*/ */
void agp_enable(u32 mode) void agp_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
if (agp_bridge->type == NOT_SUPPORTED) if (!bridge)
return; return;
agp_bridge->driver->agp_enable(mode); bridge->driver->agp_enable(bridge, mode);
} }
EXPORT_SYMBOL(agp_enable); EXPORT_SYMBOL(agp_enable);
/* When we remove the global variable agp_bridge from all drivers
* then agp_alloc_bridge and agp_generic_find_bridge need to be updated
*/
struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev)
{
if (list_empty(&agp_bridges))
return NULL;
return agp_bridge;
}
static void ipi_handler(void *null) static void ipi_handler(void *null)
{ {
...@@ -999,11 +1138,12 @@ void global_cache_flush(void) ...@@ -999,11 +1138,12 @@ void global_cache_flush(void)
} }
EXPORT_SYMBOL(global_cache_flush); EXPORT_SYMBOL(global_cache_flush);
unsigned long agp_generic_mask_memory(unsigned long addr, int type) unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
unsigned long addr, int type)
{ {
/* memory type is ignored in the generic routine */ /* memory type is ignored in the generic routine */
if (agp_bridge->driver->masks) if (bridge->driver->masks)
return addr | agp_bridge->driver->masks[0].mask; return addr | bridge->driver->masks[0].mask;
else else
return addr; return addr;
} }
......
...@@ -289,7 +289,7 @@ hp_zx1_tlbflush (struct agp_memory *mem) ...@@ -289,7 +289,7 @@ hp_zx1_tlbflush (struct agp_memory *mem)
} }
static int static int
hp_zx1_create_gatt_table (void) hp_zx1_create_gatt_table (struct agp_bridge_data *bridge)
{ {
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
int i; int i;
...@@ -317,7 +317,7 @@ hp_zx1_create_gatt_table (void) ...@@ -317,7 +317,7 @@ hp_zx1_create_gatt_table (void)
} }
static int static int
hp_zx1_free_gatt_table (void) hp_zx1_free_gatt_table (struct agp_bridge_data *bridge)
{ {
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
...@@ -367,7 +367,9 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type) ...@@ -367,7 +367,9 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
for (k = 0; for (k = 0;
k < hp->io_pages_per_kpage; k < hp->io_pages_per_kpage;
k++, j++, paddr += hp->io_page_size) { k++, j++, paddr += hp->io_page_size) {
hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type); hp->gatt[j] =
agp_bridge->driver->mask_memory(agp_bridge,
paddr, type);
} }
} }
...@@ -396,19 +398,20 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type) ...@@ -396,19 +398,20 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
} }
static unsigned long static unsigned long
hp_zx1_mask_memory (unsigned long addr, int type) hp_zx1_mask_memory (struct agp_bridge_data *bridge,
unsigned long addr, int type)
{ {
return HP_ZX1_PDIR_VALID_BIT | addr; return HP_ZX1_PDIR_VALID_BIT | addr;
} }
static void static void
hp_zx1_enable (u32 mode) hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
{ {
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
u32 command; u32 command;
command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
command = agp_collect_device_status(mode, command); command = agp_collect_device_status(bridge, mode, command);
command |= 0x00000100; command |= 0x00000100;
writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND); writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND);
......
...@@ -233,7 +233,7 @@ static int i460_configure (void) ...@@ -233,7 +233,7 @@ static int i460_configure (void)
return 0; return 0;
} }
static int i460_create_gatt_table (void) static int i460_create_gatt_table (struct agp_bridge_data *bridge)
{ {
int page_order, num_entries, i; int page_order, num_entries, i;
void *temp; void *temp;
...@@ -258,7 +258,7 @@ static int i460_create_gatt_table (void) ...@@ -258,7 +258,7 @@ static int i460_create_gatt_table (void)
return 0; return 0;
} }
static int i460_free_gatt_table (void) static int i460_free_gatt_table (struct agp_bridge_data *bridge)
{ {
int num_entries, i; int num_entries, i;
void *temp; void *temp;
...@@ -314,7 +314,8 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem, ...@@ -314,7 +314,8 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
for (i = 0, j = io_pg_start; i < mem->page_count; i++) { for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
paddr = mem->memory[i]; paddr = mem->memory[i];
for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type)); WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
paddr, mem->type));
} }
WR_FLUSH_GATT(j - 1); WR_FLUSH_GATT(j - 1);
return 0; return 0;
...@@ -427,7 +428,8 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem, ...@@ -427,7 +428,8 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
if (i460_alloc_large_page(lp) < 0) if (i460_alloc_large_page(lp) < 0)
return -ENOMEM; return -ENOMEM;
pg = lp - i460.lp_desc; pg = lp - i460.lp_desc;
WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0)); WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge,
lp->paddr, 0));
WR_FLUSH_GATT(pg); WR_FLUSH_GATT(pg);
} }
...@@ -508,12 +510,12 @@ static int i460_remove_memory (struct agp_memory *mem, ...@@ -508,12 +510,12 @@ static int i460_remove_memory (struct agp_memory *mem,
* Let's just hope nobody counts on the allocated AGP memory being there before bind time * Let's just hope nobody counts on the allocated AGP memory being there before bind time
* (I don't think current drivers do)... * (I don't think current drivers do)...
*/ */
static void *i460_alloc_page (void) static void *i460_alloc_page (struct agp_bridge_data *bridge)
{ {
void *page; void *page;
if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
page = agp_generic_alloc_page(); page = agp_generic_alloc_page(agp_bridge);
else else
/* Returning NULL would cause problems */ /* Returning NULL would cause problems */
/* AK: really dubious code. */ /* AK: really dubious code. */
...@@ -529,10 +531,11 @@ static void i460_destroy_page (void *page) ...@@ -529,10 +531,11 @@ static void i460_destroy_page (void *page)
#endif /* I460_LARGE_IO_PAGES */ #endif /* I460_LARGE_IO_PAGES */
static unsigned long i460_mask_memory (unsigned long addr, int type) static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
unsigned long addr, int type)
{ {
/* Make sure the returned address is a valid GATT entry */ /* Make sure the returned address is a valid GATT entry */
return agp_bridge->driver->masks[0].mask return bridge->driver->masks[0].mask
| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12); | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12);
} }
...@@ -624,7 +627,7 @@ static int __init agp_intel_i460_init(void) ...@@ -624,7 +627,7 @@ static int __init agp_intel_i460_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_intel_i460_pci_driver); return pci_register_driver(&agp_intel_i460_pci_driver);
} }
static void __exit agp_intel_i460_cleanup(void) static void __exit agp_intel_i460_cleanup(void)
......
...@@ -150,7 +150,7 @@ static void intel_i810_tlbflush(struct agp_memory *mem) ...@@ -150,7 +150,7 @@ static void intel_i810_tlbflush(struct agp_memory *mem)
return; return;
} }
static void intel_i810_agp_enable(u32 mode) static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
return; return;
} }
...@@ -229,7 +229,8 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, ...@@ -229,7 +229,8 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
insert: insert:
global_cache_flush(); global_cache_flush();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i810_private.registers+I810_PTE_BASE+(j*4)); intel_i810_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
} }
...@@ -268,7 +269,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) ...@@ -268,7 +269,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
return NULL; return NULL;
switch (pg_count) { switch (pg_count) {
case 1: addr = agp_bridge->driver->agp_alloc_page(); case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
break; break;
case 4: case 4:
/* kludge to get 4 physical pages for ARGB cursor */ /* kludge to get 4 physical pages for ARGB cursor */
...@@ -337,10 +338,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr) ...@@ -337,10 +338,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
kfree(curr); kfree(curr);
} }
static unsigned long intel_i810_mask_memory(unsigned long addr, int type) static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
unsigned long addr, int type)
{ {
/* Type checking must be done elsewhere */ /* Type checking must be done elsewhere */
return addr | agp_bridge->driver->masks[type].mask; return addr | bridge->driver->masks[type].mask;
} }
static struct aper_size_info_fixed intel_i830_sizes[] = static struct aper_size_info_fixed intel_i830_sizes[] =
...@@ -447,7 +449,7 @@ static void intel_i830_init_gtt_entries(void) ...@@ -447,7 +449,7 @@ static void intel_i830_init_gtt_entries(void)
/* The intel i830 automatically initializes the agp aperture during POST. /* The intel i830 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT. * Use the memory already set aside for in the GTT.
*/ */
static int intel_i830_create_gatt_table(void) static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
{ {
int page_order; int page_order;
struct aper_size_info_fixed *size; struct aper_size_info_fixed *size;
...@@ -482,7 +484,7 @@ static int intel_i830_create_gatt_table(void) ...@@ -482,7 +484,7 @@ static int intel_i830_create_gatt_table(void)
/* Return the gatt table to a sane state. Use the top of stolen /* Return the gatt table to a sane state. Use the top of stolen
* memory for the GTT. * memory for the GTT.
*/ */
static int intel_i830_free_gatt_table(void) static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
{ {
return 0; return 0;
} }
...@@ -582,7 +584,8 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int ...@@ -582,7 +584,8 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
global_cache_flush(); /* FIXME: Necessary ?*/ global_cache_flush(); /* FIXME: Necessary ?*/
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i830_private.registers+I810_PTE_BASE+(j*4)); intel_i830_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
} }
...@@ -691,7 +694,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, ...@@ -691,7 +694,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
global_cache_flush(); global_cache_flush();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), intel_i830_private.gtt+j); writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type), intel_i830_private.gtt+j);
readl(intel_i830_private.gtt+j); /* PCI Posting. */ readl(intel_i830_private.gtt+j); /* PCI Posting. */
} }
...@@ -743,7 +747,7 @@ static int intel_i915_fetch_size(void) ...@@ -743,7 +747,7 @@ static int intel_i915_fetch_size(void)
/* The intel i915 automatically initializes the agp aperture during POST. /* The intel i915 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT. * Use the memory already set aside for in the GTT.
*/ */
static int intel_i915_create_gatt_table(void) static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
{ {
int page_order; int page_order;
struct aper_size_info_fixed *size; struct aper_size_info_fixed *size;
...@@ -1758,6 +1762,8 @@ static int agp_intel_resume(struct pci_dev *pdev) ...@@ -1758,6 +1762,8 @@ static int agp_intel_resume(struct pci_dev *pdev)
intel_i915_configure(); intel_i915_configure();
else if (bridge->driver == &intel_830_driver) else if (bridge->driver == &intel_830_driver)
intel_i830_configure(); intel_i830_configure();
else if (bridge->driver == &intel_810_driver)
intel_i810_configure();
return 0; return 0;
} }
...@@ -1810,7 +1816,9 @@ static struct pci_driver agp_intel_pci_driver = { ...@@ -1810,7 +1816,9 @@ static struct pci_driver agp_intel_pci_driver = {
static int __init agp_intel_init(void) static int __init agp_intel_init(void)
{ {
return pci_module_init(&agp_intel_pci_driver); if (agp_off)
return -EINVAL;
return pci_register_driver(&agp_intel_pci_driver);
} }
static void __exit agp_intel_cleanup(void) static void __exit agp_intel_cleanup(void)
......
/*
* Intel MCH AGPGART routines.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
#include "agp.h"
#define AGP_DCACHE_MEMORY 1
#define AGP_PHYS_MEMORY 2
static struct gatt_mask intel_i810_masks[] =
{
{.mask = I810_PTE_VALID, .type = 0},
{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
{.mask = I810_PTE_VALID, .type = 0}
};
static void intel_i810_tlbflush(struct agp_memory *mem)
{
return;
}
static void intel_i810_agp_enable(u32 mode)
{
return;
}
/*
* The i810/i830 requires a physical address to program its mouse
* pointer into hardware.
* However the Xserver still writes to it through the agp aperture.
*/
static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
{
struct agp_memory *new;
void *addr;
if (pg_count != 1)
return NULL;
addr = agp_bridge->driver->agp_alloc_page();
if (addr == NULL)
return NULL;
new = agp_create_memory(1);
if (new == NULL)
return NULL;
new->memory[0] = virt_to_phys(addr);
new->page_count = 1;
new->num_scratch_pages = 1;
new->type = AGP_PHYS_MEMORY;
new->physical = new->memory[0];
return new;
}
static void intel_i810_free_by_type(struct agp_memory *curr)
{
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
}
static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
{
/* Type checking must be done elsewhere */
return addr | agp_bridge->driver->masks[type].mask;
}
static struct aper_size_info_fixed intel_i830_sizes[] =
{
{128, 32768, 5},
/* The 64M mode still requires a 128k gatt */
{64, 16384, 5}
};
static struct _intel_i830_private {
struct pci_dev *i830_dev; /* device one */
volatile u8 __iomem *registers;
int gtt_entries;
} intel_i830_private;
static void intel_i830_init_gtt_entries(void)
{
u16 gmch_ctrl;
int gtt_entries;
u8 rdct;
int local = 0;
static const int ddt[4] = { 0, 16, 32, 64 };
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
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(132);
break;
case I830_GMCH_GMS_STOLEN_1024:
gtt_entries = MB(1) - KB(132);
break;
case I830_GMCH_GMS_STOLEN_8192:
gtt_entries = MB(8) - KB(132);
break;
case I830_GMCH_GMS_LOCAL:
rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
MB(ddt[I830_RDRAM_DDT(rdct)]);
local = 1;
break;
default:
gtt_entries = 0;
break;
}
} else {
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
gtt_entries = MB(1) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_4M:
gtt_entries = MB(4) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_8M:
gtt_entries = MB(8) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_16M:
gtt_entries = MB(16) - KB(132);
break;
case I855_GMCH_GMS_STOLEN_32M:
gtt_entries = MB(32) - KB(132);
break;
default:
gtt_entries = 0;
break;
}
}
if (gtt_entries > 0)
printk(KERN_INFO PFX "Detected %dK %s memory.\n",
gtt_entries / KB(1), local ? "local" : "stolen");
else
printk(KERN_INFO PFX
"No pre-allocated video memory detected.\n");
gtt_entries /= KB(4);
intel_i830_private.gtt_entries = gtt_entries;
}
/* The intel i830 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT.
*/
static int intel_i830_create_gatt_table(void)
{
int page_order;
struct aper_size_info_fixed *size;
int num_entries;
u32 temp;
size = agp_bridge->current_size;
page_order = size->page_order;
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
temp &= 0xfff80000;
intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096);
if (!intel_i830_private.registers)
return -ENOMEM;
temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ?? */
/* 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;
}
/* Return the gatt table to a sane state. Use the top of stolen
* memory for the GTT.
*/
static int intel_i830_free_gatt_table(void)
{
return 0;
}
static int intel_i830_fetch_size(void)
{
u16 gmch_ctrl;
struct aper_size_info_fixed *values;
values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
/* 855GM/852GM/865G has 128MB aperture size */
agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
agp_bridge->aperture_size_idx = 0;
return values[0].size;
}
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
agp_bridge->aperture_size_idx = 0;
return values[0].size;
} else {
agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
agp_bridge->aperture_size_idx = 1;
return values[1].size;
}
return 0;
}
static int intel_i830_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,I810_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);
writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
}
global_cache_flush();
return 0;
}
static void intel_i830_cleanup(void)
{
iounmap((void __iomem *) intel_i830_private.registers);
}
static int intel_i830_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(); /* FIXME: ?? */
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
intel_i830_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
static int intel_i830_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++) {
writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
{
if (type == AGP_PHYS_MEMORY)
return alloc_agpphysmem_i8xx(pg_count, type);
/* always return NULL for other allocation types for now */
return NULL;
}
static int intel_8xx_fetch_size(void)
{
u8 temp;
int i;
struct aper_size_info_8 *values;
pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
values = A_SIZE_8(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);
agp_bridge->aperture_size_idx = i;
return values[i].size;
}
}
return 0;
}
static void intel_8xx_tlbflush(struct agp_memory *mem)
{
u32 temp;
pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
}
static void intel_8xx_cleanup(void)
{
u16 temp;
struct aper_size_info_8 *previous_size;
previous_size = A_SIZE_8(agp_bridge->previous_size);
pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
}
static int intel_845_configure(void)
{
u32 temp;
u8 temp2;
struct aper_size_info_8 *current_size;
current_size = A_SIZE_8(agp_bridge->current_size);
/* aperture size */
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
/* agpctrl */
pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
/* agpm */
pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
/* clear any possible error conditions */
pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
return 0;
}
/* Setup function */
static struct gatt_mask intel_generic_masks[] =
{
{.mask = 0x00000017, .type = 0}
};
static struct aper_size_info_8 intel_8xx_sizes[7] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 32},
{64, 16384, 4, 48},
{32, 8192, 3, 56},
{16, 4096, 2, 60},
{8, 2048, 1, 62},
{4, 1024, 0, 63}
};
static struct agp_bridge_driver intel_830_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_i830_sizes,
.size_type = FIXED_APER_SIZE,
.num_aperture_sizes = 2,
.needs_scratch_page = TRUE,
.configure = intel_i830_configure,
.fetch_size = intel_i830_fetch_size,
.cleanup = intel_i830_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_i830_create_gatt_table,
.free_gatt_table = intel_i830_free_gatt_table,
.insert_memory = intel_i830_insert_entries,
.remove_memory = intel_i830_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_845_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
.configure = intel_845_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
.tlb_flush = intel_8xx_tlbflush,
.mask_memory = agp_generic_mask_memory,
.masks = intel_generic_masks,
.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 = agp_generic_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,
};
static int find_i830(u16 device)
{
struct pci_dev *i830_dev;
i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
device, i830_dev);
}
if (!i830_dev)
return 0;
intel_i830_private.i830_dev = i830_dev;
return 1;
}
static int __devinit agp_intelmch_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
struct resource *r;
char *name = "(unknown)";
u8 cap_ptr = 0;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_82865_HB:
if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
bridge->driver = &intel_830_driver;
} else {
bridge->driver = &intel_845_driver;
}
name = "865";
break;
case PCI_DEVICE_ID_INTEL_82875_HB:
bridge->driver = &intel_845_driver;
name = "i875";
break;
default:
printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
pdev->device);
return -ENODEV;
};
bridge->dev = pdev;
bridge->capndx = cap_ptr;
if (bridge->driver == &intel_830_driver)
bridge->dev_private_data = &intel_i830_private;
printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
/*
* The following fixes the case where the BIOS has "forgotten" to
* provide an address range for the GART.
* 20030610 - hamish@zot.org
*/
r = &pdev->resource[0];
if (!r->start && r->end) {
if(pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
return -ENODEV;
}
}
/*
* If the device has not been properly setup, the following will catch
* the problem and should stop the system from crashing.
* 20030610 - hamish@zot.org
*/
if (pci_enable_device(pdev)) {
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
return -ENODEV;
}
/* Fill in the mode register */
if (cap_ptr) {
pci_read_config_dword(pdev,
bridge->capndx+PCI_AGP_STATUS,
&bridge->mode);
}
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
static void __devexit agp_intelmch_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
agp_remove_bridge(bridge);
if (intel_i830_private.i830_dev)
pci_dev_put(intel_i830_private.i830_dev);
agp_put_bridge(bridge);
}
static int agp_intelmch_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
pci_restore_state(pdev);
if (bridge->driver == &intel_845_driver)
intel_845_configure();
return 0;
}
static struct pci_device_id agp_intelmch_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82865_HB,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82875_HB,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{ }
};
MODULE_DEVICE_TABLE(pci, agp_intelmch_pci_table);
static struct pci_driver agp_intelmch_pci_driver = {
.name = "agpgart-intel-mch",
.id_table = agp_intelmch_pci_table,
.probe = agp_intelmch_probe,
.remove = agp_intelmch_remove,
.resume = agp_intelmch_resume,
};
/* intel_agp_init() must not be declared static for explicit
early initialization to work (ie i810fb) */
int __init agp_intelmch_init(void)
{
static int agp_initialised=0;
if (agp_initialised == 1)
return 0;
agp_initialised=1;
return pci_module_init(&agp_intelmch_pci_driver);
}
static void __exit agp_intelmch_cleanup(void)
{
pci_unregister_driver(&agp_intelmch_pci_driver);
}
module_init(agp_intelmch_init);
module_exit(agp_intelmch_cleanup);
MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
MODULE_LICENSE("GPL");
...@@ -215,7 +215,8 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type ...@@ -215,7 +215,8 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
mem->is_flushed = TRUE; mem->is_flushed = TRUE;
} }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
agp_bridge->gatt_table+nvidia_private.pg_offset+j); agp_bridge->gatt_table+nvidia_private.pg_offset+j);
readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j); /* PCI Posting. */ readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j); /* PCI Posting. */
} }
...@@ -407,7 +408,7 @@ static int __init agp_nvidia_init(void) ...@@ -407,7 +408,7 @@ static int __init agp_nvidia_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_nvidia_pci_driver); return pci_register_driver(&agp_nvidia_pci_driver);
} }
static void __exit agp_nvidia_cleanup(void) static void __exit agp_nvidia_cleanup(void)
......
...@@ -70,7 +70,7 @@ static void sis_cleanup(void) ...@@ -70,7 +70,7 @@ static void sis_cleanup(void)
(previous_size->size_value & ~(0x03))); (previous_size->size_value & ~(0x03)));
} }
static void sis_delayed_enable(u32 mode) static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
struct pci_dev *device = NULL; struct pci_dev *device = NULL;
u32 command; u32 command;
...@@ -82,7 +82,7 @@ static void sis_delayed_enable(u32 mode) ...@@ -82,7 +82,7 @@ static void sis_delayed_enable(u32 mode)
pci_name(agp_bridge->dev)); pci_name(agp_bridge->dev));
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
command = agp_collect_device_status(mode, command); command = agp_collect_device_status(bridge, mode, command);
command |= AGPSTAT_AGP_ENABLE; command |= AGPSTAT_AGP_ENABLE;
rate = (command & 0x7) << 2; rate = (command & 0x7) << 2;
...@@ -101,7 +101,7 @@ static void sis_delayed_enable(u32 mode) ...@@ -101,7 +101,7 @@ static void sis_delayed_enable(u32 mode)
* command register triggers a 5ms screwup during which the master * command register triggers a 5ms screwup during which the master
* cannot be configured * cannot be configured
*/ */
if (device->device == agp_bridge->dev->device) { if (device->device == bridge->dev->device) {
printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
msleep(10); msleep(10);
} }
...@@ -342,7 +342,7 @@ static int __init agp_sis_init(void) ...@@ -342,7 +342,7 @@ static int __init agp_sis_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_sis_pci_driver); return pci_register_driver(&agp_sis_pci_driver);
} }
static void __exit agp_sis_cleanup(void) static void __exit agp_sis_cleanup(void)
......
...@@ -141,7 +141,7 @@ static int serverworks_create_gatt_pages(int nr_tables) ...@@ -141,7 +141,7 @@ static int serverworks_create_gatt_pages(int nr_tables)
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
#endif #endif
static int serverworks_create_gatt_table(void) static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
{ {
struct aper_size_info_lvl2 *value; struct aper_size_info_lvl2 *value;
struct serverworks_page_map page_dir; struct serverworks_page_map page_dir;
...@@ -192,7 +192,7 @@ static int serverworks_create_gatt_table(void) ...@@ -192,7 +192,7 @@ static int serverworks_create_gatt_table(void)
return 0; return 0;
} }
static int serverworks_free_gatt_table(void) static int serverworks_free_gatt_table(struct agp_bridge_data *bridge)
{ {
struct serverworks_page_map page_dir; struct serverworks_page_map page_dir;
...@@ -341,7 +341,7 @@ static int serverworks_insert_memory(struct agp_memory *mem, ...@@ -341,7 +341,7 @@ static int serverworks_insert_memory(struct agp_memory *mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = SVRWRKS_GET_GATT(addr); cur_gatt = SVRWRKS_GET_GATT(addr);
writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
} }
serverworks_tlbflush(mem); serverworks_tlbflush(mem);
return 0; return 0;
...@@ -387,15 +387,15 @@ static struct aper_size_info_lvl2 serverworks_sizes[7] = ...@@ -387,15 +387,15 @@ static struct aper_size_info_lvl2 serverworks_sizes[7] =
{32, 8192, 0xfe000000} {32, 8192, 0xfe000000}
}; };
static void serverworks_agp_enable(u32 mode) static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
u32 command; u32 command;
pci_read_config_dword(serverworks_private.svrwrks_dev, pci_read_config_dword(serverworks_private.svrwrks_dev,
agp_bridge->capndx + PCI_AGP_STATUS, bridge->capndx + PCI_AGP_STATUS,
&command); &command);
command = agp_collect_device_status(mode, command); command = agp_collect_device_status(bridge, mode, command);
command &= ~0x10; /* disable FW */ command &= ~0x10; /* disable FW */
command &= ~0x08; command &= ~0x08;
...@@ -403,7 +403,7 @@ static void serverworks_agp_enable(u32 mode) ...@@ -403,7 +403,7 @@ static void serverworks_agp_enable(u32 mode)
command |= 0x100; command |= 0x100;
pci_write_config_dword(serverworks_private.svrwrks_dev, pci_write_config_dword(serverworks_private.svrwrks_dev,
agp_bridge->capndx + PCI_AGP_COMMAND, bridge->capndx + PCI_AGP_COMMAND,
command); command);
agp_device_command(command, 0); agp_device_command(command, 0);
...@@ -541,7 +541,7 @@ static int __init agp_serverworks_init(void) ...@@ -541,7 +541,7 @@ static int __init agp_serverworks_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_serverworks_pci_driver); return pci_register_driver(&agp_serverworks_pci_driver);
} }
static void __exit agp_serverworks_cleanup(void) static void __exit agp_serverworks_cleanup(void)
......
...@@ -124,27 +124,27 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, ...@@ -124,27 +124,27 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
return 0; return 0;
} }
static void uninorth_agp_enable(u32 mode) static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{ {
u32 command, scratch; u32 command, scratch;
int timeout; int timeout;
pci_read_config_dword(agp_bridge->dev, pci_read_config_dword(bridge->dev,
agp_bridge->capndx + PCI_AGP_STATUS, bridge->capndx + PCI_AGP_STATUS,
&command); &command);
command = agp_collect_device_status(mode, command); command = agp_collect_device_status(bridge, mode, command);
command |= 0x100; command |= 0x100;
uninorth_tlbflush(NULL); uninorth_tlbflush(NULL);
timeout = 0; timeout = 0;
do { do {
pci_write_config_dword(agp_bridge->dev, pci_write_config_dword(bridge->dev,
agp_bridge->capndx + PCI_AGP_COMMAND, bridge->capndx + PCI_AGP_COMMAND,
command); command);
pci_read_config_dword(agp_bridge->dev, pci_read_config_dword(bridge->dev,
agp_bridge->capndx + PCI_AGP_COMMAND, bridge->capndx + PCI_AGP_COMMAND,
&scratch); &scratch);
} while ((scratch & 0x100) == 0 && ++timeout < 1000); } while ((scratch & 0x100) == 0 && ++timeout < 1000);
if ((scratch & 0x100) == 0) if ((scratch & 0x100) == 0)
...@@ -155,7 +155,7 @@ static void uninorth_agp_enable(u32 mode) ...@@ -155,7 +155,7 @@ static void uninorth_agp_enable(u32 mode)
uninorth_tlbflush(NULL); uninorth_tlbflush(NULL);
} }
static int uninorth_create_gatt_table(void) static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
{ {
char *table; char *table;
char *table_end; char *table_end;
...@@ -212,7 +212,7 @@ static int uninorth_create_gatt_table(void) ...@@ -212,7 +212,7 @@ static int uninorth_create_gatt_table(void)
return 0; return 0;
} }
static int uninorth_free_gatt_table(void) static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
{ {
int page_order; int page_order;
char *table, *table_end; char *table, *table_end;
...@@ -375,7 +375,7 @@ static int __init agp_uninorth_init(void) ...@@ -375,7 +375,7 @@ static int __init agp_uninorth_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_uninorth_pci_driver); return pci_register_driver(&agp_uninorth_pci_driver);
} }
static void __exit agp_uninorth_cleanup(void) static void __exit agp_uninorth_cleanup(void)
......
...@@ -36,6 +36,7 @@ static int via_fetch_size(void) ...@@ -36,6 +36,7 @@ static int via_fetch_size(void)
return values[i].size; return values[i].size;
} }
} }
printk(KERN_ERR PFX "Unknown aperture size from AGP bridge (0x%x)\n", temp);
return 0; return 0;
} }
...@@ -78,12 +79,19 @@ static void via_cleanup(void) ...@@ -78,12 +79,19 @@ static void via_cleanup(void)
static void via_tlbflush(struct agp_memory *mem) static void via_tlbflush(struct agp_memory *mem)
{ {
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000008f); u32 temp;
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
pci_read_config_dword(agp_bridge->dev, VIA_GARTCTRL, &temp);
temp |= (1<<7);
temp &= ~0x7f;
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
temp &= ~(1<<7);
temp &= ~0x7f;
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
} }
static struct aper_size_info_8 via_generic_sizes[7] = static struct aper_size_info_8 via_generic_sizes[9] =
{ {
{256, 65536, 6, 0}, {256, 65536, 6, 0},
{128, 32768, 5, 128}, {128, 32768, 5, 128},
...@@ -91,7 +99,9 @@ static struct aper_size_info_8 via_generic_sizes[7] = ...@@ -91,7 +99,9 @@ static struct aper_size_info_8 via_generic_sizes[7] =
{32, 8192, 3, 224}, {32, 8192, 3, 224},
{16, 4096, 2, 240}, {16, 4096, 2, 240},
{8, 2048, 1, 248}, {8, 2048, 1, 248},
{4, 1024, 0, 252} {4, 1024, 0, 252},
{2, 512, 0, 254},
{1, 256, 0, 255}
}; };
...@@ -189,7 +199,7 @@ struct agp_bridge_driver via_driver = { ...@@ -189,7 +199,7 @@ struct agp_bridge_driver via_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.aperture_sizes = via_generic_sizes, .aperture_sizes = via_generic_sizes,
.size_type = U8_APER_SIZE, .size_type = U8_APER_SIZE,
.num_aperture_sizes = 7, .num_aperture_sizes = 9,
.configure = via_configure, .configure = via_configure,
.fetch_size = via_fetch_size, .fetch_size = via_fetch_size,
.cleanup = via_cleanup, .cleanup = via_cleanup,
...@@ -525,7 +535,7 @@ static int __init agp_via_init(void) ...@@ -525,7 +535,7 @@ static int __init agp_via_init(void)
{ {
if (agp_off) if (agp_off)
return -EINVAL; return -EINVAL;
return pci_module_init(&agp_via_pci_driver); return pci_register_driver(&agp_via_pci_driver);
} }
static void __exit agp_via_cleanup(void) static void __exit agp_via_cleanup(void)
......
...@@ -497,6 +497,7 @@ typedef struct drm_agp_head { ...@@ -497,6 +497,7 @@ typedef struct drm_agp_head {
DRM_AGP_KERN agp_info; /**< AGP device information */ DRM_AGP_KERN agp_info; /**< AGP device information */
drm_agp_mem_t *memory; /**< memory entries */ drm_agp_mem_t *memory; /**< memory entries */
unsigned long mode; /**< AGP mode */ unsigned long mode; /**< AGP mode */
struct agp_bridge_data *bridge;
int enabled; /**< whether the AGP bus as been enabled */ int enabled; /**< whether the AGP bus as been enabled */
int acquired; /**< whether the AGP device has been acquired */ int acquired; /**< whether the AGP device has been acquired */
unsigned long base; unsigned long base;
...@@ -807,7 +808,7 @@ extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, ...@@ -807,7 +808,7 @@ extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
drm_device_t *dev); drm_device_t *dev);
extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev); extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
extern DRM_AGP_MEM *drm_alloc_agp(int pages, u32 type); extern DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
extern int drm_free_agp(DRM_AGP_MEM *handle, int pages); extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start); extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
extern int drm_unbind_agp(DRM_AGP_MEM *handle); extern int drm_unbind_agp(DRM_AGP_MEM *handle);
...@@ -930,10 +931,10 @@ extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq); ...@@ -930,10 +931,10 @@ extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
extern void drm_vbl_send_signals( drm_device_t *dev ); extern void drm_vbl_send_signals( drm_device_t *dev );
/* AGP/GART support (drm_agpsupport.h) */ /* AGP/GART support (drm_agpsupport.h) */
extern drm_agp_head_t *drm_agp_init(void); extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
extern int drm_agp_acquire(struct inode *inode, struct file *filp, extern int drm_agp_acquire(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern void drm_agp_do_release(void); extern void drm_agp_do_release(drm_device_t *dev);
extern int drm_agp_release(struct inode *inode, struct file *filp, extern int drm_agp_release(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_agp_enable(struct inode *inode, struct file *filp, extern int drm_agp_enable(struct inode *inode, struct file *filp,
...@@ -948,7 +949,7 @@ extern int drm_agp_unbind(struct inode *inode, struct file *filp, ...@@ -948,7 +949,7 @@ extern int drm_agp_unbind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_agp_bind(struct inode *inode, struct file *filp, extern int drm_agp_bind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type); extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
extern int drm_agp_free_memory(DRM_AGP_MEM *handle); extern int drm_agp_free_memory(DRM_AGP_MEM *handle);
extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start); extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle); extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
......
...@@ -92,14 +92,13 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, ...@@ -92,14 +92,13 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
int retcode;
if (!dev->agp) if (!dev->agp)
return -ENODEV; return -ENODEV;
if (dev->agp->acquired) if (dev->agp->acquired)
return -EBUSY; return -EBUSY;
if ((retcode = agp_backend_acquire())) if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
return retcode; return -ENODEV;
dev->agp->acquired = 1; dev->agp->acquired = 1;
return 0; return 0;
} }
...@@ -123,7 +122,7 @@ int drm_agp_release(struct inode *inode, struct file *filp, ...@@ -123,7 +122,7 @@ int drm_agp_release(struct inode *inode, struct file *filp,
if (!dev->agp || !dev->agp->acquired) if (!dev->agp || !dev->agp->acquired)
return -EINVAL; return -EINVAL;
agp_backend_release(); agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0; dev->agp->acquired = 0;
return 0; return 0;
...@@ -134,9 +133,9 @@ int drm_agp_release(struct inode *inode, struct file *filp, ...@@ -134,9 +133,9 @@ int drm_agp_release(struct inode *inode, struct file *filp,
* *
* Calls agp_backend_release(). * Calls agp_backend_release().
*/ */
void drm_agp_do_release(void) void drm_agp_do_release(drm_device_t *dev)
{ {
agp_backend_release(); agp_backend_release(dev->agp->bridge);
} }
/** /**
...@@ -165,7 +164,7 @@ int drm_agp_enable(struct inode *inode, struct file *filp, ...@@ -165,7 +164,7 @@ int drm_agp_enable(struct inode *inode, struct file *filp,
return -EFAULT; return -EFAULT;
dev->agp->mode = mode.mode; dev->agp->mode = mode.mode;
agp_enable(mode.mode); agp_enable(dev->agp->bridge, mode.mode);
dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1; dev->agp->enabled = 1;
return 0; return 0;
...@@ -207,7 +206,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, ...@@ -207,7 +206,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request.type; type = (u32) request.type;
if (!(memory = drm_alloc_agp(pages, type))) { if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM; return -ENOMEM;
} }
...@@ -381,14 +380,19 @@ int drm_agp_free(struct inode *inode, struct file *filp, ...@@ -381,14 +380,19 @@ int drm_agp_free(struct inode *inode, struct file *filp,
* \return pointer to a drm_agp_head structure. * \return pointer to a drm_agp_head structure.
* *
*/ */
drm_agp_head_t *drm_agp_init(void) drm_agp_head_t *drm_agp_init(drm_device_t *dev)
{ {
drm_agp_head_t *head = NULL; drm_agp_head_t *head = NULL;
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
return NULL; return NULL;
memset((void *)head, 0, sizeof(*head)); memset((void *)head, 0, sizeof(*head));
agp_copy_info(&head->agp_info); if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
return NULL;
}
agp_copy_info(head->bridge, &head->agp_info);
agp_backend_release(head->bridge);
if (head->agp_info.chipset == NOT_SUPPORTED) { if (head->agp_info.chipset == NOT_SUPPORTED) {
drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
return NULL; return NULL;
...@@ -406,9 +410,9 @@ drm_agp_head_t *drm_agp_init(void) ...@@ -406,9 +410,9 @@ drm_agp_head_t *drm_agp_init(void)
} }
/** Calls agp_allocate_memory() */ /** Calls agp_allocate_memory() */
DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type) DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
{ {
return agp_allocate_memory(pages, type); return agp_allocate_memory(bridge, pages, type);
} }
/** Calls agp_free_memory() */ /** Calls agp_free_memory() */
......
...@@ -185,7 +185,7 @@ int drm_takedown( drm_device_t *dev ) ...@@ -185,7 +185,7 @@ int drm_takedown( drm_device_t *dev )
} }
dev->agp->memory = NULL; dev->agp->memory = NULL;
if ( dev->agp->acquired ) drm_agp_do_release(); if ( dev->agp->acquired ) drm_agp_do_release(dev);
dev->agp->acquired = 0; dev->agp->acquired = 0;
dev->agp->enabled = 0; dev->agp->enabled = 0;
......
...@@ -155,9 +155,9 @@ void drm_free_pages(unsigned long address, int order, int area) ...@@ -155,9 +155,9 @@ void drm_free_pages(unsigned long address, int order, int area)
#if __OS_HAS_AGP #if __OS_HAS_AGP
/** Wrapper around agp_allocate_memory() */ /** Wrapper around agp_allocate_memory() */
DRM_AGP_MEM *drm_alloc_agp(int pages, u32 type) DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
{ {
return drm_agp_allocate_memory(pages, type); return drm_agp_allocate_memory(bridge, pages, type);
} }
/** Wrapper around agp_free_memory() */ /** Wrapper around agp_free_memory() */
......
...@@ -91,7 +91,7 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct ...@@ -91,7 +91,7 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
goto error_out_unreg; goto error_out_unreg;
if (drm_core_has_AGP(dev)) { if (drm_core_has_AGP(dev)) {
dev->agp = drm_agp_init(); dev->agp = drm_agp_init(dev);
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) { if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" ); DRM_ERROR( "Cannot initialize the agpgart module.\n" );
retcode = -EINVAL; retcode = -EINVAL;
......
...@@ -1591,40 +1591,41 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info) ...@@ -1591,40 +1591,41 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
{ {
struct i810fb_par *par = (struct i810fb_par *) info->par; struct i810fb_par *par = (struct i810fb_par *) info->par;
int size; int size;
struct agp_bridge_data *bridge;
i810_fix_offsets(par); i810_fix_offsets(par);
size = par->fb.size + par->iring.size; size = par->fb.size + par->iring.size;
if (agp_backend_acquire()) { if (!(bridge = agp_backend_acquire(par->dev))) {
printk("i810fb_alloc_fbmem: cannot acquire agpgart\n"); printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
return -ENODEV; return -ENODEV;
} }
if (!(par->i810_gtt.i810_fb_memory = if (!(par->i810_gtt.i810_fb_memory =
agp_allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) { agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
printk("i810fb_alloc_fbmem: can't allocate framebuffer " printk("i810fb_alloc_fbmem: can't allocate framebuffer "
"memory\n"); "memory\n");
agp_backend_release(); agp_backend_release(bridge);
return -ENOMEM; return -ENOMEM;
} }
if (agp_bind_memory(par->i810_gtt.i810_fb_memory, if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset)) { par->fb.offset)) {
printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n"); printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
agp_backend_release(); agp_backend_release(bridge);
return -EBUSY; return -EBUSY;
} }
if (!(par->i810_gtt.i810_cursor_memory = if (!(par->i810_gtt.i810_cursor_memory =
agp_allocate_memory(par->cursor_heap.size >> 12, agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
AGP_PHYSICAL_MEMORY))) { AGP_PHYSICAL_MEMORY))) {
printk("i810fb_alloc_cursormem: can't allocate" printk("i810fb_alloc_cursormem: can't allocate"
"cursor memory\n"); "cursor memory\n");
agp_backend_release(); agp_backend_release(bridge);
return -ENOMEM; return -ENOMEM;
} }
if (agp_bind_memory(par->i810_gtt.i810_cursor_memory, if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset)) { par->cursor_heap.offset)) {
printk("i810fb_alloc_cursormem: cannot bind cursor memory\n"); printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
agp_backend_release(); agp_backend_release(bridge);
return -EBUSY; return -EBUSY;
} }
...@@ -1632,7 +1633,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info) ...@@ -1632,7 +1633,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
i810_fix_pointers(par); i810_fix_pointers(par);
agp_backend_release(); agp_backend_release(bridge);
return 0; return 0;
} }
......
...@@ -470,6 +470,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -470,6 +470,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
struct agp_kern_info gtt_info; struct agp_kern_info gtt_info;
int agp_memtype; int agp_memtype;
const char *s; const char *s;
struct agp_bridge_data *bridge;
DBG_MSG("intelfb_pci_register\n"); DBG_MSG("intelfb_pci_register\n");
...@@ -605,16 +606,16 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -605,16 +606,16 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
/* Use agpgart to manage the GATT */ /* Use agpgart to manage the GATT */
if (agp_backend_acquire()) { if (!(bridge = agp_backend_acquire(pdev))) {
ERR_MSG("cannot acquire agp\n"); ERR_MSG("cannot acquire agp\n");
cleanup(dinfo); cleanup(dinfo);
return -ENODEV; return -ENODEV;
} }
/* get the current gatt info */ /* get the current gatt info */
if (agp_copy_info(&gtt_info)) { if (agp_copy_info(bridge, &gtt_info)) {
ERR_MSG("cannot get agp info\n"); ERR_MSG("cannot get agp info\n");
agp_backend_release(); agp_backend_release(bridge);
cleanup(dinfo); cleanup(dinfo);
return -ENODEV; return -ENODEV;
} }
...@@ -637,17 +638,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -637,17 +638,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Allocate memories (which aren't stolen) */ /* Allocate memories (which aren't stolen) */
if (dinfo->accel) { if (dinfo->accel) {
if (!(dinfo->gtt_ring_mem = if (!(dinfo->gtt_ring_mem =
agp_allocate_memory(dinfo->ring.size >> 12, agp_allocate_memory(bridge, dinfo->ring.size >> 12,
AGP_NORMAL_MEMORY))) { AGP_NORMAL_MEMORY))) {
ERR_MSG("cannot allocate ring buffer memory\n"); ERR_MSG("cannot allocate ring buffer memory\n");
agp_backend_release(); agp_backend_release(bridge);
cleanup(dinfo); cleanup(dinfo);
return -ENOMEM; return -ENOMEM;
} }
if (agp_bind_memory(dinfo->gtt_ring_mem, if (agp_bind_memory(dinfo->gtt_ring_mem,
dinfo->ring.offset)) { dinfo->ring.offset)) {
ERR_MSG("cannot bind ring buffer memory\n"); ERR_MSG("cannot bind ring buffer memory\n");
agp_backend_release(); agp_backend_release(bridge);
cleanup(dinfo); cleanup(dinfo);
return -EBUSY; return -EBUSY;
} }
...@@ -661,17 +662,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -661,17 +662,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
: AGP_NORMAL_MEMORY; : AGP_NORMAL_MEMORY;
if (!(dinfo->gtt_cursor_mem = if (!(dinfo->gtt_cursor_mem =
agp_allocate_memory(dinfo->cursor.size >> 12, agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
agp_memtype))) { agp_memtype))) {
ERR_MSG("cannot allocate cursor memory\n"); ERR_MSG("cannot allocate cursor memory\n");
agp_backend_release(); agp_backend_release(bridge);
cleanup(dinfo); cleanup(dinfo);
return -ENOMEM; return -ENOMEM;
} }
if (agp_bind_memory(dinfo->gtt_cursor_mem, if (agp_bind_memory(dinfo->gtt_cursor_mem,
dinfo->cursor.offset)) { dinfo->cursor.offset)) {
ERR_MSG("cannot bind cursor memory\n"); ERR_MSG("cannot bind cursor memory\n");
agp_backend_release(); agp_backend_release(bridge);
cleanup(dinfo); cleanup(dinfo);
return -EBUSY; return -EBUSY;
} }
...@@ -686,7 +687,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -686,7 +687,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
if (dinfo->fbmem_gart) { if (dinfo->fbmem_gart) {
if (!(dinfo->gtt_fb_mem = if (!(dinfo->gtt_fb_mem =
agp_allocate_memory(dinfo->fb.size >> 12, agp_allocate_memory(bridge, dinfo->fb.size >> 12,
AGP_NORMAL_MEMORY))) { AGP_NORMAL_MEMORY))) {
WRN_MSG("cannot allocate framebuffer memory - use " WRN_MSG("cannot allocate framebuffer memory - use "
"the stolen one\n"); "the stolen one\n");
...@@ -709,7 +710,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -709,7 +710,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
dinfo->fb_start = dinfo->fb.offset << 12; dinfo->fb_start = dinfo->fb.offset << 12;
/* release agpgart */ /* release agpgart */
agp_backend_release(); agp_backend_release(bridge);
if (mtrr) if (mtrr)
set_mtrr(dinfo); set_mtrr(dinfo);
......
/* /*
* AGPGART backend specific includes. Not for userspace consumption. * AGPGART backend specific includes. Not for userspace consumption.
* *
* Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones * Copyright (C) 2002-2003 Dave Jones
* Copyright (C) 1999 Jeff Hartmann * Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Precision Insight, Inc.
...@@ -68,16 +69,19 @@ struct agp_kern_info { ...@@ -68,16 +69,19 @@ struct agp_kern_info {
* allocated. A caller may manipulate the next and prev pointers to link * allocated. A caller may manipulate the next and prev pointers to link
* each allocated item into a list. These pointers are ignored by the backend. * each allocated item into a list. These pointers are ignored by the backend.
* Everything else should never be written to, but the caller may read any of * Everything else should never be written to, but the caller may read any of
* the items to detrimine the status of this block of agp memory. * the items to determine the status of this block of agp memory.
*/ */
struct agp_bridge_data;
struct agp_memory { struct agp_memory {
int key;
struct agp_memory *next; struct agp_memory *next;
struct agp_memory *prev; struct agp_memory *prev;
struct agp_bridge_data *bridge;
unsigned long *memory;
size_t page_count; size_t page_count;
int key;
int num_scratch_pages; int num_scratch_pages;
unsigned long *memory;
off_t pg_start; off_t pg_start;
u32 type; u32 type;
u32 physical; u32 physical;
...@@ -87,14 +91,19 @@ struct agp_memory { ...@@ -87,14 +91,19 @@ struct agp_memory {
#define AGP_NORMAL_MEMORY 0 #define AGP_NORMAL_MEMORY 0
extern struct agp_bridge_data *agp_bridge;
extern struct list_head agp_bridges;
extern struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *);
extern void agp_free_memory(struct agp_memory *); extern void agp_free_memory(struct agp_memory *);
extern struct agp_memory *agp_allocate_memory(size_t, u32); extern struct agp_memory *agp_allocate_memory(struct agp_bridge_data *, size_t, u32);
extern int agp_copy_info(struct agp_kern_info *); extern int agp_copy_info(struct agp_bridge_data *, struct agp_kern_info *);
extern int agp_bind_memory(struct agp_memory *, off_t); extern int agp_bind_memory(struct agp_memory *, off_t);
extern int agp_unbind_memory(struct agp_memory *); extern int agp_unbind_memory(struct agp_memory *);
extern void agp_enable(u32); extern void agp_enable(struct agp_bridge_data *, u32);
extern int agp_backend_acquire(void); extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
extern void agp_backend_release(void); extern void agp_backend_release(struct agp_bridge_data *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _AGP_BACKEND_H */ #endif /* _AGP_BACKEND_H */
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