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
0031
0032
0033
0034 #include <linux/module.h>
0035 #include <linux/pci.h>
0036 #include <linux/slab.h>
0037
0038 #if IS_ENABLED(CONFIG_AGP)
0039 #include <asm/agp.h>
0040 #endif
0041
0042 #include <drm/drm_device.h>
0043 #include <drm/drm_drv.h>
0044 #include <drm/drm_file.h>
0045 #include <drm/drm_print.h>
0046
0047 #include "drm_legacy.h"
0048
0049 #if IS_ENABLED(CONFIG_AGP)
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 int drm_legacy_agp_info(struct drm_device *dev, struct drm_agp_info *info)
0060 {
0061 struct agp_kern_info *kern;
0062
0063 if (!dev->agp || !dev->agp->acquired)
0064 return -EINVAL;
0065
0066 kern = &dev->agp->agp_info;
0067 info->agp_version_major = kern->version.major;
0068 info->agp_version_minor = kern->version.minor;
0069 info->mode = kern->mode;
0070 info->aperture_base = kern->aper_base;
0071 info->aperture_size = kern->aper_size * 1024 * 1024;
0072 info->memory_allowed = kern->max_memory << PAGE_SHIFT;
0073 info->memory_used = kern->current_memory << PAGE_SHIFT;
0074 info->id_vendor = kern->device->vendor;
0075 info->id_device = kern->device->device;
0076
0077 return 0;
0078 }
0079 EXPORT_SYMBOL(drm_legacy_agp_info);
0080
0081 int drm_legacy_agp_info_ioctl(struct drm_device *dev, void *data,
0082 struct drm_file *file_priv)
0083 {
0084 struct drm_agp_info *info = data;
0085 int err;
0086
0087 err = drm_legacy_agp_info(dev, info);
0088 if (err)
0089 return err;
0090
0091 return 0;
0092 }
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 int drm_legacy_agp_acquire(struct drm_device *dev)
0104 {
0105 struct pci_dev *pdev = to_pci_dev(dev->dev);
0106
0107 if (!dev->agp)
0108 return -ENODEV;
0109 if (dev->agp->acquired)
0110 return -EBUSY;
0111 dev->agp->bridge = agp_backend_acquire(pdev);
0112 if (!dev->agp->bridge)
0113 return -ENODEV;
0114 dev->agp->acquired = 1;
0115 return 0;
0116 }
0117 EXPORT_SYMBOL(drm_legacy_agp_acquire);
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 int drm_legacy_agp_acquire_ioctl(struct drm_device *dev, void *data,
0128 struct drm_file *file_priv)
0129 {
0130 return drm_legacy_agp_acquire((struct drm_device *)file_priv->minor->dev);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141 int drm_legacy_agp_release(struct drm_device *dev)
0142 {
0143 if (!dev->agp || !dev->agp->acquired)
0144 return -EINVAL;
0145 agp_backend_release(dev->agp->bridge);
0146 dev->agp->acquired = 0;
0147 return 0;
0148 }
0149 EXPORT_SYMBOL(drm_legacy_agp_release);
0150
0151 int drm_legacy_agp_release_ioctl(struct drm_device *dev, void *data,
0152 struct drm_file *file_priv)
0153 {
0154 return drm_legacy_agp_release(dev);
0155 }
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 int drm_legacy_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
0168 {
0169 if (!dev->agp || !dev->agp->acquired)
0170 return -EINVAL;
0171
0172 dev->agp->mode = mode.mode;
0173 agp_enable(dev->agp->bridge, mode.mode);
0174 dev->agp->enabled = 1;
0175 return 0;
0176 }
0177 EXPORT_SYMBOL(drm_legacy_agp_enable);
0178
0179 int drm_legacy_agp_enable_ioctl(struct drm_device *dev, void *data,
0180 struct drm_file *file_priv)
0181 {
0182 struct drm_agp_mode *mode = data;
0183
0184 return drm_legacy_agp_enable(dev, *mode);
0185 }
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 int drm_legacy_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
0196 {
0197 struct drm_agp_mem *entry;
0198 struct agp_memory *memory;
0199 unsigned long pages;
0200 u32 type;
0201
0202 if (!dev->agp || !dev->agp->acquired)
0203 return -EINVAL;
0204 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
0205 if (!entry)
0206 return -ENOMEM;
0207
0208 pages = DIV_ROUND_UP(request->size, PAGE_SIZE);
0209 type = (u32) request->type;
0210 memory = agp_allocate_memory(dev->agp->bridge, pages, type);
0211 if (!memory) {
0212 kfree(entry);
0213 return -ENOMEM;
0214 }
0215
0216 entry->handle = (unsigned long)memory->key + 1;
0217 entry->memory = memory;
0218 entry->bound = 0;
0219 entry->pages = pages;
0220 list_add(&entry->head, &dev->agp->memory);
0221
0222 request->handle = entry->handle;
0223 request->physical = memory->physical;
0224
0225 return 0;
0226 }
0227 EXPORT_SYMBOL(drm_legacy_agp_alloc);
0228
0229
0230 int drm_legacy_agp_alloc_ioctl(struct drm_device *dev, void *data,
0231 struct drm_file *file_priv)
0232 {
0233 struct drm_agp_buffer *request = data;
0234
0235 return drm_legacy_agp_alloc(dev, request);
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 static struct drm_agp_mem *drm_legacy_agp_lookup_entry(struct drm_device *dev,
0248 unsigned long handle)
0249 {
0250 struct drm_agp_mem *entry;
0251
0252 list_for_each_entry(entry, &dev->agp->memory, head) {
0253 if (entry->handle == handle)
0254 return entry;
0255 }
0256 return NULL;
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267 int drm_legacy_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
0268 {
0269 struct drm_agp_mem *entry;
0270 int ret;
0271
0272 if (!dev->agp || !dev->agp->acquired)
0273 return -EINVAL;
0274 entry = drm_legacy_agp_lookup_entry(dev, request->handle);
0275 if (!entry || !entry->bound)
0276 return -EINVAL;
0277 ret = agp_unbind_memory(entry->memory);
0278 if (ret == 0)
0279 entry->bound = 0;
0280 return ret;
0281 }
0282 EXPORT_SYMBOL(drm_legacy_agp_unbind);
0283
0284
0285 int drm_legacy_agp_unbind_ioctl(struct drm_device *dev, void *data,
0286 struct drm_file *file_priv)
0287 {
0288 struct drm_agp_binding *request = data;
0289
0290 return drm_legacy_agp_unbind(dev, request);
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302 int drm_legacy_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
0303 {
0304 struct drm_agp_mem *entry;
0305 int retcode;
0306 int page;
0307
0308 if (!dev->agp || !dev->agp->acquired)
0309 return -EINVAL;
0310 entry = drm_legacy_agp_lookup_entry(dev, request->handle);
0311 if (!entry || entry->bound)
0312 return -EINVAL;
0313 page = DIV_ROUND_UP(request->offset, PAGE_SIZE);
0314 retcode = agp_bind_memory(entry->memory, page);
0315 if (retcode)
0316 return retcode;
0317 entry->bound = dev->agp->base + (page << PAGE_SHIFT);
0318 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
0319 dev->agp->base, entry->bound);
0320 return 0;
0321 }
0322 EXPORT_SYMBOL(drm_legacy_agp_bind);
0323
0324
0325 int drm_legacy_agp_bind_ioctl(struct drm_device *dev, void *data,
0326 struct drm_file *file_priv)
0327 {
0328 struct drm_agp_binding *request = data;
0329
0330 return drm_legacy_agp_bind(dev, request);
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 int drm_legacy_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
0344 {
0345 struct drm_agp_mem *entry;
0346
0347 if (!dev->agp || !dev->agp->acquired)
0348 return -EINVAL;
0349 entry = drm_legacy_agp_lookup_entry(dev, request->handle);
0350 if (!entry)
0351 return -EINVAL;
0352 if (entry->bound)
0353 agp_unbind_memory(entry->memory);
0354
0355 list_del(&entry->head);
0356
0357 agp_free_memory(entry->memory);
0358 kfree(entry);
0359 return 0;
0360 }
0361 EXPORT_SYMBOL(drm_legacy_agp_free);
0362
0363
0364 int drm_legacy_agp_free_ioctl(struct drm_device *dev, void *data,
0365 struct drm_file *file_priv)
0366 {
0367 struct drm_agp_buffer *request = data;
0368
0369 return drm_legacy_agp_free(dev, request);
0370 }
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 struct drm_agp_head *drm_legacy_agp_init(struct drm_device *dev)
0385 {
0386 struct pci_dev *pdev = to_pci_dev(dev->dev);
0387 struct drm_agp_head *head = NULL;
0388
0389 head = kzalloc(sizeof(*head), GFP_KERNEL);
0390 if (!head)
0391 return NULL;
0392 head->bridge = agp_find_bridge(pdev);
0393 if (!head->bridge) {
0394 head->bridge = agp_backend_acquire(pdev);
0395 if (!head->bridge) {
0396 kfree(head);
0397 return NULL;
0398 }
0399 agp_copy_info(head->bridge, &head->agp_info);
0400 agp_backend_release(head->bridge);
0401 } else {
0402 agp_copy_info(head->bridge, &head->agp_info);
0403 }
0404 if (head->agp_info.chipset == NOT_SUPPORTED) {
0405 kfree(head);
0406 return NULL;
0407 }
0408 INIT_LIST_HEAD(&head->memory);
0409 head->cant_use_aperture = head->agp_info.cant_use_aperture;
0410 head->page_mask = head->agp_info.page_mask;
0411 head->base = head->agp_info.aper_base;
0412 return head;
0413 }
0414
0415 EXPORT_SYMBOL(drm_legacy_agp_init);
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 void drm_legacy_agp_clear(struct drm_device *dev)
0428 {
0429 struct drm_agp_mem *entry, *tempe;
0430
0431 if (!dev->agp)
0432 return;
0433 if (!drm_core_check_feature(dev, DRIVER_LEGACY))
0434 return;
0435
0436 list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
0437 if (entry->bound)
0438 agp_unbind_memory(entry->memory);
0439 agp_free_memory(entry->memory);
0440 kfree(entry);
0441 }
0442 INIT_LIST_HEAD(&dev->agp->memory);
0443
0444 if (dev->agp->acquired)
0445 drm_legacy_agp_release(dev);
0446
0447 dev->agp->acquired = 0;
0448 dev->agp->enabled = 0;
0449 }
0450
0451 #endif