UDI/buf - buf_copy/buf_free/fixes
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / main.c
index fcdb93f..7a61d81 100644 (file)
@@ -1,34 +1,34 @@
 /*
  * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - UDI Entrypoint and Module loading
  */
-#define DEBUG  0
+#define DEBUG  1
 #define VERSION        ((0<<8)|1)
 #include <acess.h>
 #include <modules.h>
 #include <udi.h>
-#include "udi_internal.h"
-
-// === IMPORTS ===
-extern udi_init_t      pci_init;
-extern char    pci_udiprops[];
-extern size_t  pci_udiprops_size;
+#include <udi_internal.h>
+#include <udi_internal_ma.h>
+#include <trans_pci.h>
+#include <trans_nsr.h>
+#include <trans_uart.h>
 
 // === PROTOTYPES ===
  int   UDI_Install(char **Arguments);
  int   UDI_DetectDriver(void *Base);
  int   UDI_LoadDriver(void *Base);
-
-tUDI_DriverModule      *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size);
-
-tUDI_DriverInstance    *UDI_CreateInstance(tUDI_DriverModule *DriverModule);
-tUDI_DriverRegion      *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize);
-void   UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst);
+tUDI_DriverModule      *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size);
+const tUDI_MetaLang    *UDI_int_GetMetaLangByName(const char *Name);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL);
 tModuleLoader  gUDI_Loader = {
        NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL
 };
