X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FInterfaces%2FUDI%2Fmain.c;h=fcdb93ff40cb89652cd0d00f8a5a635d9a5b4df2;hb=35f7d0523c463a6b6cc4d859c2e05234bdb0c6b8;hp=aa0ad5ec11c056d991eff1153f2c149894e520d7;hpb=f8f2a501822c6ca4d87a08d490407190cae7a495;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Interfaces/UDI/main.c b/KernelLand/Modules/Interfaces/UDI/main.c index aa0ad5ec..fcdb93ff 100644 --- a/KernelLand/Modules/Interfaces/UDI/main.c +++ b/KernelLand/Modules/Interfaces/UDI/main.c @@ -6,12 +6,24 @@ #include #include #include +#include "udi_internal.h" + +// === IMPORTS === +extern udi_init_t pci_init; +extern char pci_udiprops[]; +extern size_t pci_udiprops_size; // === 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); + // === GLOBALS === MODULE_DEFINE(0, VERSION, UDI, UDI_Install, NULL, NULL); tModuleLoader gUDI_Loader = { @@ -26,6 +38,9 @@ tModuleLoader gUDI_Loader = { int UDI_Install(char **Arguments) { Module_RegisterLoader( &gUDI_Loader ); + + UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size); + return MODULE_ERR_OK; } @@ -34,7 +49,17 @@ int UDI_Install(char **Arguments) */ int UDI_DetectDriver(void *Base) { - if( Binary_FindSymbol(Base, "udi_init_info", NULL) == 0) { + Uint unused; + + if( Binary_FindSymbol(Base, "udi_init_info", &unused) == 0) { + return 0; + } + if( Binary_FindSymbol(Base, "_udiprops", &unused) == 0 ) { + Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops symbol"); + return 0; + } + if( Binary_FindSymbol(Base, "_udiprops_end", &unused) == 0) { + Log_Warning("UDI", "Driver has udi_init_info, but no _udiprops_end symbol"); return 0; } @@ -48,36 +73,167 @@ int UDI_LoadDriver(void *Base) { udi_init_t *info; char *udiprops = NULL; - int udiprops_size = 0; - int i; - // int j; - - ENTER("pBase", Base); + char *udiprops_end = 0; if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) { Binary_Unload(Base); - LEAVE('i', 0); return 0; } - if( Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops) == 0 ) { - Log_Warning("UDI", "_udiprops is not defined, this is usually bad"); + Binary_FindSymbol(Base, "_udiprops", (Uint*)&udiprops); + Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end); + 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_index_t _get_token_idx(const char *str, const char **outstr) +{ + char *end; + int ret = strtol(str, &end, 10); + if( ret < 0 || ret > 255 ) { + Log_Notice("UDI", "Value '%.*s' out of range for udi_index_t", + end-str, str); + *outstr = NULL; + return 0; + } + if( *end && !isspace(*end) ) { + Log_Notice("UDI", "No whitespace following '%.*s', got '%c'", + end-str, str, *end); + *outstr = NULL; + return 0; } - else { - Uint udiprops_end = 0; - int i, j, nLines; - char **udipropsptrs; + while( *end && isspace(*end) ) + end ++; + + *outstr = end; + return ret; +} +static udi_ubit16_t _get_token_uint16(const char *str, const char **outstr) +{ + char *end; + unsigned long ret = strtoul(str, &end, 10); + if( ret > 0xFFFF ) { + Log_Notice("UDI", "Value '%.*s' out of range for udi_ubit16_t", + end-str, str); + *outstr = NULL; + return 0; + } + if( *end && !isspace(*end) ) { + Log_Notice("UDI", "No whitespace following '%.*s', got '%c'", + end-str, str, *end); + *outstr = NULL; + return 0; + } + while( *end && isspace(*end) ) + end ++; + + *outstr = end; + return ret; +} +static udi_ubit32_t _get_token_uint32(const char *str, const char **outstr) +{ + char *end; + udi_ubit32_t ret = strtoul(str, &end, 0); + if( *end && !isspace(*end) ) { + Log_Notice("UDI", "No whitespace following '%.*s', got '%c'", + end-str, str, *end); + *outstr = NULL; + return 0; + } + while( *end && isspace(*end) ) + end ++; + + *outstr = end; + return ret; +} +static int _get_token_sym(const char *str, const char **outstr, ...) +{ + va_list args; + va_start(args, outstr); + const char *sym; + for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ ) + { + size_t len = strlen(sym); + if( memcmp(str, sym, len) != 0 ) + continue ; + if( str[len] && !isspace(str[len]) ) + continue ; - if( Binary_FindSymbol(Base, "_udiprops_end", (Uint*)&udiprops_end) == 0) - Log_Warning("UDI", "_udiprops_end is not defined"); - Log_Debug("UDI", "udiprops_end = %p", udiprops_end); - udiprops_size = udiprops_end - (Uint)udiprops; - Log_Debug("UDI", "udiprops = %p, udiprops_size = 0x%x", udiprops, udiprops_size); + // Found it! + return idx; + } + va_end(args); + + const char *end = str; + while( !isspace(*end) ) + end ++; + Log_Notice("UDI", "Unknown token '%.*s'", + end-str, str); + + *outstr = NULL; + return -1; +} + + +tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size) +{ + //UDI_int_DumpInitInfo(info); + + // TODO: Multiple modules? + tUDI_DriverModule *driver_module = NEW(tUDI_DriverModule,); + driver_module->InitInfo = info; + + // - Parse udiprops + { + const char **udipropsptrs; - Debug_HexDump("UDI_LoadDriver", udiprops, udiprops_size); - nLines = 1; - for( i = 0; i < udiprops_size; i++ ) + int nLines = 1; + for( int i = 0; i < udiprops_size; i++ ) { if( udiprops[i] == '\0' ) nLines ++; @@ -85,21 +241,229 @@ int UDI_LoadDriver(void *Base) Log_Debug("UDI", "nLines = %i", nLines); - udipropsptrs = malloc( sizeof(char*)*nLines ); - udipropsptrs[0] = udiprops; - j = 0; - for( i = 0; i < udiprops_size; i++ ) + udipropsptrs = NEW(const char*,*nLines); + int line = 0; + udipropsptrs[line++] = udiprops; + for( int i = 0; i < udiprops_size; i++ ) { if( udiprops[i] == '\0' ) { - //Log_Debug("UDI", "udipropsptrs[%i] = '%s'", j, udipropsptrs[j]); - udipropsptrs[j++] = &udiprops[i+1]; + udipropsptrs[line++] = &udiprops[i+1]; + } + } + if(udipropsptrs[line-1] == &udiprops[udiprops_size]) + nLines --; + + for( int i = 0; i < nLines; i ++ ) + { + } + + // 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 ++ ) + { + 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 ++; + } + else if( strncmp("message ", str, 8) == 0 ) { + driver_module->nMessages ++; + } + else if( strncmp("locale ", str, 7) == 0 ) { + nLocales ++; + } + else if( strncmp("region ", str, 7) == 0 ) { + nRegionTypes ++; + } + else if( strncmp("parent_bind_ops ", str, 16) == 0 ) { + driver_module->nParents ++; } } - Log_Debug("UDI", "udipropsptrs[%i] = '%s'", j, udipropsptrs[j]); - Log_Debug("UDI", "udiprops = \"%s\"", udiprops); + + // 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; + } + 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; + } + 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); + } + else if( strncmp("locale ", str, 7) == 0 ) { + // TODO: Set locale + cur_locale = 1; + } + 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); + break; + } + if( !str ) break ; + } + } + 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); + } + 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 ) + { + 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 + } + } + else { + Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]); + } + } + + // 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 ++ ) + nSecondaryRgns ++; + driver_module->nRegions = 1+nSecondaryRgns; + + // 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); + } + else + { + // Send rescan requests to all loaded instances that support a parent metalang + } + + return driver_module; +} + +void UDI_int_DumpInitInfo(udi_init_t *info) +{ Log("primary_init_info = %p = {", info->primary_init_info); { Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops); @@ -127,20 +491,149 @@ int UDI_LoadDriver(void *Base) Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths); } Log("}"); - Log("secondary_init_list = %p", info->secondary_init_list); - Log("ops_init_list = %p", info->ops_init_list); + Log("secondary_init_list = %p {", info->secondary_init_list); + for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ ) + { + Log(" [%i] = { .region_idx=%i, .rdata_size=0x%x }", + info->secondary_init_list[i].region_idx, info->secondary_init_list[i].rdata_size); + } + Log("}"); + Log("ops_init_list = %p {", info->ops_init_list); + for( int i = 0; info->ops_init_list[i].ops_idx; i++ ) + { + Log(" [%i] = {", i); + Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx); + Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx); + Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num); + Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size); + Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector); +// Log(" .op_flags = %p", info->ops_init_list[i].op_flags); + Log(" }"); + } + Log("}"); + Log("cb_init_list = %p {", info->cb_init_list); + for( int i = 0; info->cb_init_list[i].cb_idx; i++ ) + { + udi_cb_init_t *ent = &info->cb_init_list[i]; + Log(" [%i] = {", i); + Log(" .cbidx = %i", ent->cb_idx); + Log(" .meta_idx = %i", ent->meta_idx); + Log(" .meta_cb_num = %i", ent->meta_cb_num); + Log(" .scratch_requirement = 0x%x", ent->scratch_requirement); + Log(" .inline_size = 0x%x", ent->inline_size); + Log(" .inline_layout = %p", ent->inline_layout); + Log(" }"); + } +} + +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( i = 0; info->ops_init_list[i].ops_idx; i++ ) + for( int i = 1; i < DriverModule->nRegions; i ++ ) { - Log("info->ops_init_list[%i] = {", i); - Log(" .ops_idx = 0x%x", info->ops_init_list[i].ops_idx); - Log(" .meta_idx = 0x%x", info->ops_init_list[i].meta_idx); - Log(" .meta_ops_num = 0x%x", info->ops_init_list[i].meta_ops_num); - Log(" .chan_context_size = 0x%x", info->ops_init_list[i].chan_context_size); - Log(" .ops_vector = %p", info->ops_init_list[i].ops_vector); -// Log(" .op_flags = %p", info->ops_init_list[i].op_flags); - Log("}"); + //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank( + // TODO: Bind secondaries to primary } - return 0; + 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) +{ + udi_ops_init_t *ops = Inst->Module->InitInfo->ops_init_list; + while( ops->ops_idx && ops->ops_idx != index ) + ops ++; + if(ops->ops_idx == 0) + return NULL; + return ops; +} + +tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index) +{ + if( index == 0 ) + return &cMetaLang_Management; + for( int i = 0; i < Inst->Module->nMetaLangs; i ++ ) + { + if( Inst->Module->MetaLangs[i].meta_idx == index ) + return Inst->Module->MetaLangs[i].metalang; + } + return NULL; +} + +void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel) +{ + udi_cb_init_t *cb_init = NULL; + for( cb_init = Inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ ) + { + 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; + } + } + Log_Warning("UDI", "Cannot find CB init def %i for '%s'", + bind_cb_idx, Inst->Module->ModuleName); + return NULL; + +} +