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
#include <acess.h>
#include <udi.h>
#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;
{
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;
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
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;
--- /dev/null
+/*
+ * 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 <acess.h>
+#include <udi.h>
+#include "udi_internal.h"
+#include <workqueue.h>
+
+// === 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);
+}
+
#include <modules.h>
#include <udi.h>
#include "udi_internal.h"
+#include "udi_ma.h"
// === IMPORTS ===
extern udi_init_t pci_init;
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 ===
/**
{
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;
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;
*outstr = end;
return ret;
}
-static int _get_token_sym(const char *str, const char **outstr, ...)
+static size_t _get_token_str(const char *str, const char **outstr, char *output)
+{
+ size_t ret = 0;
+ const char *pos = str;
+ while( *pos && !isspace(*pos) )
+ {
+ if( *pos == '\\' )
+ {
+ pos ++;
+ switch( *pos )
+ {
+ case '_': // space
+ if(output)
+ output[ret] = ' ';
+ ret ++;
+ break;
+ case 'H': // hash
+ if(output)
+ output[ret] = '#';
+ ret ++;
+ break;
+ case '\\': // backslash
+ if(output)
+ output[ret] = '\\';
+ ret ++;
+ break;
+ // TODO: \p and \m<msgnum> (for message/disaster_message only)
+ default:
+ // Error
+ break;
+ }
+ }
+ else {
+ if(output)
+ output[ret] = *pos;
+ ret ++;
+ }
+ pos ++;
+ }
+
+ while( isspace(*pos) )
+ pos ++;
+ *outstr = pos;
+
+ if(output)
+ output[ret] = '\0';
+
+ return ret;
+}
+static int _get_token_sym_v(const char *str, const char **outstr, bool printError, const char **syms)
{
- va_list args;
- va_start(args, outstr);
const char *sym;
- for( int idx = 0; (sym = va_arg(args, const char *)); idx ++ )
+ for( int idx = 0; (sym = syms[idx]); idx ++ )
{
size_t len = strlen(sym);
if( memcmp(str, sym, len) != 0 )
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)
{
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];
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 ;
}
// 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;
}
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 ;
}
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 ;
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 ;
}
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;
}
}
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;
}
}
-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)
{
{
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 )
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;
}
--- /dev/null
+/*
+ * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * management_agent.c
+ * - Managment Agent
+ */
+#include <acess.h>
+#include <udi.h>
+#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;
+}
+
// === 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)
{
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;
}
"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"
"";
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;
typedef struct sUDI_DriverInstance tUDI_DriverInstance;
typedef struct sUDI_DriverRegion tUDI_DriverRegion;
+typedef struct sUDI_ChildBinding tUDI_ChildBinding;
+
struct sUDI_PropMessage
{
int locale;
struct {
void *OpList;
} OpGroups;
+ int nCbTypes;
+ struct {
+ size_t Size;
+ udi_layout_t *Layout;
+ } CbTypes[];
};
struct sUDI_MetaLangRef
struct sUDI_PropDevSpec
{
-
+ int MessageNum;
+ udi_ubit8_t MetaIdx;
+ tUDI_MetaLang *Metalang;
+ int nAttribs;
+ udi_instance_attr_list_t Attribs[];
};
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[];
};
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;
// --- 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 ---
{
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);
#include <acess.h>
#include <udi.h>
#include "../udi_internal.h"
+#include "../udi_ma.h"
// === EXPORTS ===
EXPORT(udi_usage_ind);
tUDI_MetaLang cMetaLang_Management = {
"udi_mgmt",
1,
- {NULL}
+ {NULL},
+
+ 1,
+ {
+ {sizeof(udi_enumerate_cb_t)-sizeof(udi_cb_t), NULL}
+ }
};
// === CODE ===
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)
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)
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 )
--- /dev/null
+/**
+ * \file physio.c
+ * \author John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <udi.h>
+#include <udi_nic.h>
+
+// === 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();
+}
+
--- /dev/null
+/*
+ * 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
+