From de9c4d3d52751c9d66c61c062b74b02f80c31bf3 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 3 Oct 2013 23:02:02 +0800 Subject: [PATCH] Modules/UDI - Implementing proper enumeration framework --- KernelLand/Modules/Interfaces/UDI/Makefile | 3 +- KernelLand/Modules/Interfaces/UDI/channels.c | 45 +- .../Modules/Interfaces/UDI/deferred_calls.c | 112 ++++ KernelLand/Modules/Interfaces/UDI/main.c | 522 ++++++++++++------ .../Modules/Interfaces/UDI/management_agent.c | 259 +++++++++ .../Modules/Interfaces/UDI/trans/bus_pci.c | 26 +- .../Modules/Interfaces/UDI/udi_internal.h | 44 +- .../Interfaces/UDI/udi_lib/meta_mgmt.c | 54 +- .../Modules/Interfaces/UDI/udi_lib/udi_nic.c | 124 +++++ KernelLand/Modules/Interfaces/UDI/udi_ma.h | 25 + 10 files changed, 1017 insertions(+), 197 deletions(-) create mode 100644 KernelLand/Modules/Interfaces/UDI/deferred_calls.c create mode 100644 KernelLand/Modules/Interfaces/UDI/management_agent.c create mode 100644 KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c create mode 100644 KernelLand/Modules/Interfaces/UDI/udi_ma.h diff --git a/KernelLand/Modules/Interfaces/UDI/Makefile b/KernelLand/Modules/Interfaces/UDI/Makefile index 57160b4a..68155a9f 100644 --- a/KernelLand/Modules/Interfaces/UDI/Makefile +++ b/KernelLand/Modules/Interfaces/UDI/Makefile @@ -9,10 +9,11 @@ LIB_OBJS += queues.o time.o LIB_OBJS += meta_mgmt.o meta_gio.o LIB_OBJS += physio.o physio/meta_bus.o physio/meta_intr.o physio/pio.o physio/dma.o LIB_OBJS += scsi.o +LIB_OBJS += udi_nic.o # - UDI->Acess Translation Layer TRANS_OBJS := bus_pci.o -OBJ = main.o channels.o +OBJ = main.o channels.o deferred_calls.o management_agent.o OBJ += $(LIB_OBJS:%=udi_lib/%) $(TRANS_OBJS:%=trans/%) NAME = UDI diff --git a/KernelLand/Modules/Interfaces/UDI/channels.c b/KernelLand/Modules/Interfaces/UDI/channels.c index 8f96d341..c5ad0967 100644 --- a/KernelLand/Modules/Interfaces/UDI/channels.c +++ b/KernelLand/Modules/Interfaces/UDI/channels.c @@ -9,10 +9,14 @@ #include #include #include "udi_internal.h" +/* + * LOCK_CHANNELS - Prevents + */ #define LOCK_CHANNELS 1 struct sUDI_ChannelSide { struct sUDI_Channel *BackPtr; + tUDI_DriverInstance *Instance; udi_index_t MetaOpsNum; const void *Ops; void *Context; @@ -41,15 +45,20 @@ struct sUDI_ChannelSide *UDI_int_ChannelGetSide(udi_channel_t channel, bool othe { tUDI_Channel *ch = *(tUDI_Channel**)channel; if(!ch) return NULL; - - int side_idx = (channel == (udi_channel_t)&ch->Side[0].BackPtr) != other_side; + + int side_idx = (channel == (udi_channel_t)&ch->Side[0].BackPtr) ? 0 : 1; + if( other_side ) + side_idx = 1 - side_idx; + + LOG("side_idx = %i, other_side=%b", side_idx, other_side); return &ch->Side[side_idx]; } -int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, udi_index_t meta_ops_num, void *context, const void *ops) +int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t meta_ops_num, void *context, const void *ops) { struct sUDI_ChannelSide *side = UDI_int_ChannelGetSide(channel, other_side); + side->Instance = inst; side->Context = context; side->MetaOpsNum = meta_ops_num; side->Ops = ops; @@ -84,10 +93,22 @@ int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance context = rgn->InitContext; } - UDI_BindChannel_Raw(channel, other_side, ops->meta_ops_num, context, ops->ops_vector); + UDI_BindChannel_Raw(channel, other_side, inst, ops->meta_ops_num, context, ops->ops_vector); return 0; } +tUDI_DriverInstance *UDI_int_ChannelGetInstance(udi_cb_t *gcb, bool other_side) +{ + ASSERT(gcb); + ASSERT(gcb->channel); + tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel); + ASSERT(ch); + + struct sUDI_ChannelSide *side = UDI_int_ChannelGetSide(gcb->channel, other_side); + + return side->Instance; +} + /** * \brief Prepare a cb for a channel call * \param gcb Generic control block for this request @@ -142,12 +163,28 @@ const void *UDI_int_ChannelPrepForCall(udi_cb_t *gcb, tUDI_MetaLang *metalang, u return newside->Ops; } +void UDI_int_ChannelFlip(udi_cb_t *gcb) +{ + ASSERT(gcb); + ASSERT(gcb->channel); + tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel); + ASSERT(ch); + + struct sUDI_ChannelSide *newside = UDI_int_ChannelGetSide(gcb->channel, true); + + gcb->channel = (udi_channel_t)&newside->BackPtr; + gcb->context = newside->Context; +} + void UDI_int_ChannelReleaseFromCall(udi_cb_t *gcb) { #if LOCK_CHANNELS ASSERT(gcb); ASSERT(gcb->channel); tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel); + if( !ch ) { + Log_Error("UDI", "Channel pointer of cb %p is NULL", gcb); + } ASSERT(ch); ch->Locked = false; diff --git a/KernelLand/Modules/Interfaces/UDI/deferred_calls.c b/KernelLand/Modules/Interfaces/UDI/deferred_calls.c new file mode 100644 index 00000000..aec1fcb5 --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/deferred_calls.c @@ -0,0 +1,112 @@ +/* + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * deferred_calls.c + * - UDI Deferred call code + * + * Used to prevent excessive recursion causing stack exhaustion + */ +#define DEBUG 0 +#include +#include +#include "udi_internal.h" +#include + +// === PROTOTYPES === +void UDI_int_Deferred_UnmashalCb(tUDI_DeferredCall *Call); +void UDI_int_Deferred_UnmashalCbU8(tUDI_DeferredCall *Call); +void UDI_int_Deferred_UnmashalCbS(tUDI_DeferredCall *Call); + +// === GLOBALS === +tWorkqueue gUDI_DeferredWorkQueue; + +// === CODE === +void UDI_int_DeferredThread(void *unused) +{ + Threads_SetName("UDI Deferred"); + Workqueue_Init(&gUDI_DeferredWorkQueue, "UDI Deferred", offsetof(tUDI_DeferredCall, Next)); + + for(;;) + { + tUDI_DeferredCall *call = Workqueue_GetWork(&gUDI_DeferredWorkQueue); + + if( !call ) + { + Log_Notice("UDI", "Deferred thread worken with no work"); + continue ; + } + + // Ummarshal calls handler and frees the call + call->Unmarshal( call ); + } +} + +void UDI_int_AddDeferred(tUDI_DeferredCall *Call) +{ + Workqueue_AddWork(&gUDI_DeferredWorkQueue, Call); +} + +tUDI_DeferredCall *UDI_int_AllocDeferred(udi_cb_t *cb, udi_op_t *handler, tUDI_DeferredUnmarshal *Unmarshal, size_t extra) +{ + tUDI_DeferredCall *ret = NEW( tUDI_DeferredCall, + extra ); + ret->Unmarshal = Unmarshal; + ret->Handler = handler; + ret->cb = cb; + return ret; +} + + +typedef void udi_op_cb_t(udi_cb_t *gcb); +void UDI_int_MakeDeferredCb(udi_cb_t *cb, udi_op_t *handler) +{ + tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCb, 0); + UDI_int_AddDeferred(call); +} +void UDI_int_Deferred_UnmashalCb(tUDI_DeferredCall *Call) +{ + UDI_int_ChannelReleaseFromCall(Call->cb); + ((udi_op_cb_t*)Call->Handler)(Call->cb); + free(Call); +} + +typedef void udi_op_cbu8_t(udi_cb_t *gcb, udi_ubit8_t arg1); +struct sData_CbU8 { + udi_ubit8_t arg1; +}; +void UDI_int_MakeDeferredCbU8(udi_cb_t *cb, udi_op_t *handler, udi_ubit8_t arg1) +{ + struct sData_CbU8 *data; + tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbU8, sizeof(*data)); + data = (void*)(call + 1); + data->arg1 = arg1; + UDI_int_AddDeferred(call); +} +void UDI_int_Deferred_UnmashalCbU8(tUDI_DeferredCall *Call) +{ + struct sData_CbU8 *data = (void*)(Call+1); + UDI_int_ChannelReleaseFromCall(Call->cb); + ((udi_op_cbu8_t*)Call->Handler)(Call->cb, data->arg1); + free(Call); +} + +typedef void udi_op_cbs_t(udi_cb_t *gcb, udi_status_t status); +struct sData_CbS { + udi_status_t status; +}; +void UDI_int_MakeDeferredCbS(udi_cb_t *cb, udi_op_t *handler, udi_status_t status) +{ + struct sData_CbS *data; + tUDI_DeferredCall *call = UDI_int_AllocDeferred(cb, handler, UDI_int_Deferred_UnmashalCbS, sizeof(*data)); + data = (void*)(call + 1); + data->status = status; + UDI_int_AddDeferred(call); +} +void UDI_int_Deferred_UnmashalCbS(tUDI_DeferredCall *Call) +{ + struct sData_CbS *data = (void*)(Call+1); + UDI_int_ChannelReleaseFromCall(Call->cb); + ((udi_op_cbs_t*)Call->Handler)(Call->cb, data->status); + free(Call); +} + diff --git a/KernelLand/Modules/Interfaces/UDI/main.c b/KernelLand/Modules/Interfaces/UDI/main.c index fcdb93ff..1d1b28c9 100644 --- a/KernelLand/Modules/Interfaces/UDI/main.c +++ b/KernelLand/Modules/Interfaces/UDI/main.c @@ -7,6 +7,7 @@ #include #include #include "udi_internal.h" +#include "udi_ma.h" // === IMPORTS === extern udi_init_t pci_init; @@ -17,18 +18,14 @@ extern size_t pci_udiprops_size; 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 = { NULL, "UDI", UDI_DetectDriver, UDI_LoadDriver, NULL }; +tUDI_DriverModule *gpUDI_LoadedModules; // === CODE === /** @@ -39,6 +36,8 @@ 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); return MODULE_ERR_OK; @@ -85,51 +84,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 +170,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,20 +231,91 @@ 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) { @@ -253,80 +351,104 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch 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 ) { + 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 ++; - } - else if( strncmp("message ", str, 8) == 0 ) { + break; + case UDIPROPS__message: driver_module->nMessages ++; - } - else if( strncmp("locale ", str, 7) == 0 ) { + break; + case UDIPROPS__locale: nLocales ++; - } - else if( strncmp("region ", str, 7) == 0 ) { - nRegionTypes ++; - } - else if( strncmp("parent_bind_ops ", str, 16) == 0 ) { + 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; } } // 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); + 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 int cur_locale = 0; int msg_index = 0; int ml_index = 0; int parent_index = 0; + int child_bind_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 ) { + if( !*str ) + continue ; + int sym = _get_token_sym_v(str, &str, true, caUDI_UdipropsNames); + switch(sym) + { + case UDIPROPS__properties_version: + if( _get_token_uint32(str, &str) != 0x101 ) { + Log_Warning("UDI", "Properties version mismatch."); + } + 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+5, &str); + ml->meta_idx = _get_token_idx(str, &str); if( !str ) continue; ml->interface_name = str; - } - else if( strncmp("message ", str, 8) == 0 ) { + break; + } + case UDIPROPS__message: + { tUDI_PropMessage *msg = &driver_module->Messages[msg_index++]; msg->locale = cur_locale; - msg->index = _get_token_uint16(str+8, &str); + 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); - } - else if( strncmp("locale ", str, 7) == 0 ) { + break; + } + case UDIPROPS__locale: // TODO: Set locale cur_locale = 1; - } - else if( strncmp("region ", str, 7) == 0 ) { - udi_index_t rgn_idx = _get_token_idx(str+7, &str); + 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]; @@ -338,7 +460,7 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch break; } if(i == next_unpop_region) { - if( next_unpop_region == nRegionTypes ) { + if( next_unpop_region == driver_module->nRegionTypes ) { // TODO: warning if reigon types overflow continue ; } @@ -349,24 +471,26 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch // Parse attributes while( *str ) { - int sym = _get_token_sym(str, &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, "normal", "fp", NULL); + rgn->Type = _get_token_sym(str, &str, true, + "normal", "fp", NULL); break; case 1: // binding - rgn->Binding = _get_token_sym(str, &str, "static", "dynamic", NULL); + rgn->Binding = _get_token_sym(str, &str, true, + "static", "dynamic", NULL); break; case 2: // priority - rgn->Priority = _get_token_sym(str, &str, + rgn->Priority = _get_token_sym(str, &str, true, "med", "lo", "hi", NULL); break; case 3: // latency - rgn->Latency = _get_token_sym(str, &str, + rgn->Latency = _get_token_sym(str, &str, true, "non_overrunable", "powerfail_warning", "overrunable", "retryable", "non_critical", NULL); break; @@ -376,10 +500,12 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch } if( !str ) break ; } - } - else if( strncmp("parent_bind_ops ", str, 16) == 0 ) { + break; + } + case UDIPROPS__parent_bind_ops: + { tUDI_BindOps *bind = &driver_module->Parents[parent_index++]; - bind->meta_idx = _get_token_idx(str+16, &str); + bind->meta_idx = _get_token_idx(str, &str); if( !str ) continue ; bind->region_idx = _get_token_idx(str, &str); if( !str ) continue ; @@ -391,10 +517,12 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch } 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 ) { + break; + } + case UDIPROPS__internal_bind_ops: + { // Get region using index - udi_index_t meta = _get_token_idx(str+18, &str); + 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 ; @@ -404,12 +532,13 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch if( rgn_idx > 0 ) { rgn ++; - for( int i = 1; i < next_unpop_region; i ++, rgn ++ ) { + int j; + for( j = 1; j < next_unpop_region; j ++, rgn ++ ) { if( rgn->RegionIdx == rgn_idx ) break; } - if(i == next_unpop_region) { - if( next_unpop_region == nRegionTypes ) { + if( j == next_unpop_region ) { + if( next_unpop_region == driver_module->nRegionTypes ) { // TODO: warning if reigon types overflow continue ; } @@ -430,9 +559,94 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch if( *str ) { // TODO: Please sir, I want an EOL } - } - else { + 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 ++; + } + // Rewind and actually parse + _get_token_str(udipropsptrs[i], &str, NULL); + + tUDI_PropDevSpec *dev = NEW_wA(tUDI_PropDevSpec, Attribs, n_attr); + 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; + switch( dev->Attribs[n_attr].attr_type ) + { + 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); + break; + case 3: // ubit32 + at->attr_length = sizeof(udi_ubit32_t); + UDI_ATTR32_SET(at->attr_value, _get_token_uint32(str, &str)); + 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 ++; + } + + break; + } + default: Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]); + break; } } @@ -446,17 +660,22 @@ 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); + tUDI_DriverInstance *inst = UDI_MA_CreateInstance(driver_module); // Enumerate so any pre-loaded drivers are detected - UDI_int_BeginEnumeration(inst); + UDI_MA_BeginEnumeration(inst); } 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 +745,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) { @@ -611,6 +760,7 @@ tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index) { if( index == 0 ) return &cMetaLang_Management; + ASSERT(Inst); for( int i = 0; i < Inst->Module->nMetaLangs; i ++ ) { if( Inst->Module->MetaLangs[i].meta_idx == index ) @@ -621,12 +771,18 @@ tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index) 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 ++ ) + const udi_cb_init_t *cb_init; + cb_init = Inst ? Inst->Module->InitInfo->cb_init_list : cUDI_MgmtCbInitList; + for( ; 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); + // TODO: Get base size using meta/cbnum + tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst, cb_init->meta_idx); + ASSERT(metalang); + ASSERTC(cb_init->meta_cb_num, <, metalang->nCbTypes); + size_t base = metalang->CbTypes[cb_init->meta_cb_num].Size; + udi_cb_t *ret = NEW(udi_cb_t, + base + cb_init->inline_size + cb_init->scratch_requirement); ret->channel = channel; return ret; } diff --git a/KernelLand/Modules/Interfaces/UDI/management_agent.c b/KernelLand/Modules/Interfaces/UDI/management_agent.c new file mode 100644 index 00000000..38a6a124 --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/management_agent.c @@ -0,0 +1,259 @@ +/* + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * management_agent.c + * - Managment Agent + */ +#include +#include +#include "udi_internal.h" +#include "udi_ma.h" + +// === CONSTANTS === +enum { + MGMT_CB_ENUM = 1, +}; +const udi_cb_init_t cUDI_MgmtCbInitList[] = { + {MGMT_CB_ENUM,0,0, 0,0,NULL}, + {0} +}; + +// === PROTOTYPES === +tUDI_DriverInstance *UDI_MA_CreateChildInstance(tUDI_DriverModule *Module, + tUDI_DriverInstance *ParentInstance, tUDI_ChildBinding *ChildBinding); + +// === GLOBALS === +tUDI_DriverInstance *gpUDI_ActiveInstances; + +// === CODE === +tUDI_DriverInstance *UDI_MA_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_MA_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_MA_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, + inst, 0, inst->Regions[0]->InitContext, pri_init->mgmt_ops); +// UDI_BindChannel_Raw(inst->ManagementChannel, false, +// NULL, 1, inst, &cUDI_MgmtOpsList); // TODO: ops list for management agent? + + 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 ++ ) + { + // TODO: Bind secondaries to primary + Log_Warning("UDI", "TODO: Bind secondary channels"); + //inst->Regions[i]->PriChannel = UDI_CreateChannel_Blank( + } + + // Add to global list of active instances + inst->Next = gpUDI_ActiveInstances; + gpUDI_ActiveInstances = inst; + + return inst; +} + +tUDI_DriverRegion *UDI_MA_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_MA_BeginEnumeration(tUDI_DriverInstance *Inst) +{ + udi_primary_init_t *pri_init = Inst->Module->InitInfo->primary_init_info; + udi_enumerate_cb_t *ecb = udi_cb_alloc_internal(NULL, MGMT_CB_ENUM, Inst->ManagementChannel); + memset(ecb, 0, sizeof(ecb)); + ecb->gcb.scratch = malloc(pri_init->mgmt_scratch_requirement); + 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); + Threads_Yield(); // Yield to allow udi_enumerate_req to run +} + +/* + * Returns number of matching attributes + * If an attribute differs, returns 0 + */ +int UDI_MA_CheckDeviceMatch(int nDevAttr, udi_instance_attr_list_t *DevAttrs, + int nEnumAttr, udi_instance_attr_list_t *EnumAttrs) +{ + int n_matches = 0; + for( int i = 0; i < nDevAttr; i ++ ) + { + udi_instance_attr_list_t *dev_attr = &DevAttrs[i]; + udi_instance_attr_list_t *enum_attr = NULL; + for( int j = 0; j < nEnumAttr; j ++ ) + { + if( strcmp(dev_attr->attr_name, EnumAttrs[j].attr_name) == 0 ) { + enum_attr = &EnumAttrs[j]; + break; + } + } + if( enum_attr ) + { + if( enum_attr->attr_length != dev_attr->attr_length ) + return 0; + if( memcmp(enum_attr->attr_value, dev_attr->attr_value, dev_attr->attr_length) != 0 ) + return 0; + n_matches ++; + } + else + { + // Attribute desired is missing, error? + } + } + return n_matches; +} + +void UDI_MA_AddChild(udi_enumerate_cb_t *cb, udi_index_t ops_idx) +{ + // Current side is MA, other is instance + tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance( UDI_GCB(cb), true ); + LOG("inst = %p", inst); + + // Search for existing child with same child_ID and ops + for( tUDI_ChildBinding *child = inst->FirstChild; child; child = child->Next ) + { + if( child->ChildID == cb->child_ID && child->Ops->ops_idx == ops_idx ) { + LOG("duplicate, not creating"); + return; + } + } + + // Create a new child + tUDI_ChildBinding *child = NEW_wA(tUDI_ChildBinding, Attribs, cb->attr_valid_length); + child->Next = NULL; + child->ChildID = cb->child_ID; + child->Ops = UDI_int_GetOps(inst, ops_idx); + child->BoundInstance = NULL; // currently unbound + child->BindOps = NULL; + child->nAttribs = cb->attr_valid_length; + memcpy(child->Attribs, cb->attr_list, sizeof(cb->attr_list[0])*cb->attr_valid_length); + + // - Locate child_bind_ops definition + for( int i = 0; i < inst->Module->nChildBindOps; i ++ ) + { + LOG(" %i == %i?", inst->Module->ChildBindOps[i].ops_idx, ops_idx); + if( inst->Module->ChildBindOps[i].ops_idx == ops_idx ) { + child->BindOps = &inst->Module->ChildBindOps[i]; + break; + } + } + if( !child->BindOps ) { + Log_Error("UDI", "Driver '%s' doesn't have a 'child_bind_ops' for %i", + inst->Module->ModuleName, ops_idx); + free(child); + return ; + } + + child->Next = inst->FirstChild; + inst->FirstChild = child; + + // and search for a handler + tUDI_MetaLang *metalang = UDI_int_GetMetaLang(inst, child->Ops->meta_idx); + int best_level = 0; + tUDI_DriverModule *best_module = NULL; + for( tUDI_DriverModule *module = gpUDI_LoadedModules; module; module = module->Next ) + { + for( int i = 0; i < module->nDevices; i ++ ) + { + if( module->Devices[i]->Metalang != metalang ) + continue ; + + int level = UDI_MA_CheckDeviceMatch( + module->Devices[i]->nAttribs, module->Devices[i]->Attribs, + child->nAttribs, child->Attribs + ); + if( level > best_level ) { + best_level = level; + best_module = module; + } + } + } + if( best_module != NULL ) + { + UDI_MA_CreateChildInstance(best_module, inst, child); + } +} + +void UDI_MA_BindParents(tUDI_DriverModule *Module) +{ + UNIMPLEMENTED(); +} + +tUDI_DriverInstance *UDI_MA_CreateChildInstance(tUDI_DriverModule *Module, + tUDI_DriverInstance *ParentInstance, tUDI_ChildBinding *ChildBinding) +{ + // Found a match, so create an instance and bind it + tUDI_DriverInstance *inst = UDI_MA_CreateInstance(Module); + ChildBinding->BoundInstance = inst; + + // TODO: Handle multi-parent drivers + ASSERTC(Module->nParents, ==, 1); + + // Bind to parent + tUDI_BindOps *parent = &Module->Parents[0]; + 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, + ParentInstance, ChildBinding->Ops->ops_idx, ChildBinding->BindOps->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"); + return NULL; + } + + udi_channel_event_cb_t ev_cb; + int n_handles = 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 = 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); + return inst; +} + diff --git a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c index b5869477..394ae39a 100644 --- a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c +++ b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c @@ -61,7 +61,27 @@ void pci_intr_detach_req(udi_intr_detach_cb_t *cb); // === CODE === void pci_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level) { - UNIMPLEMENTED(); + pci_rdata_t *rdata = UDI_GCB(cb)->context; + + switch(cb->meta_idx) + { + case 1: // mgmt + break; + } + + switch(resource_level) + { + case UDI_RESOURCES_CRITICAL: + case UDI_RESOURCES_LOW: + case UDI_RESOURCES_NORMAL: + case UDI_RESOURCES_PLENTIFUL: + break; + } + + // TODO: Initialise rdata + rdata->cur_iter = -1; + + udi_usage_res(cb); } void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) { @@ -92,7 +112,8 @@ void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) attr_list ++; cb->attr_valid_length = attr_list - cb->attr_list; - udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 0); + cb->child_ID = rdata->cur_iter; + udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 1); } break; } @@ -178,6 +199,7 @@ const char pci_udiprops[] = "requires udi 0x101\0" "provides udi_bridge 0x101\0" "meta 1 udi_bridge\0" + "enumerates 4 0 100 1 bus_name string pci\0" "region 0\0" "child_bind_ops 1 0 1\0" ""; diff --git a/KernelLand/Modules/Interfaces/UDI/udi_internal.h b/KernelLand/Modules/Interfaces/UDI/udi_internal.h index 0cc2e3ef..2d298ca7 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_internal.h +++ b/KernelLand/Modules/Interfaces/UDI/udi_internal.h @@ -15,6 +15,7 @@ typedef struct sUDI_PropMessage tUDI_PropMessage; typedef struct sUDI_PropRegion tUDI_PropRegion; +typedef struct sUDI_PropDevSpec tUDI_PropDevSpec; typedef const struct sUDI_MetaLang tUDI_MetaLang; @@ -25,6 +26,8 @@ typedef struct sUDI_DriverModule tUDI_DriverModule; typedef struct sUDI_DriverInstance tUDI_DriverInstance; typedef struct sUDI_DriverRegion tUDI_DriverRegion; +typedef struct sUDI_ChildBinding tUDI_ChildBinding; + struct sUDI_PropMessage { int locale; @@ -71,6 +74,11 @@ struct sUDI_MetaLang struct { void *OpList; } OpGroups; + int nCbTypes; + struct { + size_t Size; + udi_layout_t *Layout; + } CbTypes[]; }; struct sUDI_MetaLangRef @@ -91,7 +99,11 @@ struct sUDI_BindOps struct sUDI_PropDevSpec { - + int MessageNum; + udi_ubit8_t MetaIdx; + tUDI_MetaLang *Metalang; + int nAttribs; + udi_instance_attr_list_t Attribs[]; }; struct sUDI_DriverModule @@ -117,13 +129,22 @@ struct sUDI_DriverModule int nParents; tUDI_BindOps *Parents; + + int nChildBindOps; + tUDI_BindOps *ChildBindOps; + + int nDevices; + tUDI_PropDevSpec **Devices; + int nRegions; }; struct sUDI_DriverInstance { + struct sUDI_DriverInstance *Next; tUDI_DriverModule *Module; udi_channel_t ManagementChannel; + tUDI_ChildBinding *FirstChild; tUDI_DriverRegion *Regions[]; }; @@ -132,7 +153,22 @@ struct sUDI_DriverRegion udi_init_context_t *InitContext; }; +struct sUDI_ChildBinding +{ + tUDI_ChildBinding *Next; + + udi_ubit32_t ChildID; + tUDI_MetaLang *Metalang; + tUDI_BindOps *BindOps; + + udi_ops_init_t *Ops; + tUDI_DriverInstance *BoundInstance; + + int nAttribs; + udi_instance_attr_list_t Attribs[]; +}; +// --- Metalanguages --- extern tUDI_MetaLang cMetaLang_Management; @@ -142,9 +178,11 @@ extern tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t // --- Channels --- extern udi_channel_t UDI_CreateChannel_Blank(tUDI_MetaLang *metalang); -extern int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, udi_index_t meta_ops_num, void *context, const void *ops); +extern int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t meta_ops_num, void *context, const void *ops); extern int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t ops, udi_index_t region); +extern tUDI_DriverInstance *UDI_int_ChannelGetInstance(udi_cb_t *gcb, bool other_side); extern const void *UDI_int_ChannelPrepForCall(udi_cb_t *gcb, tUDI_MetaLang *metalang, udi_index_t meta_ops_num); +extern void UDI_int_ChannelFlip(udi_cb_t *gcb); extern void UDI_int_ChannelReleaseFromCall(udi_cb_t *gcb); // --- Async Calls --- @@ -154,9 +192,11 @@ struct sUDI_DeferredCall { struct sUDI_DeferredCall *Next; tUDI_DeferredUnmarshal *Unmarshal; + udi_cb_t *cb; udi_op_t *Handler; // ... }; +extern void UDI_int_DeferredThread(void *unused); // Worker started by main.c extern void UDI_int_AddDeferred(tUDI_DeferredCall *Call); extern void UDI_int_MakeDeferredCb(udi_cb_t *cb, udi_op_t *handler); extern void UDI_int_MakeDeferredCbU8(udi_cb_t *cb, udi_op_t *handler, udi_ubit8_t arg1); diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c index 11d35a2c..87a54fd4 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c @@ -6,6 +6,7 @@ #include #include #include "../udi_internal.h" +#include "../udi_ma.h" // === EXPORTS === EXPORT(udi_usage_ind); @@ -22,7 +23,12 @@ EXPORT(udi_final_cleanup_ack); tUDI_MetaLang cMetaLang_Management = { "udi_mgmt", 1, - {NULL} + {NULL}, + + 1, + { + {sizeof(udi_enumerate_cb_t)-sizeof(udi_cb_t), NULL} + } }; // === CODE === @@ -35,17 +41,20 @@ void udi_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level) return ; } + UDI_int_ChannelReleaseFromCall( UDI_GCB(cb) ); ops->usage_ind_op(cb, resource_level); } void udi_static_usage(udi_usage_cb_t *cb, udi_ubit8_t resource_level) { - UNIMPLEMENTED(); + cb->trace_mask = 0; + udi_usage_res(cb); } void udi_usage_res(udi_usage_cb_t *cb) { - UNIMPLEMENTED(); + // TODO: Update trace mask from cb + LOG("cb=%p{cb->trace_mask=%x}", cb, cb->trace_mask); } void udi_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) @@ -57,7 +66,9 @@ void udi_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) return ; } - ops->enumerate_req_op(cb, enumeration_level); + UDI_int_MakeDeferredCbU8( UDI_GCB(cb), (udi_op_t*)ops->enumerate_req_op, enumeration_level ); +// UDI_int_ChannelReleaseFromCall( UDI_GCB(cb) ); +// ops->enumerate_req_op(cb, enumeration_level); } void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) @@ -67,7 +78,40 @@ void udi_enumerate_no_children(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_l void udi_enumerate_ack(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_result, udi_index_t ops_idx) { - UNIMPLEMENTED(); + UDI_int_ChannelFlip( UDI_GCB(cb) ); + LOG("cb=%p, enumeration_result=%i, ops_idx=%i", cb, enumeration_result, ops_idx); + switch( enumeration_result ) + { + case UDI_ENUMERATE_OK: + #if DEBUG + for( int i = 0; i < cb->attr_valid_length; i ++ ) + { + udi_instance_attr_list_t *at = &cb->attr_list[i]; + switch(at->attr_type) + { + case UDI_ATTR_STRING: + LOG("[%i] String '%.*s'", i, at->attr_length, at->attr_value); + break; + case UDI_ATTR_UBIT32: + LOG("[%i] UBit32 0x%08x", i, UDI_ATTR32_GET(at->attr_value)); + break; + default: + LOG("[%i] %i", i, at->attr_type); + break; + } + } + #endif + // Returned a device + UDI_MA_AddChild(cb, ops_idx); + udi_enumerate_req(cb, UDI_ENUMERATE_NEXT); + return ; + case UDI_ENUMERATE_DONE: + // All done. Chain terminates + return ; + default: + Log_Notice("UDI", "Unknown enumeration_result %i", enumeration_result); + return ; + } } void udi_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID ) diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c new file mode 100644 index 00000000..6bf636bb --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c @@ -0,0 +1,124 @@ +/** + * \file physio.c + * \author John Hodge (thePowersGang) + */ +#include +#include +#include + +// === EXPORTS === +EXPORT(udi_nd_bind_req); +EXPORT(udi_nsr_bind_ack); +EXPORT(udi_nd_unbind_req); +EXPORT(udi_nsr_unbind_ack); +EXPORT(udi_nd_enable_req); +EXPORT(udi_nsr_enable_ack); +EXPORT(udi_nd_disable_req); +EXPORT(udi_nd_ctrl_req); +EXPORT(udi_nsr_ctrl_ack); +EXPORT(udi_nsr_status_ind); +EXPORT(udi_nd_info_req); +EXPORT(udi_nsr_info_ack); +// - TX +EXPORT(udi_nsr_tx_rdy); +EXPORT(udi_nd_tx_req); +EXPORT(udi_nd_exp_tx_req); +// - RX +EXPORT(udi_nsr_rx_ind); +EXPORT(udi_nsr_exp_rx_ind); +EXPORT(udi_nd_rx_rdy); + +// === CODE === +// --- Control Ops --- +void udi_nd_bind_req(udi_nic_bind_cb_t *cb, udi_index_t tx_chan_index, udi_index_t rx_chan_index) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_nd_unbind_req(udi_nic_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_unbind_ack(udi_nic_cb_t *cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_nd_enable_req(udi_nic_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_enable_ack(udi_nic_cb_t *cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_nd_disable_req(udi_nic_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nd_ctrl_req(udi_nic_ctrl_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_status_ind(udi_nic_status_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nd_info_req(udi_nic_info_cb_t *cb, udi_boolean_t reset_statistics) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_info_ack(udi_nic_info_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +// --- TX --- +void udi_nsr_tx_rdy(udi_nic_tx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nd_tx_req(udi_nic_tx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nd_exp_tx_req(udi_nic_tx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +// --- RX --- +void udi_nsr_rx_ind(udi_nic_rx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nsr_exp_rx_ind(udi_nic_rx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + +void udi_nd_rx_rdy(udi_nic_rx_cb_t *cb) +{ + UNIMPLEMENTED(); +} + diff --git a/KernelLand/Modules/Interfaces/UDI/udi_ma.h b/KernelLand/Modules/Interfaces/UDI/udi_ma.h new file mode 100644 index 00000000..dd49b92f --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/udi_ma.h @@ -0,0 +1,25 @@ +/* + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * udi_ma.h + * - Management Agent + */ +#ifndef _UDI_MA_H_ +#define _UDI_MA_H_ + +extern void UDI_MA_BindParents(tUDI_DriverModule *Module); +extern tUDI_DriverInstance *UDI_MA_CreateInstance(tUDI_DriverModule *DriverModule); +extern tUDI_DriverRegion *UDI_MA_InitRegion(tUDI_DriverInstance *Inst, udi_ubit16_t Index, udi_ubit16_t Type, size_t RDataSize); +extern void UDI_MA_BeginEnumeration(tUDI_DriverInstance *Inst); + +extern void UDI_MA_AddChild(udi_enumerate_cb_t *cb, udi_index_t ops_idx); + + +extern const udi_cb_init_t cUDI_MgmtCbInitList[]; + +extern tUDI_DriverModule *gpUDI_LoadedModules; + + +#endif + -- 2.20.1