Modules/UDI - MEI working, used for nic
[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         mei_op->backend_stub(Call->DCall.Handler, Call->DCall.cb, Call+1);
24 }
25
26 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, ...)
27 {
28         ENTER("pgcb pmeta_info imeta_ops_num ivec_idx",
29                 gcb, meta_info, meta_ops_num, vec_idx);
30         const udi_mei_op_template_t     *mei_op;
31
32         {
33                 udi_mei_ops_vec_template_t      *ops = meta_info->ops_vec_template_list;
34                 for( ; ops->meta_ops_num && ops->meta_ops_num != meta_ops_num; ops ++ )
35                         ;
36                 if( !ops->meta_ops_num ) {
37                         LEAVE('-');
38                         return ;
39                 }
40                 mei_op = &ops->op_template_list[vec_idx-1];
41         }
42         
43         LOG("%s", mei_op->op_name);
44
45         // Check CB type
46         udi_index_t     cb_type;
47         tUDI_MetaLang   *metalang = UDI_int_GetCbType(gcb, &cb_type);
48         //if( metalang->MeiInfo != meta_info )
49         //      return ;
50         if( mei_op->meta_cb_num != cb_type ) {
51                 LEAVE('-');
52                 return ;
53         }
54         // Check call type
55         udi_op_t        *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
56         udi_op_t        *op = ops[vec_idx];
57         
58         // Start va_args
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         if( indirect_call )
65         {
66                 va_list args;
67                 va_start(args, vec_idx);
68                 size_t  marshal_size = _udi_marshal_values(NULL, mei_op->marshal_layout, args);
69                 va_end(args);
70                 tUDI_MeiCall    *call = malloc(sizeof(tUDI_MeiCall) + marshal_size);
71                 call->DCall.Next = NULL;
72                 call->DCall.Unmarshal = _udi_mei_call_unmarshal;
73                 call->DCall.cb = gcb;
74                 call->DCall.Handler = op;
75                 call->mei_op = mei_op;
76                 void    *marshal_space = (void*)(call+1);
77                 va_start(args, vec_idx);
78                 _udi_marshal_values(marshal_space, mei_op->marshal_layout, args);
79                 va_end(args);
80                 
81                 UDI_int_AddDeferred(&call->DCall);
82         }
83         else
84         {
85                 va_list args;
86                 va_start(args, vec_idx);
87                 mei_op->direct_stub( op, gcb, args );
88                 va_end(args);
89         }
90         LEAVE('-');
91 }
92

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