/* * AGPGART driver. * Copyright (C) 2004 Silicon Graphics, Inc. * Copyright (C) 2002-2005 Dave Jones. * Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * TODO: * - Allocate more than order 0 pages to avoid too much linear map splitting.
*/ #include <linux/module.h> #include <linux/pci.h> #include <linux/pagemap.h> #include <linux/miscdevice.h> #include <linux/pm.h> #include <linux/agp_backend.h> #include <linux/vmalloc.h> #include <linux/dma-mapping.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/slab.h> #include <asm/io.h> #ifdef CONFIG_X86 #include <asm/set_memory.h> #endif #include"agp.h"
__u32 *agp_gatt_table; int agp_memory_reserved;
/* * Needed by the Nforce GART driver for the time being. Would be * nice to do this some other way instead of needing this export.
*/
EXPORT_SYMBOL_GPL(agp_memory_reserved);
/* * Generic routines for handling agp_memory structures - * They use the basic page allocation routines to do the brunt of the work.
*/
void agp_free_key(int key)
{ if (key < 0) return;
if (key < MAXKEY)
clear_bit(key, agp_bridge->key_list);
}
EXPORT_SYMBOL(agp_free_key);
staticint agp_get_key(void)
{ int bit;
bit = find_first_zero_bit(agp_bridge->key_list, MAXKEY); if (bit < MAXKEY) {
set_bit(bit, agp_bridge->key_list); return bit;
} return -1;
}
/* * Use kmalloc if possible for the page list. Otherwise fall back to * vmalloc. This speeds things up and also saves memory for small AGP * regions.
*/
/** * agp_free_memory - free memory associated with an agp_memory pointer. * * @curr: agp_memory pointer to be freed. * * It is the only function that can be called when the backend is not owned * by the caller. (So it can free memory on client death.)
*/ void agp_free_memory(struct agp_memory *curr)
{
size_t i;
if (curr == NULL) return;
if (curr->is_bound)
agp_unbind_memory(curr);
if (curr->type >= AGP_USER_TYPES) {
agp_generic_free_by_type(curr); return;
}
if (curr->type != 0) {
curr->bridge->driver->free_by_type(curr); return;
} if (curr->page_count != 0) { if (curr->bridge->driver->agp_destroy_pages) {
curr->bridge->driver->agp_destroy_pages(curr);
} else {
for (i = 0; i < curr->page_count; i++) {
curr->bridge->driver->agp_destroy_page(
curr->pages[i],
AGP_PAGE_DESTROY_UNMAP);
} for (i = 0; i < curr->page_count; i++) {
curr->bridge->driver->agp_destroy_page(
curr->pages[i],
AGP_PAGE_DESTROY_FREE);
}
}
}
agp_free_key(curr->key);
agp_free_page_array(curr);
kfree(curr);
}
EXPORT_SYMBOL(agp_free_memory);
/** * agp_allocate_memory - allocate a group of pages of a certain type. * * @bridge: an agp_bridge_data struct allocated for the AGP host bridge. * @page_count: size_t argument of the number of pages * @type: u32 argument of the type of memory to be allocated. * * Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which * maps to physical ram. Any other type is device dependent. * * It returns NULL whenever memory is unavailable.
*/ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
size_t page_count, u32 type)
{ int scratch_pages; struct agp_memory *new;
size_t i; int cur_memory;
/** * agp_copy_info - copy bridge state information * * @bridge: an agp_bridge_data struct allocated for the AGP host bridge. * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. * * This function copies information about the agp bridge device and the state of * the agp backend into an agp_kern_info pointer.
*/ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
{
memset(info, 0, sizeof(struct agp_kern_info)); if (!bridge) {
info->chipset = NOT_SUPPORTED; return -EIO;
}
/* End - Routine to copy over information structure */
/* * Routines for handling swapping of agp_memory into the GATT - * These routines take agp_memory and insert them into the GATT. * They call device specific routines to actually write to the GATT.
*/
/** * agp_bind_memory - Bind an agp_memory structure into the GATT. * * @curr: agp_memory pointer * @pg_start: an offset into the graphics aperture translation table * * It returns -EINVAL if the pointer == NULL. * It returns -EBUSY if the area of the table requested is already in use.
*/ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
{ int ret_val;
if (curr == NULL) return -EINVAL;
if (curr->is_bound) {
printk(KERN_INFO PFX "memory %p is already bound!\n", curr); return -EINVAL;
} if (!curr->is_flushed) {
curr->bridge->driver->cache_flush();
curr->is_flushed = true;
}
/** * agp_unbind_memory - Removes an agp_memory structure from the GATT * * @curr: agp_memory pointer to be removed from the GATT. * * It returns -EINVAL if this piece of agp_memory is not currently bound to * the graphics aperture translation table or if the agp_memory pointer == NULL
*/ int agp_unbind_memory(struct agp_memory *curr)
{ int ret_val;
if (curr == NULL) return -EINVAL;
if (!curr->is_bound) {
printk(KERN_INFO PFX "memory %p was not bound!\n", curr); return -EINVAL;
}
if (*requested_mode & AGP2_RESERVED_MASK) {
printk(KERN_INFO PFX "reserved bits set (%x) in mode 0x%x. Fixed.\n",
*requested_mode & AGP2_RESERVED_MASK, *requested_mode);
*requested_mode &= ~AGP2_RESERVED_MASK;
}
/* * Some dumb bridges are programmed to disobey the AGP2 spec. * This is likely a BIOS misprogramming rather than poweron default, or * it would be a lot more common. * https://bugs.freedesktop.org/show_bug.cgi?id=8816 * AGPv2 spec 6.1.9 states: * The RATE field indicates the data transfer rates supported by this * device. A.G.P. devices must report all that apply. * Fix them up as best we can.
*/ switch (*bridge_agpstat & 7) { case 4:
*bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X);
printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate. " "Fixing up support for x2 & x1\n"); break; case 2:
*bridge_agpstat |= AGPSTAT2_1X;
printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate. " "Fixing up support for x1\n"); break; default: break;
}
/* 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 */ if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
*bridge_agpstat &= ~AGPSTAT_SBA;
/* Set rate */ if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
*bridge_agpstat &= ~AGPSTAT2_4X;
/* Now we know what mode it should be, clear out the unwanted bits. */ if (*bridge_agpstat & AGPSTAT2_4X)
*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */
if (*requested_mode & AGP3_RESERVED_MASK) {
printk(KERN_INFO PFX "reserved bits set (%x) in mode 0x%x. Fixed.\n",
*requested_mode & AGP3_RESERVED_MASK, *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=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
*requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
}
/* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values. */
*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
/* SBA *must* be supported for AGP v3 */
*bridge_agpstat |= AGPSTAT_SBA;
/* * Set speed. * Check for invalid speeds. This can happen when applications * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
*/ if (*requested_mode & AGPSTAT_MODE_3_0) { /* * 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. * AGP2.x 4x -> AGP3.0 4x.
*/ if (*requested_mode & AGPSTAT2_4X) {
printk(KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~AGPSTAT2_4X;
*requested_mode |= AGPSTAT3_4X;
}
} else { /* * The caller doesn't know what they are doing. We are in 3.0 mode, * but have been passed an AGP 2.x mode. * Convert AGP 1x,2x,4x -> AGP 3.0 4x.
*/
printk(KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
current->comm, *requested_mode);
*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
*requested_mode |= AGPSTAT3_4X;
}
if (*requested_mode & AGPSTAT3_8X) { if (!(*bridge_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
printk(KERN_INFO PFX "%s requested AGPx8 but bridge not capable.\n", current->comm); return;
} if (!(*vga_agpstat & AGPSTAT3_8X)) {
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
printk(KERN_INFO PFX "%s requested AGPx8 but graphic card not capable.\n", current->comm); return;
} /* All set, bridge & device can do AGP x8*/
*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); goto done;
/* * If we didn't specify an AGP mode, we see if both * the graphics card, and the bridge can do x8, and use if so. * If not, we fall back to x4 mode.
*/ if ((*bridge_agpstat & AGPSTAT3_8X) && (*vga_agpstat & AGPSTAT3_8X)) {
printk(KERN_INFO PFX "No AGP mode specified. Setting to highest mode " "supported by bridge & card (x8).\n");
*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
*vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
} else {
printk(KERN_INFO PFX "Fell back to AGPx4 mode because "); if (!(*bridge_agpstat & AGPSTAT3_8X)) {
printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n",
*bridge_agpstat, origbridge);
*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*bridge_agpstat |= AGPSTAT3_4X;
} if (!(*vga_agpstat & AGPSTAT3_8X)) {
printk(KERN_INFO PFX "graphics card couldn't do x8. vga_agpstat:%x (orig=%x)\n",
*vga_agpstat, origvga);
*vga_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
*vga_agpstat |= AGPSTAT3_4X;
}
}
}
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;
/** * 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;
u32 vga_agpstat;
u8 cap_ptr;
for (;;) {
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); if (cap_ptr) break;
}
/* * Ok, here we have a AGP device. Disable impossible * settings, and adjust the readqueue to the minimum.
*/
pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat);
/* disable FW if it's not supported */ if (!((bridge_agpstat & 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 */ if (agp_bridge->mode & AGPSTAT_MODE_3_0)
agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); else
agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat); if (bridge_agpstat == 0) /* Something bad happened. FIXME: Return error code? */ return;
bridge_agpstat |= AGPSTAT_AGP_ENABLE;
/* Do AGP version specific frobbing. */ if (bridge->major_version >= 3) { if (bridge->mode & AGPSTAT_MODE_3_0) { /* If we have 3.5, we can do the isoch stuff. */ if (bridge->minor_version >= 5)
agp_3_5_enable(bridge);
agp_device_command(bridge_agpstat, true); return;
} else { /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
bridge_agpstat &= ~(7<<10) ;
pci_read_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, &temp);
temp |= (1<<9);
pci_write_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, temp);
dev_info(&bridge->dev->dev, "bridge is in legacy mode, falling back to 2.x\n");
}
}
int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
{ char *table; char *table_end; int page_order; int num_entries; int i; void *temp; struct page *page;
/* The generic routines can't handle 2 level gatt's */ if (bridge->driver->size_type == LVL2_APER_SIZE) return -EINVAL;
bridge->driver->cache_flush(); #ifdef CONFIG_X86 if (set_memory_uc((unsignedlong)table, 1 << page_order))
printk(KERN_WARNING "Could not set GATT table memory to UC!\n");
/* * Basic Page Allocation Routines - * These routines handle page allocation and by default they reserve the allocated * memory. They also handle incrementing the current_memory_agp value, Which is checked * against a maximum value.
*/
int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
{ struct page * page; int i, ret = -ENOMEM;
for (i = 0; i < num_pages; i++) {
page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); /* agp_free_memory() needs gart address */ if (page == NULL) goto out;
unsignedlong agp_generic_mask_memory(struct agp_bridge_data *bridge,
dma_addr_t addr, int type)
{ /* memory type is ignored in the generic routine */ if (bridge->driver->masks) return addr | bridge->driver->masks[0].mask; else return addr;
}
EXPORT_SYMBOL(agp_generic_mask_memory);
int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge, int type)
{ if (type >= AGP_USER_TYPES) return 0; return type;
}
EXPORT_SYMBOL(agp_generic_type_to_mask_type);
/* * These functions are implemented according to the AGPv3 spec, * which covers implementation details that had previously been * left open.
*/
int agp3_generic_fetch_size(void)
{
u16 temp_size; int i; struct aper_size_info_16 *values;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.