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