fcdb93ff40cb89652cd0d00f8a5a635d9a5b4df2
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / main.c
1 /*
2  * Acess2 UDI Layer
3  */
4 #define DEBUG   0
5 #define VERSION ((0<<8)|1)
6 #include <acess.h>
7 #include <modules.h>
8 #include <udi.h>
9 #include "udi_internal.h"
10
11 // === IMPORTS ===
12 extern udi_init_t       pci_init;
13 extern char     pci_udiprops[];
14 extern size_t   pci_udiprops_size;
15
16 // === PROTOTYPES ===
17  int    UDI_Install(char **Arguments);
18  int    UDI_DetectDriver(void *Base);
19  int    UDI_LoadDriver(void *Base);
20
21 tUDI_DriverModule       *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size);
22
23 tUDI_DriverInstance     *UDI_CreateInstance(tUDI_DriverModule *DriverModule);
24 tUDI_DriverRegion       *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize);
25 void    UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst);
26
27 // === GLOBALS ===
28 MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
29 tModuleLoader   gUDI_Loader = {
30         NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL
31 };
32
33 // === CODE ===
34 /**
35  * \fn int UDI_Install(char **Arguments)
36  * \brief Stub intialisation routine
37  */
38 int UDI_Install(char **Arguments)
39 {
40         Module_RegisterLoader( &gUDI_Loader );
41
42         UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
43
44         return MODULE_ERR_OK;
45 }
46
47 /**
48  * \brief Detects if a driver should be loaded by the UDI subsystem
49  */
50 int UDI_DetectDriver(void *Base)
51 {
52         Uint    unused;
53         
54         if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) {
55                 return 0;
56         }
57         if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) {
58                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol");
59                 return 0;
60         }
61         if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) {
62                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol");
63                 return 0;
64         }
65         
66         return 1;
67 }
68
69 /**
70  * \fn int UDI_LoadDriver(void *Base)
71  */
72 int UDI_LoadDriver(void *Base)
73 {
74         udi_init_t      *info;
75         char    *udiprops = NULL;
76         char    *udiprops_end = 0;
77         
78         if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
79                 Binary_Unload(Base);
80                 return 0;
81         }
82         
83         Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops);
84         Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end);
85         Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
86
87         UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
88
89         #if 0
90         // Create initial driver instance
91         tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
92         
93         // Bind to parent
94         // TODO: This will move to udi_enumerate_ack handling
95         for( int i = 0; i < driver_module->nParents; i ++ )
96         {
97                 tUDI_BindOps    *parent = &driver_module->Parents[i];
98                 udi_channel_t channel = UDI_CreateChannel_Blank( UDI_int_GetMetaLang(inst, parent->meta_idx) );
99                 
100                 UDI_BindChannel(channel,true,  inst, parent->ops_idx, parent->region_idx);
101                 //UDI_BindChannel(channel,false, parent_inst, parent_chld->ops_idx, parent_chld->region_idx);
102                 
103                 udi_cb_t *bind_cb = udi_cb_alloc_internal(inst, parent->bind_cb_idx, channel);
104                 if( !bind_cb ) {
105                         Log_Warning("UDI", "Bind CB index is invalid");
106                         continue ;
107                 }
108
109                 udi_channel_event_cb_t  ev_cb;
110                  int    n_handles = driver_module->InitInfo->primary_init_info->per_parent_paths;
111                 udi_buf_path_t  handles[n_handles];
112                 memset(&ev_cb, 0, sizeof(ev_cb));
113                 ev_cb.gcb.channel = channel;
114                 ev_cb.event = UDI_CHANNEL_BOUND;
115                 ev_cb.params.parent_bound.bind_cb = bind_cb;
116                 ev_cb.params.parent_bound.parent_ID = i+1;
117                 ev_cb.params.parent_bound.path_handles = handles;
118                 
119                 for( int i = 0; i < n_handles; i ++ ) {
120                         //handles[i] = udi_buf_path_alloc_internal(inst);
121                         handles[i] = 0;
122                 }
123                 
124                 udi_channel_event_ind(&ev_cb);
125         }
126
127         // Send enumeraton request
128         #endif
129         
130         return 0;
131 }
132
133 static udi_index_t _get_token_idx(const char *str, const char **outstr)
134 {
135         char    *end;
136         int ret = strtol(str, &end, 10);
137         if( ret < 0 || ret > 255 ) {
138                 Log_Notice("UDI", "Value '%.*s' out of range for udi_index_t",
139                         end-str, str);
140                 *outstr = NULL;
141                 return 0;
142         }
143         if( *end && !isspace(*end) ) {
144                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
145                         end-str, str, *end);
146                 *outstr = NULL;
147                 return 0;
148         }
149         while( *end && isspace(*end) )
150                 end ++;
151         
152         *outstr = end;
153         return ret;
154 }
155 static udi_ubit16_t _get_token_uint16(const char *str, const char **outstr)
156 {
157         char    *end;
158         unsigned long ret = strtoul(str, &end, 10);
159         if( ret > 0xFFFF ) {
160                 Log_Notice("UDI", "Value '%.*s' out of range for udi_ubit16_t",
161                         end-str, str);
162                 *outstr = NULL;
163                 return 0;
164         }
165         if( *end && !isspace(*end) ) {
166                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
167                         end-str, str, *end);
168                 *outstr = NULL;
169                 return 0;
170         }
171         while( *end && isspace(*end) )
172                 end ++;
173         
174         *outstr = end;
175         return ret;
176 }
177 static udi_ubit32_t _get_token_uint32(const char *str, const char **outstr)
178 {
179         char    *end;
180         udi_ubit32_t ret = strtoul(str, &end, 0);
181         if( *end && !isspace(*end) ) {
182                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
183                         end-str, str, *end);
184                 *outstr = NULL;
185                 return 0;
186         }
187         while( *end && isspace(*end) )
188                 end ++;
189         
190         *outstr = end;
191         return ret;
192 }
193 static int _get_token_sym(const char *str, const char **outstr, ...)
194 {
195         va_list args;
196         va_start(args, outstr);
197         const char *sym;
198         for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
199         {
200                 size_t len = strlen(sym);
201                 if( memcmp(str, sym, len) != 0 )
202                         continue ;
203                 if( str[len] && !isspace(str[len]) )
204                         continue ;
205                 
206                 // Found it!
207                 return idx;
208         }
209         va_end(args);
210
211         const char *end = str;
212         while( !isspace(*end) )
213                 end ++;
214         Log_Notice("UDI", "Unknown token '%.*s'",
215                 end-str, str);  
216
217         *outstr = NULL;
218         return -1;
219 }
220
221
222 tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size)
223 {
224         //UDI_int_DumpInitInfo(info);
225         
226         // TODO: Multiple modules?
227         tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,);
228         driver_module->InitInfo = info;
229
230         // - Parse udiprops
231         {
232                 const char      **udipropsptrs;
233                 
234                 
235                 int nLines = 1;
236                 for( int i = 0; i < udiprops_size; i++ )
237                 {
238                         if( udiprops[i] == '\0' )
239                                 nLines ++;
240                 }
241                 
242                 Log_Debug("UDI", "nLines = %i", nLines);
243                 
244                 udipropsptrs = NEW(const char*,*nLines);
245                 int line = 0;
246                 udipropsptrs[line++] = udiprops;
247                 for( int i = 0; i < udiprops_size; i++ )
248                 {
249                         if( udiprops[i] == '\0' ) {
250                                 udipropsptrs[line++] = &udiprops[i+1];
251                         }
252                 }
253                 if(udipropsptrs[line-1] == &udiprops[udiprops_size])
254                         nLines --;
255                 
256                 for( int i = 0; i < nLines; i ++ )
257                 {
258                 }
259                 
260                 // Parse out:
261                 // 'message' into driver_module->Messages
262                 // 'region' into driver_module->RegionTypes
263                 // 'module' into driver_module->ModuleName
264                 
265                  int    nLocales = 1;
266                  int    nRegionTypes = 0;
267                 for( int i = 0; i < nLines; i ++ )
268                 {
269                         const char *str = udipropsptrs[i];
270                         if( strncmp("module ", str, 7) == 0 ) {
271                                 driver_module->ModuleName = str + 7;
272                         }
273                         else if( strncmp("meta ", str, 5) == 0 ) {
274                                 driver_module->nMetaLangs ++;
275                         }
276                         else if( strncmp("message ", str, 8) == 0 ) {
277                                 driver_module->nMessages ++;
278                         }
279                         else if( strncmp("locale ", str, 7) == 0 ) {
280                                 nLocales ++;
281                         }
282                         else if( strncmp("region ", str, 7) == 0 ) {
283                                 nRegionTypes ++;
284                         }
285                         else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
286                                 driver_module->nParents ++;
287                         }
288                 }
289
290                 // Allocate structures
291                 driver_module->Messages    = NEW(tUDI_PropMessage, * driver_module->nMessages);
292                 driver_module->nRegionTypes = nRegionTypes;
293                 driver_module->RegionTypes = NEW(tUDI_PropRegion,  * driver_module->nRegionTypes);
294                 driver_module->MetaLangs   = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
295                 driver_module->Parents     = NEW(tUDI_BindOps,     * driver_module->nParents);
296
297                 // Populate
298                  int    cur_locale = 0;
299                  int    msg_index = 0;
300                  int    ml_index = 0;
301                  int    parent_index = 0;
302                  int    next_unpop_region = 1;
303                 for( int i = 0; i < nLines; i ++ )
304                 {
305                         const char *str = udipropsptrs[i];
306                         if( strncmp("module ", str, 7) == 0 ) {
307                                 driver_module->ModuleName = str + 7;
308                         }
309                         else if( strncmp("meta ", str, 5) == 0 ) {
310                                 tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
311                                 ml->meta_idx = _get_token_idx(str+5, &str);
312                                 if( !str )      continue;
313                                 ml->interface_name = str;
314                         }
315                         else if( strncmp("message ", str, 8) == 0 ) {
316                                 tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
317                                 msg->locale = cur_locale;
318                                 msg->index = _get_token_uint16(str+8, &str);
319                                 if( !str )      continue ;
320                                 msg->string = str;
321                                 
322                                 //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
323                         }
324                         else if( strncmp("locale ", str, 7) == 0 ) {
325                                 // TODO: Set locale
326                                 cur_locale = 1;
327                         }
328                         else if( strncmp("region ", str, 7) == 0 ) {
329                                 udi_index_t rgn_idx = _get_token_idx(str+7, &str);
330                                 if( !str )      continue ;
331                                 // Search for region index (just in case internal_bind_ops appears earlier)
332                                 tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
333                                 if( rgn_idx > 0 )
334                                 {
335                                         rgn ++;
336                                         for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
337                                                 if( rgn->RegionIdx == rgn_idx )
338                                                         break;
339                                         }
340                                         if(i == next_unpop_region) {
341                                                 if( next_unpop_region == nRegionTypes ) {
342                                                         // TODO: warning if reigon types overflow
343                                                         continue ;
344                                                 }
345                                                 next_unpop_region ++;
346                                                 rgn->RegionIdx = rgn_idx;
347                                         }
348                                 }
349                                 // Parse attributes
350                                 while( *str )
351                                 {
352                                         int sym = _get_token_sym(str, &str,
353                                                 "type", "binding", "priority", "latency", "overrun_time", NULL
354                                                 );
355                                         if( !str )      break ;
356                                         switch(sym)
357                                         {
358                                         case 0: // type
359                                                 rgn->Type = _get_token_sym(str, &str, "normal", "fp", NULL);
360                                                 break;
361                                         case 1: // binding
362                                                 rgn->Binding = _get_token_sym(str, &str, "static", "dynamic", NULL);
363                                                 break;
364                                         case 2: // priority
365                                                 rgn->Priority = _get_token_sym(str, &str,
366                                                         "med", "lo", "hi", NULL);
367                                                 break;
368                                         case 3: // latency
369                                                 rgn->Latency = _get_token_sym(str, &str,
370                                                         "non_overrunable", "powerfail_warning", "overrunable",
371                                                         "retryable", "non_critical", NULL);
372                                                 break;
373                                         case 4: // overrun_time
374                                                 rgn->OverrunTime = _get_token_uint32(str, &str);
375                                                 break;
376                                         }
377                                         if( !str )      break ;
378                                 }
379                         }
380                         else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
381                                 tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
382                                 bind->meta_idx = _get_token_idx(str+16, &str);
383                                 if( !str )      continue ;
384                                 bind->region_idx = _get_token_idx(str, &str);
385                                 if( !str )      continue ;
386                                 bind->ops_idx = _get_token_idx(str, &str);
387                                 if( !str )      continue ;
388                                 bind->bind_cb_idx = _get_token_idx(str, &str);
389                                 if( *str ) {
390                                         // Expected EOL, didn't get it :(
391                                 }
392                                 Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
393                                         bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
394                         }
395                         else if( strncmp("internal_bind_ops ", str, 18) == 0 ) {
396                                 // Get region using index
397                                 udi_index_t meta = _get_token_idx(str+18, &str);
398                                 if( !str )      continue ;
399                                 udi_index_t rgn_idx = _get_token_idx(str, &str);
400                                 if( !str )      continue ;
401                                 
402                                 // Search for region index (just in case the relevant 'region' comes after)
403                                 tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
404                                 if( rgn_idx > 0 )
405                                 {
406                                         rgn ++;
407                                         for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
408                                                 if( rgn->RegionIdx == rgn_idx )
409                                                         break;
410                                         }
411                                         if(i == next_unpop_region) {
412                                                 if( next_unpop_region == nRegionTypes ) {
413                                                         // TODO: warning if reigon types overflow
414                                                         continue ;
415                                                 }
416                                                 next_unpop_region ++;
417                                                 rgn->RegionIdx = rgn_idx;
418                                         }
419                                 }
420                 
421                                 // Set properties
422                                 rgn->BindMeta = meta;
423                                 
424                                 rgn->PriBindOps = _get_token_idx(str, &str);
425                                 if( !str )      continue ;
426                                 rgn->SecBindOps = _get_token_idx(str, &str);
427                                 if( !str )      continue ;
428                                 rgn->BindCb = _get_token_idx(str, &str);
429                                 if( !str )      continue ;
430                                 if( *str ) {
431                                         // TODO: Please sir, I want an EOL
432                                 }
433                         }
434                         else {
435                                 Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
436                         }
437                 }
438                 
439                 // Sort message list
440                 // TODO: Sort message list
441         }
442
443          int    nSecondaryRgns = 0;
444         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
445                 nSecondaryRgns ++;
446         driver_module->nRegions = 1+nSecondaryRgns;
447
448         
449         // Check for orphan drivers, and create an instance of them when loaded
450         if( driver_module->nParents == 0 )
451         {
452                 tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
453         
454                 // Enumerate so any pre-loaded drivers are detected     
455                 UDI_int_BeginEnumeration(inst);
456         }
457         else
458         {
459                 // Send rescan requests to all loaded instances that support a parent metalang
460         }
461
462         return driver_module;
463 }
464
465 void UDI_int_DumpInitInfo(udi_init_t *info)
466 {
467         Log("primary_init_info = %p = {", info->primary_init_info);
468         {
469                 Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
470                 Log("  .usage_ind_op: %p() - 0x%02x",
471                         info->primary_init_info->mgmt_ops->usage_ind_op,
472                         info->primary_init_info->mgmt_op_flags[0]
473                         );
474                 Log("  .enumerate_req_op: %p() - 0x%02x",
475                         info->primary_init_info->mgmt_ops->enumerate_req_op,
476                         info->primary_init_info->mgmt_op_flags[1]
477                         );
478                 Log("  .devmgmt_req_op: %p() - 0x%02x",
479                         info->primary_init_info->mgmt_ops->devmgmt_req_op,
480                         info->primary_init_info->mgmt_op_flags[2]
481                         );
482                 Log("  .final_cleanup_req_op: %p() - 0x%02x",
483                         info->primary_init_info->mgmt_ops->final_cleanup_req_op,
484                         info->primary_init_info->mgmt_op_flags[3]
485                         );
486                 Log(" }");
487                 Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
488                 Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
489                 Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
490                 Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
491                 Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
492         }
493         Log("}");
494         Log("secondary_init_list = %p {", info->secondary_init_list);
495         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
496         {
497                 Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
498                         info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
499         }
500         Log("}");
501         Log("ops_init_list = %p {", info->ops_init_list);
502         for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
503         {
504                 Log(" [%i] = {", i);
505                 Log("  .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
506                 Log("  .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
507                 Log("  .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
508                 Log("  .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
509                 Log("  .ops_vector = %p", info->ops_init_list[i].ops_vector);
510 //              Log("  .op_flags = %p", info->ops_init_list[i].op_flags);
511                 Log(" }");
512         }
513         Log("}");
514         Log("cb_init_list = %p {", info->cb_init_list);
515         for( int i = 0; info->cb_init_list[i].cb_idx; i++ )
516         {
517                 udi_cb_init_t   *ent = &info->cb_init_list[i];
518                 Log(" [%i] = {", i);
519                 Log("  .cbidx = %i", ent->cb_idx);
520                 Log("  .meta_idx = %i", ent->meta_idx);
521                 Log("  .meta_cb_num = %i", ent->meta_cb_num);
522                 Log("  .scratch_requirement = 0x%x", ent->scratch_requirement);
523                 Log("  .inline_size = 0x%x", ent->inline_size);
524                 Log("  .inline_layout = %p", ent->inline_layout);
525                 Log(" }");
526         }
527 }
528
529 tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule)
530 {
531         tUDI_DriverInstance     *inst = NEW_wA(tUDI_DriverInstance, Regions, DriverModule->nRegions);
532         udi_primary_init_t      *pri_init = DriverModule->InitInfo->primary_init_info;
533         inst->Module = DriverModule;
534         inst->Regions[0] = UDI_InitRegion(inst, 0, 0, pri_init->rdata_size);
535         udi_secondary_init_t    *sec_init = DriverModule->InitInfo->secondary_init_list;
536         if( sec_init )
537         {
538                 for( int i = 0; sec_init[i].region_idx; i ++ )
539                 {
540                         inst->Regions[1+i] = UDI_InitRegion(inst, i,
541                                 sec_init[i].region_idx, sec_init[i].rdata_size);
542                 }
543         }
544
545         inst->ManagementChannel = UDI_CreateChannel_Blank(&cMetaLang_Management);
546         UDI_BindChannel_Raw(inst->ManagementChannel, true,
547                 0, inst->Regions[0]->InitContext, pri_init->mgmt_ops);
548 //      UDI_BindChannel_Raw(inst->ManagementChannel, false,
549 //              1, inst, &cUDI_ManagementMetaagent_Ops);        // TODO: ops list for management
550
551         for( int i = 0; i < DriverModule->nRegions; i ++ )
552                 Log("Rgn %i: %p", i, inst->Regions[i]);
553
554         // Send usage indication
555         char scratch[pri_init->mgmt_scratch_requirement];
556         {
557                 udi_usage_cb_t ucb;
558                 memset(&ucb, 0, sizeof(ucb));
559                 ucb.gcb.scratch = scratch;
560                 ucb.gcb.channel = inst->ManagementChannel;
561                 udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
562                 // TODO: Ensure that udi_usage_res is called
563         }
564         
565         for( int i = 1; i < DriverModule->nRegions; i ++ )
566         {
567                 //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank(
568                 // TODO: Bind secondaries to primary
569         }
570         
571         return inst;
572 }
573
574 tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize)
575 {
576 //      ASSERTCR( RDataSize, <=, UDI_MIN_ALLOC_LIMIT, NULL );
577         ASSERTCR( RDataSize, >=, sizeof(udi_init_context_t), NULL );
578         tUDI_DriverRegion       *rgn = NEW(tUDI_DriverRegion,+RDataSize);
579         rgn->InitContext = (void*)(rgn+1);
580         rgn->InitContext->region_idx = Type;
581 //      rgn->InitContext->limits
582         return rgn;
583 }
584
585 void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst)
586 {
587         udi_primary_init_t *pri_init = Inst->Module->InitInfo->primary_init_info;
588         char scratch[pri_init->mgmt_scratch_requirement];
589         udi_enumerate_cb_t      ecb;
590         memset(&ecb, 0, sizeof(ecb));
591         ecb.gcb.scratch = scratch;
592         ecb.gcb.channel = Inst->ManagementChannel;
593         ecb.child_data = malloc( pri_init->child_data_size);
594         ecb.attr_list = NEW(udi_instance_attr_list_t, *pri_init->enumeration_attr_list_length);
595         ecb.attr_valid_length = 0;
596         udi_enumerate_req(&ecb, UDI_ENUMERATE_START);
597 }
598
599 // TODO: Move this stuff out
600 udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
601 {
602         udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list;
603         while( ops->ops_idx && ops->ops_idx != index )
604                 ops ++;
605         if(ops->ops_idx == 0)
606                 return NULL;
607         return ops;
608 }
609
610 tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index)
611 {
612         if( index == 0 )
613                 return &cMetaLang_Management;
614         for( int i = 0; i < Inst->Module->nMetaLangs; i ++ )
615         {
616                 if( Inst->Module->MetaLangs[i].meta_idx == index )
617                         return Inst->Module->MetaLangs[i].metalang;
618         }
619         return NULL;
620 }
621
622 void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
623 {
624         udi_cb_init_t   *cb_init = NULL;
625         for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
626         {
627                 if( cb_init->cb_idx == bind_cb_idx )
628                 {
629                         udi_cb_t *ret = NEW(udi_cb_t, + cb_init->inline_size + cb_init->scratch_requirement);
630                         ret->channel = channel;
631                         return ret;
632                 }
633         }
634         Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
635                 bind_cb_idx, Inst->Module->ModuleName);
636         return NULL;
637         
638 }
639

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