frontend.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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 ssize_t agp_read(struct file *file, char __user *buf,
  556. size_t count, loff_t * ppos)
  557. {
  558. return -EINVAL;
  559. }
  560. static ssize_t agp_write(struct file *file, const char __user *buf,
  561. size_t count, loff_t * ppos)
  562. {
  563. return -EINVAL;
  564. }
  565. static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
  566. {
  567. struct agp_info userinfo;
  568. struct agp_kern_info kerninfo;
  569. agp_copy_info(agp_bridge, &kerninfo);
  570. memset(&userinfo, 0, sizeof(userinfo));
  571. userinfo.version.major = kerninfo.version.major;
  572. userinfo.version.minor = kerninfo.version.minor;
  573. userinfo.bridge_id = kerninfo.device->vendor |
  574. (kerninfo.device->device << 16);
  575. userinfo.agp_mode = kerninfo.mode;
  576. userinfo.aper_base = kerninfo.aper_base;
  577. userinfo.aper_size = kerninfo.aper_size;
  578. userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
  579. userinfo.pg_used = kerninfo.current_memory;
  580. if (copy_to_user(arg, &userinfo, sizeof(struct agp_info)))
  581. return -EFAULT;
  582. return 0;
  583. }
  584. int agpioc_acquire_wrap(struct agp_file_private *priv)
  585. {
  586. struct agp_controller *controller;
  587. DBG("");
  588. if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags)))
  589. return -EPERM;
  590. if (agp_fe.current_controller != NULL)
  591. return -EBUSY;
  592. if (!agp_bridge)
  593. return -ENODEV;
  594. if (atomic_read(&agp_bridge->agp_in_use))
  595. return -EBUSY;
  596. atomic_inc(&agp_bridge->agp_in_use);
  597. agp_fe.backend_acquired = true;
  598. controller = agp_find_controller_by_pid(priv->my_pid);
  599. if (controller != NULL) {
  600. agp_controller_make_current(controller);
  601. } else {
  602. controller = agp_create_controller(priv->my_pid);
  603. if (controller == NULL) {
  604. agp_fe.backend_acquired = false;
  605. agp_backend_release(agp_bridge);
  606. return -ENOMEM;
  607. }
  608. agp_insert_controller(controller);
  609. agp_controller_make_current(controller);
  610. }
  611. set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags);
  612. set_bit(AGP_FF_IS_VALID, &priv->access_flags);
  613. return 0;
  614. }
  615. int agpioc_release_wrap(struct agp_file_private *priv)
  616. {
  617. DBG("");
  618. agp_controller_release_current(agp_fe.current_controller, priv);
  619. return 0;
  620. }
  621. int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
  622. {
  623. struct agp_setup mode;
  624. DBG("");
  625. if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
  626. return -EFAULT;
  627. agp_enable(agp_bridge, mode.agp_mode);
  628. return 0;
  629. }
  630. static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
  631. {
  632. struct agp_region reserve;
  633. struct agp_client *client;
  634. struct agp_file_private *client_priv;
  635. DBG("");
  636. if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
  637. return -EFAULT;
  638. if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
  639. return -EFAULT;
  640. client = agp_find_client_by_pid(reserve.pid);
  641. if (reserve.seg_count == 0) {
  642. /* remove a client */
  643. client_priv = agp_find_private(reserve.pid);
  644. if (client_priv != NULL) {
  645. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  646. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  647. }
  648. if (client == NULL) {
  649. /* client is already removed */
  650. return 0;
  651. }
  652. return agp_remove_client(reserve.pid);
  653. } else {
  654. struct agp_segment *segment;
  655. if (reserve.seg_count >= 16384)
  656. return -EINVAL;
  657. segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count),
  658. GFP_KERNEL);
  659. if (segment == NULL)
  660. return -ENOMEM;
  661. if (copy_from_user(segment, (void __user *) reserve.seg_list,
  662. sizeof(struct agp_segment) * reserve.seg_count)) {
  663. kfree(segment);
  664. return -EFAULT;
  665. }
  666. reserve.seg_list = segment;
  667. if (client == NULL) {
  668. /* Create the client and add the segment */
  669. client = agp_create_client(reserve.pid);
  670. if (client == NULL) {
  671. kfree(segment);
  672. return -ENOMEM;
  673. }
  674. client_priv = agp_find_private(reserve.pid);
  675. if (client_priv != NULL) {
  676. set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
  677. set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
  678. }
  679. }
  680. return agp_create_segment(client, &reserve);
  681. }
  682. /* Will never really happen */
  683. return -EINVAL;
  684. }
  685. int agpioc_protect_wrap(struct agp_file_private *priv)
  686. {
  687. DBG("");
  688. /* This function is not currently implemented */
  689. return -EINVAL;
  690. }
  691. static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
  692. {
  693. struct agp_memory *memory;
  694. struct agp_allocate alloc;
  695. DBG("");
  696. if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
  697. return -EFAULT;
  698. if (alloc.type >= AGP_USER_TYPES)
  699. return -EINVAL;
  700. memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
  701. if (memory == NULL)
  702. return -ENOMEM;
  703. alloc.key = memory->key;
  704. alloc.physical = memory->physical;
  705. if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) {
  706. agp_free_memory_wrap(memory);
  707. return -EFAULT;
  708. }
  709. return 0;
  710. }
  711. int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
  712. {
  713. struct agp_memory *memory;
  714. DBG("");
  715. memory = agp_find_mem_by_key(arg);
  716. if (memory == NULL)
  717. return -EINVAL;
  718. agp_free_memory_wrap(memory);
  719. return 0;
  720. }
  721. static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
  722. {
  723. struct agp_bind bind_info;
  724. struct agp_memory *memory;
  725. DBG("");
  726. if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind)))
  727. return -EFAULT;
  728. memory = agp_find_mem_by_key(bind_info.key);
  729. if (memory == NULL)
  730. return -EINVAL;
  731. return agp_bind_memory(memory, bind_info.pg_start);
  732. }
  733. static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
  734. {
  735. struct agp_memory *memory;
  736. struct agp_unbind unbind;
  737. DBG("");
  738. if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind)))
  739. return -EFAULT;
  740. memory = agp_find_mem_by_key(unbind.key);
  741. if (memory == NULL)
  742. return -EINVAL;
  743. return agp_unbind_memory(memory);
  744. }
  745. static long agp_ioctl(struct file *file,
  746. unsigned int cmd, unsigned long arg)
  747. {
  748. struct agp_file_private *curr_priv = file->private_data;
  749. int ret_val = -ENOTTY;
  750. DBG("priv=%p, cmd=%x", curr_priv, cmd);
  751. mutex_lock(&(agp_fe.agp_mutex));
  752. if ((agp_fe.current_controller == NULL) &&
  753. (cmd != AGPIOC_ACQUIRE)) {
  754. ret_val = -EINVAL;
  755. goto ioctl_out;
  756. }
  757. if ((agp_fe.backend_acquired != true) &&
  758. (cmd != AGPIOC_ACQUIRE)) {
  759. ret_val = -EBUSY;
  760. goto ioctl_out;
  761. }
  762. if (cmd != AGPIOC_ACQUIRE) {
  763. if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
  764. ret_val = -EPERM;
  765. goto ioctl_out;
  766. }
  767. /* Use the original pid of the controller,
  768. * in case it's threaded */
  769. if (agp_fe.current_controller->pid != curr_priv->my_pid) {
  770. ret_val = -EBUSY;
  771. goto ioctl_out;
  772. }
  773. }
  774. switch (cmd) {
  775. case AGPIOC_INFO:
  776. ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg);
  777. break;
  778. case AGPIOC_ACQUIRE:
  779. ret_val = agpioc_acquire_wrap(curr_priv);
  780. break;
  781. case AGPIOC_RELEASE:
  782. ret_val = agpioc_release_wrap(curr_priv);
  783. break;
  784. case AGPIOC_SETUP:
  785. ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
  786. break;
  787. case AGPIOC_RESERVE:
  788. ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
  789. break;
  790. case AGPIOC_PROTECT:
  791. ret_val = agpioc_protect_wrap(curr_priv);
  792. break;
  793. case AGPIOC_ALLOCATE:
  794. ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
  795. break;
  796. case AGPIOC_DEALLOCATE:
  797. ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
  798. break;
  799. case AGPIOC_BIND:
  800. ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
  801. break;
  802. case AGPIOC_UNBIND:
  803. ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
  804. break;
  805. case AGPIOC_CHIPSET_FLUSH:
  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. .unlocked_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. }