agpsupport.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* agpsupport.c -- DRM support for AGP/GART backend -*- linux-c -*-
  2.  * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  * 
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25.  * DEALINGS IN THE SOFTWARE.
  26.  * 
  27.  * Author: Rickard E. (Rik) Faith <faith@valinux.com>
  28.  *
  29.  */
  30. #define __NO_VERSION__
  31. #include "drmP.h"
  32. #include <linux/module.h>
  33. #if LINUX_VERSION_CODE < 0x020400
  34. #include "agpsupport-pre24.h"
  35. #else
  36. #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
  37. #define DRM_AGP_PUT inter_module_put("drm_agp")
  38. #endif
  39. static const drm_agp_t *drm_agp = NULL;
  40. int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd,
  41.  unsigned long arg)
  42. {
  43. drm_file_t  *priv  = filp->private_data;
  44. drm_device_t  *dev  = priv->dev;
  45. agp_kern_info    *kern;
  46. drm_agp_info_t   info;
  47. if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL;
  48. kern                   = &dev->agp->agp_info;
  49. info.agp_version_major = kern->version.major;
  50. info.agp_version_minor = kern->version.minor;
  51. info.mode              = kern->mode;
  52. info.aperture_base     = kern->aper_base;
  53. info.aperture_size     = kern->aper_size * 1024 * 1024;
  54. info.memory_allowed    = kern->max_memory << PAGE_SHIFT;
  55. info.memory_used       = kern->current_memory << PAGE_SHIFT;
  56. info.id_vendor         = kern->device->vendor;
  57. info.id_device         = kern->device->device;
  58. if (copy_to_user((drm_agp_info_t *)arg, &info, sizeof(info)))
  59. return -EFAULT;
  60. return 0;
  61. }
  62. int drm_agp_acquire(struct inode *inode, struct file *filp, unsigned int cmd,
  63.     unsigned long arg)
  64. {
  65. drm_file_t  *priv  = filp->private_data;
  66. drm_device_t  *dev  = priv->dev;
  67. int              retcode;
  68. if (dev->agp->acquired || !drm_agp->acquire) return -EINVAL;
  69. if ((retcode = drm_agp->acquire())) return retcode;
  70. dev->agp->acquired = 1;
  71. return 0;
  72. }
  73. int drm_agp_release(struct inode *inode, struct file *filp, unsigned int cmd,
  74.     unsigned long arg)
  75. {
  76. drm_file_t  *priv  = filp->private_data;
  77. drm_device_t  *dev  = priv->dev;
  78. if (!dev->agp->acquired || !drm_agp->release) return -EINVAL;
  79. drm_agp->release();
  80. dev->agp->acquired = 0;
  81. return 0;
  82. }
  83. void _drm_agp_release(void)
  84. {
  85. if (drm_agp->release) drm_agp->release();
  86. }
  87. int drm_agp_enable(struct inode *inode, struct file *filp, unsigned int cmd,
  88.    unsigned long arg)
  89. {
  90. drm_file_t  *priv  = filp->private_data;
  91. drm_device_t  *dev  = priv->dev;
  92. drm_agp_mode_t   mode;
  93. if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL;
  94. if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode)))
  95. return -EFAULT;
  96. dev->agp->mode    = mode.mode;
  97. drm_agp->enable(mode.mode);
  98. dev->agp->base    = dev->agp->agp_info.aper_base;
  99. dev->agp->enabled = 1;
  100. return 0;
  101. }
  102. int drm_agp_alloc(struct inode *inode, struct file *filp, unsigned int cmd,
  103.   unsigned long arg)
  104. {
  105. drm_file_t  *priv  = filp->private_data;
  106. drm_device_t  *dev  = priv->dev;
  107. drm_agp_buffer_t request;
  108. drm_agp_mem_t    *entry;
  109. agp_memory       *memory;
  110. unsigned long    pages;
  111. u32   type;
  112. if (!dev->agp->acquired) return -EINVAL;
  113. if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
  114. return -EFAULT;
  115. if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
  116. return -ENOMEM;
  117.    
  118.     memset(entry, 0, sizeof(*entry));
  119. pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
  120. type = (u32) request.type;
  121. if (!(memory = drm_alloc_agp(pages, type))) {
  122. drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
  123. return -ENOMEM;
  124. }
  125. entry->handle    = (unsigned long)memory->memory;
  126. entry->memory    = memory;
  127. entry->bound     = 0;
  128. entry->pages     = pages;
  129. entry->prev      = NULL;
  130. entry->next      = dev->agp->memory;
  131. if (dev->agp->memory) dev->agp->memory->prev = entry;
  132. dev->agp->memory = entry;
  133. request.handle   = entry->handle;
  134.         request.physical = memory->physical;
  135. if (copy_to_user((drm_agp_buffer_t *)arg, &request, sizeof(request))) {
  136. dev->agp->memory       = entry->next;
  137. dev->agp->memory->prev = NULL;
  138. drm_free_agp(memory, pages);
  139. drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
  140. return -EFAULT;
  141. }
  142. return 0;
  143. }
  144. static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t *dev,
  145.    unsigned long handle)
  146. {
  147. drm_agp_mem_t *entry;
  148. for (entry = dev->agp->memory; entry; entry = entry->next) {
  149. if (entry->handle == handle) return entry;
  150. }
  151. return NULL;
  152. }
  153. int drm_agp_unbind(struct inode *inode, struct file *filp, unsigned int cmd,
  154.    unsigned long arg)
  155. {
  156. drm_file_t   *priv  = filp->private_data;
  157. drm_device_t   *dev  = priv->dev;
  158. drm_agp_binding_t request;
  159. drm_agp_mem_t     *entry;
  160. if (!dev->agp->acquired) return -EINVAL;
  161. if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
  162. return -EFAULT;
  163. if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
  164. return -EINVAL;
  165. if (!entry->bound) return -EINVAL;
  166. return drm_unbind_agp(entry->memory);
  167. }
  168. int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd,
  169.  unsigned long arg)
  170. {
  171. drm_file_t   *priv  = filp->private_data;
  172. drm_device_t   *dev  = priv->dev;
  173. drm_agp_binding_t request;
  174. drm_agp_mem_t     *entry;
  175. int               retcode;
  176. int               page;
  177. if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL;
  178. if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request)))
  179. return -EFAULT;
  180. if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
  181. return -EINVAL;
  182. if (entry->bound) return -EINVAL;
  183. page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
  184. if ((retcode = drm_bind_agp(entry->memory, page))) return retcode;
  185. entry->bound = dev->agp->base + (page << PAGE_SHIFT);
  186. DRM_DEBUG("base = 0x%lx entry->bound = 0x%lxn", 
  187.   dev->agp->base, entry->bound);
  188. return 0;
  189. }
  190. int drm_agp_free(struct inode *inode, struct file *filp, unsigned int cmd,
  191.  unsigned long arg)
  192. {
  193. drm_file_t  *priv  = filp->private_data;
  194. drm_device_t  *dev  = priv->dev;
  195. drm_agp_buffer_t request;
  196. drm_agp_mem_t    *entry;
  197. if (!dev->agp->acquired) return -EINVAL;
  198. if (copy_from_user(&request, (drm_agp_buffer_t *)arg, sizeof(request)))
  199. return -EFAULT;
  200. if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
  201. return -EINVAL;
  202. if (entry->bound) drm_unbind_agp(entry->memory);
  203.    
  204. if (entry->prev) entry->prev->next = entry->next;
  205. else             dev->agp->memory  = entry->next;
  206. if (entry->next) entry->next->prev = entry->prev;
  207. drm_free_agp(entry->memory, entry->pages);
  208. drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
  209. return 0;
  210. }
  211. drm_agp_head_t *drm_agp_init(void)
  212. {
  213. drm_agp_head_t *head         = NULL;
  214. drm_agp = DRM_AGP_GET;
  215. if (drm_agp) {
  216. if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
  217. return NULL;
  218. memset((void *)head, 0, sizeof(*head));
  219. drm_agp->copy_info(&head->agp_info);
  220. if (head->agp_info.chipset == NOT_SUPPORTED) {
  221. drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
  222. return NULL;
  223. }
  224. head->memory = NULL;
  225. switch (head->agp_info.chipset) {
  226. case INTEL_GENERIC: head->chipset = "Intel";         break;
  227. case INTEL_LX: head->chipset = "Intel 440LX";   break;
  228. case INTEL_BX: head->chipset = "Intel 440BX";   break;
  229. case INTEL_GX: head->chipset = "Intel 440GX";   break;
  230. case INTEL_I810: head->chipset = "Intel i810";    break;
  231. #if LINUX_VERSION_CODE >= 0x020400
  232. case INTEL_I840: head->chipset = "Intel i840";    break;
  233. #endif
  234. case VIA_GENERIC: head->chipset = "VIA";           break;
  235. case VIA_VP3: head->chipset = "VIA VP3";       break;
  236. case VIA_MVP3: head->chipset = "VIA MVP3";      break;
  237. #if LINUX_VERSION_CODE >= 0x020400
  238. case VIA_MVP4: head->chipset = "VIA MVP4";      break;
  239. case VIA_APOLLO_KX133: head->chipset = "VIA Apollo KX133"; 
  240. break;
  241. case VIA_APOLLO_KT133: head->chipset = "VIA Apollo KT133"; 
  242. break;
  243. #endif
  244. case VIA_APOLLO_PRO:  head->chipset = "VIA Apollo Pro";
  245. break;
  246. case SIS_GENERIC: head->chipset = "SiS";           break;
  247. case AMD_GENERIC: head->chipset = "AMD";           break;
  248. case AMD_IRONGATE: head->chipset = "AMD Irongate";  break;
  249. case ALI_GENERIC: head->chipset = "ALi";           break;
  250. case ALI_M1541:  head->chipset = "ALi M1541";     break;
  251. case ALI_M1621:  head->chipset = "ALi M1621";  break;
  252. case ALI_M1631:  head->chipset = "ALi M1631";  break;
  253. case ALI_M1632:  head->chipset = "ALi M1632";  break;
  254. case ALI_M1641:  head->chipset = "ALi M1641";  break;
  255. case ALI_M1647:  head->chipset = "ALi M1647";  break;
  256. case ALI_M1651:  head->chipset = "ALi M1651";  break;
  257. case SVWRKS_GENERIC: head->chipset = "Serverworks Generic";
  258. break;
  259. case SVWRKS_HE:  head->chipset = "Serverworks HE"; break;
  260. case SVWRKS_LE:  head->chipset = "Serverworks LE"; break;
  261. default: head->chipset = "Unknown";       break;
  262. }
  263. DRM_INFO("AGP %d.%d on %s @ 0x%08lx %ZuMBn",
  264.  head->agp_info.version.major,
  265.  head->agp_info.version.minor,
  266.  head->chipset,
  267.  head->agp_info.aper_base,
  268.  head->agp_info.aper_size);
  269. }
  270. return head;
  271. }
  272. void drm_agp_uninit(void)
  273. {
  274. DRM_AGP_PUT;
  275. drm_agp = NULL;
  276. }
  277. agp_memory *drm_agp_allocate_memory(size_t pages, u32 type)
  278. {
  279. if (!drm_agp->allocate_memory) return NULL;
  280. return drm_agp->allocate_memory(pages, type);
  281. }
  282. int drm_agp_free_memory(agp_memory *handle)
  283. {
  284. if (!handle || !drm_agp->free_memory) return 0;
  285. drm_agp->free_memory(handle);
  286. return 1;
  287. }
  288. int drm_agp_bind_memory(agp_memory *handle, off_t start)
  289. {
  290. if (!handle || !drm_agp->bind_memory) return -EINVAL;
  291. return drm_agp->bind_memory(handle, start);
  292. }
  293. int drm_agp_unbind_memory(agp_memory *handle)
  294. {
  295. if (!handle || !drm_agp->unbind_memory) return -EINVAL;
  296. return drm_agp->unbind_memory(handle);
  297. }