VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / char / agp / generic.c
index ba6c102..f656624 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * AGPGART driver.
- * Copyright (C) 2002-2003 Dave Jones.
+ * Copyright (C) 2002-2004 Dave Jones.
  * Copyright (C) 1999 Jeff Hartmann.
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
  * 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 
+ * 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: 
+ * TODO:
  * - Allocate more than order 0 pages to avoid too much linear map splitting.
  */
 #include <linux/config.h>
@@ -37,7 +37,7 @@
 #include <linux/vmalloc.h>
 #include "agp.h"
 
-__u32 *agp_gatt_table; 
+__u32 *agp_gatt_table;
 int agp_memory_reserved;
 
 /*
@@ -46,7 +46,7 @@ int agp_memory_reserved;
  */
 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.
  */
@@ -142,12 +142,12 @@ EXPORT_SYMBOL(agp_free_memory);
  *     agp_allocate_memory  -  allocate a group of pages of a certain type.
  *
  *     @page_count:    size_t argument of the number of pages
- *     @type:  u32 argument of the type of memory to be allocated.  
+ *     @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. 
+ *     It returns NULL whenever memory is unavailable.
  */
 struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
 {
@@ -311,7 +311,7 @@ EXPORT_SYMBOL(agp_copy_info);
 
 /**
  *     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
  *
@@ -347,9 +347,9 @@ EXPORT_SYMBOL(agp_bind_memory);
 
 /**
  *     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
  */
@@ -404,12 +404,18 @@ static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
                *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X);   /* 2X */
 
        if (*cmd & AGPSTAT2_1X)
-               *cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X);   /* 1Xf */
+               *cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X);   /* 1X */
 }
 
-
+/*
+ * mode = requested mode.
+ * cmd = PCI_AGP_STATUS from agp bridge.
+ * tmp = PCI_AGP_STATUS from graphic card.
+ */
 static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
 {
+       u32 origcmd=*cmd, origtmp=*tmp;
+
        /* ARQSZ - Set the value to the maximum one.
         * Don't allow the mode register to override values. */
        *cmd = ((*cmd & ~AGPSTAT_ARQSZ) |
@@ -452,17 +458,43 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
                *mode |= AGPSTAT3_4X;
        }
 
-       if (!((*cmd & AGPSTAT3_8X) && (*tmp & AGPSTAT3_8X) && (*mode & AGPSTAT3_8X)))
-               *cmd &= ~AGPSTAT3_8X;
+       if (*mode & AGPSTAT3_8X) {
+               if (!(*cmd & AGPSTAT3_8X)) {
+                       *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+                       *cmd |= AGPSTAT3_4X;
+                       printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
+                       return;
+               }
+               if (!(*tmp & AGPSTAT3_8X)) {
+                       *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+                       *cmd |= AGPSTAT3_4X;
+                       printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
+                       return;
+               }
+               /* All set, bridge & device can do AGP x8*/
+               *cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+               return;
 
-       if (!((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X) && (*mode & AGPSTAT3_4X)))
-               *cmd &= ~AGPSTAT3_4X;
+       } else {
 
-       /* Clear out unwanted bits. */
-       if (*cmd & AGPSTAT3_8X)
-               *cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
-       if (*cmd & AGPSTAT3_4X)
+               /*
+                * If we didn't specify AGPx8, we can only do x4.
+                * If the hardware can't do x4, we're up shit creek, and never
+                *  should have got this far.
+                */
                *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+               if ((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X))
+                       *cmd |= AGPSTAT3_4X;
+               else {
+                       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",
+                                                       origcmd, origtmp, *cmd, *tmp);
+                       if (!(*cmd & AGPSTAT3_4X))
+                               printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
+                       if (!(*tmp & AGPSTAT3_4X))
+                               printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+               }
+       }
 }
 
 //FIXME: This doesn't smell right.
@@ -479,8 +511,10 @@ u32 agp_collect_device_status(u32 mode, u32 cmd)
                if (!cap_ptr)
                        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.
                 */
                pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp);
@@ -489,7 +523,7 @@ u32 agp_collect_device_status(u32 mode, u32 cmd)
                cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) |
                     min_t(u32, (mode & AGPSTAT_RQ_DEPTH),
                         min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH))));
-               
+
                /* disable FW if it's not supported */
                if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW)))
                        cmd &= ~AGPSTAT_FW;
@@ -663,7 +697,7 @@ int agp_generic_create_gatt_table(void)
                                            agp_bridge->current_size;
                                        break;
                                }
-                               temp = agp_bridge->current_size;        
+                               temp = agp_bridge->current_size;
                        } else {
                                agp_bridge->aperture_size_idx = i;
                        }
@@ -684,7 +718,7 @@ int agp_generic_create_gatt_table(void)
                SetPageReserved(page);
 
        agp_bridge->gatt_table_real = (u32 *) table;
-       agp_gatt_table = (void *)table; 
+       agp_gatt_table = (void *)table;
 
        agp_bridge->driver->cache_flush();
        agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
@@ -870,9 +904,9 @@ void agp_generic_free_by_type(struct agp_memory *curr)
 EXPORT_SYMBOL(agp_generic_free_by_type);
 
 
-/* 
+/*
  * Basic Page Allocation Routines -
- * These routines handle page allocation and by default they reserve the allocated 
+ * 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.
  */
@@ -883,7 +917,7 @@ void *agp_generic_alloc_page(void)
 
        page = alloc_page(GFP_KERNEL);
        if (page == NULL)
-               return 0;
+               return NULL;
 
        map_page_into_agp(page);
 
@@ -914,9 +948,9 @@ EXPORT_SYMBOL(agp_generic_destroy_page);
 /* End Basic Page Allocation Routines */
 
 
-/** 
+/**
  * agp_enable  -  initialise the agp point-to-point connection.
- * 
+ *
  * @mode:      agp mode register value to configure with.
  */
 void agp_enable(u32 mode)