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

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