drm_agpsupport.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * \file drm_agpsupport.c
  3. * DRM support for AGP/GART backend
  4. *
  5. * \author Rickard E. (Rik) Faith <faith@valinux.com>
  6. * \author Gareth Hughes <gareth@valinux.com>
  7. */
  8. /*
  9. * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  10. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  11. * All Rights Reserved.
  12. *
  13. * Permission is hereby granted, free of charge, to any person obtaining a
  14. * copy of this software and associated documentation files (the "Software"),
  15. * to deal in the Software without restriction, including without limitation
  16. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  17. * and/or sell copies of the Software, and to permit persons to whom the
  18. * Software is furnished to do so, subject to the following conditions:
  19. *
  20. * The above copyright notice and this permission notice (including the next
  21. * paragraph) shall be included in all copies or substantial portions of the
  22. * Software.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  27. * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  28. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  29. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  30. * OTHER DEALINGS IN THE SOFTWARE.
  31. */
  32. #include <linux/module.h>
  33. #include <linux/pci.h>
  34. #include <linux/slab.h>
  35. #include <asm/agp.h>
  36. #include <drm/drm_agpsupport.h>
  37. #include <drm/drm_device.h>
  38. #include <drm/drm_drv.h>
  39. #include <drm/drm_file.h>
  40. #include <drm/drm_print.h>
  41. #include "drm_legacy.h"
  42. /**
  43. * Get AGP information.
  44. *
  45. * \param inode device inode.
  46. * \param file_priv DRM file private.
  47. * \param cmd command.
  48. * \param arg pointer to a (output) drm_agp_info structure.
  49. * \return zero on success or a negative number on failure.
  50. *
  51. * Verifies the AGP device has been initialized and acquired and fills in the
  52. * drm_agp_info structure with the information in drm_agp_head::agp_info.
  53. */
  54. int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
  55. {
  56. struct agp_kern_info *kern;
  57. if (!dev->agp || !dev->agp->acquired)
  58. return -EINVAL;
  59. kern = &dev->agp->agp_info;
  60. info->agp_version_major = kern->version.major;
  61. info->agp_version_minor = kern->version.minor;
  62. info->mode = kern->mode;
  63. info->aperture_base = kern->aper_base;
  64. info->aperture_size = kern->aper_size * 1024 * 1024;
  65. info->memory_allowed = kern->max_memory << PAGE_SHIFT;
  66. info->memory_used = kern->current_memory << PAGE_SHIFT;
  67. info->id_vendor = kern->device->vendor;
  68. info->id_device = kern->device->device;
  69. return 0;
  70. }
  71. EXPORT_SYMBOL(drm_agp_info);
  72. int drm_agp_info_ioctl(struct drm_device *dev, void *data,
  73. struct drm_file *file_priv)
  74. {
  75. struct drm_agp_info *info = data;
  76. int err;
  77. err = drm_agp_info(dev, info);
  78. if (err)
  79. return err;
  80. return 0;
  81. }
  82. /**
  83. * Acquire the AGP device.
  84. *
  85. * \param dev DRM device that is to acquire AGP.
  86. * \return zero on success or a negative number on failure.
  87. *
  88. * Verifies the AGP device hasn't been acquired before and calls
  89. * \c agp_backend_acquire.
  90. */
  91. int drm_agp_acquire(struct drm_device *dev)
  92. {
  93. if (!dev->agp)
  94. return -ENODEV;
  95. if (dev->agp->acquired)
  96. return -EBUSY;
  97. dev->agp->bridge = agp_backend_acquire(dev->pdev);
  98. if (!dev->agp->bridge)
  99. return -ENODEV;
  100. dev->agp->acquired = 1;
  101. return 0;
  102. }
  103. EXPORT_SYMBOL(drm_agp_acquire);
  104. /**
  105. * Acquire the AGP device (ioctl).
  106. *
  107. * \param inode device inode.
  108. * \param file_priv DRM file private.
  109. * \param cmd command.
  110. * \param arg user argument.
  111. * \return zero on success or a negative number on failure.
  112. *
  113. * Verifies the AGP device hasn't been acquired before and calls
  114. * \c agp_backend_acquire.
  115. */
  116. int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
  117. struct drm_file *file_priv)
  118. {
  119. return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
  120. }
  121. /**
  122. * Release the AGP device.
  123. *
  124. * \param dev DRM device that is to release AGP.
  125. * \return zero on success or a negative number on failure.
  126. *
  127. * Verifies the AGP device has been acquired and calls \c agp_backend_release.
  128. */
  129. int drm_agp_release(struct drm_device *dev)
  130. {
  131. if (!dev->agp || !dev->agp->acquired)
  132. return -EINVAL;
  133. agp_backend_release(dev->agp->bridge);
  134. dev->agp->acquired = 0;
  135. return 0;
  136. }
  137. EXPORT_SYMBOL(drm_agp_release);
  138. int drm_agp_release_ioctl(struct drm_device *dev, void *data,
  139. struct drm_file *file_priv)
  140. {
  141. return drm_agp_release(dev);
  142. }
  143. /**
  144. * Enable the AGP bus.
  145. *
  146. * \param dev DRM device that has previously acquired AGP.
  147. * \param mode Requested AGP mode.
  148. * \return zero on success or a negative number on failure.
  149. *
  150. * Verifies the AGP device has been acquired but not enabled, and calls
  151. * \c agp_enable.
  152. */
  153. int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
  154. {
  155. if (!dev->agp || !dev->agp->acquired)
  156. return -EINVAL;
  157. dev->agp->mode = mode.mode;
  158. agp_enable(dev->agp->bridge, mode.mode);
  159. dev->agp->enabled = 1;
  160. return 0;
  161. }
  162. EXPORT_SYMBOL(drm_agp_enable);
  163. int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
  164. struct drm_file *file_priv)
  165. {
  166. struct drm_agp_mode *mode = data;
  167. return drm_agp_enable(dev, *mode);
  168. }
  169. /**
  170. * Allocate AGP memory.
  171. *
  172. * \param inode device inode.
  173. * \param file_priv file private pointer.
  174. * \param cmd command.
  175. * \param arg pointer to a drm_agp_buffer structure.
  176. * \return zero on success or a negative number on failure.
  177. *
  178. * Verifies the AGP device is present and has been acquired, allocates the
  179. * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it.
  180. */
  181. int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
  182. {
  183. struct drm_agp_mem *entry;
  184. struct agp_memory *memory;
  185. unsigned long pages;
  186. u32 type;
  187. if (!dev->agp || !dev->agp->acquired)
  188. return -EINVAL;
  189. entry = kzalloc(sizeof(*entry), GFP_KERNEL);
  190. if (!entry)
  191. return -ENOMEM;
  192. pages = DIV_ROUND_UP(request->size, PAGE_SIZE);
  193. type = (u32) request->type;
  194. memory = agp_allocate_memory(dev->agp->bridge, pages, type);
  195. if (!memory) {
  196. kfree(entry);
  197. return -ENOMEM;
  198. }
  199. entry->handle = (unsigned long)memory->key + 1;
  200. entry->memory = memory;
  201. entry->bound = 0;
  202. entry->pages = pages;
  203. list_add(&entry->head, &dev->agp->memory);
  204. request->handle = entry->handle;
  205. request->physical = memory->physical;
  206. return 0;
  207. }
  208. EXPORT_SYMBOL(drm_agp_alloc);
  209. int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
  210. struct drm_file *file_priv)
  211. {
  212. struct drm_agp_buffer *request = data;
  213. return drm_agp_alloc(dev, request);
  214. }
  215. /**
  216. * Search for the AGP memory entry associated with a handle.
  217. *
  218. * \param dev DRM device structure.
  219. * \param handle AGP memory handle.
  220. * \return pointer to the drm_agp_mem structure associated with \p handle.
  221. *
  222. * Walks through drm_agp_head::memory until finding a matching handle.
  223. */
  224. static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device *dev,
  225. unsigned long handle)
  226. {
  227. struct drm_agp_mem *entry;
  228. list_for_each_entry(entry, &dev->agp->memory, head) {
  229. if (entry->handle == handle)
  230. return entry;
  231. }
  232. return NULL;
  233. }
  234. /**
  235. * Unbind AGP memory from the GATT (ioctl).
  236. *
  237. * \param inode device inode.
  238. * \param file_priv DRM file private.
  239. * \param cmd command.
  240. * \param arg pointer to a drm_agp_binding structure.
  241. * \return zero on success or a negative number on failure.
  242. *
  243. * Verifies the AGP device is present and acquired, looks-up the AGP memory
  244. * entry and passes it to the unbind_agp() function.
  245. */
  246. int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
  247. {
  248. struct drm_agp_mem *entry;
  249. int ret;
  250. if (!dev->agp || !dev->agp->acquired)
  251. return -EINVAL;
  252. entry = drm_agp_lookup_entry(dev, request->handle);
  253. if (!entry || !entry->bound)
  254. return -EINVAL;
  255. ret = drm_unbind_agp(entry->memory);
  256. if (ret == 0)
  257. entry->bound = 0;
  258. return ret;
  259. }
  260. EXPORT_SYMBOL(drm_agp_unbind);
  261. int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
  262. struct drm_file *file_priv)
  263. {
  264. struct drm_agp_binding *request = data;
  265. return drm_agp_unbind(dev, request);
  266. }
  267. /**
  268. * Bind AGP memory into the GATT (ioctl)
  269. *
  270. * \param inode device inode.
  271. * \param file_priv DRM file private.
  272. * \param cmd command.
  273. * \param arg pointer to a drm_agp_binding structure.
  274. * \return zero on success or a negative number on failure.
  275. *
  276. * Verifies the AGP device is present and has been acquired and that no memory
  277. * is currently bound into the GATT. Looks-up the AGP memory entry and passes
  278. * it to bind_agp() function.
  279. */
  280. int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
  281. {
  282. struct drm_agp_mem *entry;
  283. int retcode;
  284. int page;
  285. if (!dev->agp || !dev->agp->acquired)
  286. return -EINVAL;
  287. entry = drm_agp_lookup_entry(dev, request->handle);
  288. if (!entry || entry->bound)
  289. return -EINVAL;
  290. page = DIV_ROUND_UP(request->offset, PAGE_SIZE);
  291. retcode = drm_bind_agp(entry->memory, page);
  292. if (retcode)
  293. return retcode;
  294. entry->bound = dev->agp->base + (page << PAGE_SHIFT);
  295. DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
  296. dev->agp->base, entry->bound);
  297. return 0;
  298. }
  299. EXPORT_SYMBOL(drm_agp_bind);
  300. int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
  301. struct drm_file *file_priv)
  302. {
  303. struct drm_agp_binding *request = data;
  304. return drm_agp_bind(dev, request);
  305. }
  306. /**
  307. * Free AGP memory (ioctl).
  308. *
  309. * \param inode device inode.
  310. * \param file_priv DRM file private.
  311. * \param cmd command.
  312. * \param arg pointer to a drm_agp_buffer structure.
  313. * \return zero on success or a negative number on failure.
  314. *
  315. * Verifies the AGP device is present and has been acquired and looks up the
  316. * AGP memory entry. If the memory is currently bound, unbind it via
  317. * unbind_agp(). Frees it via free_agp() as well as the entry itself
  318. * and unlinks from the doubly linked list it's inserted in.
  319. */
  320. int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
  321. {
  322. struct drm_agp_mem *entry;
  323. if (!dev->agp || !dev->agp->acquired)
  324. return -EINVAL;
  325. entry = drm_agp_lookup_entry(dev, request->handle);
  326. if (!entry)
  327. return -EINVAL;
  328. if (entry->bound)
  329. drm_unbind_agp(entry->memory);
  330. list_del(&entry->head);
  331. drm_free_agp(entry->memory, entry->pages);
  332. kfree(entry);
  333. return 0;
  334. }
  335. EXPORT_SYMBOL(drm_agp_free);
  336. int drm_agp_free_ioctl(struct drm_device *dev, void *data,
  337. struct drm_file *file_priv)
  338. {
  339. struct drm_agp_buffer *request = data;
  340. return drm_agp_free(dev, request);
  341. }
  342. /**
  343. * Initialize the AGP resources.
  344. *
  345. * \return pointer to a drm_agp_head structure.
  346. *
  347. * Gets the drm_agp_t structure which is made available by the agpgart module
  348. * via the inter_module_* functions. Creates and initializes a drm_agp_head
  349. * structure.
  350. *
  351. * Note that final cleanup of the kmalloced structure is directly done in
  352. * drm_pci_agp_destroy.
  353. */
  354. struct drm_agp_head *drm_agp_init(struct drm_device *dev)
  355. {
  356. struct drm_agp_head *head = NULL;
  357. head = kzalloc(sizeof(*head), GFP_KERNEL);
  358. if (!head)
  359. return NULL;
  360. head->bridge = agp_find_bridge(dev->pdev);
  361. if (!head->bridge) {
  362. head->bridge = agp_backend_acquire(dev->pdev);
  363. if (!head->bridge) {
  364. kfree(head);
  365. return NULL;
  366. }
  367. agp_copy_info(head->bridge, &head->agp_info);
  368. agp_backend_release(head->bridge);
  369. } else {
  370. agp_copy_info(head->bridge, &head->agp_info);
  371. }
  372. if (head->agp_info.chipset == NOT_SUPPORTED) {
  373. kfree(head);
  374. return NULL;
  375. }
  376. INIT_LIST_HEAD(&head->memory);
  377. head->cant_use_aperture = head->agp_info.cant_use_aperture;
  378. head->page_mask = head->agp_info.page_mask;
  379. head->base = head->agp_info.aper_base;
  380. return head;
  381. }
  382. /* Only exported for i810.ko */
  383. EXPORT_SYMBOL(drm_agp_init);
  384. /**
  385. * drm_legacy_agp_clear - Clear AGP resource list
  386. * @dev: DRM device
  387. *
  388. * Iterate over all AGP resources and remove them. But keep the AGP head
  389. * intact so it can still be used. It is safe to call this if AGP is disabled or
  390. * was already removed.
  391. *
  392. * Cleanup is only done for drivers who have DRIVER_LEGACY set.
  393. */
  394. void drm_legacy_agp_clear(struct drm_device *dev)
  395. {
  396. struct drm_agp_mem *entry, *tempe;
  397. if (!dev->agp)
  398. return;
  399. if (!drm_core_check_feature(dev, DRIVER_LEGACY))
  400. return;
  401. list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
  402. if (entry->bound)
  403. drm_unbind_agp(entry->memory);
  404. drm_free_agp(entry->memory, entry->pages);
  405. kfree(entry);
  406. }
  407. INIT_LIST_HEAD(&dev->agp->memory);
  408. if (dev->agp->acquired)
  409. drm_agp_release(dev);
  410. dev->agp->acquired = 0;
  411. dev->agp->enabled = 0;
  412. }