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

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