0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
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
0044
0045
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
0065
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
0087
0088
0089
0090
0091
0092
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
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
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
0234
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
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