frontend.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  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/init.h>
  34. #include <linux/miscdevice.h>
  35. #include <linux/agp_backend.h>
  36. #include <linux/agpgart.h>
  37. #include <linux/slab.h>
  38. #include <linux/mm.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, vma->vm_page_prot)) {
  472. goto out_again;
  473. }
  474. mutex_unlock(&(agp_fe.agp_mutex));
  475. return 0;
  476. }
  477. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  478. if (size != current_size)
  479. goto out_inval;
  480. DBG("controller vm_ops=%p", kerninfo.vm_ops);
  481. if (kerninfo.vm_ops) {
  482. vma->vm_ops = kerninfo.vm_ops;
  483. } else if (io_remap_pfn_range(vma, vma->vm_start,
  484. kerninfo.aper_base >> PAGE_SHIFT,
  485. size, vma->vm_page_prot)) {
  486. goto out_again;
  487. }
  488. mutex_unlock(&(agp_fe.agp_mutex));
  489. return 0;
  490. }
  491. out_eperm:
  492. mutex_unlock(&(agp_fe.agp_mutex));
  493. return -EPERM;
  494. out_inval:
  495. mutex_unlock(&(agp_fe.agp_mutex));
  496. return -EINVAL;
  497. out_again:
  498. mutex_unlock(&(agp_fe.agp_mutex));
  499. return -EAGAIN;
  500. }
  501. static int agp_release(struct inode *inode, struct file *file)
  502. {
  503. struct agp_file_private *priv = file->private_data;
  504. mutex_lock(&(agp_fe.agp_mutex));
  505. DBG("priv=%p", priv);
  506. if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
  507. struct agp_controller *controller;
  508. controller = agp_find_controller_by_pid(priv->my_pid);
  509. if (controller != NULL) {
  510. if (controller == agp_fe.current_controller)
  511. agp_controller_release_current(controller, priv);
  512. agp_remove_controller(controller);
  513. controller = NULL;
  514. }
  515. }
  516. if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags))
  517. agp_remove_client(priv->my_pid);
  518. agp_remove_file_private(priv);
  519. kfree(priv);
  520. file->private_data = NULL;
  521. mutex_unlock(&(agp_fe.agp_mutex));
  522. return 0;
  523. }
  524. static int agp_open(struct inode *inode, struct file *file)
  525. {
  526. int minor = iminor(inode);
  527. struct agp_file_private *priv;
  528. struct agp_client *client;
  529. int rc = -ENXIO;
  530. mutex_lock(&(agp_fe.agp_mutex));
  531. if (minor != AGPGART_MINOR)
  532. goto err_out;
  533. priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
  534. if (priv == NULL)
  535. goto err_out_nomem;
  536. set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
  537. priv->my_pid = current->pid;
  538. if ((current->uid == 0) || (current->suid == 0)) {
  539. /* Root priv, can be controller */
  540. set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
  541. }
  542. client = agp_find_client_by_pid(current->pid);
  543. if (client != NULL) {
  544. set_bit(AGP_FF_IS_CLIENT, &priv->access_flags);
  545. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  546. }
  547. file->private_data = (void *) priv;
  548. agp_insert_file_private(priv);
  549. DBG("private=%p, client=%p", priv, client);
  550. mutex_unlock(&(agp_fe.agp_mutex));
  551. return 0;
  552. err_out_nomem:
  553. rc = -ENOMEM;
  554. err_out:
  555. mutex_unlock(&(agp_fe.agp_mutex));
  556. return rc;
  557. }
  558. static ssize_t agp_read(struct file *file, char __user *buf,
  559. size_t count, loff_t * ppos)
  560. {
  561. return -EINVAL;
  562. }
  563. static ssize_t agp_write(struct file *file, const char __user *buf,
  564. size_t count, loff_t * ppos)
  565. {
  566. return -EINVAL;
  567. }
  568. static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
  569. {
  570. struct agp_info userinfo;
  571. struct agp_kern_info kerninfo;
  572. agp_copy_info(agp_bridge, &kerninfo);
  573. userinfo.version.major = kerninfo.version.major;
  574. userinfo.version.minor = kerninfo.version.minor;
  575. userinfo.bridge_id = kerninfo.device->vendor |
  576. (kerninfo.device->device << 16);
  577. userinfo.agp_mode = kerninfo.mode;
  578. userinfo.aper_base = kerninfo.aper_base;
  579. userinfo.aper_size = kerninfo.aper_size;
  580. userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
  581. userinfo.pg_used = kerninfo.current_memory;
  582. if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
  583. return -EFAULT;
  584. return 0;
  585. }
  586. int agpioc_acquire_wrap(struct agp_file_private *priv)
  587. {
  588. struct agp_controller *controller;
  589. DBG("");
  590. if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
  591. return -EPERM;
  592. if (agp_fe.current_controller != NULL)
  593. return -EBUSY;
  594. if (!agp_bridge)
  595. return -ENODEV;
  596. if (atomic_read(&agp_bridge->agp_in_use))
  597. return -EBUSY;
  598. atomic_inc(&agp_bridge->agp_in_use);
  599. agp_fe.backend_acquired = TRUE;
  600. controller = agp_find_controller_by_pid(priv->my_pid);
  601. if (controller != NULL) {
  602. agp_controller_make_current(controller);
  603. } else {
  604. controller = agp_create_controller(priv->my_pid);
  605. if (controller == NULL) {
  606. agp_fe.backend_acquired = FALSE;
  607. agp_backend_release(agp_bridge);
  608. return -ENOMEM;
  609. }
  610. agp_insert_controller(controller);
  611. agp_controller_make_current(controller);
  612. }
  613. set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
  614. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  615. return 0;
  616. }
  617. int agpioc_release_wrap(struct agp_file_private *priv)
  618. {
  619. DBG("");
  620. agp_controller_release_current(agp_fe.current_controller, priv);
  621. return 0;
  622. }
  623. int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
  624. {
  625. struct agp_setup mode;
  626. DBG("");
  627. if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
  628. return -EFAULT;
  629. agp_enable(agp_bridge, mode.agp_mode);
  630. return 0;
  631. }
  632. static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
  633. {
  634. struct agp_region reserve;
  635. struct agp_client *client;
  636. struct agp_file_private *client_priv;
  637. DBG("");
  638. if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
  639. return -EFAULT;
  640. if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
  641. return -EFAULT;
  642. client = agp_find_client_by_pid(reserve.pid);
  643. if (reserve.seg_count == 0) {
  644. /* remove a client */
  645. client_priv = agp_find_private(reserve.pid);
  646. if (client_priv != NULL) {
  647. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  648. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  649. }
  650. if (client == NULL) {
  651. /* client is already removed */
  652. return 0;
  653. }
  654. return agp_remove_client(reserve.pid);
  655. } else {
  656. struct agp_segment *segment;
  657. if (reserve.seg_count >= 16384)
  658. return -EINVAL;
  659. segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
  660. GFP_KERNEL);
  661. if (segment == NULL)
  662. return -ENOMEM;
  663. if (copy_from_user(segment, (void __user *) reserve.seg_list,
  664. sizeof(struct agp_segment) * reserve.seg_count)) {
  665. kfree(segment);
  666. return -EFAULT;
  667. }
  668. reserve.seg_list = segment;
  669. if (client == NULL) {
  670. /* Create the client and add the segment */
  671. client = agp_create_client(reserve.pid);
  672. if (client == NULL) {
  673. kfree(segment);
  674. return -ENOMEM;
  675. }
  676. client_priv = agp_find_private(reserve.pid);
  677. if (client_priv != NULL) {
  678. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  679. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  680. }
  681. }
  682. return agp_create_segment(client, &reserve);
  683. }
  684. /* Will never really happen */
  685. return -EINVAL;
  686. }
  687. int agpioc_protect_wrap(struct agp_file_private *priv)
  688. {
  689. DBG("");
  690. /* This function is not currently implemented */
  691. return -EINVAL;
  692. }
  693. static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
  694. {
  695. struct agp_memory *memory;
  696. struct agp_allocate alloc;
  697. DBG("");
  698. if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
  699. return -EFAULT;
  700. if (alloc.type >= AGP_USER_TYPES)
  701. return -EINVAL;
  702. memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
  703. if (memory == NULL)
  704. return -ENOMEM;
  705. alloc.key = memory->key;
  706. alloc.physical = memory->physical;
  707. if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
  708. agp_free_memory_wrap(memory);
  709. return -EFAULT;
  710. }
  711. return 0;
  712. }
  713. int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
  714. {
  715. struct agp_memory *memory;
  716. DBG("");
  717. memory = agp_find_mem_by_key(arg);
  718. if (memory == NULL)
  719. return -EINVAL;
  720. agp_free_memory_wrap(memory);
  721. return 0;
  722. }
  723. static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
  724. {
  725. struct agp_bind bind_info;
  726. struct agp_memory *memory;
  727. DBG("");
  728. if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
  729. return -EFAULT;
  730. memory = agp_find_mem_by_key(bind_info.key);
  731. if (memory == NULL)
  732. return -EINVAL;
  733. return agp_bind_memory(memory, bind_info.pg_start);
  734. }
  735. static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
  736. {
  737. struct agp_memory *memory;
  738. struct agp_unbind unbind;
  739. DBG("");
  740. if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
  741. return -EFAULT;
  742. memory = agp_find_mem_by_key(unbind.key);
  743. if (memory == NULL)
  744. return -EINVAL;
  745. return agp_unbind_memory(memory);
  746. }
  747. static int agp_ioctl(struct inode *inode, struct file *file,
  748. unsigned int cmd, unsigned long arg)
  749. {
  750. struct agp_file_private *curr_priv = file->private_data;
  751. int ret_val = -ENOTTY;
  752. DBG("priv=%p, cmd=%x", curr_priv, cmd);
  753. mutex_lock(&(agp_fe.agp_mutex));
  754. if ((agp_fe.current_controller == NULL) &&
  755. (cmd != AGPIOC_ACQUIRE)) {
  756. ret_val = -EINVAL;
  757. goto ioctl_out;
  758. }
  759. if ((agp_fe.backend_acquired != TRUE) &&
  760. (cmd != AGPIOC_ACQUIRE)) {
  761. ret_val = -EBUSY;
  762. goto ioctl_out;
  763. }
  764. if (cmd != AGPIOC_ACQUIRE) {
  765. if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
  766. ret_val = -EPERM;
  767. goto ioctl_out;
  768. }
  769. /* Use the original pid of the controller,
  770. * in case it's threaded */
  771. if (agp_fe.current_controller->pid != curr_priv->my_pid) {
  772. ret_val = -EBUSY;
  773. goto ioctl_out;
  774. }
  775. }
  776. switch (cmd) {
  777. case AGPIOC_INFO:
  778. ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
  779. break;
  780. case AGPIOC_ACQUIRE:
  781. ret_val = agpioc_acquire_wrap(curr_priv);
  782. break;
  783. case AGPIOC_RELEASE:
  784. ret_val = agpioc_release_wrap(curr_priv);
  785. break;
  786. case AGPIOC_SETUP:
  787. ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
  788. break;
  789. case AGPIOC_RESERVE:
  790. ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
  791. break;
  792. case AGPIOC_PROTECT:
  793. ret_val = agpioc_protect_wrap(curr_priv);
  794. break;
  795. case AGPIOC_ALLOCATE:
  796. ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
  797. break;
  798. case AGPIOC_DEALLOCATE:
  799. ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
  800. break;
  801. case AGPIOC_BIND:
  802. ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
  803. break;
  804. case AGPIOC_UNBIND:
  805. ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
  806. break;
  807. }
  808. ioctl_out:
  809. DBG("ioctl returns %d\n", ret_val);
  810. mutex_unlock(&(agp_fe.agp_mutex));
  811. return ret_val;
  812. }
  813. static const struct file_operations agp_fops =
  814. {
  815. .owner = THIS_MODULE,
  816. .llseek = no_llseek,
  817. .read = agp_read,
  818. .write = agp_write,
  819. .ioctl = agp_ioctl,
  820. #ifdef CONFIG_COMPAT
  821. .compat_ioctl = compat_agp_ioctl,
  822. #endif
  823. .mmap = agp_mmap,
  824. .open = agp_open,
  825. .release = agp_release,
  826. };
  827. static struct miscdevice agp_miscdev =
  828. {
  829. .minor = AGPGART_MINOR,
  830. .name = "agpgart",
  831. .fops = &agp_fops
  832. };
  833. int agp_frontend_initialize(void)
  834. {
  835. memset(&agp_fe, 0, sizeof(struct agp_front_data));
  836. mutex_init(&(agp_fe.agp_mutex));
  837. if (misc_register(&agp_miscdev)) {
  838. printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
  839. return -EIO;
  840. }
  841. return 0;
  842. }
  843. void agp_frontend_cleanup(void)
  844. {
  845. misc_deregister(&agp_miscdev);
  846. }