Modules/UDI - GIO Metalanguage Binding, GIO UART support, init error handling
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / udi_lib / core / mei.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * udi_lib/mei.c
6  * - Metalanguage-to-Environment Interface
7  */
8 #define DEBUG   1
9 #include <udi.h>
10 #include <acess.h>
11 #include <udi_internal.h>
12
13 typedef struct {
14         tUDI_DeferredCall       DCall;
15         const udi_mei_op_template_t     *mei_op;
16 } tUDI_MeiCall;
17
18 // === CODE ===
19 void _udi_mei_call_unmarshal(tUDI_DeferredCall *DCall)
20 {
21         tUDI_MeiCall    *Call = (void*)DCall;
22         const udi_mei_op_template_t     *mei_op = Call->mei_op;
23         LOG("%s backend", mei_op->op_name);
24         mei_op->backend_stub(Call->DCall.Handler, Call->DCall.cb, Call+1);
25 }
26
27 void udi_mei_call(udi_cb_t *gcb, udi_mei_init_t *meta_info, udi_index_t meta_ops_num, udi_index_t vec_idx, ...)
28 {
29 //      ENTER("pgcb pmeta_info imeta_ops_num ivec_idx",
30 //              gcb, meta_info, meta_ops_num, vec_idx);
31         const udi_mei_op_template_t     *mei_op;
32
33         {
34                 udi_mei_ops_vec_template_t      *ops = meta_info->ops_vec_template_list;
35                 for( ; ops->meta_ops_num && ops->meta_ops_num != meta_ops_num; ops ++ )
36                         ;
37                 if( !ops->meta_ops_num ) {
38 //                      LEAVE('-');
39                         return ;
40                 }
41                 mei_op = &ops->op_template_list[vec_idx-1];
42         }
43         
44         // Check CB type
45         udi_index_t     cb_type;
46         tUDI_MetaLang   *metalang = UDI_int_GetCbType(gcb, &cb_type);
47         if( meta_info != metalang->MeiInfo && mei_op->meta_cb_num != cb_type ) {
48                 Log_Warning("UDI", "%s meta cb mismatch want %p:%i got %p:%i",
49                         mei_op->op_name,
50                         meta_info, mei_op->meta_cb_num,
51                         metalang->MeiInfo, cb_type
52                         );
53                 ASSERTC(meta_info, ==, metalang->MeiInfo);
54                 ASSERTC(mei_op->meta_cb_num, ==, cb_type);
55 //              LEAVE('-');
56                 return ;
57         }
58         
59         // Determine if indirect call is needed
60         // > check stack depth?
61         // > Direction?
62          int indirect_call = (mei_op->op_category == UDI_MEI_OPCAT_REQ)
63                 || (mei_op->op_category == UDI_MEI_OPCAT_IND);
64         
65         LOG("%s %sdirect", mei_op->op_name, (indirect_call ? "in" : ""));
66         
67         // Check call type
68         udi_op_t        *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
69         udi_op_t        *op = ops[vec_idx];
70         
71         // Change ownership of chained cbs
72         size_t  chain_ofs = metalang->CbTypes[cb_type].ChainOfs;
73         if( chain_ofs )
74         {
75                 udi_cb_t        *chained_cb = gcb;
76                 while( (chained_cb = *(udi_cb_t**)((void*)chained_cb + chain_ofs)) )
77                         UDI_int_ChannelFlip(chained_cb);
78         }
79         
80         if( indirect_call )
81         {
82                 va_list args;
83                 va_start(args, vec_idx);
84                 size_t  marshal_size = _udi_marshal_values(NULL, mei_op->marshal_layout, args);
85                 if( marshal_size == 0 && mei_op->marshal_layout[0] != UDI_DL_END ) {
86                         Warning("udi_mei_call(%s) - Marshalling failure", mei_op->op_name);
87 //                      LEAVE('-');
88                         return ;
89                 }
90                 va_end(args);
91                 tUDI_MeiCall    *call = malloc(sizeof(tUDI_MeiCall) + marshal_size);
92                 call->DCall.Next = NULL;
93                 call->DCall.Unmarshal = _udi_mei_call_unmarshal;
94                 call->DCall.cb = gcb;
95                 call->DCall.Handler = op;
96                 call->mei_op = mei_op;
97                 void    *marshal_space = (void*)(call+1);
98                 va_start(args, vec_idx);
99                 _udi_marshal_values(marshal_space, mei_op->marshal_layout, args);
100                 va_end(args);
101                 
102                 UDI_int_AddDeferred(&call->DCall);
103         }
104         else
105         {
106                 va_list args;
107                 va_start(args, vec_idx);
108                 mei_op->direct_stub( op, gcb, args );
109                 va_end(args);
110         }
111 //      LEAVE('-');
112 }
113

UCC git Repository :: git.ucc.asn.au