#include <acess.h>
#include <udi.h>
#include "udi_internal.h"
+#define LOCK_CHANNELS 1
struct sUDI_ChannelSide {
struct sUDI_Channel *BackPtr;
+ udi_index_t MetaOpsNum;
const void *Ops;
void *Context;
};
typedef struct sUDI_Channel
{
- enum eUDI_MetaLang MetaLang;
- udi_index_t MetaOpsNum;
+ tUDI_MetaLang *MetaLang;
+ bool Locked;
struct sUDI_ChannelSide Side[2];
} tUDI_Channel;
// === CODE ===
-udi_channel_t UDI_CreateChannel(enum eUDI_MetaLang metalang, udi_index_t meta_ops_num,
- tUDI_DriverInstance *ThisEnd, udi_index_t ThisOpsIndex,
- tUDI_DriverInstance *OtherEnd, udi_index_t OtherOpsIndex)
+udi_channel_t UDI_CreateChannel_Blank(tUDI_MetaLang *metalang)
{
tUDI_Channel *ret = NEW(tUDI_Channel,);
- struct {
- tUDI_DriverInstance *inst;
- udi_index_t ops_index;
- } ends[2] = {
- {ThisEnd, ThisOpsIndex},
- {OtherEnd, OtherOpsIndex}
- };
+
ret->MetaLang = metalang;
- ret->MetaOpsNum = meta_ops_num;
- for( int i = 0; i < 2; i ++ )
- {
- if( !ends[i].inst ) {
- continue ;
- }
- tUDI_DriverModule *mod = ends[i].inst->Module;
- ret->Side[i].BackPtr = ret;
- udi_ops_init_t *ops = mod->InitInfo->ops_init_list;;
- while( ops->ops_idx && ops->ops_idx != ends[i].ops_index )
- ops++;
- ASSERTR(ops->ops_idx, NULL); // TODO: Pretty error
- ASSERTCR(ops->meta_idx, <, mod->nMetaLangs, NULL);
- ASSERTCR(mod->MetaLangs[ops->meta_idx], ==, metalang, NULL);
- ASSERTCR(ops->meta_ops_num, ==, meta_ops_num, NULL);
- if( ops->chan_context_size ) {
- ret->Side[i].Context = malloc(ops->chan_context_size);
- }
- ret->Side[i].Ops = ops->ops_vector;
- }
+ ret->Side[0].BackPtr = ret;
+ ret->Side[1].BackPtr = ret;
+
return (udi_channel_t)&ret->Side[0].BackPtr;
}
+struct sUDI_ChannelSide *UDI_int_ChannelGetSide(udi_channel_t channel, bool other_side)
+{
+ tUDI_Channel *ch = *(tUDI_Channel**)channel;
+ if(!ch) return NULL;
+
+ int side_idx = (channel == (udi_channel_t)&ch->Side[0].BackPtr) != 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)
+{
+ struct sUDI_ChannelSide *side = UDI_int_ChannelGetSide(channel, other_side);
+ side->Context = context;
+ side->MetaOpsNum = meta_ops_num;
+ side->Ops = ops;
+ return 0;
+}
+
+int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t ops_idx, udi_index_t region)
+{
+ tUDI_Channel *ch = *(tUDI_Channel**)channel;
+
+ tUDI_DriverRegion *rgn = inst->Regions[region];
+
+ udi_ops_init_t *ops = UDI_int_GetOps(inst, ops_idx);
+ if( !ops ) {
+ Log_Warning("UDI", "Ops ID invalid for '%s' (%i)", inst->Module, ops_idx);
+ return 1;
+ }
+
+ tUDI_MetaLang *ops_ml = UDI_int_GetMetaLang(inst, ops->meta_idx);
+ if( ops_ml != ch->MetaLang ) {
+ Log_Warning("UDI", "Attempt by %s to bind with mismatched channel '%s' op '%s' channel",
+ inst->Module, ops_ml->Name, ch->MetaLang->Name);
+ return 3;
+ }
+
+ void *context;
+ if( ops->chan_context_size ) {
+ context = malloc( ops->chan_context_size );
+ ((udi_chan_context_t*)context)->rdata = rgn->InitContext;
+ }
+ else {
+ context = rgn->InitContext;
+ }
+
+ UDI_BindChannel_Raw(channel, other_side, ops->meta_ops_num, context, ops->ops_vector);
+ return 0;
+}
+
/**
* \brief Prepare a cb for a channel call
* \param gcb Generic control block for this request
* Updates the channel and context fields of the gcb, checks the metalanguage and returns
* the handler list for the other end of the channel.
*/
-const void *UDI_int_ChannelPrepForCall(udi_cb_t *gcb, enum eUDI_MetaLang metalang, udi_index_t meta_ops_num)
+const void *UDI_int_ChannelPrepForCall(udi_cb_t *gcb, tUDI_MetaLang *metalang, udi_index_t meta_ops_num)
{
+ ASSERT(gcb);
+ ASSERT(gcb->channel);
tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel);
- ASSERTCR(ch->MetaLang, ==, metalang, NULL);
+ ASSERT(ch);
- struct sUDI_ChannelSide *newside = (gcb->channel == (udi_channel_t)&ch->Side[0].BackPtr ? &ch->Side[1] : &ch->Side[0]);
+ // TODO: Allow calls without auto-lock
+ #if LOCK_CHANNELS
+ if( ch->Locked ) {
+ Log_Warning("UDI", "Channel %s:%i used while blocked (before handler was fired)",
+ ch->MetaLang->Name, meta_ops_num);
+ return NULL;
+ }
+ ch->Locked = true;
+ #endif
+
+ struct sUDI_ChannelSide *newside = UDI_int_ChannelGetSide(gcb->channel, true);
+ if( metalang == NULL )
+ {
+ if( ch->MetaLang == &cMetaLang_Management ) {
+ Log_Warning("UDI", "Invalid udi_channel_event_ind on Management metalang");
+ return NULL;
+ }
+ }
+ else
+ {
+ if( ch->MetaLang != metalang || newside->MetaOpsNum != meta_ops_num ) {
+ Log_Warning("UDI", "Metalanguage mismatch %s:%i req != %s:%i ch",
+ metalang->Name, meta_ops_num,
+ ch->MetaLang->Name, newside->MetaOpsNum);
+ return NULL;
+ }
+ }
-// gcb->initiator_context = gcb->context;
gcb->channel = (udi_channel_t)&newside->BackPtr;
gcb->context = newside->Context;
+ if( !newside->Ops ) {
+ Log_Warning("UDI", "Target end of %p(%s:%i) is unbound",
+ ch, ch->MetaLang->Name, newside->MetaOpsNum);
+ }
return newside->Ops;
}
+void UDI_int_ChannelReleaseFromCall(udi_cb_t *gcb)
+{
+ #if LOCK_CHANNELS
+ ASSERT(gcb);
+ ASSERT(gcb->channel);
+ tUDI_Channel *ch = *(tUDI_Channel**)(gcb->channel);
+ ASSERT(ch);
+
+ ch->Locked = false;
+ #endif
+}
+
#include <udi.h>
#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);
int UDI_Install(char **Arguments)
{
Module_RegisterLoader( &gUDI_Loader );
+
+ UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size);
+
return MODULE_ERR_OK;
}
char *udiprops = NULL;
char *udiprops_end = 0;
- ENTER("pBase", Base);
-
if( Binary_FindSymbol(Base, "udi_init_info", (Uint*)&info) == 0) {
Binary_Unload(Base);
- LEAVE('i', 0);
return 0;
}
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);
- #if 0
- Log("primary_init_info = %p = {", info->primary_init_info);
- {
- Log(" .mgmt_ops = %p = {", info->primary_init_info->mgmt_ops);
- Log(" .usage_ind_op: %p() - 0x%02x",
- info->primary_init_info->mgmt_ops->usage_ind_op,
- info->primary_init_info->mgmt_op_flags[0]
- );
- Log(" .enumerate_req_op: %p() - 0x%02x",
- info->primary_init_info->mgmt_ops->enumerate_req_op,
- info->primary_init_info->mgmt_op_flags[1]
- );
- Log(" .devmgmt_req_op: %p() - 0x%02x",
- info->primary_init_info->mgmt_ops->devmgmt_req_op,
- info->primary_init_info->mgmt_op_flags[2]
- );
- Log(" .final_cleanup_req_op: %p() - 0x%02x",
- info->primary_init_info->mgmt_ops->final_cleanup_req_op,
- info->primary_init_info->mgmt_op_flags[3]
- );
- Log(" }");
- Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
- Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
- Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
- Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
- Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
- }
- Log("}");
- 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);
+ UDI_int_LoadDriver(Base, info, udiprops, udiprops_end - udiprops);
+
+ #if 0
+ // Create initial driver instance
+ tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
- for( int i = 0; info->ops_init_list[i].ops_idx; i++ )
+ // Bind to parent
+ // TODO: This will move to udi_enumerate_ack handling
+ for( int i = 0; i < driver_module->nParents; 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("}");
+ 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;
+}
+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,);
// - Parse udiprops
{
- char **udipropsptrs;
+ const char **udipropsptrs;
- Log_Debug("UDI", "udiprops = %p, udiprops_end = %p", udiprops, udiprops_end);
- size_t udiprops_size = udiprops_end - udiprops;
int nLines = 1;
for( int i = 0; i < udiprops_size; i++ )
Log_Debug("UDI", "nLines = %i", nLines);
- udipropsptrs = NEW(char*,*nLines);
+ udipropsptrs = NEW(const char*,*nLines);
int line = 0;
udipropsptrs[line++] = udiprops;
for( int i = 0; i < udiprops_size; i++ )
// 'region' into driver_module->RegionTypes
// 'module' into driver_module->ModuleName
- int nMessages = 0;
int nLocales = 1;
int nRegionTypes = 0;
for( int i = 0; i < nLines; 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 ) {
- nMessages ++;
+ 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 ++;
+ }
}
// Allocate structures
- driver_module->nMessages = nMessages;
- driver_module->Messages = NEW(tUDI_PropMessage, *nMessages);
+ driver_module->Messages = NEW(tUDI_PropMessage, * driver_module->nMessages);
driver_module->nRegionTypes = nRegionTypes;
- driver_module->RegionTypes = NEW(tUDI_PropRegion, *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;
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++];
+ char *end;
+ ml->meta_idx = strtoul(str+5, &end, 10);
+ if( *end != ' ' && !end != '\t' ) {
+ // TODO: handle 'meta' error
+ continue ;
+ }
+ while( isspace(*end) )
+ end ++;
+ ml->interface_name = end;
+ }
else if( strncmp("message ", str, 8) == 0 ) {
tUDI_PropMessage *msg = &driver_module->Messages[msg_index++];
char *end;
end ++;
msg->string = end;
- Log_Debug("UDI", "Message %i/%i: '%s'", msg->locale, msg->index, msg->string);
+ //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 ) {
- nRegionTypes ++;
+ //else if( strncmp("region ", str, 7) == 0 ) {
+ // nRegionTypes ++;
+ //}
+ else if( strncmp("parent_bind_ops ", str, 16) == 0 ) {
+ tUDI_BindOps *bind = &driver_module->Parents[parent_index++];
+ char *end;
+ bind->meta_idx = strtoul(str+16, &end, 10);
+ while(isspace(*end)) end++;
+ bind->region_idx = strtoul(end, &end, 10);
+ while(isspace(*end)) end++;
+ bind->ops_idx = strtoul(end, &end, 10);
+ while(isspace(*end)) end++;
+ bind->bind_cb_idx = strtoul(end, &end, 10);
+ 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
+ //}
else {
Log_Debug("UDI", "udipropsptrs[%i] = '%s'", i, udipropsptrs[i]);
}
int nSecondaryRgns = 0;
for( int i = 0; info->secondary_init_list && info->secondary_init_list[i].region_idx; i ++ )
nSecondaryRgns ++;
- driver_module->nSecondaryRegions = nSecondaryRgns;
+ driver_module->nRegions = 1+nSecondaryRgns;
+
- // Create initial driver instance
- tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
+ // Check for orphan drivers, and create an instance of them when loaded
+ if( driver_module->nParents == 0 )
+ {
+ tUDI_DriverInstance *inst = UDI_CreateInstance(driver_module);
+
+ // Enumerate so any pre-loaded drivers are detected
+ UDI_int_BeginEnumeration(inst);
+ }
+ else
+ {
+ // Send rescan requests to all loaded instances that support a parent metalang
+ }
- for( int i = 0; i < 1+driver_module->nSecondaryRegions; i ++ )
- Log("Rgn %i: %p", i, inst->Regions[i]);
+ return driver_module;
+}
- // Send usage indication
- udi_usage_cb_t ucb;
- memset(&ucb, 0, sizeof(ucb));
- ucb.gcb.channel = inst->ManagementChannel;
- udi_usage_ind(&ucb, UDI_RESOURCES_NORMAL);
-
- return 0;
+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);
+ Log(" .usage_ind_op: %p() - 0x%02x",
+ info->primary_init_info->mgmt_ops->usage_ind_op,
+ info->primary_init_info->mgmt_op_flags[0]
+ );
+ Log(" .enumerate_req_op: %p() - 0x%02x",
+ info->primary_init_info->mgmt_ops->enumerate_req_op,
+ info->primary_init_info->mgmt_op_flags[1]
+ );
+ Log(" .devmgmt_req_op: %p() - 0x%02x",
+ info->primary_init_info->mgmt_ops->devmgmt_req_op,
+ info->primary_init_info->mgmt_op_flags[2]
+ );
+ Log(" .final_cleanup_req_op: %p() - 0x%02x",
+ info->primary_init_info->mgmt_ops->final_cleanup_req_op,
+ info->primary_init_info->mgmt_op_flags[3]
+ );
+ Log(" }");
+ Log(" .mgmt_scratch_requirement = 0x%x", info->primary_init_info->mgmt_scratch_requirement);
+ Log(" .enumeration_attr_list_length = 0x%x", info->primary_init_info->enumeration_attr_list_length);
+ Log(" .rdata_size = 0x%x", info->primary_init_info->rdata_size);
+ Log(" .child_data_size = 0x%x", info->primary_init_info->child_data_size);
+ Log(" .per_parent_paths = 0x%x", info->primary_init_info->per_parent_paths);
+ }
+ Log("}");
+ 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, (1+DriverModule->nSecondaryRegions));
+ 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, DriverModule->InitInfo->primary_init_info->rdata_size);
+ 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->Regions[1+i] = UDI_InitRegion(inst, i,
+ sec_init[i].region_idx, sec_init[i].rdata_size);
}
}
- inst->ManagementChannel = UDI_CreateChannel(METALANG_MGMT, 0, NULL, 0, inst, 0);
+ //inst->ManagementChannel = UDI_CreateChannel(METALANG_MGMT, 0, NULL, 0, inst, 0);
+ 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, NULL); // 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 );
+ 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;
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;
+
+}
+
--- /dev/null
+/*
+ * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * trans/bus_pci.c
+ * - PCI Bus Driver
+ */
+#include <udi.h>
+#include <udi_physio.h>
+#include <drv_pci.h> // acess
+
+// === MACROS ===
+/* Copied from http://projectudi.cvs.sourceforge.net/viewvc/projectudi/udiref/driver/udi_dpt/udi_dpt.h */
+#define DPT_SET_ATTR_BOOLEAN(attr, name, val) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_BOOLEAN; \
+ (attr)->attr_length = sizeof(udi_boolean_t); \
+ UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define DPT_SET_ATTR32(attr, name, val) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_UBIT32; \
+ (attr)->attr_length = sizeof(udi_ubit32_t); \
+ UDI_ATTR32_SET((attr)->attr_value, (val))
+
+#define DPT_SET_ATTR_ARRAY8(attr, name, val, len) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_ARRAY8; \
+ (attr)->attr_length = (len); \
+ udi_memcpy((attr)->attr_value, (val), (len))
+
+#define DPT_SET_ATTR_STRING(attr, name, val, len) \
+ udi_strcpy((attr)->attr_name, (name)); \
+ (attr)->attr_type = UDI_ATTR_STRING; \
+ (attr)->attr_length = (len); \
+ udi_strncpy_rtrim((char *)(attr)->attr_value, (val), (len))
+
+
+// === TYPES ===
+typedef struct
+{
+ udi_init_context_t init_context;
+
+ tPCIDev cur_iter;
+} pci_rdata_t;
+
+// === PROTOTYPES ===
+void pci_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level);
+void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level);
+void pci_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID);
+void pci_final_cleanup_req(udi_mgmt_cb_t *cb);
+
+void pci_bridge_ch_event_ind(udi_channel_event_cb_t *cb);
+void pci_unbind_req(udi_bus_bind_cb_t *cb);
+void pci_bind_req_op(udi_bus_bind_cb_t *cb);
+void pci_intr_attach_req(udi_intr_attach_cb_t *cb);
+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();
+}
+void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
+{
+ pci_rdata_t *rdata = UDI_GCB(cb)->context;
+ switch(enumeration_level)
+ {
+ case UDI_ENUMERATE_START:
+ case UDI_ENUMERATE_START_RESCAN:
+ rdata->cur_iter = -1;
+ case UDI_ENUMERATE_NEXT:
+ // TODO: Filters
+ if( (rdata->cur_iter = PCI_GetDeviceByClass(0,0, rdata->cur_iter)) == -1 )
+ {
+ udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
+ }
+ else
+ {
+ udi_instance_attr_list_t *attr_list = cb->attr_list;
+ Uint16 ven, dev;
+ Uint32 class;
+ PCI_GetDeviceInfo(rdata->cur_iter, &ven, &dev, &class);
+
+ DPT_SET_ATTR_STRING(attr_list, "bus_type", "pci", 3);
+ attr_list ++;
+ DPT_SET_ATTR32(attr_list, "pci_vendor_id", ven);
+ attr_list ++;
+ DPT_SET_ATTR32(attr_list, "pci_device_id", dev);
+ attr_list ++;
+
+ cb->attr_valid_length = attr_list - cb->attr_list;
+ udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 0);
+ }
+ break;
+ }
+}
+void pci_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID)
+{
+ UNIMPLEMENTED();
+}
+void pci_final_cleanup_req(udi_mgmt_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+
+void pci_bridge_ch_event_ind(udi_channel_event_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+void pci_unbind_req(udi_bus_bind_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+void pci_bind_req_op(udi_bus_bind_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+void pci_intr_attach_req(udi_intr_attach_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+void pci_intr_detach_req(udi_intr_detach_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+
+// === UDI Functions ===
+udi_mgmt_ops_t pci_mgmt_ops = {
+ pci_usage_ind,
+ pci_enumerate_req,
+ pci_devmgmt_req,
+ pci_final_cleanup_req
+};
+udi_ubit8_t pci_mgmt_op_flags[4] = {0,0,0,0};
+udi_bus_bridge_ops_t pci_bridge_ops = {
+ pci_bridge_ch_event_ind,
+ pci_unbind_req,
+ pci_bind_req_op,
+ pci_intr_attach_req,
+ pci_intr_detach_req
+};
+udi_ubit8_t pci_bridge_op_flags[5] = {0,0,0,0,0};
+udi_primary_init_t pci_pri_init = {
+ .mgmt_ops = &pci_mgmt_ops,
+ .mgmt_op_flags = pci_mgmt_op_flags,
+ .mgmt_scratch_requirement = 0,
+ .enumeration_attr_list_length = 4,
+ .rdata_size = sizeof(pci_rdata_t),
+ .child_data_size = 0,
+ .per_parent_paths = 0
+};
+udi_ops_init_t pci_ops_list[] = {
+ {
+ 1, 1, UDI_BUS_BRIDGE_OPS_NUM,
+ 0,
+ (udi_ops_vector_t*)&pci_bridge_ops,
+ pci_bridge_op_flags
+ },
+ {0}
+};
+udi_init_t pci_init = {
+ .primary_init_info = &pci_pri_init,
+ .ops_init_list = pci_ops_list
+};
+const char pci_udiprops[] =
+ "properties_version 0x101\0"
+ "message 1 Acess2 Kernel\0"
+ "message 3 Acess2 PCI Bus\0"
+ "supplier 1\0"
+ "contact 2\0"
+ "name 3\0"
+ "module acess_pci\0"
+ "shortname acesspci\0"
+ "requires udi 0x101\0"
+ "provides udi_bridge 0x101\0"
+ "meta 1 udi_bridge\0"
+ "region 0\0"
+ "child_bind_ops 1 0 1\0"
+ "";
+size_t pci_udiprops_size = sizeof(pci_udiprops);