Merge branch 'master' of ssh.ucc.asn.au:tpg/acess2
[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         unsigned long ret = strtoul(str, &end, 10);
125         if( ret > 255 ) {
126                 Log_Notice("UDI", "Value '%.*s' (0x%lx) out of range for udi_index_t",
127                         end-str, str, ret);
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' (0x%lx) out of range for udi_ubit16_t",
149                         end-str, str, ret);
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         #define IF_ERROR(op)    if(!str){error_hit=1;op;}
423         for( int i = 0; i < nLines; i ++ )
424         {
425                 const char *str = udipropsptrs[i];
426                 if( !*str )
427                         continue ;
428                  int    sym = _get_token_sym_v(str, &str, true, caUDI_UdipropsNames);
429                 //LOG("Processing option '%s'", (sym >= 0 ? caUDI_UdipropsNames[sym] : "ERR"));
430                 switch(sym)
431                 {
432                 case UDIPROPS__properties_version:
433                         if( _get_token_uint32(str, &str) != 0x101 ) {
434                                 Log_Warning("UDI", "Properties version mismatch.");
435                                 error_hit = true;
436                         }
437                         break;
438                 case UDIPROPS__module:
439                         driver_module->ModuleName = str;
440                         break;
441                 case UDIPROPS__meta: {
442                         tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
443                         ml->meta_idx = _get_token_idx(str, &str);
444                         IF_ERROR(continue);
445                         ml->interface_name = str;
446                         // TODO: May need to trim trailing spaces
447                         ml->metalang = UDI_int_GetMetaLangByName(ml->interface_name);
448                         if( !ml->metalang ) {
449                                 Log_Error("UDI", "Module %s referenced unsupported metalang %s",
450                                         driver_module->ModuleName, ml->interface_name);
451                                 error_hit = true;
452                                 // TODO: error
453                         }
454                         break; }
455                 case UDIPROPS__message:
456                         {
457                         tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
458                         msg->locale = cur_locale;
459                         msg->index = _get_token_uint16(str, &str);
460                         IF_ERROR(continue);
461                         msg->string = str;
462                         //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
463                         break;
464                         }
465                 case UDIPROPS__locale:
466                         // TODO: Set locale
467                         cur_locale = 1;
468                         break;
469                 case UDIPROPS__region:
470                         {
471                         udi_index_t rgn_idx = _get_token_idx(str, &str);
472                         IF_ERROR(continue);
473                         // Search for region index (just in case internal_bind_ops appears earlier)
474                         tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
475                         if( rgn_idx > 0 )
476                         {
477                                 rgn ++;
478                                 for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
479                                         if( rgn->RegionIdx == rgn_idx )
480                                                 break;
481                                 }
482                                 if(i == next_unpop_region) {
483                                         if( next_unpop_region == driver_module->nRegionTypes ) {
484                                                 // TODO: warning if reigon types overflow
485                                                 continue ;
486                                         }
487                                         next_unpop_region ++;
488                                         rgn->RegionIdx = rgn_idx;
489                                 }
490                         }
491                         // Parse attributes
492                         while( *str )
493                         {
494                                 int sym = _get_token_sym(str, &str, true,
495                                         "type", "binding", "priority", "latency", "overrun_time", NULL
496                                         );
497                                 if( !str )      break ;
498                                 switch(sym)
499                                 {
500                                 case 0: // type
501                                         rgn->Type = _get_token_sym(str, &str, true,
502                                                 "normal", "fp", NULL);
503                                         break;
504                                 case 1: // binding
505                                         rgn->Binding = _get_token_sym(str, &str, true,
506                                                 "static", "dynamic", NULL);
507                                         break;
508                                 case 2: // priority
509                                         rgn->Priority = _get_token_sym(str, &str, true,
510                                                 "med", "lo", "hi", NULL);
511                                         break;
512                                 case 3: // latency
513                                         rgn->Latency = _get_token_sym(str, &str, true,
514                                                 "non_overrunable", "powerfail_warning", "overrunable",
515                                                 "retryable", "non_critical", NULL);
516                                         break;
517                                 case 4: // overrun_time
518                                         rgn->OverrunTime = _get_token_uint32(str, &str);
519                                         break;
520                                 }
521                                 IF_ERROR(break);
522                         }
523                         break;
524                         }
525                 case UDIPROPS__parent_bind_ops:
526                         {
527                         tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
528                         bind->meta_idx = _get_token_idx(str, &str);
529                         IF_ERROR(continue);
530                         bind->region_idx = _get_token_idx(str, &str);
531                         IF_ERROR(continue);
532                         bind->ops_idx = _get_token_idx(str, &str);
533                         IF_ERROR(continue);
534                         bind->bind_cb_idx = _get_token_idx(str, &str);
535                         IF_ERROR(continue);
536                         if( *str ) {
537                                 // Expected EOL, didn't get it :(
538                         }
539                         Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
540                                 bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
541                         break;
542                         }
543                 case UDIPROPS__internal_bind_ops:
544                         {
545                         // Get region using index
546                         udi_index_t meta = _get_token_idx(str, &str);
547                         IF_ERROR(continue);
548                         udi_index_t rgn_idx = _get_token_idx(str, &str);
549                         IF_ERROR(continue);
550                         
551                         // Search for region index (just in case the relevant 'region' comes after)
552                         tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
553                         if( rgn_idx > 0 )
554                         {
555                                 rgn ++;
556                                  int    j;
557                                 for( j = 1; j < next_unpop_region; j ++, rgn ++ ) {
558                                         if( rgn->RegionIdx == rgn_idx )
559                                                 break;
560                                 }
561                                 if( j == next_unpop_region ) {
562                                         if( next_unpop_region == driver_module->nRegionTypes ) {
563                                                 // TODO: warning if reigon types overflow
564                                                 continue ;
565                                         }
566                                         next_unpop_region ++;
567                                         rgn->RegionIdx = rgn_idx;
568                                 }
569                         }
570         
571                         // Set properties
572                         rgn->BindMeta = meta;
573                         
574                         rgn->PriBindOps = _get_token_idx(str, &str);
575                         IF_ERROR(continue);
576                         rgn->SecBindOps = _get_token_idx(str, &str);
577                         IF_ERROR(continue);
578                         rgn->BindCb = _get_token_idx(str, &str);
579                         IF_ERROR(continue);
580                         if( *str ) {
581                                 // TODO: Please sir, I want an EOL
582                         }
583                         break;
584                         }
585                 case UDIPROPS__child_bind_ops:
586                         {
587                         tUDI_BindOps    *bind = &driver_module->ChildBindOps[child_bind_index++];
588                         bind->meta_idx = _get_token_idx(str, &str);
589                         IF_ERROR(continue);
590                         bind->region_idx = _get_token_idx(str, &str);
591                         IF_ERROR(continue);
592                         bind->ops_idx = _get_token_idx(str, &str);
593                         IF_ERROR(continue);
594                         if( *str ) {
595                                 // Expected EOL, didn't get it :(
596                         }
597                         Log_Debug("UDI", "Child bind - meta:%i,rgn:%i,ops:%i",
598                                 bind->meta_idx, bind->region_idx, bind->ops_idx);
599                         break;
600                         }
601                 case UDIPROPS__supplier:
602                 case UDIPROPS__contact:
603                 case UDIPROPS__name:
604                 case UDIPROPS__shortname:
605                 case UDIPROPS__release:
606                         break;
607                 //case UDIPROPS__requires:
608                 //      // TODO: Requires
609                 //      break;
610                 case UDIPROPS__device:
611                         {
612                          int    n_attr = 0;
613                         // Count properties (and validate)
614                         _get_token_uint16(str, &str);   // message
615                         IF_ERROR(continue);
616                         _get_token_idx(str, &str);      // meta
617                         IF_ERROR(continue);
618                         while( *str )
619                         {
620                                 _get_token_str(str, &str, NULL);
621                                 IF_ERROR(break);
622                                 _get_token_sym(str, &str, true, "string", "ubit32", "boolean", "array", NULL);
623                                 IF_ERROR(break);
624                                 _get_token_str(str, &str, NULL);
625                                 IF_ERROR(break);
626                                 n_attr ++;
627                         }
628                         // Rewind and actually parse
629                         // - Eat the 'device' token and hence reset 'str'
630                         _get_token_str(udipropsptrs[i], &str, NULL);
631                         
632                         tUDI_PropDevSpec *dev = NEW_wA(tUDI_PropDevSpec, Attribs, n_attr);
633                         driver_module->Devices[device_index++] = dev;;
634                         dev->MessageNum = _get_token_uint16(str, &str);
635                         dev->MetaIdx = _get_token_idx(str, &str);
636                         dev->nAttribs = n_attr;
637                         n_attr = 0;
638                         while( *str )
639                         {
640                                 udi_instance_attr_list_t *at = &dev->Attribs[n_attr];
641                                 _get_token_str(str, &str, at->attr_name);
642                                 IF_ERROR(break);
643                                 at->attr_type = _get_token_sym(str, &str, true,
644                                         " ", "string", "array", "ubit32", "boolean", NULL);
645                                 IF_ERROR(break);
646                                 udi_ubit32_t    val;
647                                 switch( dev->Attribs[n_attr].attr_type )
648                                 {
649                                 case 1: // String
650                                         at->attr_length = _get_token_str(str, &str, (char*)at->attr_value);
651                                         break;
652                                 case 2: // Array
653                                         // TODO: Array
654                                         Log_Warning("UDI", "TODO: Parse 'array' attribute in 'device'");
655                                         _get_token_str(str, &str, NULL);
656                                         error_hit = true;
657                                         break;
658                                 case 3: // ubit32
659                                         at->attr_length = sizeof(udi_ubit32_t);
660                                         val = _get_token_uint32(str, &str);
661                                         Log_Debug("UDI", "device %i: Value '%s'=%x", device_index,
662                                                 at->attr_name, val);
663                                         UDI_ATTR32_SET(at->attr_value, val);
664                                         break;
665                                 case 4: // boolean
666                                         at->attr_length = sizeof(udi_boolean_t);
667                                         UDI_ATTR32_SET(at->attr_value, _get_token_bool(str, &str));
668                                         break;
669                                 }
670                                 IF_ERROR(break);
671                                 n_attr ++;
672                         }
673                         
674                         break;
675                         }
676                 default:
677                         Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
678                         break;
679                 }
680         }
681         free(udipropsptrs);
682         if( error_hit ) {
683                 Log_Error("UDI", "Error encountered while parsing udiprops for '%s' (LoadBase=%p), bailing",
684                         driver_module->ModuleName, LoadBase);
685                 for( int i = 0; i < device_index; i ++ )
686                         free(driver_module->Devices[i]);
687                 free(driver_module->Messages);
688                 free(driver_module->RegionTypes);
689                 free(driver_module->MetaLangs);
690                 free(driver_module->Parents);
691                 free(driver_module->ChildBindOps);
692                 free(driver_module->Devices);
693                 free(driver_module);
694                 return NULL;
695         }
696         ASSERTC(device_index, ==, driver_module->nDevices);
697
698         for( int i = 0; i < driver_module->nDevices; i ++ ) {
699                 ASSERT(driver_module);
700                 ASSERT(driver_module->Devices[i]);
701                 driver_module->Devices[i]->Metalang = UDI_int_GetMetaLang(driver_module,
702                         driver_module->Devices[i]->MetaIdx);
703         }
704         
705         // Sort message list
706         // TODO: Sort message list
707
708          int    nSecondaryRgns = 0;
709         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
710                 nSecondaryRgns ++;
711         driver_module->nRegions = 1+nSecondaryRgns;
712
713         
714         // -- Add to loaded module list
715         driver_module->Next = gpUDI_LoadedModules;
716         gpUDI_LoadedModules = driver_module;
717         
718         // Check for orphan drivers, and create an instance of them when loaded
719         if( driver_module->nParents == 0 )
720         {
721                 UDI_MA_CreateInstance(driver_module, NULL, NULL);
722         }
723         else
724         {
725                 // Search running instances for unbound children that can be bound to this driver
726                 UDI_MA_BindParents(driver_module);
727         }
728
729         return driver_module;
730 }
731
732 void UDI_int_DumpInitInfo(udi_init_t *info)
733 {
734         Log("primary_init_info = %p = {", info->primary_init_info);
735         {
736                 Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
737                 Log("  .usage_ind_op: %p() - 0x%02x",
738                         info->primary_init_info->mgmt_ops->usage_ind_op,
739                         info->primary_init_info->mgmt_op_flags[0]
740                         );
741                 Log("  .enumerate_req_op: %p() - 0x%02x",
742                         info->primary_init_info->mgmt_ops->enumerate_req_op,
743                         info->primary_init_info->mgmt_op_flags[1]
744                         );
745                 Log("  .devmgmt_req_op: %p() - 0x%02x",
746                         info->primary_init_info->mgmt_ops->devmgmt_req_op,
747                         info->primary_init_info->mgmt_op_flags[2]
748                         );
749                 Log("  .final_cleanup_req_op: %p() - 0x%02x",
750                         info->primary_init_info->mgmt_ops->final_cleanup_req_op,
751                         info->primary_init_info->mgmt_op_flags[3]
752                         );
753                 Log(" }");
754                 Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
755                 Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
756                 Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
757                 Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
758                 Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
759         }
760         Log("}");
761         Log("secondary_init_list = %p {", info->secondary_init_list);
762         for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
763         {
764                 Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }",
765                         info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size);
766         }
767         Log("}");
768         Log("ops_init_list = %p {", info->ops_init_list);
769         for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
770         {
771                 Log(" [%i] = {", i);
772                 Log("  .ops_idx = 0x%x", info->ops_init_list[i].ops_idx);
773                 Log("  .meta_idx = 0x%x", info->ops_init_list[i].meta_idx);
774                 Log("  .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num);
775                 Log("  .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size);
776                 Log("  .ops_vector = %p", info->ops_init_list[i].ops_vector);
777 //              Log("  .op_flags = %p", info->ops_init_list[i].op_flags);
778                 Log(" }");
779         }
780         Log("}");
781         Log("cb_init_list = %p {", info->cb_init_list);
782         for( int i = 0; info->cb_init_list[i].cb_idx; i++ )
783         {
784                 udi_cb_init_t   *ent = &info->cb_init_list[i];
785                 Log(" [%i] = {", i);
786                 Log("  .cbidx = %i", ent->cb_idx);
787                 Log("  .meta_idx = %i", ent->meta_idx);
788                 Log("  .meta_cb_num = %i", ent->meta_cb_num);
789                 Log("  .scratch_requirement = 0x%x", ent->scratch_requirement);
790                 Log("  .inline_size = 0x%x", ent->inline_size);
791                 Log("  .inline_layout = %p", ent->inline_layout);
792                 Log(" }");
793         }
794 }
795
796 // TODO: Move this stuff out
797 udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
798 {
799         udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list;
800         while( ops->ops_idx && ops->ops_idx != index )
801                 ops ++;
802         if(ops->ops_idx == 0)
803                 return NULL;
804         return ops;
805 }
806
807 tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverModule *Module, udi_index_t index)
808 {
809         if( index == 0 )
810                 return &cMetaLang_Management;
811         ASSERT(Module);
812         for( int i = 0; i < Module->nMetaLangs; i ++ )
813         {
814                 if( Module->MetaLangs[i].meta_idx == index )
815                         return Module->MetaLangs[i].metalang;
816         }
817         return NULL;
818 }
819
820 const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name)
821 {
822         //extern tUDI_MetaLang  cMetaLang_Management;
823         extern tUDI_MetaLang    cMetaLang_BusBridge;
824         extern tUDI_MetaLang    cMetaLang_GIO;
825         extern tUDI_MetaLang    cMetaLang_NIC;
826         const tUDI_MetaLang     *langs[] = {
827                 &cMetaLang_BusBridge,
828                 &cMetaLang_GIO,
829                 &cMetaLang_NIC,
830                 NULL
831         };
832         for( int i = 0; langs[i]; i ++ )
833         {
834                 if( strcmp(Name, langs[i]->Name) == 0 )
835                         return langs[i];
836         }
837         return NULL;
838 }
839

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