frontend.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. /*
  2. * AGPGART driver frontend
  3. * Copyright (C) 2004 Silicon Graphics, Inc.
  4. * Copyright (C) 2002-2003 Dave Jones
  5. * Copyright (C) 1999 Jeff Hartmann
  6. * Copyright (C) 1999 Precision Insight, Inc.
  7. * Copyright (C) 1999 Xi Graphics, Inc.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included
  17. * in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
  23. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  24. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  25. * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. */
  28. #include <linux/types.h>
  29. #include <linux/kernel.h>
  30. #include <linux/module.h>
  31. #include <linux/mman.h>
  32. #include <linux/pci.h>
  33. #include <linux/miscdevice.h>
  34. #include <linux/agp_backend.h>
  35. #include <linux/agpgart.h>
  36. #include <linux/slab.h>
  37. #include <linux/mm.h>
  38. #include <linux/fs.h>
  39. #include <linux/sched.h>
  40. #include <asm/uaccess.h>
  41. #include <asm/pgtable.h>
  42. #include "agp.h"
  43. struct agp_front_data agp_fe;
  44. struct agp_memory *agp_find_mem_by_key(int key)
  45. {
  46. struct agp_memory *curr;
  47. if (agp_fe.current_controller == NULL)
  48. return NULL;
  49. curr = agp_fe.current_controller->pool;
  50. while (curr != NULL) {
  51. if (curr->key == key)
  52. break;
  53. curr = curr->next;
  54. }
  55. DBG("key=%d -> mem=%p", key, curr);
  56. return curr;
  57. }
  58. static void agp_remove_from_pool(struct agp_memory *temp)
  59. {
  60. struct agp_memory *prev;
  61. struct agp_memory *next;
  62. /* Check to see if this is even in the memory pool */
  63. DBG("mem=%p", temp);
  64. if (agp_find_mem_by_key(temp->key) != NULL) {
  65. next = temp->next;
  66. prev = temp->prev;
  67. if (prev != NULL) {
  68. prev->next = next;
  69. if (next != NULL)
  70. next->prev = prev;
  71. } else {
  72. /* This is the first item on the list */
  73. if (next != NULL)
  74. next->prev = NULL;
  75. agp_fe.current_controller->pool = next;
  76. }
  77. }
  78. }
  79. /*
  80. * Routines for managing each client's segment list -
  81. * These routines handle adding and removing segments
  82. * to each auth'ed client.
  83. */
  84. static struct
  85. agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client,
  86. unsigned long offset,
  87. int size, pgprot_t page_prot)
  88. {
  89. struct agp_segment_priv *seg;
  90. int num_segments, i;
  91. off_t pg_start;
  92. size_t pg_count;
  93. pg_start = offset / 4096;
  94. pg_count = size / 4096;
  95. seg = *(client->segments);
  96. num_segments = client->num_segments;
  97. for (i = 0; i < client->num_segments; i++) {
  98. if ((seg[i].pg_start == pg_start) &&
  99. (seg[i].pg_count == pg_count) &&
  100. (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) {
  101. return seg + i;
  102. }
  103. }
  104. return NULL;
  105. }
  106. static void agp_remove_seg_from_client(struct agp_client *client)
  107. {
  108. DBG("client=%p", client);
  109. if (client->segments != NULL) {
  110. if (*(client->segments) != NULL) {
  111. DBG("Freeing %p from client %p", *(client->segments), client);
  112. kfree(*(client->segments));
  113. }
  114. DBG("Freeing %p from client %p", client->segments, client);
  115. kfree(client->segments);
  116. client->segments = NULL;
  117. }
  118. }
  119. static void agp_add_seg_to_client(struct agp_client *client,
  120. struct agp_segment_priv ** seg, int num_segments)
  121. {
  122. struct agp_segment_priv **prev_seg;
  123. prev_seg = client->segments;
  124. if (prev_seg != NULL)
  125. agp_remove_seg_from_client(client);
  126. DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client);
  127. client->num_segments = num_segments;
  128. client->segments = seg;
  129. }
  130. static pgprot_t agp_convert_mmap_flags(int prot)
  131. {
  132. unsigned long prot_bits;
  133. prot_bits = calc_vm_prot_bits(prot) | VM_SHARED;
  134. return vm_get_page_prot(prot_bits);
  135. }
  136. int agp_create_segment(struct agp_client *client, struct agp_region *region)
  137. {
  138. struct agp_segment_priv **ret_seg;
  139. struct agp_segment_priv *seg;
  140. struct agp_segment *user_seg;
  141. size_t i;
  142. seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL);
  143. if (seg == NULL) {
  144. kfree(region->seg_list);
  145. region->seg_list = NULL;
  146. return -ENOMEM;
  147. }
  148. user_seg = region->seg_list;
  149. for (i = 0; i < region->seg_count; i++) {
  150. seg[i].pg_start = user_seg[i].pg_start;
  151. seg[i].pg_count = user_seg[i].pg_count;
  152. seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot);
  153. }
  154. kfree(region->seg_list);
  155. region->seg_list = NULL;
  156. ret_seg = kmalloc(sizeof(void *), GFP_KERNEL);
  157. if (ret_seg == NULL) {
  158. kfree(seg);
  159. return -ENOMEM;
  160. }
  161. *ret_seg = seg;
  162. agp_add_seg_to_client(client, ret_seg, region->seg_count);
  163. return 0;
  164. }
  165. /* End - Routines for managing each client's segment list */
  166. /* This function must only be called when current_controller != NULL */
  167. static void agp_insert_into_pool(struct agp_memory * temp)
  168. {
  169. struct agp_memory *prev;
  170. prev = agp_fe.current_controller->pool;
  171. if (prev != NULL) {
  172. prev->prev = temp;
  173. temp->next = prev;
  174. }
  175. agp_fe.current_controller->pool = temp;
  176. }
  177. /* File private list routines */
  178. struct agp_file_private *agp_find_private(pid_t pid)
  179. {
  180. struct agp_file_private *curr;
  181. curr = agp_fe.file_priv_list;
  182. while (curr != NULL) {
  183. if (curr->my_pid == pid)
  184. return curr;
  185. curr = curr->next;
  186. }
  187. return NULL;
  188. }
  189. static void agp_insert_file_private(struct agp_file_private * priv)
  190. {
  191. struct agp_file_private *prev;
  192. prev = agp_fe.file_priv_list;
  193. if (prev != NULL)
  194. prev->prev = priv;
  195. priv->next = prev;
  196. agp_fe.file_priv_list = priv;
  197. }
  198. static void agp_remove_file_private(struct agp_file_private * priv)
  199. {
  200. struct agp_file_private *next;
  201. struct agp_file_private *prev;
  202. next = priv->next;
  203. prev = priv->prev;
  204. if (prev != NULL) {
  205. prev->next = next;
  206. if (next != NULL)
  207. next->prev = prev;
  208. } else {
  209. if (next != NULL)
  210. next->prev = NULL;
  211. agp_fe.file_priv_list = next;
  212. }
  213. }
  214. /* End - File flag list routines */
  215. /*
  216. * Wrappers for agp_free_memory & agp_allocate_memory
  217. * These make sure that internal lists are kept updated.
  218. */
  219. void agp_free_memory_wrap(struct agp_memory *memory)
  220. {
  221. agp_remove_from_pool(memory);
  222. agp_free_memory(memory);
  223. }
  224. struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
  225. {
  226. struct agp_memory *memory;
  227. memory = agp_allocate_memory(agp_bridge, pg_count, type);
  228. if (memory == NULL)
  229. return NULL;
  230. agp_insert_into_pool(memory);
  231. return memory;
  232. }
  233. /* Routines for managing the list of controllers -
  234. * These routines manage the current controller, and the list of
  235. * controllers
  236. */
  237. static struct agp_controller *agp_find_controller_by_pid(pid_t id)
  238. {
  239. struct agp_controller *controller;
  240. controller = agp_fe.controllers;
  241. while (controller != NULL) {
  242. if (controller->pid == id)
  243. return controller;
  244. controller = controller->next;
  245. }
  246. return NULL;
  247. }
  248. static struct agp_controller *agp_create_controller(pid_t id)
  249. {
  250. struct agp_controller *controller;
  251. controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL);
  252. if (controller == NULL)
  253. return NULL;
  254. controller->pid = id;
  255. return controller;
  256. }
  257. static int agp_insert_controller(struct agp_controller *controller)
  258. {
  259. struct agp_controller *prev_controller;
  260. prev_controller = agp_fe.controllers;
  261. controller->next = prev_controller;
  262. if (prev_controller != NULL)
  263. prev_controller->prev = controller;
  264. agp_fe.controllers = controller;
  265. return 0;
  266. }
  267. static void agp_remove_all_clients(struct agp_controller *controller)
  268. {
  269. struct agp_client *client;
  270. struct agp_client *temp;
  271. client = controller->clients;
  272. while (client) {
  273. struct agp_file_private *priv;
  274. temp = client;
  275. agp_remove_seg_from_client(temp);
  276. priv = agp_find_private(temp->pid);
  277. if (priv != NULL) {
  278. clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
  279. clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  280. }
  281. client = client->next;
  282. kfree(temp);
  283. }
  284. }
  285. static void agp_remove_all_memory(struct agp_controller *controller)
  286. {
  287. struct agp_memory *memory;
  288. struct agp_memory *temp;
  289. memory = controller->pool;
  290. while (memory) {
  291. temp = memory;
  292. memory = memory->next;
  293. agp_free_memory_wrap(temp);
  294. }
  295. }
  296. static int agp_remove_controller(struct agp_controller *controller)
  297. {
  298. struct agp_controller *prev_controller;
  299. struct agp_controller *next_controller;
  300. prev_controller = controller->prev;
  301. next_controller = controller->next;
  302. if (prev_controller != NULL) {
  303. prev_controller->next = next_controller;
  304. if (next_controller != NULL)
  305. next_controller->prev = prev_controller;
  306. } else {
  307. if (next_controller != NULL)
  308. next_controller->prev = NULL;
  309. agp_fe.controllers = next_controller;
  310. }
  311. agp_remove_all_memory(controller);
  312. agp_remove_all_clients(controller);
  313. if (agp_fe.current_controller == controller) {
  314. agp_fe.current_controller = NULL;
  315. agp_fe.backend_acquired = false;
  316. agp_backend_release(agp_bridge);
  317. }
  318. kfree(controller);
  319. return 0;
  320. }
  321. static void agp_controller_make_current(struct agp_controller *controller)
  322. {
  323. struct agp_client *clients;
  324. clients = controller->clients;
  325. while (clients != NULL) {
  326. struct agp_file_private *priv;
  327. priv = agp_find_private(clients->pid);
  328. if (priv != NULL) {
  329. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  330. set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  331. }
  332. clients = clients->next;
  333. }
  334. agp_fe.current_controller = controller;
  335. }
  336. static void agp_controller_release_current(struct agp_controller *controller,
  337. struct agp_file_private *controller_priv)
  338. {
  339. struct agp_client *clients;
  340. clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags);
  341. clients = controller->clients;
  342. while (clients != NULL) {
  343. struct agp_file_private *priv;
  344. priv = agp_find_private(clients->pid);
  345. if (priv != NULL)
  346. clear_bit(AGP_FF_IS_VALID, &priv->access_flags);
  347. clients = clients->next;
  348. }
  349. agp_fe.current_controller = NULL;
  350. agp_fe.used_by_controller = false;
  351. agp_backend_release(agp_bridge);
  352. }
  353. /*
  354. * Routines for managing client lists -
  355. * These routines are for managing the list of auth'ed clients.
  356. */
  357. static struct agp_client
  358. *agp_find_client_in_controller(struct agp_controller *controller, pid_t id)
  359. {
  360. struct agp_client *client;
  361. if (controller == NULL)
  362. return NULL;
  363. client = controller->clients;
  364. while (client != NULL) {
  365. if (client->pid == id)
  366. return client;
  367. client = client->next;
  368. }
  369. return NULL;
  370. }
  371. static struct agp_controller *agp_find_controller_for_client(pid_t id)
  372. {
  373. struct agp_controller *controller;
  374. controller = agp_fe.controllers;
  375. while (controller != NULL) {
  376. if ((agp_find_client_in_controller(controller, id)) != NULL)
  377. return controller;
  378. controller = controller->next;
  379. }
  380. return NULL;
  381. }
  382. struct agp_client *agp_find_client_by_pid(pid_t id)
  383. {
  384. struct agp_client *temp;
  385. if (agp_fe.current_controller == NULL)
  386. return NULL;
  387. temp = agp_find_client_in_controller(agp_fe.current_controller, id);
  388. return temp;
  389. }
  390. static void agp_insert_client(struct agp_client *client)
  391. {
  392. struct agp_client *prev_client;
  393. prev_client = agp_fe.current_controller->clients;
  394. client->next = prev_client;
  395. if (prev_client != NULL)
  396. prev_client->prev = client;
  397. agp_fe.current_controller->clients = client;
  398. agp_fe.current_controller->num_clients++;
  399. }
  400. struct agp_client *agp_create_client(pid_t id)
  401. {
  402. struct agp_client *new_client;
  403. new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL);
  404. if (new_client == NULL)
  405. return NULL;
  406. new_client->pid = id;
  407. agp_insert_client(new_client);
  408. return new_client;
  409. }
  410. int agp_remove_client(pid_t id)
  411. {
  412. struct agp_client *client;
  413. struct agp_client *prev_client;
  414. struct agp_client *next_client;
  415. struct agp_controller *controller;
  416. controller = agp_find_controller_for_client(id);
  417. if (controller == NULL)
  418. return -EINVAL;
  419. client = agp_find_client_in_controller(controller, id);
  420. if (client == NULL)
  421. return -EINVAL;
  422. prev_client = client->prev;
  423. next_client = client->next;
  424. if (prev_client != NULL) {
  425. prev_client->next = next_client;
  426. if (next_client != NULL)
  427. next_client->prev = prev_client;
  428. } else {
  429. if (next_client != NULL)
  430. next_client->prev = NULL;
  431. controller->clients = next_client;
  432. }
  433. controller->num_clients--;
  434. agp_remove_seg_from_client(client);
  435. kfree(client);
  436. return 0;
  437. }
  438. /* End - Routines for managing client lists */
  439. /* File Operations */
  440. static int agp_mmap(struct file *file, struct vm_area_struct *vma)
  441. {
  442. unsigned int size, current_size;
  443. unsigned long offset;
  444. struct agp_client *client;
  445. struct agp_file_private *priv = file->private_data;
  446. struct agp_kern_info kerninfo;
  447. mutex_lock(&(agp_fe.agp_mutex));
  448. if (agp_fe.backend_acquired != true)
  449. goto out_eperm;
  450. if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
  451. goto out_eperm;
  452. agp_copy_info(agp_bridge, &kerninfo);
  453. size = vma->vm_end - vma->vm_start;
  454. current_size = kerninfo.aper_size;
  455. current_size = current_size * 0x100000;
  456. offset = vma->vm_pgoff << PAGE_SHIFT;
  457. DBG("%lx:%lx", offset, offset+size);
  458. if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
  459. if ((size + offset) > current_size)
  460. goto out_inval;
  461. client = agp_find_client_by_pid(current->pid);
  462. if (client == NULL)
  463. goto out_eperm;
  464. if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot))
  465. goto out_inval;
  466. DBG("client vm_ops=%p", kerninfo.vm_ops);
  467. if (kerninfo.vm_ops) {
  468. vma->vm_ops = kerninfo.vm_ops;
  469. } else if (io_remap_pfn_range(vma, vma->vm_start,
  470. (kerninfo.aper_base + offset) >> PAGE_SHIFT,
  471. size,
  472. pgprot_writecombine(vma->vm_page_prot))) {
  473. goto out_again;
  474. }
  475. mutex_unlock(&(agp_fe.agp_mutex));
  476. return 0;
  477. }
  478. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  479. if (size != current_size)
  480. goto out_inval;
  481. DBG("controller vm_ops=%p", kerninfo.vm_ops);
  482. if (kerninfo.vm_ops) {
  483. vma->vm_ops = kerninfo.vm_ops;
  484. } else if (io_remap_pfn_range(vma, vma->vm_start,
  485. kerninfo.aper_base >> PAGE_SHIFT,
  486. size,
  487. pgprot_writecombine(vma->vm_page_prot))) {
  488. goto out_again;
  489. }
  490. mutex_unlock(&(agp_fe.agp_mutex));
  491. return 0;
  492. }
  493. out_eperm:
  494. mutex_unlock(&(agp_fe.agp_mutex));
  495. return -EPERM;
  496. out_inval:
  497. mutex_unlock(&(agp_fe.agp_mutex));
  498. return -EINVAL;
  499. out_again:
  500. mutex_unlock(&(agp_fe.agp_mutex));
  501. return -EAGAIN;
  502. }
  503. static int agp_release(struct inode *inode, struct file *file)
  504. {
  505. struct agp_file_private *priv = file->private_data;
  506. mutex_lock(&(agp_fe.agp_mutex));
  507. DBG("priv=%p", priv);
  508. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  509. struct agp_controller *controller;
  510. controller = agp_find_controller_by_pid(priv->my_pid);
  511. if (controller != NULL) {
  512. if (controller == agp_fe.current_controller)
  513. agp_controller_release_current(controller, priv);
  514. agp_remove_controller(controller);
  515. controller = NULL;
  516. }
  517. }
  518. if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
  519. agp_remove_client(priv->my_pid);
  520. agp_remove_file_private(priv);
  521. kfree(priv);
  522. file->private_data = NULL;
  523. mutex_unlock(&(agp_fe.agp_mutex));
  524. return 0;
  525. }
  526. static int agp_open(struct inode *inode, struct file *file)
  527. {
  528. int minor = iminor(inode);
  529. struct agp_file_private *priv;
  530. struct agp_client *client;
  531. if (minor != AGPGART_MINOR)
  532. return -ENXIO;
  533. mutex_lock(&(agp_fe.agp_mutex));
  534. priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
  535. if (priv == NULL) {
  536. mutex_unlock(&(agp_fe.agp_mutex));
  537. return -ENOMEM;
  538. }
  539. set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
  540. priv->my_pid = current->pid;
  541. if (capable(CAP_SYS_RAWIO))
  542. /* Root priv, can be controller */
  543. set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
  544. client = agp_find_client_by_pid(current->pid);
  545. if (client != NULL) {
  546. set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  547. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  548. }
  549. file->private_data = (void *) priv;
  550. agp_insert_file_private(priv);
  551. DBG("private=%p, client=%p", priv, client);
  552. mutex_unlock(&(agp_fe.agp_mutex));
  553. return 0;
  554. }
  555. static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
  556. {
  557. struct agp_info userinfo;
  558. struct agp_kern_info kerninfo;
  559. agp_copy_info(agp_bridge, &kerninfo);
  560. memset(&userinfo, 0, sizeof(userinfo));
  561. userinfo.version.major = kerninfo.version.major;
  562. userinfo.version.minor = kerninfo.version.minor;
  563. userinfo.bridge_id = kerninfo.device->vendor |
  564. (kerninfo.device->device << 16);
  565. userinfo.agp_mode = kerninfo.mode;
  566. userinfo.aper_base = kerninfo.aper_base;
  567. userinfo.aper_size = kerninfo.aper_size;
  568. userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
  569. userinfo.pg_used = kerninfo.current_memory;
  570. if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
  571. return -EFAULT;
  572. return 0;
  573. }
  574. int agpioc_acquire_wrap(struct agp_file_private *priv)
  575. {
  576. struct agp_controller *controller;
  577. DBG("");
  578. if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
  579. return -EPERM;
  580. if (agp_fe.current_controller != NULL)
  581. return -EBUSY;
  582. if (!agp_bridge)
  583. return -ENODEV;
  584. if (atomic_read(&agp_bridge->agp_in_use))
  585. return -EBUSY;
  586. atomic_inc(&agp_bridge->agp_in_use);
  587. agp_fe.backend_acquired = true;
  588. controller = agp_find_controller_by_pid(priv->my_pid);
  589. if (controller != NULL) {
  590. agp_controller_make_current(controller);
  591. } else {
  592. controller = agp_create_controller(priv->my_pid);
  593. if (controller == NULL) {
  594. agp_fe.backend_acquired = false;
  595. agp_backend_release(agp_bridge);
  596. return -ENOMEM;
  597. }
  598. agp_insert_controller(controller);
  599. agp_controller_make_current(controller);
  600. }
  601. set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
  602. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  603. return 0;
  604. }
  605. int agpioc_release_wrap(struct agp_file_private *priv)
  606. {
  607. DBG("");
  608. agp_controller_release_current(agp_fe.current_controller, priv);
  609. return 0;
  610. }
  611. int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
  612. {
  613. struct agp_setup mode;
  614. DBG("");
  615. if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
  616. return -EFAULT;
  617. agp_enable(agp_bridge, mode.agp_mode);
  618. return 0;
  619. }
  620. static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
  621. {
  622. struct agp_region reserve;
  623. struct agp_client *client;
  624. struct agp_file_private *client_priv;
  625. DBG("");
  626. if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
  627. return -EFAULT;
  628. if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
  629. return -EFAULT;
  630. client = agp_find_client_by_pid(reserve.pid);
  631. if (reserve.seg_count == 0) {
  632. /* remove a client */
  633. client_priv = agp_find_private(reserve.pid);
  634. if (client_priv != NULL) {
  635. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  636. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  637. }
  638. if (client == NULL) {
  639. /* client is already removed */
  640. return 0;
  641. }
  642. return agp_remove_client(reserve.pid);
  643. } else {
  644. struct agp_segment *segment;
  645. if (reserve.seg_count >= 16384)
  646. return -EINVAL;
  647. segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
  648. GFP_KERNEL);
  649. if (segment == NULL)
  650. return -ENOMEM;
  651. if (copy_from_user(segment, (void __user *) reserve.seg_list,
  652. sizeof(struct agp_segment) * reserve.seg_count)) {
  653. kfree(segment);
  654. return -EFAULT;
  655. }
  656. reserve.seg_list = segment;
  657. if (client == NULL) {
  658. /* Create the client and add the segment */
  659. client = agp_create_client(reserve.pid);
  660. if (client == NULL) {
  661. kfree(segment);
  662. return -ENOMEM;
  663. }
  664. client_priv = agp_find_private(reserve.pid);
  665. if (client_priv != NULL) {
  666. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  667. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  668. }
  669. }
  670. return agp_create_segment(client, &reserve);
  671. }
  672. /* Will never really happen */
  673. return -EINVAL;
  674. }
  675. int agpioc_protect_wrap(struct agp_file_private *priv)
  676. {
  677. DBG("");
  678. /* This function is not currently implemented */
  679. return -EINVAL;
  680. }
  681. static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
  682. {
  683. struct agp_memory *memory;
  684. struct agp_allocate alloc;
  685. DBG("");
  686. if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
  687. return -EFAULT;
  688. if (alloc.type >= AGP_USER_TYPES)
  689. return -EINVAL;
  690. memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
  691. if (memory == NULL)
  692. return -ENOMEM;
  693. alloc.key = memory->key;
  694. alloc.physical = memory->physical;
  695. if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
  696. agp_free_memory_wrap(memory);
  697. return -EFAULT;
  698. }
  699. return 0;
  700. }
  701. int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
  702. {
  703. struct agp_memory *memory;
  704. DBG("");
  705. memory = agp_find_mem_by_key(arg);
  706. if (memory == NULL)
  707. return -EINVAL;
  708. agp_free_memory_wrap(memory);
  709. return 0;
  710. }
  711. static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
  712. {
  713. struct agp_bind bind_info;
  714. struct agp_memory *memory;
  715. DBG("");
  716. if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
  717. return -EFAULT;
  718. memory = agp_find_mem_by_key(bind_info.key);
  719. if (memory == NULL)
  720. return -EINVAL;
  721. return agp_bind_memory(memory, bind_info.pg_start);
  722. }
  723. static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
  724. {
  725. struct agp_memory *memory;
  726. struct agp_unbind unbind;
  727. DBG("");
  728. if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
  729. return -EFAULT;
  730. memory = agp_find_mem_by_key(unbind.key);
  731. if (memory == NULL)
  732. return -EINVAL;
  733. return agp_unbind_memory(memory);
  734. }
  735. static long agp_ioctl(struct file *file,
  736. unsigned int cmd, unsigned long arg)
  737. {
  738. struct agp_file_private *curr_priv = file->private_data;
  739. int ret_val = -ENOTTY;
  740. DBG("priv=%p, cmd=%x", curr_priv, cmd);
  741. mutex_lock(&(agp_fe.agp_mutex));
  742. if ((agp_fe.current_controller == NULL) &&
  743. (cmd != AGPIOC_ACQUIRE)) {
  744. ret_val = -EINVAL;
  745. goto ioctl_out;
  746. }
  747. if ((agp_fe.backend_acquired != true) &&
  748. (cmd != AGPIOC_ACQUIRE)) {
  749. ret_val = -EBUSY;
  750. goto ioctl_out;
  751. }
  752. if (cmd != AGPIOC_ACQUIRE) {
  753. if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
  754. ret_val = -EPERM;
  755. goto ioctl_out;
  756. }
  757. /* Use the original pid of the controller,
  758. * in case it's threaded */
  759. if (agp_fe.current_controller->pid != curr_priv->my_pid) {
  760. ret_val = -EBUSY;
  761. goto ioctl_out;
  762. }
  763. }
  764. switch (cmd) {
  765. case AGPIOC_INFO:
  766. ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
  767. break;
  768. case AGPIOC_ACQUIRE:
  769. ret_val = agpioc_acquire_wrap(curr_priv);
  770. break;
  771. case AGPIOC_RELEASE:
  772. ret_val = agpioc_release_wrap(curr_priv);
  773. break;
  774. case AGPIOC_SETUP:
  775. ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
  776. break;
  777. case AGPIOC_RESERVE:
  778. ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
  779. break;
  780. case AGPIOC_PROTECT:
  781. ret_val = agpioc_protect_wrap(curr_priv);
  782. break;
  783. case AGPIOC_ALLOCATE:
  784. ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
  785. break;
  786. case AGPIOC_DEALLOCATE:
  787. ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
  788. break;
  789. case AGPIOC_BIND:
  790. ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
  791. break;
  792. case AGPIOC_UNBIND:
  793. ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
  794. break;
  795. case AGPIOC_CHIPSET_FLUSH:
  796. break;
  797. }
  798. ioctl_out:
  799. DBG("ioctl returns %d\n", ret_val);
  800. mutex_unlock(&(agp_fe.agp_mutex));
  801. return ret_val;
  802. }
  803. static const struct file_operations agp_fops =
  804. {
  805. .owner = THIS_MODULE,
  806. .llseek = no_llseek,
  807. .unlocked_ioctl = agp_ioctl,
  808. #ifdef CONFIG_COMPAT
  809. .compat_ioctl = compat_agp_ioctl,
  810. #endif
  811. .mmap = agp_mmap,
  812. .open = agp_open,
  813. .release = agp_release,
  814. };
  815. static struct miscdevice agp_miscdev =
  816. {
  817. .minor = AGPGART_MINOR,
  818. .name = "agpgart",
  819. .fops = &agp_fops
  820. };
  821. int agp_frontend_initialize(void)
  822. {
  823. memset(&agp_fe, 0, sizeof(struct agp_front_data));
  824. mutex_init(&(agp_fe.agp_mutex));
  825. if (misc_register(&agp_miscdev)) {
  826. printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
  827. return -EIO;
  828. }
  829. return 0;
  830. }
  831. void agp_frontend_cleanup(void)
  832. {
  833. misc_deregister(&agp_miscdev);
  834. }