Modules/UDI - Channel code implimented (partially)
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / channels.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * channels.c
6  * - Channel code
7  */
8 #define DEBUG   0
9 #include <acess.h>
10 #include <udi.h>
11 #include "udi_internal.h"
12
13 struct sUDI_ChannelSide {
14         struct sUDI_Channel     *BackPtr;
15         const void      *Ops;
16         void    *Context;
17 };
18
19 typedef struct sUDI_Channel
20 {
21         enum eUDI_MetaLang      MetaLang;
22         udi_index_t     MetaOpsNum;
23         struct sUDI_ChannelSide  Side[2];
24 } tUDI_Channel;
25
26 // === CODE ===
27 udi_channel_t UDI_CreateChannel(enum eUDI_MetaLang metalang, udi_index_t meta_ops_num,
28         tUDI_DriverInstance *ThisEnd, udi_index_t ThisOpsIndex,
29         tUDI_DriverInstance *OtherEnd, udi_index_t OtherOpsIndex)
30 {
31         tUDI_Channel    *ret = NEW(tUDI_Channel,);
32         struct {
33                 tUDI_DriverInstance     *inst;
34                 udi_index_t     ops_index;
35         } ends[2] = {
36                 {ThisEnd, ThisOpsIndex},
37                 {OtherEnd, OtherOpsIndex}
38         };
39         ret->MetaLang = metalang;
40         ret->MetaOpsNum = meta_ops_num;
41         for( int i = 0; i < 2; i ++ )
42         {
43                 if( !ends[i].inst ) {
44                         continue ;
45                 }
46                 tUDI_DriverModule       *mod = ends[i].inst->Module;
47                 ret->Side[i].BackPtr = ret;
48                 udi_ops_init_t  *ops = mod->InitInfo->ops_init_list;;
49                 while( ops->ops_idx && ops->ops_idx != ends[i].ops_index )
50                         ops++;
51                 ASSERTR(ops->ops_idx, NULL);    // TODO: Pretty error
52                 ASSERTCR(ops->meta_idx, <, mod->nMetaLangs, NULL);
53                 ASSERTCR(mod->MetaLangs[ops->meta_idx], ==, metalang, NULL);
54                 ASSERTCR(ops->meta_ops_num, ==, meta_ops_num, NULL);
55                 if( ops->chan_context_size ) {
56                         ret->Side[i].Context = malloc(ops->chan_context_size);
57                 }
58                 ret->Side[i].Ops = ops->ops_vector;
59         }
60         return (udi_channel_t)&ret->Side[0].BackPtr;
61 }
62
63 /**
64  * \brief Prepare a cb for a channel call
65  * \param gcb   Generic control block for this request
66  * \param metalang      UDI metalanguage (used for validation)
67  * \return Pointer to ops list
68  * \retval NULL Metalangage validation failed
69  *
70  * Updates the channel and context fields of the gcb, checks the metalanguage and returns
71  * the handler list for the other end of the channel.
72  */
73 const void *UDI_int_ChannelPrepForCall(udi_cb_t *gcb, enum eUDI_MetaLang metalang, udi_index_t meta_ops_num)
74 {
75         tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel);
76         ASSERTCR(ch->MetaLang, ==, metalang, NULL);
77
78         struct sUDI_ChannelSide *newside = (gcb->channel == (udi_channel_t)&ch->Side[0].BackPtr ? &ch->Side[1] : &ch->Side[0]);
79
80 //      gcb->initiator_context = gcb->context;
81         gcb->channel = (udi_channel_t)&newside->BackPtr;
82         gcb->context = newside->Context;
83         return newside->Ops;
84 }
85

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