X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=KernelLand%2FModules%2FInterfaces%2FUDI%2Fmain.c;h=7a61d81f3acce68b17d8f99921b48bba579e8bf8;hb=bf4936e107e62b9c03e8cbf78395ef462e50fb47;hp=fcdb93ff40cb89652cd0d00f8a5a635d9a5b4df2;hpb=3daf8debc9b2f75a905be8e45ee24e571d056764;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Interfaces/UDI/main.c b/KernelLand/Modules/Interfaces/UDI/main.c index fcdb93ff..7a61d81f 100644 --- a/KernelLand/Modules/Interfaces/UDI/main.c +++ b/KernelLand/Modules/Interfaces/UDI/main.c @@ -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 #include #include -#include "udi_internal.h" - -// === IMPORTS === -extern udi_init_t pci_init; -extern char pci_udiprops[]; -extern size_t pci_udiprops_size; +#include +#include +#include +#include +#include // === 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 (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; - }