Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * AGPGART driver backend routines.
0003  * Copyright (C) 2004 Silicon Graphics, Inc.
0004  * Copyright (C) 2002-2003 Dave Jones.
0005  * Copyright (C) 1999 Jeff Hartmann.
0006  * Copyright (C) 1999 Precision Insight, Inc.
0007  * Copyright (C) 1999 Xi Graphics, Inc.
0008  *
0009  * Permission is hereby granted, free of charge, to any person obtaining a
0010  * copy of this software and associated documentation files (the "Software"),
0011  * to deal in the Software without restriction, including without limitation
0012  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0013  * and/or sell copies of the Software, and to permit persons to whom the
0014  * Software is furnished to do so, subject to the following conditions:
0015  *
0016  * The above copyright notice and this permission notice shall be included
0017  * in all copies or substantial portions of the Software.
0018  *
0019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0020  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0022  * JEFF HARTMANN, DAVE JONES, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
0023  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0024  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
0025  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0026  *
0027  * TODO:
0028  * - Allocate more than order 0 pages to avoid too much linear map splitting.
0029  */
0030 #include <linux/module.h>
0031 #include <linux/pci.h>
0032 #include <linux/init.h>
0033 #include <linux/slab.h>
0034 #include <linux/pagemap.h>
0035 #include <linux/miscdevice.h>
0036 #include <linux/pm.h>
0037 #include <linux/agp_backend.h>
0038 #include <linux/agpgart.h>
0039 #include <linux/vmalloc.h>
0040 #include <asm/io.h>
0041 #include "agp.h"
0042 
0043 /* Due to XFree86 brain-damage, we can't go to 1.0 until they
0044  * fix some real stupidity. It's only by chance we can bump
0045  * past 0.99 at all due to some boolean logic error. */
0046 #define AGPGART_VERSION_MAJOR 0
0047 #define AGPGART_VERSION_MINOR 103
0048 static const struct agp_version agp_current_version =
0049 {
0050     .major = AGPGART_VERSION_MAJOR,
0051     .minor = AGPGART_VERSION_MINOR,
0052 };
0053 
0054 struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *) =
0055     &agp_generic_find_bridge;
0056 
0057 struct agp_bridge_data *agp_bridge;
0058 LIST_HEAD(agp_bridges);
0059 EXPORT_SYMBOL(agp_bridge);
0060 EXPORT_SYMBOL(agp_bridges);
0061 EXPORT_SYMBOL(agp_find_bridge);
0062 
0063 /**
0064  *  agp_backend_acquire  -  attempt to acquire an agp backend.
0065  *  @pdev: the PCI device
0066  *
0067  */
0068 struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
0069 {
0070     struct agp_bridge_data *bridge;
0071 
0072     bridge = agp_find_bridge(pdev);
0073 
0074     if (!bridge)
0075         return NULL;
0076 
0077     if (atomic_read(&bridge->agp_in_use))
0078         return NULL;
0079     atomic_inc(&bridge->agp_in_use);
0080     return bridge;
0081 }
0082 EXPORT_SYMBOL(agp_backend_acquire);
0083 
0084 
0085 /**
0086  *  agp_backend_release  -  release the lock on the agp backend.
0087  *  @bridge: the AGP backend to release
0088  *
0089  *  The caller must insure that the graphics aperture translation table
0090  *  is read for use by another entity.
0091  *
0092  *  (Ensure that all memory it bound is unbound.)
0093  */
0094 void agp_backend_release(struct agp_bridge_data *bridge)
0095 {
0096 
0097     if (bridge)
0098         atomic_dec(&bridge->agp_in_use);
0099 }
0100 EXPORT_SYMBOL(agp_backend_release);
0101 
0102 
0103 static const struct { int mem, agp; } maxes_table[] = {
0104     {0, 0},
0105     {32, 4},
0106     {64, 28},
0107     {128, 96},
0108     {256, 204},
0109     {512, 440},
0110     {1024, 942},
0111     {2048, 1920},
0112     {4096, 3932}
0113 };
0114 
0115 static int agp_find_max(void)
0116 {
0117     long memory, index, result;
0118 
0119 #if PAGE_SHIFT < 20
0120     memory = totalram_pages() >> (20 - PAGE_SHIFT);
0121 #else
0122     memory = totalram_pages() << (PAGE_SHIFT - 20);
0123 #endif
0124     index = 1;
0125 
0126     while ((memory > maxes_table[index].mem) && (index < 8))
0127         index++;
0128 
0129     result = maxes_table[index - 1].agp +
0130        ( (memory - maxes_table[index - 1].mem)  *
0131          (maxes_table[index].agp - maxes_table[index - 1].agp)) /
0132        (maxes_table[index].mem - maxes_table[index - 1].mem);
0133 
0134     result = result << (20 - PAGE_SHIFT);
0135     return result;
0136 }
0137 
0138 
0139 static int agp_backend_initialize(struct agp_bridge_data *bridge)
0140 {
0141     int size_value, rc, got_gatt=0, got_keylist=0;
0142 
0143     bridge->max_memory_agp = agp_find_max();
0144     bridge->version = &agp_current_version;
0145 
0146     if (bridge->driver->needs_scratch_page) {
0147         struct page *page = bridge->driver->agp_alloc_page(bridge);
0148 
0149         if (!page) {
0150             dev_err(&bridge->dev->dev,
0151                 "can't get memory for scratch page\n");
0152             return -ENOMEM;
0153         }
0154 
0155         bridge->scratch_page_page = page;
0156         bridge->scratch_page_dma = page_to_phys(page);
0157 
0158         bridge->scratch_page = bridge->driver->mask_memory(bridge,
0159                            bridge->scratch_page_dma, 0);
0160     }
0161 
0162     size_value = bridge->driver->fetch_size();
0163     if (size_value == 0) {
0164         dev_err(&bridge->dev->dev, "can't determine aperture size\n");
0165         rc = -EINVAL;
0166         goto err_out;
0167     }
0168     if (bridge->driver->create_gatt_table(bridge)) {
0169         dev_err(&bridge->dev->dev,
0170             "can't get memory for graphics translation table\n");
0171         rc = -ENOMEM;
0172         goto err_out;
0173     }
0174     got_gatt = 1;
0175 
0176     bridge->key_list = vzalloc(PAGE_SIZE * 4);
0177     if (bridge->key_list == NULL) {
0178         dev_err(&bridge->dev->dev,
0179             "can't allocate memory for key lists\n");
0180         rc = -ENOMEM;
0181         goto err_out;
0182     }
0183     got_keylist = 1;
0184 
0185     /* FIXME vmalloc'd memory not guaranteed contiguous */
0186 
0187     if (bridge->driver->configure()) {
0188         dev_err(&bridge->dev->dev, "error configuring host chipset\n");
0189         rc = -EINVAL;
0190         goto err_out;
0191     }
0192     INIT_LIST_HEAD(&bridge->mapped_list);
0193     spin_lock_init(&bridge->mapped_lock);
0194 
0195     return 0;
0196 
0197 err_out:
0198     if (bridge->driver->needs_scratch_page) {
0199         struct page *page = bridge->scratch_page_page;
0200 
0201         bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
0202         bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
0203     }
0204     if (got_gatt)
0205         bridge->driver->free_gatt_table(bridge);
0206     if (got_keylist) {
0207         vfree(bridge->key_list);
0208         bridge->key_list = NULL;
0209     }
0210     return rc;
0211 }
0212 
0213 /* cannot be __exit b/c as it could be called from __init code */
0214 static void agp_backend_cleanup(struct agp_bridge_data *bridge)
0215 {
0216     if (bridge->driver->cleanup)
0217         bridge->driver->cleanup();
0218     if (bridge->driver->free_gatt_table)
0219         bridge->driver->free_gatt_table(bridge);
0220 
0221     vfree(bridge->key_list);
0222     bridge->key_list = NULL;
0223 
0224     if (bridge->driver->agp_destroy_page &&
0225         bridge->driver->needs_scratch_page) {
0226         struct page *page = bridge->scratch_page_page;
0227 
0228         bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
0229         bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
0230     }
0231 }
0232 
0233 /* When we remove the global variable agp_bridge from all drivers
0234  * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
0235  */
0236 
0237 struct agp_bridge_data *agp_alloc_bridge(void)
0238 {
0239     struct agp_bridge_data *bridge;
0240 
0241     bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
0242     if (!bridge)
0243         return NULL;
0244 
0245     atomic_set(&bridge->agp_in_use, 0);
0246     atomic_set(&bridge->current_memory_agp, 0);
0247 
0248     if (list_empty(&agp_bridges))
0249         agp_bridge = bridge;
0250 
0251     return bridge;
0252 }
0253 EXPORT_SYMBOL(agp_alloc_bridge);
0254 
0255 
0256 void agp_put_bridge(struct agp_bridge_data *bridge)
0257 {
0258         kfree(bridge);
0259 
0260         if (list_empty(&agp_bridges))
0261                 agp_bridge = NULL;
0262 }
0263 EXPORT_SYMBOL(agp_put_bridge);
0264 
0265 
0266 int agp_add_bridge(struct agp_bridge_data *bridge)
0267 {
0268     int error;
0269 
0270     if (agp_off) {
0271         error = -ENODEV;
0272         goto err_put_bridge;
0273     }
0274 
0275     if (!bridge->dev) {
0276         printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
0277         error = -EINVAL;
0278         goto err_put_bridge;
0279     }
0280 
0281     /* Grab reference on the chipset driver. */
0282     if (!try_module_get(bridge->driver->owner)) {
0283         dev_info(&bridge->dev->dev, "can't lock chipset driver\n");
0284         error = -EINVAL;
0285         goto err_put_bridge;
0286     }
0287 
0288     error = agp_backend_initialize(bridge);
0289     if (error) {
0290         dev_info(&bridge->dev->dev,
0291              "agp_backend_initialize() failed\n");
0292         goto err_out;
0293     }
0294 
0295     if (list_empty(&agp_bridges)) {
0296         error = agp_frontend_initialize();
0297         if (error) {
0298             dev_info(&bridge->dev->dev,
0299                  "agp_frontend_initialize() failed\n");
0300             goto frontend_err;
0301         }
0302 
0303         dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n",
0304              bridge->driver->fetch_size(), bridge->gart_bus_addr);
0305 
0306     }
0307 
0308     list_add(&bridge->list, &agp_bridges);
0309     return 0;
0310 
0311 frontend_err:
0312     agp_backend_cleanup(bridge);
0313 err_out:
0314     module_put(bridge->driver->owner);
0315 err_put_bridge:
0316     agp_put_bridge(bridge);
0317     return error;
0318 }
0319 EXPORT_SYMBOL_GPL(agp_add_bridge);
0320 
0321 
0322 void agp_remove_bridge(struct agp_bridge_data *bridge)
0323 {
0324     agp_backend_cleanup(bridge);
0325     list_del(&bridge->list);
0326     if (list_empty(&agp_bridges))
0327         agp_frontend_cleanup();
0328     module_put(bridge->driver->owner);
0329 }
0330 EXPORT_SYMBOL_GPL(agp_remove_bridge);
0331 
0332 int agp_off;
0333 int agp_try_unsupported_boot;
0334 EXPORT_SYMBOL(agp_off);
0335 EXPORT_SYMBOL(agp_try_unsupported_boot);
0336 
0337 static int __init agp_init(void)
0338 {
0339     if (!agp_off)
0340         printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
0341             AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
0342     return 0;
0343 }
0344 
0345 static void __exit agp_exit(void)
0346 {
0347 }
0348 
0349 #ifndef MODULE
0350 static __init int agp_setup(char *s)
0351 {
0352     if (!strcmp(s,"off"))
0353         agp_off = 1;
0354     if (!strcmp(s,"try_unsupported"))
0355         agp_try_unsupported_boot = 1;
0356     return 1;
0357 }
0358 __setup("agp=", agp_setup);
0359 #endif
0360 
0361 MODULE_AUTHOR("Dave Jones, Jeff Hartmann");
0362 MODULE_DESCRIPTION("AGP GART driver");
0363 MODULE_LICENSE("GPL and additional rights");
0364 MODULE_ALIAS_MISCDEV(AGPGART_MINOR);
0365 
0366 module_init(agp_init);
0367 module_exit(agp_exit);
0368