+tUDI_DriverModule      *gpUDI_LoadedModules;
 
 // === CODE ===
 /**
@@ -39,7 +39,11 @@ int UDI_Install(char **Arguments)
 {
        Module_RegisterLoader( &gUDI_Loader );
 
+       Proc_SpawnWorker(UDI_int_DeferredThread, NULL);
+
        UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
+       UDI_int_LoadDriver(NULL, &acessnsr_init, acessnsr_udiprops, acessnsr_udiprops_size);
+       UDI_int_LoadDriver(NULL, &acessuart_init, acessuart_udiprops, acessuart_udiprops_size);
 
        return MODULE_ERR_OK;
 }
@@ -85,51 +89,32 @@ int UDI_LoadDriver(void *Base)
        Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
 
        UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
-
-       #if 0
-       // Create initial driver instance
-       tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
-       
-       // Bind to parent
-       // TODO: This will move to udi_enumerate_ack handling
-       for( int i = 0; i < driver_module->nParents; i ++ )
-       {
-               tUDI_BindOps    *parent = &driver_module->Parents[i];
-               udi_channel_t channel = UDI_CreateChannel_Blank( UDI_int_GetMetaLang(inst, parent->meta_idx) );
-               
-               UDI_BindChannel(channel,true,  inst, parent->ops_idx, parent->region_idx);
-               //UDI_BindChannel(channel,false, parent_inst, parent_chld->ops_idx, parent_chld->region_idx);
-               
-               udi_cb_t *bind_cb = udi_cb_alloc_internal(inst, parent->bind_cb_idx, channel);
-               if( !bind_cb ) {
-                       Log_Warning("UDI", "Bind CB index is invalid");
-                       continue ;
-               }
-
-               udi_channel_event_cb_t  ev_cb;
-                int    n_handles = driver_module->InitInfo->primary_init_info->per_parent_paths;
-               udi_buf_path_t  handles[n_handles];
-               memset(&ev_cb, 0, sizeof(ev_cb));
-               ev_cb.gcb.channel = channel;
-               ev_cb.event = UDI_CHANNEL_BOUND;
-               ev_cb.params.parent_bound.bind_cb = bind_cb;
-               ev_cb.params.parent_bound.parent_ID = i+1;
-               ev_cb.params.parent_bound.path_handles = handles;
-               
-               for( int i = 0; i < n_handles; i ++ ) {
-                       //handles[i] = udi_buf_path_alloc_internal(inst);
-                       handles[i] = 0;
-               }
-               
-               udi_channel_event_ind(&ev_cb);
-       }
-
-       // Send enumeraton request
-       #endif
        
        return 0;
 }
 
+static udi_boolean_t _get_token_bool(const char *str, const char **outstr)
+{
+       udi_boolean_t   ret;
+       switch(*str++)
+       {
+       case 't':
+       case 'T':
+               ret = 1;
+               break;
+       case 'f':
+       case 'F':
+               ret = 0;
+               break;
+       default:
+               *outstr = NULL;
+               return 0;
+       }
+       while( isspace(*str) )
+               str ++;
+       *outstr = str;
+       return ret;
+}
 static udi_index_t _get_token_idx(const char *str, const char **outstr)
 {
        char    *end;
@@ -190,12 +175,59 @@ static udi_ubit32_t _get_token_uint32(const char *str, const char **outstr)
        *outstr = end;
        return ret;
 }
-static int _get_token_sym(const char *str, const char **outstr, ...)
+static size_t _get_token_str(const char *str, const char **outstr, char *output)
+{
+       size_t  ret = 0;
+       const char *pos = str;
+       while( *pos && !isspace(*pos) )
+       {
+               if( *pos == '\\' )
+               {
+                       pos ++;
+                       switch( *pos )
+                       {
+                       case '_':       // space
+                               if(output)
+                                       output[ret] = ' ';
+                               ret ++;
+                               break;
+                       case 'H':       // hash
+                               if(output)
+                                       output[ret] = '#';
+                               ret ++;
+                               break;
+                       case '\\':      // backslash
+                               if(output)
+                                       output[ret] = '\\';
+                               ret ++;
+                               break;
+                       // TODO: \p and \m<msgnum> (for message/disaster_message only)
+                       default:
+                               // Error
+                               break;
+                       }
+               }
+               else {
+                       if(output)
+                               output[ret] = *pos;
+                       ret ++;
+               }
+               pos ++;
+       }
+
+       while( isspace(*pos) )
+               pos ++;
+       *outstr = pos;  
+
+       if(output)
+               output[ret] = '\0';
+
+       return ret;
+}
+static int _get_token_sym_v(const char *str, const char **outstr, bool printError, const char **syms)
 {
-       va_list args;
-       va_start(args, outstr);
        const char *sym;
-       for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
+       for( int idx = 0; (sym = syms[idx]); idx ++ )
        {
                size_t len = strlen(sym);
                if( memcmp(str, sym, len) != 0 )
@@ -204,22 +236,93 @@ static int _get_token_sym(const char *str, const char **outstr, ...)
                        continue ;
                
                // Found it!
+               str += len;
+               while( isspace(*str) )
+                       str ++;
+               *outstr = str;
                return idx;
        }
-       va_end(args);
 
+       // Unknown symbol, find the end of the symbol and error
        const char *end = str;
        while( !isspace(*end) )
                end ++;
-       Log_Notice("UDI", "Unknown token '%.*s'",
-               end-str, str);  
+       
+       if( printError ) {
+               Log_Notice("UDI", "Unknown token '%.*s'", end-str, str);
+       }
 
        *outstr = NULL;
        return -1;
+       
+}
+static int _get_token_sym(const char *str, const char **outstr, bool printError, ...)
+{
+       va_list args;
+       const char *sym;
+        int    count = 0;
+       va_start(args, printError);
+       for( ; (sym = va_arg(args, const char *)); count ++ )
+               ;
+       va_end(args);
+
+       const char      *symlist[count+1];      
+       va_start(args, printError);
+       for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
+               symlist[idx] = sym;
+       symlist[count] = NULL;
+       
+       return _get_token_sym_v(str, outstr, printError, symlist);
 }
 
+enum {
+       UDIPROPS__properties_version,
+       UDIPROPS__module,
+       UDIPROPS__meta,
+       UDIPROPS__message,
+       UDIPROPS__locale,
+       UDIPROPS__region,
+       UDIPROPS__parent_bind_ops,
+       UDIPROPS__internal_bind_ops,
+       UDIPROPS__child_bind_ops,
+       UDIPROPS__supplier,
+       UDIPROPS__contact,
+       UDIPROPS__name,
+       UDIPROPS__shortname,
+       UDIPROPS__release,
+       
+       UDIPROPS__requires,
+       UDIPROPS__device,
+       UDIPROPS__enumerates,
+
+       UDIPROPS_last
+};
+#define _defpropname(name)     [ UDIPROPS__##name ] = #name
+const char *caUDI_UdipropsNames[] = {
+       _defpropname(properties_version),
+       _defpropname(module),
+       _defpropname(meta),
+       _defpropname(message),
+       _defpropname(locale),
+       _defpropname(region),
+       _defpropname(parent_bind_ops),
+       _defpropname(internal_bind_ops),
+       _defpropname(child_bind_ops),
+       _defpropname(supplier),
+       _defpropname(contact),
+       _defpropname(name),
+       _defpropname(shortname),
+       _defpropname(release),
+       _defpropname(requires),
+       
+       _defpropname(device),
+       _defpropname(enumerates),
+       
+       [UDIPROPS_last] = NULL
+};
+#undef _defpropname
 
-tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size)
+tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size)
 {
        //UDI_int_DumpInitInfo(info);
        
@@ -228,217 +331,367 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch
        driver_module->InitInfo = info;
 
        // - Parse udiprops
+       const char      **udipropsptrs;
+       
+       int nLines = 1;
+       for( int i = 0; i < udiprops_size; i++ )
        {
-               const char      **udipropsptrs;
-               
-               
-               int nLines = 1;
-               for( int i = 0; i < udiprops_size; i++ )
-               {
-                       if( udiprops[i] == '\0' )
-                               nLines ++;
-               }
-               
-               Log_Debug("UDI", "nLines = %i", nLines);
-               
-               udipropsptrs = NEW(const char*,*nLines);
-               int line = 0;
-               udipropsptrs[line++] = udiprops;
-               for( int i = 0; i < udiprops_size; i++ )
-               {
-                       if( udiprops[i] == '\0' ) {
-                               udipropsptrs[line++] = &udiprops[i+1];
-                       }
+               if( udiprops[i] == '\0' )
+                       nLines ++;
+       }
+       
+       Log_Debug("UDI", "nLines = %i", nLines);
+       
+       udipropsptrs = NEW(const char*,*nLines);
+       int line = 0;
+       udipropsptrs[line++] = udiprops;
+       for( int i = 0; i < udiprops_size; i++ )
+       {
+               if( udiprops[i] == '\0' ) {
+                       udipropsptrs[line++] = &udiprops[i+1];
                }
-               if(udipropsptrs[line-1] == &udiprops[udiprops_size])
-                       nLines --;
-               
-               for( int i = 0; i < nLines; i ++ )
+       }
+       if(udipropsptrs[line-1] == &udiprops[udiprops_size])
+               nLines --;
+       
+       // Parse out:
+       // 'message' into driver_module->Messages
+       // 'region' into driver_module->RegionTypes
+       // 'module' into driver_module->ModuleName
+       
+        int    nLocales = 1;
+       for( int i = 0; i < nLines; i ++ )
+       {
+               const char *str = udipropsptrs[i];
+                int    sym = _get_token_sym_v(str, &str, false, caUDI_UdipropsNames);
+               switch(sym)
                {
+               case UDIPROPS__module:
+                       driver_module->ModuleName = str;
+                       break;
+               case UDIPROPS__meta:
+                       driver_module->nMetaLangs ++;
+                       break;
+               case UDIPROPS__message:
+                       driver_module->nMessages ++;
+                       break;
+               case UDIPROPS__locale:
+                       nLocales ++;
+                       break;
+               case UDIPROPS__region:
+                       driver_module->nRegionTypes ++;
+                       break;
+               case UDIPROPS__device:
+                       driver_module->nDevices ++;
+                       break;
+               case UDIPROPS__parent_bind_ops:
+                       driver_module->nParents ++;
+                       break;
+               case UDIPROPS__child_bind_ops:
+                       driver_module->nChildBindOps ++;
+                       break;
+               default:
+                       // quiet ignore
+                       break;
                }
-               
-               // Parse out:
-               // 'message' into driver_module->Messages
-               // 'region' into driver_module->RegionTypes
-               // 'module' into driver_module->ModuleName
-               
-                int    nLocales = 1;
-                int    nRegionTypes = 0;
-               for( int i = 0; i < nLines; i ++ )
+       }
+
+       // Allocate structures
+       LOG("nMessages = %i, nMetaLangs = %i",
+               driver_module->nMessages,
+               driver_module->nMetaLangs);
+       driver_module->Messages     = NEW(tUDI_PropMessage, * driver_module->nMessages);
+       driver_module->RegionTypes  = NEW(tUDI_PropRegion,  * driver_module->nRegionTypes);
+       driver_module->MetaLangs    = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
+       driver_module->Parents      = NEW(tUDI_BindOps,     * driver_module->nParents);
+       driver_module->ChildBindOps = NEW(tUDI_BindOps,     * driver_module->nChildBindOps);
+       driver_module->Devices      = NEW(tUDI_PropDevSpec*,* driver_module->nDevices);
+
+       // Populate
+       bool    error_hit = false;
+        int    cur_locale = 0;
+        int    msg_index = 0;
+        int    ml_index = 0;
+        int    parent_index = 0;
+        int    child_bind_index = 0;
+        int    device_index = 0;
+        int    next_unpop_region = 1;
+       for( int i = 0; i < nLines; i ++ )
+       {
+               const char *str = udipropsptrs[i];
+               if( !*str )
+                       continue ;
+                int    sym = _get_token_sym_v(str, &str, true, caUDI_UdipropsNames);
+               switch(sym)
                {
-                       const char *str = udipropsptrs[i];
-                       if( strncmp("module ", str, 7) == 0 ) {
-                               driver_module->ModuleName = str + 7;
-                       }
-                       else if( strncmp("meta ", str, 5) == 0 ) {
-                               driver_module->nMetaLangs ++;
+               case UDIPROPS__properties_version:
+                       if( _get_token_uint32(str, &str) != 0x101 ) {
+                               Log_Warning("UDI", "Properties version mismatch.");
+                               error_hit = true;
                        }
-                       else if( strncmp("message ", str, 8) == 0 ) {
-                               driver_module->nMessages ++;
+                       break;
+               case UDIPROPS__module:
+                       driver_module->ModuleName = str;
+                       break;
+               case UDIPROPS__meta: {
+                       tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
+                       ml->meta_idx = _get_token_idx(str, &str);
+                       if( !str )      continue;
+                       ml->interface_name = str;
+                       // TODO: May need to trim trailing spaces
+                       ml->metalang = UDI_int_GetMetaLangByName(ml->interface_name);
+                       if( !ml->metalang ) {
+                               Log_Error("UDI", "Module %s referenced unsupported metalang %s",
+                                       driver_module->ModuleName, ml->interface_name);
+                               error_hit = true;
+                               // TODO: error
                        }
-                       else if( strncmp("locale ", str, 7) == 0 ) {
-                               nLocales ++;
+                       break; }
+               case UDIPROPS__message:
+                       {
+                       tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
+                       msg->locale = cur_locale;
+                       msg->index = _get_token_uint16(str, &str);
+                       if( !str )      continue ;
+                       msg->string = str;
+                       //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
+                       break;
                        }
-                       else if( strncmp("region ", str, 7) == 0 ) {
-                               nRegionTypes ++;
-                       }
-                       else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
-                               driver_module->nParents ++;
+               case UDIPROPS__locale:
+                       // TODO: Set locale
+                       cur_locale = 1;
+                       break;
+               case UDIPROPS__region:
+                       {
+                       udi_index_t rgn_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       // Search for region index (just in case internal_bind_ops appears earlier)
+                       tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
+                       if( rgn_idx > 0 )
+                       {
+                               rgn ++;
+                               for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
+                                       if( rgn->RegionIdx == rgn_idx )
+                                               break;
+                               }
+                               if(i == next_unpop_region) {
+                                       if( next_unpop_region == driver_module->nRegionTypes ) {
+                                               // TODO: warning if reigon types overflow
+                                               continue ;
+                                       }
+                                       next_unpop_region ++;
+                                       rgn->RegionIdx = rgn_idx;
+                               }
                        }
-               }
-
-               // Allocate structures
-               driver_module->Messages    = NEW(tUDI_PropMessage, * driver_module->nMessages);
-               driver_module->nRegionTypes = nRegionTypes;
-               driver_module->RegionTypes = NEW(tUDI_PropRegion,  * driver_module->nRegionTypes);
-               driver_module->MetaLangs   = NEW(tUDI_MetaLangRef, * driver_module->nMetaLangs);
-               driver_module->Parents     = NEW(tUDI_BindOps,     * driver_module->nParents);
-
-               // Populate
-                int    cur_locale = 0;
-                int    msg_index = 0;
-                int    ml_index = 0;
-                int    parent_index = 0;
-                int    next_unpop_region = 1;
-               for( int i = 0; i < nLines; i ++ )
-               {
-                       const char *str = udipropsptrs[i];
-                       if( strncmp("module ", str, 7) == 0 ) {
-                               driver_module->ModuleName = str + 7;
+                       // Parse attributes
+                       while( *str )
+                       {
+                               int sym = _get_token_sym(str, &str, true,
+                                       "type", "binding", "priority", "latency", "overrun_time", NULL
+                                       );
+                               if( !str )      break ;
+                               switch(sym)
+                               {
+                               case 0: // type
+                                       rgn->Type = _get_token_sym(str, &str, true,
+                                               "normal", "fp", NULL);
+                                       break;
+                               case 1: // binding
+                                       rgn->Binding = _get_token_sym(str, &str, true,
+                                               "static", "dynamic", NULL);
+                                       break;
+                               case 2: // priority
+                                       rgn->Priority = _get_token_sym(str, &str, true,
+                                               "med", "lo", "hi", NULL);
+                                       break;
+                               case 3: // latency
+                                       rgn->Latency = _get_token_sym(str, &str, true,
+                                               "non_overrunable", "powerfail_warning", "overrunable",
+                                               "retryable", "non_critical", NULL);
+                                       break;
+                               case 4: // overrun_time
+                                       rgn->OverrunTime = _get_token_uint32(str, &str);
+                                       break;
+                               }
+                               if( !str )      break ;
                        }
-                       else if( strncmp("meta ", str, 5) == 0 ) {
-                               tUDI_MetaLangRef *ml = &driver_module->MetaLangs[ml_index++];
-                               ml->meta_idx = _get_token_idx(str+5, &str);
-                               if( !str )      continue;
-                               ml->interface_name = str;
+                       break;
                        }
-                       else if( strncmp("message ", str, 8) == 0 ) {
-                               tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
-                               msg->locale = cur_locale;
-                               msg->index = _get_token_uint16(str+8, &str);
-                               if( !str )      continue ;
-                               msg->string = str;
-                               
-                               //Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
+               case UDIPROPS__parent_bind_ops:
+                       {
+                       tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
+                       bind->meta_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       bind->region_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       bind->ops_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       bind->bind_cb_idx = _get_token_idx(str, &str);
+                       if( *str ) {
+                               // Expected EOL, didn't get it :(
                        }
-                       else if( strncmp("locale ", str, 7) == 0 ) {
-                               // TODO: Set locale
-                               cur_locale = 1;
+                       Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
+                               bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
+                       break;
                        }
-                       else if( strncmp("region ", str, 7) == 0 ) {
-                               udi_index_t rgn_idx = _get_token_idx(str+7, &str);
-                               if( !str )      continue ;
-                               // Search for region index (just in case internal_bind_ops appears earlier)
-                               tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
-                               if( rgn_idx > 0 )
-                               {
-                                       rgn ++;
-                                       for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
-                                               if( rgn->RegionIdx == rgn_idx )
-                                                       break;
-                                       }
-                                       if(i == next_unpop_region) {
-                                               if( next_unpop_region == nRegionTypes ) {
-                                                       // TODO: warning if reigon types overflow
-                                                       continue ;
-                                               }
-                                               next_unpop_region ++;
-                                               rgn->RegionIdx = rgn_idx;
-                                       }
-                               }
-                               // Parse attributes
-                               while( *str )
-                               {
-                                       int sym = _get_token_sym(str, &str,
-                                               "type", "binding", "priority", "latency", "overrun_time", NULL
-                                               );
-                                       if( !str )      break ;
-                                       switch(sym)
-                                       {
-                                       case 0: // type
-                                               rgn->Type = _get_token_sym(str, &str, "normal", "fp", NULL);
-                                               break;
-                                       case 1: // binding
-                                               rgn->Binding = _get_token_sym(str, &str, "static", "dynamic", NULL);
-                                               break;
-                                       case 2: // priority
-                                               rgn->Priority = _get_token_sym(str, &str,
-                                                       "med", "lo", "hi", NULL);
-                                               break;
-                                       case 3: // latency
-                                               rgn->Latency = _get_token_sym(str, &str,
-                                                       "non_overrunable", "powerfail_warning", "overrunable",
-                                                       "retryable", "non_critical", NULL);
-                                               break;
-                                       case 4: // overrun_time
-                                               rgn->OverrunTime = _get_token_uint32(str, &str);
+               case UDIPROPS__internal_bind_ops:
+                       {
+                       // Get region using index
+                       udi_index_t meta = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       udi_index_t rgn_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       
+                       // Search for region index (just in case the relevant 'region' comes after)
+                       tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
+                       if( rgn_idx > 0 )
+                       {
+                               rgn ++;
+                                int    j;
+                               for( j = 1; j < next_unpop_region; j ++, rgn ++ ) {
+                                       if( rgn->RegionIdx == rgn_idx )
                                                break;
+                               }
+                               if( j == next_unpop_region ) {
+                                       if( next_unpop_region == driver_module->nRegionTypes ) {
+                                               // TODO: warning if reigon types overflow
+                                               continue ;
                                        }
-                                       if( !str )      break ;
+                                       next_unpop_region ++;
+                                       rgn->RegionIdx = rgn_idx;
                                }
                        }
-                       else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
-                               tUDI_BindOps    *bind = &driver_module->Parents[parent_index++];
-                               bind->meta_idx = _get_token_idx(str+16, &str);
-                               if( !str )      continue ;
-                               bind->region_idx = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               bind->ops_idx = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               bind->bind_cb_idx = _get_token_idx(str, &str);
-                               if( *str ) {
-                                       // Expected EOL, didn't get it :(
-                               }
-                               Log_Debug("UDI", "Parent bind - meta:%i,rgn:%i,ops:%i,bind:%i",
-                                       bind->meta_idx, bind->region_idx, bind->ops_idx, bind->bind_cb_idx);
+       
+                       // Set properties
+                       rgn->BindMeta = meta;
+                       
+                       rgn->PriBindOps = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       rgn->SecBindOps = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       rgn->BindCb = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       if( *str ) {
+                               // TODO: Please sir, I want an EOL
+                       }
+                       break;
+                       }
+               case UDIPROPS__child_bind_ops:
+                       {
+                       tUDI_BindOps    *bind = &driver_module->ChildBindOps[child_bind_index++];
+                       bind->meta_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       bind->region_idx = _get_token_idx(str, &str);
+                       if( !str )      continue ;
+                       bind->ops_idx = _get_token_idx(str, &str);
+                       if( *str ) {
+                               // Expected EOL, didn't get it :(
+                       }
+                       Log_Debug("UDI", "Child bind - meta:%i,rgn:%i,ops:%i",
+                               bind->meta_idx, bind->region_idx, bind->ops_idx);
+                       break;
+                       }
+               case UDIPROPS__supplier:
+               case UDIPROPS__contact:
+               case UDIPROPS__name:
+               case UDIPROPS__shortname:
+               case UDIPROPS__release:
+                       break;
+               //case UDIPROPS__requires:
+               //      // TODO: Requires
+               //      break;
+               case UDIPROPS__device:
+                       {
+                        int    n_attr = 0;
+                       // Count properties (and validate)
+                       _get_token_idx(str, &str);      // message
+                       if( !str )      continue;
+                       _get_token_idx(str, &str);      // meta
+                       if( !str )      continue;
+                       while( *str )
+                       {
+                               _get_token_str(str, &str, NULL);
+                               if( !str )      break;
+                               _get_token_sym(str, &str, true, "string", "ubit32", "boolean", "array", NULL);
+                               if( !str )      break;
+                               _get_token_str(str, &str, NULL);
+                               if( !str )      break;
+                               n_attr ++;
                        }
-                       else if( strncmp("internal_bind_ops ", str, 18) == 0 ) {
-                               // Get region using index
-                               udi_index_t meta = _get_token_idx(str+18, &str);
-                               if( !str )      continue ;
-                               udi_index_t rgn_idx = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               
-                               // Search for region index (just in case the relevant 'region' comes after)
-                               tUDI_PropRegion *rgn = &driver_module->RegionTypes[0];
-                               if( rgn_idx > 0 )
+                       // Rewind and actually parse
+                       _get_token_str(udipropsptrs[i], &str, NULL);
+                       
+                       tUDI_PropDevSpec *dev = NEW_wA(tUDI_PropDevSpec, Attribs, n_attr);
+                       driver_module->Devices[device_index++] = dev;;
+                       dev->MessageNum = _get_token_idx(str, &str);
+                       dev->MetaIdx = _get_token_idx(str, &str);
+                       dev->nAttribs = n_attr;
+                       n_attr = 0;
+                       while( *str )
+                       {
+                               udi_instance_attr_list_t *at = &dev->Attribs[n_attr];
+                               _get_token_str(str, &str, at->attr_name);
+                               if( !str )      break;
+                               at->attr_type = _get_token_sym(str, &str, true,
+                                       " ", "string", "array", "ubit32", "boolean", NULL);
+                               if( !str )      break;
+                               udi_ubit32_t    val;
+                               switch( dev->Attribs[n_attr].attr_type )
                                {
-                                       rgn ++;
-                                       for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) {
-                                               if( rgn->RegionIdx == rgn_idx )
-                                                       break;
-                                       }
-                                       if(i == next_unpop_region) {
-                                               if( next_unpop_region == nRegionTypes ) {
-                                                       // TODO: warning if reigon types overflow
-                                                       continue ;
-                                               }
-                                               next_unpop_region ++;
-                                               rgn->RegionIdx = rgn_idx;
-                                       }
-                               }
-               
-                               // Set properties
-                               rgn->BindMeta = meta;
-                               
-                               rgn->PriBindOps = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               rgn->SecBindOps = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               rgn->BindCb = _get_token_idx(str, &str);
-                               if( !str )      continue ;
-                               if( *str ) {
-                                       // TODO: Please sir, I want an EOL
+                               case 1: // String
+                                       at->attr_length = _get_token_str(str, &str, (char*)at->attr_value);
+                                       break;
+                               case 2: // Array
+                                       // TODO: Array
+                                       Log_Warning("UDI", "TODO: Parse 'array' attribute in 'device'");
+                                       _get_token_str(str, &str, NULL);
+                                       error_hit = true;
+                                       break;
+                               case 3: // ubit32
+                                       at->attr_length = sizeof(udi_ubit32_t);
+                                       val = _get_token_uint32(str, &str);
+                                       Log_Debug("UDI", "device %i: Value '%s'=%x", device_index,
+                                               at->attr_name, val);
+                                       UDI_ATTR32_SET(at->attr_value, val);
+                                       break;
+                               case 4: // boolean
+                                       at->attr_length = sizeof(udi_boolean_t);
+                                       UDI_ATTR32_SET(at->attr_value, _get_token_bool(str, &str));
+                                       break;
                                }
+                               if( !str )      break;
+                               n_attr ++;
                        }
-                       else {
-                               Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
+                       
+                       break;
                        }
+               default:
+                       Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
+                       break;
                }
-               
-               // Sort message list
-               // TODO: Sort message list
        }
+       free(udipropsptrs);
+       if( error_hit ) {
+               Log_Error("UDI", "Error encountered while parsing udiprops for '%s' (%p), bailing",
+                       driver_module->ModuleName, LoadBase);
+               for( int i = 0; i < device_index; i ++ )
+                       free(driver_module->Devices[i]);
+               free(driver_module->Messages);
+               free(driver_module->RegionTypes);
+               free(driver_module->MetaLangs);
+               free(driver_module->Parents);
+               free(driver_module->ChildBindOps);
+               free(driver_module->Devices);
+               free(driver_module);
+               return NULL;
+       }
+
+       for( int i = 0; i < driver_module->nDevices; i ++ )
+               driver_module->Devices[i]->Metalang = UDI_int_GetMetaLang(driver_module,
+                       driver_module->Devices[i]->MetaIdx);
+       
+       // Sort message list
+       // TODO: Sort message list
 
         int    nSecondaryRgns = 0;
        for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
@@ -446,17 +699,19 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch
        driver_module->nRegions = 1+nSecondaryRgns;
 
        
+       // -- Add to loaded module list
+       driver_module->Next = gpUDI_LoadedModules;
+       gpUDI_LoadedModules = driver_module;
+       
        // Check for orphan drivers, and create an instance of them when loaded
        if( driver_module->nParents == 0 )
        {
-               tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
-       
-               // Enumerate so any pre-loaded drivers are detected     
-               UDI_int_BeginEnumeration(inst);
+               UDI_MA_CreateInstance(driver_module, NULL, NULL);
        }
        else
        {
-               // Send rescan requests to all loaded instances that support a parent metalang
+               // Search running instances for unbound children that can be bound to this driver
+               UDI_MA_BindParents(driver_module);
        }
 
        return driver_module;
@@ -526,76 +781,6 @@ void UDI_int_DumpInitInfo(udi_init_t *info)
        }
 }
 
-tUDI_DriverInstance *UDI_CreateInstance(tUDI_DriverModule *DriverModule)
-{
-       tUDI_DriverInstance     *inst = NEW_wA(tUDI_DriverInstance, Regions, DriverModule->nRegions);
-       udi_primary_init_t      *pri_init = DriverModule->InitInfo->primary_init_info;
-       inst->Module = DriverModule;
-       inst->Regions[0] = UDI_InitRegion(inst, 0, 0, pri_init->rdata_size);
-       udi_secondary_init_t    *sec_init = DriverModule->InitInfo->secondary_init_list;
-       if( sec_init )
-       {
-               for( int i = 0; sec_init[i].region_idx; i ++ )
-               {
-                       inst->Regions[1+i] = UDI_InitRegion(inst, i,
-                               sec_init[i].region_idx, sec_init[i].rdata_size);
-               }
-       }
-
-       inst->ManagementChannel = UDI_CreateChannel_Blank(&cMetaLang_Management);
-       UDI_BindChannel_Raw(inst->ManagementChannel, true,
-               0, inst->Regions[0]->InitContext, pri_init->mgmt_ops);
-//     UDI_BindChannel_Raw(inst->ManagementChannel, false,
-//             1, inst, &cUDI_ManagementMetaagent_Ops);        // TODO: ops list for management
-
-       for( int i = 0; i < DriverModule->nRegions; i ++ )
-               Log("Rgn %i: %p", i, inst->Regions[i]);
-
-       // Send usage indication
-       char scratch[pri_init->mgmt_scratch_requirement];
-       {
-               udi_usage_cb_t ucb;
-               memset(&ucb, 0, sizeof(ucb));
-               ucb.gcb.scratch = scratch;
-               ucb.gcb.channel = inst->ManagementChannel;
-               udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
-               // TODO: Ensure that udi_usage_res is called
-       }
-       
-       for( int i = 1; i < DriverModule->nRegions; i ++ )
-       {
-               //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank(
-               // TODO: Bind secondaries to primary
-       }
-       
-       return inst;
-}
-
-tUDI_DriverRegion *UDI_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize)
-{
-//     ASSERTCR( RDataSize, <=, UDI_MIN_ALLOC_LIMIT, NULL );
-       ASSERTCR( RDataSize, >=, sizeof(udi_init_context_t), NULL );
-       tUDI_DriverRegion       *rgn = NEW(tUDI_DriverRegion,+RDataSize);
-       rgn->InitContext = (void*)(rgn+1);
-       rgn->InitContext->region_idx = Type;
-//     rgn->InitContext->limits
-       return rgn;
-}
-
-void UDI_int_BeginEnumeration(tUDI_DriverInstance *Inst)
-{
-       udi_primary_init_t *pri_init = Inst->Module->InitInfo->primary_init_info;
-       char scratch[pri_init->mgmt_scratch_requirement];
-       udi_enumerate_cb_t      ecb;
-       memset(&ecb, 0, sizeof(ecb));
-       ecb.gcb.scratch = scratch;
-       ecb.gcb.channel = Inst->ManagementChannel;
-       ecb.child_data = malloc( pri_init->child_data_size);
-       ecb.attr_list = NEW(udi_instance_attr_list_t, *pri_init->enumeration_attr_list_length);
-       ecb.attr_valid_length = 0;
-       udi_enumerate_req(&ecb, UDI_ENUMERATE_START);
-}
-
 // TODO: Move this stuff out
 udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
 {
@@ -607,33 +792,36 @@ udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index)
        return ops;
 }
 
-tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index)
+tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverModule *Module, udi_index_t index)
 {
        if( index == 0 )
                return &cMetaLang_Management;
-       for( int i = 0; i < Inst->Module->nMetaLangs; i ++ )
+       ASSERT(Module);
+       for( int i = 0; i < Module->nMetaLangs; i ++ )
        {
-               if( Inst->Module->MetaLangs[i].meta_idx == index )
-                       return Inst->Module->MetaLangs[i].metalang;
+               if( Module->MetaLangs[i].meta_idx == index )
+                       return Module->MetaLangs[i].metalang;
        }
        return NULL;
 }
 
-void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
+const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name)
 {
-       udi_cb_init_t   *cb_init = NULL;
-       for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
+       //extern tUDI_MetaLang  cMetaLang_Management;
+       extern tUDI_MetaLang    cMetaLang_BusBridge;
+       extern tUDI_MetaLang    cMetaLang_GIO;
+       extern tUDI_MetaLang    cMetaLang_NIC;
+       const tUDI_MetaLang     *langs[] = {
+               &cMetaLang_BusBridge,
+               &cMetaLang_GIO,
+               &cMetaLang_NIC,
+               NULL
+       };
+       for( int i = 0; langs[i]; i ++ )
        {
-               if( cb_init->cb_idx == bind_cb_idx )
-               {
-                       udi_cb_t *ret = NEW(udi_cb_t, + cb_init->inline_size + cb_init->scratch_requirement);
-                       ret->channel = channel;
-                       return ret;
-               }
+               if( strcmp(Name, langs[i]->Name) == 0 )
+                       return langs[i];
        }
-       Log_Warning("UDI", "Cannot find CB init def %i for '%s'",
-               bind_cb_idx, Inst->Module->ModuleName);
        return NULL;
-       
 }
 

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