3 * \author John Hodge (thePowersGang)
4 * \brief Control block code
9 #include <udi_internal.h>
10 #include <udi_internal_ma.h> // for cUDI_MgmtCbInitList
12 typedef struct sUDI_CBHeader
14 tUDI_MetaLang *Metalang;
15 udi_index_t MetaCBNum;
20 tUDI_MetaLang *UDI_int_GetCbType(udi_cb_t *cb, udi_index_t *meta_cb_num)
22 tUDI_CBHeader *hdr = (void*)cb - offsetof(tUDI_CBHeader, cb);
24 *meta_cb_num = hdr->MetaCBNum;
28 udi_cb_t *udi_cb_alloc_internal_v(tUDI_MetaLang *Meta, udi_index_t MetaCBNum,
29 size_t inline_size, size_t scratch_size, udi_channel_t channel)
31 ASSERTC(MetaCBNum, <, Meta->nCbTypes);
32 size_t base = Meta->CbTypes[MetaCBNum].Size;
33 ASSERTC(base, >=, sizeof(udi_cb_t));
34 base -= sizeof(udi_cb_t);
35 LOG("+ %i + %i + %i", base, inline_size, scratch_size);
36 tUDI_CBHeader *cbhdr = NEW(tUDI_CBHeader, + base + inline_size + scratch_size);
37 cbhdr->Metalang = Meta;
38 cbhdr->MetaCBNum = MetaCBNum;
39 udi_cb_t *ret = &cbhdr->cb;
40 ret->channel = channel;
41 ret->scratch = (void*)(ret + 1) + base + inline_size;
44 void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
46 const udi_cb_init_t *cb_init;
47 LOG("Inst=%p, bind_cb_idx=%i, channel=%p", Inst, bind_cb_idx, channel);
50 ASSERT(Inst->Module->InitInfo);
51 ASSERT(Inst->Module->InitInfo->cb_init_list);
53 for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
55 if( cb_init->cb_idx == bind_cb_idx )
57 // TODO: Get base size using meta/cbnum
58 tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst->Module, cb_init->meta_idx);
60 Log_Warning("UDI", "Metalang referenced in %s CB %i is invalid (%i)",
61 Inst->Module->ModuleName, bind_cb_idx, cb_init->meta_idx);
64 return udi_cb_alloc_internal_v(metalang, cb_init->meta_cb_num,
65 cb_init->inline_size, cb_init->scratch_requirement, channel);
67 ASSERTC(cb_init->meta_cb_num, <, metalang->nCbTypes);
68 size_t base = metalang->CbTypes[cb_init->meta_cb_num].Size;
69 ASSERTC(base, >=, sizeof(udi_cb_t));
70 base -= sizeof(udi_cb_t);
71 LOG("+ %i + %i + %i", base, cb_init->inline_size, cb_init->scratch_requirement);
72 udi_cb_t *ret = NEW(udi_cb_t, + base
73 + cb_init->inline_size + cb_init->scratch_requirement);
74 ret->channel = channel;
75 ret->scratch = (void*)ret + sizeof(udi_cb_t) + base + cb_init->inline_size;
80 Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
81 bind_cb_idx, Inst->Module->ModuleName);
86 udi_cb_alloc_call_t *callback, //!< Function to be called when the CB is allocated
87 udi_cb_t *gcb, //!< Parent Control Block
89 udi_channel_t default_channel
92 tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance(gcb, false, NULL);
93 void *ret = udi_cb_alloc_internal(inst, cb_idx, default_channel);
97 void udi_cb_alloc_dynamic(
98 udi_cb_alloc_call_t *callback,
101 udi_channel_t default_channel,
102 udi_size_t inline_size,
103 udi_layout_t *inline_layout
109 void udi_cb_alloc_batch(
110 udi_cb_alloc_batch_call_t *callback, //!<
114 udi_boolean_t with_buf,
116 udi_buf_path_t path_handle
122 void udi_cb_free(udi_cb_t *cb)
124 tUDI_CBHeader *hdr = (void*)cb - offsetof(tUDI_CBHeader, cb);
125 // TODO: Ensure that cb is inactive
129 void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb)
135 EXPORT(udi_cb_alloc);
136 EXPORT(udi_cb_alloc_dynamic);
137 EXPORT(udi_cb_alloc_batch);