7a61d81f3acce68b17d8f99921b48bba579e8bf8
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / main.c
1 /*
2  * Acess2 UDI Layer
3  * - By John Hodge (thePowersGang)
4  *
5  * main.c
6  * - UDI Entrypoint and Module loading
7  */
8 #define DEBUG   1
9 #define VERSION ((0<<8)|1)
10 #include <acess.h>
11 #include <modules.h>
12 #include <udi.h>
13 #include <udi_internal.h>
14 #include <udi_internal_ma.h>
15 #include <trans_pci.h>
16 #include <trans_nsr.h>
17 #include <trans_uart.h>
18
19 // === PROTOTYPES ===
20  int    UDI_Install(char **Arguments);
21  int    UDI_DetectDriver(void *Base);
22  int    UDI_LoadDriver(void *Base);
23 tUDI_DriverModule       *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size);
24 const tUDI_MetaLang     *UDI_int_GetMetaLangByName(const char *Name);
25
26 // === GLOBALS ===
27 MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
28 tModuleLoader   gUDI_Loader = {
29         NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL
30 };
31 tUDI_DriverModule       *gpUDI_LoadedModules;
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         Proc_SpawnWorker(UDI_int_DeferredThread, NULL);
43
44         UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
45         UDI_int_LoadDriver(NULL, &acessnsr_init, acessnsr_udiprops, acessnsr_udiprops_size);
46         UDI_int_LoadDriver(NULL, &acessuart_init, acessuart_udiprops, acessuart_udiprops_size);
47
48         return MODULE_ERR_OK;
49 }
50
51 /**
52  * \brief Detects if a driver should be loaded by the UDI subsystem
53  */
54 int UDI_DetectDriver(void *Base)
55 {
56         Uint    unused;
57         
58         if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) {
59                 return 0;
60         }
61         if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) {
62                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol");
63                 return 0;
64         }
65         if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) {
66                 Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol");
67                 return 0;
68         }
69         
70         return 1;
71 }
72
73 /**
74  * \fn int UDI_LoadDriver(void *Base)
75  */
76 int UDI_LoadDriver(void *Base)
77 {
78         udi_init_t      *info;
79         char    *udiprops = NULL;
80         char    *udiprops_end = 0;
81         
82         if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
83                 Binary_Unload(Base);
84                 return 0;
85         }
86         
87         Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops);
88         Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end);
89         Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
90
91         UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
92         
93         return 0;
94 }
95
96 static udi_boolean_t _get_token_bool(const char *str, const char **outstr)
97 {
98         udi_boolean_t   ret;
99         switch(*str++)
100         {
101         case 't':
102         case 'T':
103                 ret = 1;
104                 break;
105         case 'f':
106         case 'F':
107                 ret = 0;
108                 break;
109         default:
110                 *outstr = NULL;
111                 return 0;
112         }
113         while( isspace(*str) )
114                 str ++;
115         *outstr = str;
116         return ret;
117 }
118 static udi_index_t _get_token_idx(const char *str, const char **outstr)
119 {
120         char    *end;
121         int ret = strtol(str, &end, 10);
122         if( ret < 0 || ret > 255 ) {
123                 Log_Notice("UDI", "Value '%.*s' out of range for udi_index_t",
124                         end-str, str);
125                 *outstr = NULL;
126                 return 0;
127         }
128         if( *end && !isspace(*end) ) {
129                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
130                         end-str, str, *end);
131                 *outstr = NULL;
132                 return 0;
133         }
134         while( *end && isspace(*end) )
135                 end ++;
136         
137         *outstr = end;
138         return ret;
139 }
140 static udi_ubit16_t _get_token_uint16(const char *str, const char **outstr)
141 {
142         char    *end;
143         unsigned long ret = strtoul(str, &end, 10);
144         if( ret > 0xFFFF ) {
145                 Log_Notice("UDI", "Value '%.*s' out of range for udi_ubit16_t",
146                         end-str, str);
147                 *outstr = NULL;
148                 return 0;
149         }
150         if( *end && !isspace(*end) ) {
151                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
152                         end-str, str, *end);
153                 *outstr = NULL;
154                 return 0;
155         }
156         while( *end && isspace(*end) )
157                 end ++;
158         
159         *outstr = end;
160         return ret;
161 }
162 static udi_ubit32_t _get_token_uint32(const char *str, const char **outstr)
163 {
164         char    *end;
165         udi_ubit32_t ret = strtoul(str, &end, 0);
166         if( *end && !isspace(*end) ) {
167                 Log_Notice("UDI", "No whitespace following '%.*s', got '%c'",
168                         end-str, str, *end);
169                 *outstr = NULL;
170                 return 0;
171         }
172         while( *end && isspace(*end) )
173                 end ++;
174         
175         *outstr = end;
176         return ret;
177 }
178 static size_t _get_token_str(const char *str, const char **outstr, char *output)
179 {
180         size_t  ret = 0;
181         const char *pos = str;
182         while( *pos && !isspace(*pos) )
183         {
184                 if( *pos == '\\' )
185                 {
186                         pos ++;
187                         switch( *pos )
188                         {
189                         case '_':       // space
190                                 if(output)
191                                         output[ret] = ' ';
192                                 ret ++;
193                                 break;
194                         case 'H':       // hash
195                                 if(output)
196                                         output[ret] = '#';
197                                 ret ++;
198                                 break;
199                         case '\\':      // backslash
200                                 if(output)
201                                         output[ret] = '\\';
202                                 ret ++;
203                                 break;
204                         // TODO: \p and \m<msgnum> (for message/disaster_message only)
205                         default:
206                                 // Error
207                                 break;
208                         }
209                 }
210                 else {
211                         if(output)
212                                 output[ret] = *pos;
213                         ret ++;
214                 }
215                 pos ++;
216         }
217
218         while( isspace(*pos) )
219                 pos ++;
220         *outstr = pos;  
221
222         if(output)
223                 output[ret] = '\0';
224
225         return ret;
226 }
227 static int _get_token_sym_v(const char *str, const char **outstr, bool printError, const char **syms)
228 {
229         const char *sym;
230         for( int idx = 0; (sym = syms[idx]); idx ++ )
231         {
232                 size_t len = strlen(sym);
233                 if( memcmp(str, sym, len) != 0 )
234                         continue ;
235                 if( str[len] && !isspace(str[len]) )
236                         continue ;
237                 
238                 // Found it!
239                 str += len;
240                 while( isspace(*str) )
241                         str ++;
242                 *outstr = str;
243                 return idx;
244         }
245
246         // Unknown symbol, find the end of the symbol and error
247         const char *end = str;
248         while( !isspace(*end) )
249                 end ++;
250         
251         if( printError ) {
252                 Log_Notice("UDI", "Unknown token '%.*s'", end-str, str);
253         }
254
255         *outstr = NULL;
256         return -1;
257         
258 }
259 static int _get_token_sym(const char *str, const char **outstr, bool printError, ...)
260 {
261         va_list args;
262         const char *sym;
263          int    count = 0;
264         va_start(args, printError);
265         for( ; (sym = va_arg(args, const char *)); count ++ )
266                 ;
267         va_end(args);
268
269         const char      *symlist[count+1];      
270         va_start(args, printError);
271         for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
272                 symlist[idx] = sym;
273         symlist[count] = NULL;
274         
275         return _get_token_sym_v(str, outstr, printError, symlist);
276 }
277
278 enum {
279         UDIPROPS__properties_version,
280         UDIPROPS__module,
281         UDIPROPS__meta,
282         UDIPROPS__message,
283         UDIPROPS__locale,
284         UDIPROPS__region,
285         UDIPROPS__parent_bind_ops,
286         UDIPROPS__internal_bind_ops,
287         UDIPROPS__child_bind_ops,
288         UDIPROPS__supplier,
289         UDIPROPS__contact,
290         UDIPROPS__name,
291         UDIPROPS__shortname,
292         UDIPROPS__release,
293         
294         UDIPROPS__requires,
295         UDIPROPS__device,
296         UDIPROPS__enumerates,
297
298         UDIPROPS_last
299 };
300 #define _defpropname(name)      [ UDIPROPS__##name ] = #name
301 const char *caUDI_UdipropsNames[] = {
302         _defpropname(properties_version),
303         _defpropname(module),
304         _defpropname(meta),
305         _defpropname(message),
306         _defpropname(locale),
307         _defpropname(region),
308         _defpropname(parent_bind_ops),
309         _defpropname(internal_bind_ops),
310         _defpropname(child_bind_ops),
311         _defpropname(supplier),
312         _defpropname(contact),
313         _defpropname(name),
314         _defpropname(shortname),
315         _defpropname(release),
316         _defpropname(requires),
317         
318         _defpropname(device),
319         _defpropname(enumerates),
320         
321         [UDIPROPS_last] = NULL
322 };
323 #undef _defpropname
324
325 tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size)
326 {
327         //UDI_int_DumpInitInfo(info);
328         
329         // TODO: Multiple modules?
330         tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,);
331         driver_module->InitInfo = info;
332
333         // - Parse udiprops
334         const char      **udipropsptrs;
335         
336         int nLines = 1;
337         for( int i = 0; i < udiprops_size; i++ )
338         {
339                 if( udiprops[i] == '\0' )
340                         nLines ++;
341         }
342         
343         Log_Debug("UDI", "nLines = %i", nLines);
344         
345         udipropsptrs = NEW(const char*,*nLines);
346         int line = 0;
347         udipropsptrs[line++] = udiprops;
348         for( int i = 0; i < udiprops_size; i++ )
349         {
350                 if( udiprops[i] == '\0' ) {
351                         udipropsptrs[line++] = &udiprops[i+1];
352                 }
353         }
354         if(udipropsptrs[line-1] == &udiprops[udiprops_size])
355                 nLines --;
356         
357         // Parse out:
358         // 'message' into driver_module->Messages
359         // 'region' into driver_module->RegionTypes
360         // 'module' into driver_module->ModuleName
361         
362          int    nLocales = 1;
363         for( int i = 0; i < nLines; i ++ )
364         {
365                 const char *str = udipropsptrs[i];
366                  int    sym = _get_token_sym_v(str, &str, false, caUDI_UdipropsNames);
367                 switch(sym)
368                 {
369                 case UDIPROPS__module:
370                         driver_module->ModuleName = str;
371                         break;
372                 case UDIPROPS__meta:
373                         driver_module->nMetaLangs ++;
374                         break;
375                 case UDIPROPS__message:
376                         driver_module->nMessages ++;
377                         break;
378                 case UDIPROPS__locale:
379                         nLocales ++;
380                         break;
381                 case UDIPROPS__region:
382                         driver_module->nRegionTypes ++;
383                         break;
384                 case UDIPROPS__device:
385                         driver_module->nDevices ++;
386                         break;
387                 case UDIPROPS__parent_bind_ops:
388                         driver_module->nParents ++;
389                         break;
390                 case UDIPROPS__child_bind_ops:
391                         driver_module->nChildBindOps ++;
392                         break;
393                 default:
394                         // quiet ignore
395                         break;
396                 }
397         }
398
399         // Allocate structures
400         LOG("nMessages = %i, nMetaLangs = %i",
401                 driver_module->nMessages,
402                 driver_module->nMetaLangs);
403         driver_module->Messages     = NEW(tUDI_PropMessage, * driver_module->nMessages);
404         driver_module->RegionTypes  = NEW(tUDI_PropRegion,  * driver_module->nRegionTypes);
405         driver_module->MetaLangs    = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
406         driver_module->Parents      = NEW(tUDI_BindOps,     * driver_module->nParents);
407         driver_module->ChildBindOps = NEW(tUDI_BindOps,     * driver_module->nChildBindOps);
408         driver_module->Devices      = NEW(tUDI_PropDevSpec*,* driver_module->nDevices);
409
410         // Populate
411         bool    error_hit = false;
412          int    cur_locale = 0;
413          int    msg_index = 0;
414          int    ml_index = 0;
415          int    parent_index = 0;
416          int    child_bind_index = 0;
417          int    device_index = 0;
418          int    next_unpop_region = 1;
419         for( int i = 0; i < nLines; i ++ )
420         {
421                 const char *str = udipropsptrs[i];
422                 if( !*str )
423                         continue ;
424                  int    sym = _get_token_sym_v(str, &str, true, caUDI_UdipropsNames);
425                 switch(sym)
426                 {
427                 case UDIPROPS__properties_version:
428                         if( _get_token_uint32(str, &str) != 0x101 ) {
429                                 Log_Warning("UDI", "Properties version mismatch.");
430                                 error_hit = true;
431                         }
432                         break;
433                 case UDIPROPS__module:
434                         driver_module->ModuleName = str;
435                         break;
436                 case UDIPROPS__meta: {
437                         tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
438                         ml->meta_idx = _get_token_idx(str, &str);
439                         if( !str )      continue;
440                         ml->interface_name = str;
441                         // TODO: May need to trim trailing spaces
442                         ml->metalang = UDI_int_GetMetaLangByName(ml->interface_name);
443                         if( !ml->metalang ) {
444                                 Log_Error("UDI", "Module %s referenced unsupported metalang %s",
445                                         driver_module->ModuleName, ml->interface_name);
446                                 error_hit = true;
447                                 // TODO: error
448                         }
449                         break; }
450                 case UDIPROPS__message:
451                         {
452                         tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
453                         msg->locale = cur_locale;
454                         msg->index = _get_token_uint16(str, &str);
455                         if( !str )      continue ;
456                         msg->string = str;
457                         //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
458                         break;
459                         }
460                 case UDIPROPS__locale:
461                         // TODO: Set locale
462                         cur_locale = 1;
463                         break;
464                 case UDIPROPS__region:
465                         {
466                         udi_index_t rgn_idx = _get_token_idx(str, &str);
467                         if( !str )      continue ;
468                         // Search for region index (just in case internal_bind_ops appears earlier)
469                         tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
470                         if( rgn_idx > 0 )
471                         {
472                                 rgn ++;
473                                 for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
474                                         if( rgn->RegionIdx == rgn_idx )
475                                                 break;
476                                 }
477                                 if(i == next_unpop_region) {
478                                         if( next_unpop_region == driver_module->nRegionTypes ) {
479                                                 // TODO: warning if reigon types overflow
480                                                 continue ;
481                                         }
482                                         next_unpop_region ++;
483                                         rgn->RegionIdx = rgn_idx;
484                                 }
485                         }
486                         // Parse attributes
487                         while( *str )
488                         {
489                                 int sym = _get_token_sym(str, &str, true,
490                                         "type", "binding", "priority", "latency", "overrun_time", NULL
491                                         );
492                                 if( !str )      break ;
493                                 switch(sym)
494                                 {
495                                 case 0: // type
496                                         rgn->Type = _get_token_sym(str, &str, true,
497                                                 "normal", "fp", NULL);
498                                         break;
499                                 case 1: // binding
500                                         rgn->Binding = _get_token_sym(str, &str, true,
501                                                 "static", "dynamic", NULL);
502                                         break;
503                                 case 2: // priority
504                                         rgn->Priority = _get_token_sym(str, &str, true,
505                                                 "med", "lo", "hi", NULL);
506                                         break;
507                                 case 3: // latency
508                                         rgn->Latency = _get_token_sym(str, &str, true,
509                                                 "non_overrunable", "powerfail_warning", "overrunable",
510                                                 "retryable", "non_critical", NULL);
511                                         break;
512                                 case 4: // overrun_time
513                                         rgn->OverrunTime = _get_token_uint32(str, &str);
514                                         break;
515                                 }
516                                 if( !str )      break ;
517                         }
518                         break;
519                         }
520                 case UDIPROPS__parent_bind_ops:
521                         {
522                         tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
523                         bind->meta_idx = _get_token_idx(str, &str);
524                         if( !str )      continue ;
525                         bind->region_idx = _get_token_idx(str, &str);
526                         if( !str )      continue ;
527                         bind->ops_idx = _get_token_idx(str, &str);
528                         if( !str )      continue ;
529                         bind->bind_cb_idx = _get_token_idx(str, &str);
530                         if( *str ) {
531                                 // Expected EOL, didn't get it :(
532                         }
533                         Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
534                                 bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
535                         break;
536                         }
537                 case UDIPROPS__internal_bind_ops:
538                         {
539                         // Get region using index
540                         udi_index_t meta = _get_token_idx(str, &str);
541                         if( !str )      continue ;
542                         udi_index_t rgn_idx = _get_token_idx(str, &str);
543                         if( !str )      continue ;
544                         
545                         // Search for region index (just in case the relevant 'region' comes after)
546                         tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
547                         if( rgn_idx > 0 )
548                         {
549                                 rgn ++;
550                                  int    j;
551                                 for( j = 1; j < next_unpop_region; j ++, rgn ++ ) {
552                                         if( rgn->RegionIdx == rgn_idx )
553                                                 break;
554                                 }
555                                 if( j == next_unpop_region ) {
556                                         if( next_unpop_region == driver_module->nRegionTypes ) {
557                                                 // TODO: warning if reigon types overflow
558                                                 continue ;
559                                         }
560                                         next_unpop_region ++;
561                                         rgn->RegionIdx = rgn_idx;
562                                 }
563                         }
564         
565                         // Set properties
566                         rgn->BindMeta = meta;
567                         
568                         rgn->PriBindOps = _get_token_idx(str, &str);
569                         if( !str )      continue ;
570                         rgn->SecBindOps = _get_token_idx(str, &str);
571                         if( !str )      continue ;
572                         rgn->BindCb = _get_token_idx(str, &str);
573                         if( !str )      continue ;
574                         if( *str ) {
575                                 // TODO: Please sir, I want an EOL
576                         }
577                         break;
578                         }
579                 case UDIPROPS__child_bind_ops:
580                         {
581                         tUDI_BindOps    *bind = &driver_module->ChildBindOps[child_bind_index++];
582                         bind->meta_idx = _get_token_idx(str, &str);
583                         if( !str )      continue ;
584                         bind->region_idx = _get_token_idx(str, &str);
585                         if( !str )      continue ;
586                         bind->ops_idx = _get_token_idx(str, &str);
587                         if( *str ) {
588                                 // Expected EOL, didn't get it :(
589                         }
590                         Log_Debug("UDI", "Child bind - meta:%i,rgn:%i,ops:%i",
591                                 bind->meta_idx, bind->region_idx, bind->ops_idx);
592                         break;
593                         }
594                 case UDIPROPS__supplier:
595                 case UDIPROPS__contact:
596                 case UDIPROPS__name:
597                 case UDIPROPS__shortname:
598                 case UDIPROPS__release:
599                         break;
600                 //case UDIPROPS__requires:
601                 //      // TODO: Requires
602                 //      break;
603                 case UDIPROPS__device:
604                         {
605                          int    n_attr = 0;
606                         // Count properties (and validate)
607                         _get_token_idx(str, &str);      // message
608                         if( !str )      continue;
609                         _get_token_idx(str, &str);      // meta
610                         if( !str )      continue;
611                         while( *str )
612                         {
613                                 _get_token_str(str, &str, NULL);
614                                 if( !str )      break;
615                                 _get_token_sym(str, &str, true, "string", "ubit32", "boolean", "array", NULL);
616                                 if( !str )      break;
617                                 _get_token_str(str, &str, NULL);
618                                 if( !str )      break;
619                                 n_attr ++;
620                         }
621                         // Rewind and actually parse
622                         _get_token_str(udipropsptrs[i], &str, NULL);
623                         
624                         tUDI_PropDevSpec *dev = NEW_wA(tUDI_PropDevSpec, Attribs, n_attr);
625                         driver_module->Devices[device_index++] = dev;;
626                         dev->MessageNum = _get_token_idx(str, &str);
627                         dev->MetaIdx = _get_token_idx(str, &str);
628                         dev->nAttribs = n_attr;
629                         n_attr = 0;
630                         while( *str )
631                         {
632                                 udi_instance_attr_list_t *at = &dev->Attribs[n_attr];
633                                 _get_token_str(str, &str, at->attr_name);
634                                 if( !str )      break;
635                                 at->attr_type = _get_token_sym(str, &str, true,
636                                         " ", "string", "array", "ubit32", "boolean", NULL);
637                                 if( !str )      break;
638                                 udi_ubit32_t    val;
639                                 switch( dev->Attribs[n_attr].attr_type )
640                                 {
641                                 case 1: // String
642                                         at->attr_length = _get_token_str(str, &str, (char*)at->attr_value);
643                                         break;
644                                 case 2: // Array
645                                         // TODO: Array
646                                         Log_Warning("UDI", "TODO: Parse 'array' attribute in 'device'");
647                                         _get_token_str(str, &str, NULL);
648                                         error_hit = true;
649                                         break;
650                                 case 3: // ubit32
651                                         at->attr_length = sizeof(udi_ubit32_t);
652                                         val = _get_token_uint32(str, &str);
653                                         Log_Debug("UDI", "device %i: Value '%s'=%x", device_index,
654                                                 at->attr_name, val);
655                                         UDI_ATTR32_SET(at->attr_value, val);
656                                         break;
657                                 case 4: // boolean
658                                         at->attr_length = sizeof(udi_boolean_t);
659                                         UDI_ATTR32_SET(at->attr_value, _get_token_bool(str, &str));
660                                         break;
661                                 }
662                                 if( !str )      break;
663                                 n_attr ++;
664                         }
665                         
666                         break;
667                         }
668                 default:
669                         Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
670                         break;
671                 }
672         }
673         free(udipropsptrs);
674         if( error_hit ) {
675                 Log_Error("UDI", "Error encountered while parsing udiprops for '%s' (%p), bailing",
676                         driver_module->ModuleName, LoadBase);
677                 for( int i = 0; i < device_index; i ++ )
678                         free(driver_module->Devices[i]);
679                 free(driver_module->Messages);
680                 free(driver_module->RegionTypes);
681                 free(driver_module->MetaLangs);
682                 free(driver_module->Parents);
683                 free(driver_module->ChildBindOps);
684                 free(driver_module->Devices);
685                 free(driver_module);
686                 return NULL;
687         }
688
689         for( int i = 0; i < driver_module->nDevices; i ++ )
690                 driver_module->Devices[i]->Metalang = UDI_int_GetMetaLang(driver_module,
691                         driver_module->Devices[i]->MetaIdx);
692         
693         // Sort message list
694         // TODO: Sort message list
695
696          int    nSecondaryRgns = 0;
697         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
698                 nSecondaryRgns ++;
699         driver_module->nRegions = 1+nSecondaryRgns;
700
701         
702         // -- Add to loaded module list
703         driver_module->Next = gpUDI_LoadedModules;
704         gpUDI_LoadedModules = driver_module;
705         
706         // Check for orphan drivers, and create an instance of them when loaded
707         if( driver_module->nParents == 0 )
708         {
709                 UDI_MA_CreateInstance(driver_module, NULL, NULL);
710         }
711         else
712         {
713                 // Search running instances for unbound children that can be bound to this driver
714                 UDI_MA_BindParents(driver_module);
715         }
716
717         return driver_module;
718 }
719
720 void UDI_int_DumpInitInfo(udi_init_t *info)
721 {
722         Log("primary_init_info = %p = {", info->primary_init_info);
723         {
724                 Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
725                 Log("  .usage_ind_op: %p() - 0x%02x",
726                         info->primary_init_info->mgmt_ops->usage_ind_op,
727                         info->primary_init_info->mgmt_op_flags[0]
728                         );
729                 Log("  .enumerate_req_op: %p() - 0x%02x",
730                         info->primary_init_info->mgmt_ops->enumerate_req_op,
731                         info->primary_init_info->mgmt_op_flags[1]
732                         );
733                 Log("  .devmgmt_req_op: %p() - 0x%02x",
734                         info->primary_init_info->mgmt_ops->devmgmt_req_op,
735                         info->primary_init_info->mgmt_op_flags[2]
736                         );
737                 Log("  .final_cleanup_req_op: %p() - 0x%02x",
738                         info->primary_init_info->mgmt_ops->final_cleanup_req_op,
739                         info->primary_init_info->mgmt_op_flags[3]
740                         );
741                 Log(" }");
742                 Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
743                 Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
744                 Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
745                 Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
746                 Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
747         }
748         Log("}");
749         Log("secondary_init_list = %p {", info->secondary_init_list);
750         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
751         {
752                 Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
753                         info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
754         }
755         Log("}");
756         Log("ops_init_list = %p {", info->ops_init_list);
757         for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
758         {
759                 Log(" [%i] = {", i);
760                 Log("  .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
761                 Log("  .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
762                 Log("  .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
763                 Log("  .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
764                 Log("  .ops_vector = %p", info->ops_init_list[i].ops_vector);
765 //              Log("  .op_flags = %p", info->ops_init_list[i].op_flags);
766                 Log(" }");
767         }
768         Log("}");
769         Log("cb_init_list = %p {", info->cb_init_list);
770         for( int i = 0; info->cb_init_list[i].cb_idx; i++ )
771         {
772                 udi_cb_init_t   *ent = &info->cb_init_list[i];
773                 Log(" [%i] = {", i);
774                 Log("  .cbidx = %i", ent->cb_idx);
775                 Log("  .meta_idx = %i", ent->meta_idx);
776                 Log("  .meta_cb_num = %i", ent->meta_cb_num);
777                 Log("  .scratch_requirement = 0x%x", ent->scratch_requirement);
778                 Log("  .inline_size = 0x%x", ent->inline_size);
779                 Log("  .inline_layout = %p", ent->inline_layout);
780                 Log(" }");
781         }
782 }
783
784 // TODO: Move this stuff out
785 udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
786 {
787         udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list;
788         while( ops->ops_idx && ops->ops_idx != index )
789                 ops ++;
790         if(ops->ops_idx == 0)
791                 return NULL;
792         return ops;
793 }
794
795 tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverModule *Module, udi_index_t index)
796 {
797         if( index == 0 )
798                 return &cMetaLang_Management;
799         ASSERT(Module);
800         for( int i = 0; i < Module->nMetaLangs; i ++ )
801         {
802                 if( Module->MetaLangs[i].meta_idx == index )
803                         return Module->MetaLangs[i].metalang;
804         }
805         return NULL;
806 }
807
808 const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name)
809 {
810         //extern tUDI_MetaLang  cMetaLang_Management;
811         extern tUDI_MetaLang    cMetaLang_BusBridge;
812         extern tUDI_MetaLang    cMetaLang_GIO;
813         extern tUDI_MetaLang    cMetaLang_NIC;
814         const tUDI_MetaLang     *langs[] = {
815                 &cMetaLang_BusBridge,
816                 &cMetaLang_GIO,
817                 &cMetaLang_NIC,
818                 NULL
819         };
820         for( int i = 0; langs[i]; i ++ )
821         {
822                 if( strcmp(Name, langs[i]->Name) == 0 )
823                         return langs[i];
824         }
825         return NULL;
826 }
827

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