PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c

https://github.com/gby/linux
C | 858 lines | 487 code | 122 blank | 249 comment | 52 complexity | 4e1ce1cc44d078316508cf3d428b49b0 MD5 | raw file
  1. /**
  2. * Copyright (c) 2010-2012 Broadcom. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions, and the following disclaimer,
  9. * without modification.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The names of the above-listed copyright holders may not be used
  14. * to endorse or promote products derived from this software without
  15. * specific prior written permission.
  16. *
  17. * ALTERNATIVELY, this software may be distributed under the terms of the
  18. * GNU General Public License ("GPL") version 2, as published by the Free
  19. * Software Foundation.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  22. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  23. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  24. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  25. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. #include <linux/module.h>
  34. #include <linux/types.h>
  35. #include "interface/vchi/vchi.h"
  36. #include "vchiq.h"
  37. #include "vchiq_core.h"
  38. #include "vchiq_util.h"
  39. #define vchiq_status_to_vchi(status) ((int32_t)status)
  40. typedef struct {
  41. VCHIQ_SERVICE_HANDLE_T handle;
  42. VCHIU_QUEUE_T queue;
  43. VCHI_CALLBACK_T callback;
  44. void *callback_param;
  45. } SHIM_SERVICE_T;
  46. /* ----------------------------------------------------------------------
  47. * return pointer to the mphi message driver function table
  48. * -------------------------------------------------------------------- */
  49. const VCHI_MESSAGE_DRIVER_T *
  50. vchi_mphi_message_driver_func_table(void)
  51. {
  52. return NULL;
  53. }
  54. /* ----------------------------------------------------------------------
  55. * return a pointer to the 'single' connection driver fops
  56. * -------------------------------------------------------------------- */
  57. const VCHI_CONNECTION_API_T *
  58. single_get_func_table(void)
  59. {
  60. return NULL;
  61. }
  62. VCHI_CONNECTION_T *vchi_create_connection(
  63. const VCHI_CONNECTION_API_T *function_table,
  64. const VCHI_MESSAGE_DRIVER_T *low_level)
  65. {
  66. (void)function_table;
  67. (void)low_level;
  68. return NULL;
  69. }
  70. /***********************************************************
  71. * Name: vchi_msg_peek
  72. *
  73. * Arguments: const VCHI_SERVICE_HANDLE_T handle,
  74. * void **data,
  75. * uint32_t *msg_size,
  76. * VCHI_FLAGS_T flags
  77. *
  78. * Description: Routine to return a pointer to the current message (to allow in
  79. * place processing). The message can be removed using
  80. * vchi_msg_remove when you're finished
  81. *
  82. * Returns: int32_t - success == 0
  83. *
  84. ***********************************************************/
  85. int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
  86. void **data,
  87. uint32_t *msg_size,
  88. VCHI_FLAGS_T flags)
  89. {
  90. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  91. VCHIQ_HEADER_T *header;
  92. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  93. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  94. if (flags == VCHI_FLAGS_NONE)
  95. if (vchiu_queue_is_empty(&service->queue))
  96. return -1;
  97. header = vchiu_queue_peek(&service->queue);
  98. *data = header->data;
  99. *msg_size = header->size;
  100. return 0;
  101. }
  102. EXPORT_SYMBOL(vchi_msg_peek);
  103. /***********************************************************
  104. * Name: vchi_msg_remove
  105. *
  106. * Arguments: const VCHI_SERVICE_HANDLE_T handle,
  107. *
  108. * Description: Routine to remove a message (after it has been read with
  109. * vchi_msg_peek)
  110. *
  111. * Returns: int32_t - success == 0
  112. *
  113. ***********************************************************/
  114. int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
  115. {
  116. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  117. VCHIQ_HEADER_T *header;
  118. header = vchiu_queue_pop(&service->queue);
  119. vchiq_release_message(service->handle, header);
  120. return 0;
  121. }
  122. EXPORT_SYMBOL(vchi_msg_remove);
  123. /***********************************************************
  124. * Name: vchi_msg_queue
  125. *
  126. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  127. * ssize_t (*copy_callback)(void *context, void *dest,
  128. * size_t offset, size_t maxsize),
  129. * void *context,
  130. * uint32_t data_size
  131. *
  132. * Description: Thin wrapper to queue a message onto a connection
  133. *
  134. * Returns: int32_t - success == 0
  135. *
  136. ***********************************************************/
  137. static
  138. int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
  139. ssize_t (*copy_callback)(void *context, void *dest,
  140. size_t offset, size_t maxsize),
  141. void *context,
  142. uint32_t data_size)
  143. {
  144. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  145. VCHIQ_STATUS_T status;
  146. while (1) {
  147. status = vchiq_queue_message(service->handle,
  148. copy_callback,
  149. context,
  150. data_size);
  151. /*
  152. * vchiq_queue_message() may return VCHIQ_RETRY, so we need to
  153. * implement a retry mechanism since this function is supposed
  154. * to block until queued
  155. */
  156. if (status != VCHIQ_RETRY)
  157. break;
  158. msleep(1);
  159. }
  160. return vchiq_status_to_vchi(status);
  161. }
  162. static ssize_t
  163. vchi_queue_kernel_message_callback(void *context,
  164. void *dest,
  165. size_t offset,
  166. size_t maxsize)
  167. {
  168. memcpy(dest, context + offset, maxsize);
  169. return maxsize;
  170. }
  171. int
  172. vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
  173. void *data,
  174. unsigned int size)
  175. {
  176. return vchi_msg_queue(handle,
  177. vchi_queue_kernel_message_callback,
  178. data,
  179. size);
  180. }
  181. EXPORT_SYMBOL(vchi_queue_kernel_message);
  182. struct vchi_queue_user_message_context {
  183. void __user *data;
  184. };
  185. static ssize_t
  186. vchi_queue_user_message_callback(void *context,
  187. void *dest,
  188. size_t offset,
  189. size_t maxsize)
  190. {
  191. struct vchi_queue_user_message_context *copycontext = context;
  192. if (copy_from_user(dest, copycontext->data + offset, maxsize))
  193. return -EFAULT;
  194. return maxsize;
  195. }
  196. int
  197. vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
  198. void __user *data,
  199. unsigned int size)
  200. {
  201. struct vchi_queue_user_message_context copycontext = {
  202. .data = data
  203. };
  204. return vchi_msg_queue(handle,
  205. vchi_queue_user_message_callback,
  206. &copycontext,
  207. size);
  208. }
  209. EXPORT_SYMBOL(vchi_queue_user_message);
  210. /***********************************************************
  211. * Name: vchi_bulk_queue_receive
  212. *
  213. * Arguments: VCHI_BULK_HANDLE_T handle,
  214. * void *data_dst,
  215. * const uint32_t data_size,
  216. * VCHI_FLAGS_T flags
  217. * void *bulk_handle
  218. *
  219. * Description: Routine to setup a rcv buffer
  220. *
  221. * Returns: int32_t - success == 0
  222. *
  223. ***********************************************************/
  224. int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,
  225. void *data_dst,
  226. uint32_t data_size,
  227. VCHI_FLAGS_T flags,
  228. void *bulk_handle)
  229. {
  230. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  231. VCHIQ_BULK_MODE_T mode;
  232. VCHIQ_STATUS_T status;
  233. switch ((int)flags) {
  234. case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
  235. | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  236. WARN_ON(!service->callback);
  237. mode = VCHIQ_BULK_MODE_CALLBACK;
  238. break;
  239. case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
  240. mode = VCHIQ_BULK_MODE_BLOCKING;
  241. break;
  242. case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  243. case VCHI_FLAGS_NONE:
  244. mode = VCHIQ_BULK_MODE_NOCALLBACK;
  245. break;
  246. default:
  247. WARN(1, "unsupported message\n");
  248. return vchiq_status_to_vchi(VCHIQ_ERROR);
  249. }
  250. while (1) {
  251. status = vchiq_bulk_receive(service->handle, data_dst,
  252. data_size, bulk_handle, mode);
  253. /*
  254. * vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
  255. * implement a retry mechanism since this function is supposed
  256. * to block until queued
  257. */
  258. if (status != VCHIQ_RETRY)
  259. break;
  260. msleep(1);
  261. }
  262. return vchiq_status_to_vchi(status);
  263. }
  264. EXPORT_SYMBOL(vchi_bulk_queue_receive);
  265. /***********************************************************
  266. * Name: vchi_bulk_queue_transmit
  267. *
  268. * Arguments: VCHI_BULK_HANDLE_T handle,
  269. * const void *data_src,
  270. * uint32_t data_size,
  271. * VCHI_FLAGS_T flags,
  272. * void *bulk_handle
  273. *
  274. * Description: Routine to transmit some data
  275. *
  276. * Returns: int32_t - success == 0
  277. *
  278. ***********************************************************/
  279. int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,
  280. const void *data_src,
  281. uint32_t data_size,
  282. VCHI_FLAGS_T flags,
  283. void *bulk_handle)
  284. {
  285. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  286. VCHIQ_BULK_MODE_T mode;
  287. VCHIQ_STATUS_T status;
  288. switch ((int)flags) {
  289. case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
  290. | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  291. WARN_ON(!service->callback);
  292. mode = VCHIQ_BULK_MODE_CALLBACK;
  293. break;
  294. case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
  295. case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
  296. mode = VCHIQ_BULK_MODE_BLOCKING;
  297. break;
  298. case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  299. case VCHI_FLAGS_NONE:
  300. mode = VCHIQ_BULK_MODE_NOCALLBACK;
  301. break;
  302. default:
  303. WARN(1, "unsupported message\n");
  304. return vchiq_status_to_vchi(VCHIQ_ERROR);
  305. }
  306. while (1) {
  307. status = vchiq_bulk_transmit(service->handle, data_src,
  308. data_size, bulk_handle, mode);
  309. /*
  310. * vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
  311. * implement a retry mechanism since this function is supposed
  312. * to block until queued
  313. */
  314. if (status != VCHIQ_RETRY)
  315. break;
  316. msleep(1);
  317. }
  318. return vchiq_status_to_vchi(status);
  319. }
  320. EXPORT_SYMBOL(vchi_bulk_queue_transmit);
  321. /***********************************************************
  322. * Name: vchi_msg_dequeue
  323. *
  324. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  325. * void *data,
  326. * uint32_t max_data_size_to_read,
  327. * uint32_t *actual_msg_size
  328. * VCHI_FLAGS_T flags
  329. *
  330. * Description: Routine to dequeue a message into the supplied buffer
  331. *
  332. * Returns: int32_t - success == 0
  333. *
  334. ***********************************************************/
  335. int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
  336. void *data,
  337. uint32_t max_data_size_to_read,
  338. uint32_t *actual_msg_size,
  339. VCHI_FLAGS_T flags)
  340. {
  341. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  342. VCHIQ_HEADER_T *header;
  343. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  344. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  345. if (flags == VCHI_FLAGS_NONE)
  346. if (vchiu_queue_is_empty(&service->queue))
  347. return -1;
  348. header = vchiu_queue_pop(&service->queue);
  349. memcpy(data, header->data, header->size < max_data_size_to_read ?
  350. header->size : max_data_size_to_read);
  351. *actual_msg_size = header->size;
  352. vchiq_release_message(service->handle, header);
  353. return 0;
  354. }
  355. EXPORT_SYMBOL(vchi_msg_dequeue);
  356. /***********************************************************
  357. * Name: vchi_held_msg_release
  358. *
  359. * Arguments: VCHI_HELD_MSG_T *message
  360. *
  361. * Description: Routine to release a held message (after it has been read with
  362. * vchi_msg_hold)
  363. *
  364. * Returns: int32_t - success == 0
  365. *
  366. ***********************************************************/
  367. int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)
  368. {
  369. /*
  370. * Convert the service field pointer back to an
  371. * VCHIQ_SERVICE_HANDLE_T which is an int.
  372. * This pointer is opaque to everything except
  373. * vchi_msg_hold which simply upcasted the int
  374. * to a pointer.
  375. */
  376. vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service,
  377. (VCHIQ_HEADER_T *)message->message);
  378. return 0;
  379. }
  380. EXPORT_SYMBOL(vchi_held_msg_release);
  381. /***********************************************************
  382. * Name: vchi_msg_hold
  383. *
  384. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  385. * void **data,
  386. * uint32_t *msg_size,
  387. * VCHI_FLAGS_T flags,
  388. * VCHI_HELD_MSG_T *message_handle
  389. *
  390. * Description: Routine to return a pointer to the current message (to allow
  391. * in place processing). The message is dequeued - don't forget
  392. * to release the message using vchi_held_msg_release when you're
  393. * finished.
  394. *
  395. * Returns: int32_t - success == 0
  396. *
  397. ***********************************************************/
  398. int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
  399. void **data,
  400. uint32_t *msg_size,
  401. VCHI_FLAGS_T flags,
  402. VCHI_HELD_MSG_T *message_handle)
  403. {
  404. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  405. VCHIQ_HEADER_T *header;
  406. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  407. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  408. if (flags == VCHI_FLAGS_NONE)
  409. if (vchiu_queue_is_empty(&service->queue))
  410. return -1;
  411. header = vchiu_queue_pop(&service->queue);
  412. *data = header->data;
  413. *msg_size = header->size;
  414. /*
  415. * upcast the VCHIQ_SERVICE_HANDLE_T which is an int
  416. * to a pointer and stuff it in the held message.
  417. * This pointer is opaque to everything except
  418. * vchi_held_msg_release which simply downcasts it back
  419. * to an int.
  420. */
  421. message_handle->service =
  422. (struct opaque_vchi_service_t *)(long)service->handle;
  423. message_handle->message = header;
  424. return 0;
  425. }
  426. EXPORT_SYMBOL(vchi_msg_hold);
  427. /***********************************************************
  428. * Name: vchi_initialise
  429. *
  430. * Arguments: VCHI_INSTANCE_T *instance_handle
  431. *
  432. * Description: Initialises the hardware but does not transmit anything
  433. * When run as a Host App this will be called twice hence the need
  434. * to malloc the state information
  435. *
  436. * Returns: 0 if successful, failure otherwise
  437. *
  438. ***********************************************************/
  439. int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
  440. {
  441. VCHIQ_INSTANCE_T instance;
  442. VCHIQ_STATUS_T status;
  443. status = vchiq_initialise(&instance);
  444. *instance_handle = (VCHI_INSTANCE_T)instance;
  445. return vchiq_status_to_vchi(status);
  446. }
  447. EXPORT_SYMBOL(vchi_initialise);
  448. /***********************************************************
  449. * Name: vchi_connect
  450. *
  451. * Arguments: VCHI_CONNECTION_T **connections
  452. * const uint32_t num_connections
  453. * VCHI_INSTANCE_T instance_handle)
  454. *
  455. * Description: Starts the command service on each connection,
  456. * causing INIT messages to be pinged back and forth
  457. *
  458. * Returns: 0 if successful, failure otherwise
  459. *
  460. ***********************************************************/
  461. int32_t vchi_connect(VCHI_CONNECTION_T **connections,
  462. const uint32_t num_connections,
  463. VCHI_INSTANCE_T instance_handle)
  464. {
  465. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  466. (void)connections;
  467. (void)num_connections;
  468. return vchiq_connect(instance);
  469. }
  470. EXPORT_SYMBOL(vchi_connect);
  471. /***********************************************************
  472. * Name: vchi_disconnect
  473. *
  474. * Arguments: VCHI_INSTANCE_T instance_handle
  475. *
  476. * Description: Stops the command service on each connection,
  477. * causing DE-INIT messages to be pinged back and forth
  478. *
  479. * Returns: 0 if successful, failure otherwise
  480. *
  481. ***********************************************************/
  482. int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
  483. {
  484. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  485. return vchiq_status_to_vchi(vchiq_shutdown(instance));
  486. }
  487. EXPORT_SYMBOL(vchi_disconnect);
  488. /***********************************************************
  489. * Name: vchi_service_open
  490. * Name: vchi_service_create
  491. *
  492. * Arguments: VCHI_INSTANCE_T *instance_handle
  493. * SERVICE_CREATION_T *setup,
  494. * VCHI_SERVICE_HANDLE_T *handle
  495. *
  496. * Description: Routine to open a service
  497. *
  498. * Returns: int32_t - success == 0
  499. *
  500. ***********************************************************/
  501. static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
  502. VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)
  503. {
  504. SHIM_SERVICE_T *service =
  505. (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);
  506. if (!service->callback)
  507. goto release;
  508. switch (reason) {
  509. case VCHIQ_MESSAGE_AVAILABLE:
  510. vchiu_queue_push(&service->queue, header);
  511. service->callback(service->callback_param,
  512. VCHI_CALLBACK_MSG_AVAILABLE, NULL);
  513. goto done;
  514. break;
  515. case VCHIQ_BULK_TRANSMIT_DONE:
  516. service->callback(service->callback_param,
  517. VCHI_CALLBACK_BULK_SENT, bulk_user);
  518. break;
  519. case VCHIQ_BULK_RECEIVE_DONE:
  520. service->callback(service->callback_param,
  521. VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
  522. break;
  523. case VCHIQ_SERVICE_CLOSED:
  524. service->callback(service->callback_param,
  525. VCHI_CALLBACK_SERVICE_CLOSED, NULL);
  526. break;
  527. case VCHIQ_SERVICE_OPENED:
  528. /* No equivalent VCHI reason */
  529. break;
  530. case VCHIQ_BULK_TRANSMIT_ABORTED:
  531. service->callback(service->callback_param,
  532. VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
  533. bulk_user);
  534. break;
  535. case VCHIQ_BULK_RECEIVE_ABORTED:
  536. service->callback(service->callback_param,
  537. VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
  538. bulk_user);
  539. break;
  540. default:
  541. WARN(1, "not supported\n");
  542. break;
  543. }
  544. release:
  545. vchiq_release_message(service->handle, header);
  546. done:
  547. return VCHIQ_SUCCESS;
  548. }
  549. static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
  550. SERVICE_CREATION_T *setup)
  551. {
  552. SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);
  553. (void)instance;
  554. if (service) {
  555. if (vchiu_queue_init(&service->queue, 64)) {
  556. service->callback = setup->callback;
  557. service->callback_param = setup->callback_param;
  558. } else {
  559. kfree(service);
  560. service = NULL;
  561. }
  562. }
  563. return service;
  564. }
  565. static void service_free(SHIM_SERVICE_T *service)
  566. {
  567. if (service) {
  568. vchiu_queue_delete(&service->queue);
  569. kfree(service);
  570. }
  571. }
  572. int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
  573. SERVICE_CREATION_T *setup,
  574. VCHI_SERVICE_HANDLE_T *handle)
  575. {
  576. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  577. SHIM_SERVICE_T *service = service_alloc(instance, setup);
  578. *handle = (VCHI_SERVICE_HANDLE_T)service;
  579. if (service) {
  580. VCHIQ_SERVICE_PARAMS_T params;
  581. VCHIQ_STATUS_T status;
  582. memset(&params, 0, sizeof(params));
  583. params.fourcc = setup->service_id;
  584. params.callback = shim_callback;
  585. params.userdata = service;
  586. params.version = setup->version.version;
  587. params.version_min = setup->version.version_min;
  588. status = vchiq_open_service(instance, &params,
  589. &service->handle);
  590. if (status != VCHIQ_SUCCESS) {
  591. service_free(service);
  592. service = NULL;
  593. *handle = NULL;
  594. }
  595. }
  596. return (service != NULL) ? 0 : -1;
  597. }
  598. EXPORT_SYMBOL(vchi_service_open);
  599. int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,
  600. SERVICE_CREATION_T *setup,
  601. VCHI_SERVICE_HANDLE_T *handle)
  602. {
  603. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  604. SHIM_SERVICE_T *service = service_alloc(instance, setup);
  605. *handle = (VCHI_SERVICE_HANDLE_T)service;
  606. if (service) {
  607. VCHIQ_SERVICE_PARAMS_T params;
  608. VCHIQ_STATUS_T status;
  609. memset(&params, 0, sizeof(params));
  610. params.fourcc = setup->service_id;
  611. params.callback = shim_callback;
  612. params.userdata = service;
  613. params.version = setup->version.version;
  614. params.version_min = setup->version.version_min;
  615. status = vchiq_add_service(instance, &params, &service->handle);
  616. if (status != VCHIQ_SUCCESS) {
  617. service_free(service);
  618. service = NULL;
  619. *handle = NULL;
  620. }
  621. }
  622. return (service != NULL) ? 0 : -1;
  623. }
  624. EXPORT_SYMBOL(vchi_service_create);
  625. int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
  626. {
  627. int32_t ret = -1;
  628. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  629. if (service) {
  630. VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
  631. if (status == VCHIQ_SUCCESS) {
  632. service_free(service);
  633. service = NULL;
  634. }
  635. ret = vchiq_status_to_vchi(status);
  636. }
  637. return ret;
  638. }
  639. EXPORT_SYMBOL(vchi_service_close);
  640. int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
  641. {
  642. int32_t ret = -1;
  643. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  644. if (service) {
  645. VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
  646. if (status == VCHIQ_SUCCESS) {
  647. service_free(service);
  648. service = NULL;
  649. }
  650. ret = vchiq_status_to_vchi(status);
  651. }
  652. return ret;
  653. }
  654. EXPORT_SYMBOL(vchi_service_destroy);
  655. int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
  656. VCHI_SERVICE_OPTION_T option,
  657. int value)
  658. {
  659. int32_t ret = -1;
  660. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  661. VCHIQ_SERVICE_OPTION_T vchiq_option;
  662. switch (option) {
  663. case VCHI_SERVICE_OPTION_TRACE:
  664. vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
  665. break;
  666. case VCHI_SERVICE_OPTION_SYNCHRONOUS:
  667. vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS;
  668. break;
  669. default:
  670. service = NULL;
  671. break;
  672. }
  673. if (service) {
  674. VCHIQ_STATUS_T status =
  675. vchiq_set_service_option(service->handle,
  676. vchiq_option,
  677. value);
  678. ret = vchiq_status_to_vchi(status);
  679. }
  680. return ret;
  681. }
  682. EXPORT_SYMBOL(vchi_service_set_option);
  683. int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, short *peer_version)
  684. {
  685. int32_t ret = -1;
  686. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  687. if (service)
  688. {
  689. VCHIQ_STATUS_T status;
  690. status = vchiq_get_peer_version(service->handle, peer_version);
  691. ret = vchiq_status_to_vchi(status);
  692. }
  693. return ret;
  694. }
  695. EXPORT_SYMBOL(vchi_get_peer_version);
  696. /***********************************************************
  697. * Name: vchi_service_use
  698. *
  699. * Arguments: const VCHI_SERVICE_HANDLE_T handle
  700. *
  701. * Description: Routine to increment refcount on a service
  702. *
  703. * Returns: void
  704. *
  705. ***********************************************************/
  706. int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
  707. {
  708. int32_t ret = -1;
  709. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  710. if (service)
  711. ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
  712. return ret;
  713. }
  714. EXPORT_SYMBOL(vchi_service_use);
  715. /***********************************************************
  716. * Name: vchi_service_release
  717. *
  718. * Arguments: const VCHI_SERVICE_HANDLE_T handle
  719. *
  720. * Description: Routine to decrement refcount on a service
  721. *
  722. * Returns: void
  723. *
  724. ***********************************************************/
  725. int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
  726. {
  727. int32_t ret = -1;
  728. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  729. if (service)
  730. ret = vchiq_status_to_vchi(
  731. vchiq_release_service(service->handle));
  732. return ret;
  733. }
  734. EXPORT_SYMBOL(vchi_service_release);