PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://gitlab.com/openbar/rpi-linux
C | 860 lines | 484 code | 114 blank | 262 comment | 51 complexity | 839165c06bbdbfdcd863e6377f5a7533 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. #include <stddef.h>
  40. #define vchiq_status_to_vchi(status) ((int32_t)status)
  41. typedef struct {
  42. VCHIQ_SERVICE_HANDLE_T handle;
  43. VCHIU_QUEUE_T queue;
  44. VCHI_CALLBACK_T callback;
  45. void *callback_param;
  46. } SHIM_SERVICE_T;
  47. /* ----------------------------------------------------------------------
  48. * return pointer to the mphi message driver function table
  49. * -------------------------------------------------------------------- */
  50. const VCHI_MESSAGE_DRIVER_T *
  51. vchi_mphi_message_driver_func_table(void)
  52. {
  53. return NULL;
  54. }
  55. /* ----------------------------------------------------------------------
  56. * return a pointer to the 'single' connection driver fops
  57. * -------------------------------------------------------------------- */
  58. const VCHI_CONNECTION_API_T *
  59. single_get_func_table(void)
  60. {
  61. return NULL;
  62. }
  63. VCHI_CONNECTION_T *vchi_create_connection(
  64. const VCHI_CONNECTION_API_T *function_table,
  65. const VCHI_MESSAGE_DRIVER_T *low_level)
  66. {
  67. (void)function_table;
  68. (void)low_level;
  69. return NULL;
  70. }
  71. /***********************************************************
  72. * Name: vchi_msg_peek
  73. *
  74. * Arguments: const VCHI_SERVICE_HANDLE_T handle,
  75. * void **data,
  76. * uint32_t *msg_size,
  77. * VCHI_FLAGS_T flags
  78. *
  79. * Description: Routine to return a pointer to the current message (to allow in
  80. * place processing). The message can be removed using
  81. * vchi_msg_remove when you're finished
  82. *
  83. * Returns: int32_t - success == 0
  84. *
  85. ***********************************************************/
  86. int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
  87. void **data,
  88. uint32_t *msg_size,
  89. VCHI_FLAGS_T flags)
  90. {
  91. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  92. VCHIQ_HEADER_T *header;
  93. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  94. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  95. if (flags == VCHI_FLAGS_NONE)
  96. if (vchiu_queue_is_empty(&service->queue))
  97. return -1;
  98. header = vchiu_queue_peek(&service->queue);
  99. *data = header->data;
  100. *msg_size = header->size;
  101. return 0;
  102. }
  103. EXPORT_SYMBOL(vchi_msg_peek);
  104. /***********************************************************
  105. * Name: vchi_msg_remove
  106. *
  107. * Arguments: const VCHI_SERVICE_HANDLE_T handle,
  108. *
  109. * Description: Routine to remove a message (after it has been read with
  110. * vchi_msg_peek)
  111. *
  112. * Returns: int32_t - success == 0
  113. *
  114. ***********************************************************/
  115. int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
  116. {
  117. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  118. VCHIQ_HEADER_T *header;
  119. header = vchiu_queue_pop(&service->queue);
  120. vchiq_release_message(service->handle, header);
  121. return 0;
  122. }
  123. EXPORT_SYMBOL(vchi_msg_remove);
  124. /***********************************************************
  125. * Name: vchi_msg_queue
  126. *
  127. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  128. * const void *data,
  129. * uint32_t data_size,
  130. * VCHI_FLAGS_T flags,
  131. * void *msg_handle,
  132. *
  133. * Description: Thin wrapper to queue a message onto a connection
  134. *
  135. * Returns: int32_t - success == 0
  136. *
  137. ***********************************************************/
  138. int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
  139. const void *data,
  140. uint32_t data_size,
  141. VCHI_FLAGS_T flags,
  142. void *msg_handle)
  143. {
  144. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  145. VCHIQ_ELEMENT_T element = {data, data_size};
  146. VCHIQ_STATUS_T status;
  147. (void)msg_handle;
  148. WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
  149. status = vchiq_queue_message(service->handle, &element, 1);
  150. /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to
  151. ** implement a retry mechanism since this function is supposed
  152. ** to block until queued
  153. */
  154. while (status == VCHIQ_RETRY) {
  155. msleep(1);
  156. status = vchiq_queue_message(service->handle, &element, 1);
  157. }
  158. return vchiq_status_to_vchi(status);
  159. }
  160. EXPORT_SYMBOL(vchi_msg_queue);
  161. /***********************************************************
  162. * Name: vchi_bulk_queue_receive
  163. *
  164. * Arguments: VCHI_BULK_HANDLE_T handle,
  165. * void *data_dst,
  166. * const uint32_t data_size,
  167. * VCHI_FLAGS_T flags
  168. * void *bulk_handle
  169. *
  170. * Description: Routine to setup a rcv buffer
  171. *
  172. * Returns: int32_t - success == 0
  173. *
  174. ***********************************************************/
  175. int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,
  176. void *data_dst,
  177. uint32_t data_size,
  178. VCHI_FLAGS_T flags,
  179. void *bulk_handle)
  180. {
  181. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  182. VCHIQ_BULK_MODE_T mode;
  183. VCHIQ_STATUS_T status;
  184. switch ((int)flags) {
  185. case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
  186. | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  187. WARN_ON(!service->callback);
  188. mode = VCHIQ_BULK_MODE_CALLBACK;
  189. break;
  190. case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
  191. mode = VCHIQ_BULK_MODE_BLOCKING;
  192. break;
  193. case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  194. case VCHI_FLAGS_NONE:
  195. mode = VCHIQ_BULK_MODE_NOCALLBACK;
  196. break;
  197. default:
  198. WARN(1, "unsupported message\n");
  199. return vchiq_status_to_vchi(VCHIQ_ERROR);
  200. }
  201. status = vchiq_bulk_receive(service->handle, data_dst, data_size,
  202. bulk_handle, mode);
  203. /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
  204. ** implement a retry mechanism since this function is supposed
  205. ** to block until queued
  206. */
  207. while (status == VCHIQ_RETRY) {
  208. msleep(1);
  209. status = vchiq_bulk_receive(service->handle, data_dst,
  210. data_size, bulk_handle, mode);
  211. }
  212. return vchiq_status_to_vchi(status);
  213. }
  214. EXPORT_SYMBOL(vchi_bulk_queue_receive);
  215. /***********************************************************
  216. * Name: vchi_bulk_queue_transmit
  217. *
  218. * Arguments: VCHI_BULK_HANDLE_T handle,
  219. * const void *data_src,
  220. * uint32_t data_size,
  221. * VCHI_FLAGS_T flags,
  222. * void *bulk_handle
  223. *
  224. * Description: Routine to transmit some data
  225. *
  226. * Returns: int32_t - success == 0
  227. *
  228. ***********************************************************/
  229. int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,
  230. const void *data_src,
  231. uint32_t data_size,
  232. VCHI_FLAGS_T flags,
  233. void *bulk_handle)
  234. {
  235. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  236. VCHIQ_BULK_MODE_T mode;
  237. VCHIQ_STATUS_T status;
  238. switch ((int)flags) {
  239. case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
  240. | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  241. WARN_ON(!service->callback);
  242. mode = VCHIQ_BULK_MODE_CALLBACK;
  243. break;
  244. case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
  245. case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
  246. mode = VCHIQ_BULK_MODE_BLOCKING;
  247. break;
  248. case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
  249. case VCHI_FLAGS_NONE:
  250. mode = VCHIQ_BULK_MODE_NOCALLBACK;
  251. break;
  252. default:
  253. WARN(1, "unsupported message\n");
  254. return vchiq_status_to_vchi(VCHIQ_ERROR);
  255. }
  256. status = vchiq_bulk_transmit(service->handle, data_src, data_size,
  257. bulk_handle, mode);
  258. /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
  259. ** implement a retry mechanism since this function is supposed
  260. ** to block until queued
  261. */
  262. while (status == VCHIQ_RETRY) {
  263. msleep(1);
  264. status = vchiq_bulk_transmit(service->handle, data_src,
  265. data_size, bulk_handle, mode);
  266. }
  267. return vchiq_status_to_vchi(status);
  268. }
  269. EXPORT_SYMBOL(vchi_bulk_queue_transmit);
  270. /***********************************************************
  271. * Name: vchi_msg_dequeue
  272. *
  273. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  274. * void *data,
  275. * uint32_t max_data_size_to_read,
  276. * uint32_t *actual_msg_size
  277. * VCHI_FLAGS_T flags
  278. *
  279. * Description: Routine to dequeue a message into the supplied buffer
  280. *
  281. * Returns: int32_t - success == 0
  282. *
  283. ***********************************************************/
  284. int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
  285. void *data,
  286. uint32_t max_data_size_to_read,
  287. uint32_t *actual_msg_size,
  288. VCHI_FLAGS_T flags)
  289. {
  290. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  291. VCHIQ_HEADER_T *header;
  292. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  293. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  294. if (flags == VCHI_FLAGS_NONE)
  295. if (vchiu_queue_is_empty(&service->queue))
  296. return -1;
  297. header = vchiu_queue_pop(&service->queue);
  298. memcpy(data, header->data, header->size < max_data_size_to_read ?
  299. header->size : max_data_size_to_read);
  300. *actual_msg_size = header->size;
  301. vchiq_release_message(service->handle, header);
  302. return 0;
  303. }
  304. EXPORT_SYMBOL(vchi_msg_dequeue);
  305. /***********************************************************
  306. * Name: vchi_msg_queuev
  307. *
  308. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  309. * VCHI_MSG_VECTOR_T *vector,
  310. * uint32_t count,
  311. * VCHI_FLAGS_T flags,
  312. * void *msg_handle
  313. *
  314. * Description: Thin wrapper to queue a message onto a connection
  315. *
  316. * Returns: int32_t - success == 0
  317. *
  318. ***********************************************************/
  319. vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
  320. vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) ==
  321. offsetof(VCHIQ_ELEMENT_T, data));
  322. vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) ==
  323. offsetof(VCHIQ_ELEMENT_T, size));
  324. int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle,
  325. VCHI_MSG_VECTOR_T *vector,
  326. uint32_t count,
  327. VCHI_FLAGS_T flags,
  328. void *msg_handle)
  329. {
  330. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  331. (void)msg_handle;
  332. WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
  333. return vchiq_status_to_vchi(vchiq_queue_message(service->handle,
  334. (const VCHIQ_ELEMENT_T *)vector, count));
  335. }
  336. EXPORT_SYMBOL(vchi_msg_queuev);
  337. /***********************************************************
  338. * Name: vchi_held_msg_release
  339. *
  340. * Arguments: VCHI_HELD_MSG_T *message
  341. *
  342. * Description: Routine to release a held message (after it has been read with
  343. * vchi_msg_hold)
  344. *
  345. * Returns: int32_t - success == 0
  346. *
  347. ***********************************************************/
  348. int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)
  349. {
  350. vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service,
  351. (VCHIQ_HEADER_T *)message->message);
  352. return 0;
  353. }
  354. EXPORT_SYMBOL(vchi_held_msg_release);
  355. /***********************************************************
  356. * Name: vchi_msg_hold
  357. *
  358. * Arguments: VCHI_SERVICE_HANDLE_T handle,
  359. * void **data,
  360. * uint32_t *msg_size,
  361. * VCHI_FLAGS_T flags,
  362. * VCHI_HELD_MSG_T *message_handle
  363. *
  364. * Description: Routine to return a pointer to the current message (to allow
  365. * in place processing). The message is dequeued - don't forget
  366. * to release the message using vchi_held_msg_release when you're
  367. * finished.
  368. *
  369. * Returns: int32_t - success == 0
  370. *
  371. ***********************************************************/
  372. int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
  373. void **data,
  374. uint32_t *msg_size,
  375. VCHI_FLAGS_T flags,
  376. VCHI_HELD_MSG_T *message_handle)
  377. {
  378. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  379. VCHIQ_HEADER_T *header;
  380. WARN_ON((flags != VCHI_FLAGS_NONE) &&
  381. (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
  382. if (flags == VCHI_FLAGS_NONE)
  383. if (vchiu_queue_is_empty(&service->queue))
  384. return -1;
  385. header = vchiu_queue_pop(&service->queue);
  386. *data = header->data;
  387. *msg_size = header->size;
  388. message_handle->service =
  389. (struct opaque_vchi_service_t *)service->handle;
  390. message_handle->message = header;
  391. return 0;
  392. }
  393. EXPORT_SYMBOL(vchi_msg_hold);
  394. /***********************************************************
  395. * Name: vchi_initialise
  396. *
  397. * Arguments: VCHI_INSTANCE_T *instance_handle
  398. *
  399. * Description: Initialises the hardware but does not transmit anything
  400. * When run as a Host App this will be called twice hence the need
  401. * to malloc the state information
  402. *
  403. * Returns: 0 if successful, failure otherwise
  404. *
  405. ***********************************************************/
  406. int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
  407. {
  408. VCHIQ_INSTANCE_T instance;
  409. VCHIQ_STATUS_T status;
  410. status = vchiq_initialise(&instance);
  411. *instance_handle = (VCHI_INSTANCE_T)instance;
  412. return vchiq_status_to_vchi(status);
  413. }
  414. EXPORT_SYMBOL(vchi_initialise);
  415. /***********************************************************
  416. * Name: vchi_connect
  417. *
  418. * Arguments: VCHI_CONNECTION_T **connections
  419. * const uint32_t num_connections
  420. * VCHI_INSTANCE_T instance_handle)
  421. *
  422. * Description: Starts the command service on each connection,
  423. * causing INIT messages to be pinged back and forth
  424. *
  425. * Returns: 0 if successful, failure otherwise
  426. *
  427. ***********************************************************/
  428. int32_t vchi_connect(VCHI_CONNECTION_T **connections,
  429. const uint32_t num_connections,
  430. VCHI_INSTANCE_T instance_handle)
  431. {
  432. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  433. (void)connections;
  434. (void)num_connections;
  435. return vchiq_connect(instance);
  436. }
  437. EXPORT_SYMBOL(vchi_connect);
  438. /***********************************************************
  439. * Name: vchi_disconnect
  440. *
  441. * Arguments: VCHI_INSTANCE_T instance_handle
  442. *
  443. * Description: Stops the command service on each connection,
  444. * causing DE-INIT messages to be pinged back and forth
  445. *
  446. * Returns: 0 if successful, failure otherwise
  447. *
  448. ***********************************************************/
  449. int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
  450. {
  451. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  452. return vchiq_status_to_vchi(vchiq_shutdown(instance));
  453. }
  454. EXPORT_SYMBOL(vchi_disconnect);
  455. /***********************************************************
  456. * Name: vchi_service_open
  457. * Name: vchi_service_create
  458. *
  459. * Arguments: VCHI_INSTANCE_T *instance_handle
  460. * SERVICE_CREATION_T *setup,
  461. * VCHI_SERVICE_HANDLE_T *handle
  462. *
  463. * Description: Routine to open a service
  464. *
  465. * Returns: int32_t - success == 0
  466. *
  467. ***********************************************************/
  468. static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
  469. VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)
  470. {
  471. SHIM_SERVICE_T *service =
  472. (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);
  473. if (!service->callback)
  474. goto release;
  475. switch (reason) {
  476. case VCHIQ_MESSAGE_AVAILABLE:
  477. vchiu_queue_push(&service->queue, header);
  478. service->callback(service->callback_param,
  479. VCHI_CALLBACK_MSG_AVAILABLE, NULL);
  480. goto done;
  481. break;
  482. case VCHIQ_BULK_TRANSMIT_DONE:
  483. service->callback(service->callback_param,
  484. VCHI_CALLBACK_BULK_SENT, bulk_user);
  485. break;
  486. case VCHIQ_BULK_RECEIVE_DONE:
  487. service->callback(service->callback_param,
  488. VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
  489. break;
  490. case VCHIQ_SERVICE_CLOSED:
  491. service->callback(service->callback_param,
  492. VCHI_CALLBACK_SERVICE_CLOSED, NULL);
  493. break;
  494. case VCHIQ_SERVICE_OPENED:
  495. /* No equivalent VCHI reason */
  496. break;
  497. case VCHIQ_BULK_TRANSMIT_ABORTED:
  498. service->callback(service->callback_param,
  499. VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
  500. bulk_user);
  501. break;
  502. case VCHIQ_BULK_RECEIVE_ABORTED:
  503. service->callback(service->callback_param,
  504. VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
  505. bulk_user);
  506. break;
  507. default:
  508. WARN(1, "not supported\n");
  509. break;
  510. }
  511. release:
  512. vchiq_release_message(service->handle, header);
  513. done:
  514. return VCHIQ_SUCCESS;
  515. }
  516. static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
  517. SERVICE_CREATION_T *setup)
  518. {
  519. SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);
  520. (void)instance;
  521. if (service) {
  522. if (vchiu_queue_init(&service->queue, 64)) {
  523. service->callback = setup->callback;
  524. service->callback_param = setup->callback_param;
  525. } else {
  526. kfree(service);
  527. service = NULL;
  528. }
  529. }
  530. return service;
  531. }
  532. static void service_free(SHIM_SERVICE_T *service)
  533. {
  534. if (service) {
  535. vchiu_queue_delete(&service->queue);
  536. kfree(service);
  537. }
  538. }
  539. int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
  540. SERVICE_CREATION_T *setup,
  541. VCHI_SERVICE_HANDLE_T *handle)
  542. {
  543. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  544. SHIM_SERVICE_T *service = service_alloc(instance, setup);
  545. *handle = (VCHI_SERVICE_HANDLE_T)service;
  546. if (service) {
  547. VCHIQ_SERVICE_PARAMS_T params;
  548. VCHIQ_STATUS_T status;
  549. memset(&params, 0, sizeof(params));
  550. params.fourcc = setup->service_id;
  551. params.callback = shim_callback;
  552. params.userdata = service;
  553. params.version = setup->version.version;
  554. params.version_min = setup->version.version_min;
  555. status = vchiq_open_service(instance, &params,
  556. &service->handle);
  557. if (status != VCHIQ_SUCCESS) {
  558. service_free(service);
  559. service = NULL;
  560. *handle = NULL;
  561. }
  562. }
  563. return (service != NULL) ? 0 : -1;
  564. }
  565. EXPORT_SYMBOL(vchi_service_open);
  566. int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,
  567. SERVICE_CREATION_T *setup,
  568. VCHI_SERVICE_HANDLE_T *handle)
  569. {
  570. VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
  571. SHIM_SERVICE_T *service = service_alloc(instance, setup);
  572. *handle = (VCHI_SERVICE_HANDLE_T)service;
  573. if (service) {
  574. VCHIQ_SERVICE_PARAMS_T params;
  575. VCHIQ_STATUS_T status;
  576. memset(&params, 0, sizeof(params));
  577. params.fourcc = setup->service_id;
  578. params.callback = shim_callback;
  579. params.userdata = service;
  580. params.version = setup->version.version;
  581. params.version_min = setup->version.version_min;
  582. status = vchiq_add_service(instance, &params, &service->handle);
  583. if (status != VCHIQ_SUCCESS) {
  584. service_free(service);
  585. service = NULL;
  586. *handle = NULL;
  587. }
  588. }
  589. return (service != NULL) ? 0 : -1;
  590. }
  591. EXPORT_SYMBOL(vchi_service_create);
  592. int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
  593. {
  594. int32_t ret = -1;
  595. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  596. if (service) {
  597. VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
  598. if (status == VCHIQ_SUCCESS) {
  599. service_free(service);
  600. service = NULL;
  601. }
  602. ret = vchiq_status_to_vchi(status);
  603. }
  604. return ret;
  605. }
  606. EXPORT_SYMBOL(vchi_service_close);
  607. int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
  608. {
  609. int32_t ret = -1;
  610. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  611. if (service) {
  612. VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
  613. if (status == VCHIQ_SUCCESS) {
  614. service_free(service);
  615. service = NULL;
  616. }
  617. ret = vchiq_status_to_vchi(status);
  618. }
  619. return ret;
  620. }
  621. EXPORT_SYMBOL(vchi_service_destroy);
  622. int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle,
  623. VCHI_SERVICE_OPTION_T option,
  624. int value)
  625. {
  626. int32_t ret = -1;
  627. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  628. VCHIQ_SERVICE_OPTION_T vchiq_option;
  629. switch (option) {
  630. case VCHI_SERVICE_OPTION_TRACE:
  631. vchiq_option = VCHIQ_SERVICE_OPTION_TRACE;
  632. break;
  633. case VCHI_SERVICE_OPTION_SYNCHRONOUS:
  634. vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS;
  635. break;
  636. default:
  637. service = NULL;
  638. break;
  639. }
  640. if (service) {
  641. VCHIQ_STATUS_T status =
  642. vchiq_set_service_option(service->handle,
  643. vchiq_option,
  644. value);
  645. ret = vchiq_status_to_vchi(status);
  646. }
  647. return ret;
  648. }
  649. EXPORT_SYMBOL(vchi_service_set_option);
  650. int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )
  651. {
  652. int32_t ret = -1;
  653. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  654. if(service)
  655. {
  656. VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version);
  657. ret = vchiq_status_to_vchi( status );
  658. }
  659. return ret;
  660. }
  661. EXPORT_SYMBOL(vchi_get_peer_version);
  662. /* ----------------------------------------------------------------------
  663. * read a uint32_t from buffer.
  664. * network format is defined to be little endian
  665. * -------------------------------------------------------------------- */
  666. uint32_t
  667. vchi_readbuf_uint32(const void *_ptr)
  668. {
  669. const unsigned char *ptr = _ptr;
  670. return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
  671. }
  672. /* ----------------------------------------------------------------------
  673. * write a uint32_t to buffer.
  674. * network format is defined to be little endian
  675. * -------------------------------------------------------------------- */
  676. void
  677. vchi_writebuf_uint32(void *_ptr, uint32_t value)
  678. {
  679. unsigned char *ptr = _ptr;
  680. ptr[0] = (unsigned char)((value >> 0) & 0xFF);
  681. ptr[1] = (unsigned char)((value >> 8) & 0xFF);
  682. ptr[2] = (unsigned char)((value >> 16) & 0xFF);
  683. ptr[3] = (unsigned char)((value >> 24) & 0xFF);
  684. }
  685. /* ----------------------------------------------------------------------
  686. * read a uint16_t from buffer.
  687. * network format is defined to be little endian
  688. * -------------------------------------------------------------------- */
  689. uint16_t
  690. vchi_readbuf_uint16(const void *_ptr)
  691. {
  692. const unsigned char *ptr = _ptr;
  693. return ptr[0] | (ptr[1] << 8);
  694. }
  695. /* ----------------------------------------------------------------------
  696. * write a uint16_t into the buffer.
  697. * network format is defined to be little endian
  698. * -------------------------------------------------------------------- */
  699. void
  700. vchi_writebuf_uint16(void *_ptr, uint16_t value)
  701. {
  702. unsigned char *ptr = _ptr;
  703. ptr[0] = (value >> 0) & 0xFF;
  704. ptr[1] = (value >> 8) & 0xFF;
  705. }
  706. /***********************************************************
  707. * Name: vchi_service_use
  708. *
  709. * Arguments: const VCHI_SERVICE_HANDLE_T handle
  710. *
  711. * Description: Routine to increment refcount on a service
  712. *
  713. * Returns: void
  714. *
  715. ***********************************************************/
  716. int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
  717. {
  718. int32_t ret = -1;
  719. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  720. if (service)
  721. ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
  722. return ret;
  723. }
  724. EXPORT_SYMBOL(vchi_service_use);
  725. /***********************************************************
  726. * Name: vchi_service_release
  727. *
  728. * Arguments: const VCHI_SERVICE_HANDLE_T handle
  729. *
  730. * Description: Routine to decrement refcount on a service
  731. *
  732. * Returns: void
  733. *
  734. ***********************************************************/
  735. int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
  736. {
  737. int32_t ret = -1;
  738. SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
  739. if (service)
  740. ret = vchiq_status_to_vchi(
  741. vchiq_release_service(service->handle));
  742. return ret;
  743. }
  744. EXPORT_SYMBOL(vchi_service_release);