From 8d3b2c5f55f648f964afe7540a9fca97ab0b17d6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 6 Oct 2013 19:13:14 +0800 Subject: [PATCH] Modules/UDI - Attributes, PIO, CB allocation and channel_spawn --- KernelLand/Modules/Interfaces/UDI/Makefile | 2 +- KernelLand/Modules/Interfaces/UDI/channels.c | 66 +++++++++++--- KernelLand/Modules/Interfaces/UDI/main.c | 38 --------- .../Modules/Interfaces/UDI/management_agent.c | 13 ++- .../Modules/Interfaces/UDI/trans/bus_pci.c | 54 +++++++++++- .../Modules/Interfaces/UDI/udi_internal.h | 15 +++- .../Modules/Interfaces/UDI/udi_lib/attr.c | 73 ++++++++++++++++ .../Modules/Interfaces/UDI/udi_lib/cb.c | 46 +++++++++- .../Modules/Interfaces/UDI/udi_lib/imc.c | 31 +++++-- .../Interfaces/UDI/udi_lib/meta_mgmt.c | 2 +- .../Modules/Interfaces/UDI/udi_lib/physio.c | 85 ++++++++++++++++++- .../Interfaces/UDI/udi_lib/physio/dma.c | 5 ++ .../Interfaces/UDI/udi_lib/physio/meta_bus.c | 1 + .../Interfaces/UDI/udi_lib/physio/meta_intr.c | 25 +++--- .../Interfaces/UDI/udi_lib/physio/pio.c | 53 +++++++++++- 15 files changed, 425 insertions(+), 84 deletions(-) create mode 100644 KernelLand/Modules/Interfaces/UDI/udi_lib/attr.c diff --git a/KernelLand/Modules/Interfaces/UDI/Makefile b/KernelLand/Modules/Interfaces/UDI/Makefile index a895de43..886674bd 100644 --- a/KernelLand/Modules/Interfaces/UDI/Makefile +++ b/KernelLand/Modules/Interfaces/UDI/Makefile @@ -5,7 +5,7 @@ CPPFLAGS = -I../../../../UDI/include # - UDI Library Files LIB_OBJS := logging.o strmem.o imc.o mem.o buf.o cb.o -LIB_OBJS += queues.o time.o +LIB_OBJS += queues.o time.o attr.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 diff --git a/KernelLand/Modules/Interfaces/UDI/channels.c b/KernelLand/Modules/Interfaces/UDI/channels.c index c5ad0967..6e595941 100644 --- a/KernelLand/Modules/Interfaces/UDI/channels.c +++ b/KernelLand/Modules/Interfaces/UDI/channels.c @@ -10,15 +10,21 @@ #include #include "udi_internal.h" /* - * LOCK_CHANNELS - Prevents + * LOCK_CHANNELS + * - Prevents multiple non-dispatched operations on one channel + * TODO: This should actually lock the GCB, not the channel */ #define LOCK_CHANNELS 1 +#define MAX_SPAWN_IDX 6 + struct sUDI_ChannelSide { struct sUDI_Channel *BackPtr; tUDI_DriverInstance *Instance; + udi_index_t RegionIdx; udi_index_t MetaOpsNum; const void *Ops; + void *AllocatedContext; void *Context; }; @@ -27,6 +33,7 @@ typedef struct sUDI_Channel tUDI_MetaLang *MetaLang; bool Locked; struct sUDI_ChannelSide Side[2]; + struct sUDI_Channel *SpawnBinds[MAX_SPAWN_IDX]; } tUDI_Channel; // === CODE === @@ -41,6 +48,24 @@ udi_channel_t UDI_CreateChannel_Blank(tUDI_MetaLang *metalang) return (udi_channel_t)&ret->Side[0].BackPtr; } +udi_channel_t UDI_CreateChannel_Linked(udi_channel_t orig, udi_ubit8_t spawn_idx) +{ + tUDI_Channel *ch = *(tUDI_Channel**)orig; + ASSERT(ch); + ASSERTC(spawn_idx, <, MAX_SPAWN_IDX); + // TODO: mutex + if( ch->SpawnBinds[spawn_idx] ) { + tUDI_Channel *ret = ch->SpawnBinds[spawn_idx]; + ch->SpawnBinds[spawn_idx] = NULL; + // TODO: mutex + return (udi_channel_t)&ret->Side[1].BackPtr; + } + udi_channel_t ret = UDI_CreateChannel_Blank( ch->MetaLang ); + ch->SpawnBinds[spawn_idx] = *(tUDI_Channel**)ret; + // TODO: Mutex + return ret; +} + struct sUDI_ChannelSide *UDI_int_ChannelGetSide(udi_channel_t channel, bool other_side) { tUDI_Channel *ch = *(tUDI_Channel**)channel; @@ -55,17 +80,18 @@ struct sUDI_ChannelSide *UDI_int_ChannelGetSide(udi_channel_t channel, bool othe return &ch->Side[side_idx]; } -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) +int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t region_idx, 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->RegionIdx = region_idx; 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) +int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t ops_idx, udi_index_t region, void *context, bool is_child_bind, udi_ubit32_t child_ID) { tUDI_Channel *ch = *(tUDI_Channel**)channel; @@ -84,31 +110,45 @@ int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance return 3; } - void *context; - if( ops->chan_context_size ) { + if( context ) { + // Use provided context pointer + } + else if( ops->chan_context_size ) + { + if( is_child_bind ) + ASSERTCR( ops->chan_context_size, >=, sizeof(udi_child_chan_context_t), 4 ); + else + ASSERTCR( ops->chan_context_size, >=, sizeof(udi_chan_context_t), 4 ); context = malloc( ops->chan_context_size ); ((udi_chan_context_t*)context)->rdata = rgn->InitContext; + if( is_child_bind ) + ((udi_child_chan_context_t*)context)->child_ID = child_ID; + + // TODO: The driver may change the channel context, but this must be freed by the environment + UDI_int_ChannelGetSide(channel, other_side)->AllocatedContext = context; } else { context = rgn->InitContext; } - UDI_BindChannel_Raw(channel, other_side, inst, ops->meta_ops_num, context, ops->ops_vector); + UDI_BindChannel_Raw(channel, other_side, inst, region, ops->meta_ops_num, context, ops->ops_vector); return 0; } -tUDI_DriverInstance *UDI_int_ChannelGetInstance(udi_cb_t *gcb, bool other_side) +tUDI_DriverInstance *UDI_int_ChannelGetInstance(udi_cb_t *gcb, bool other_side, udi_index_t *region_idx) { - 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); - + if(region_idx) + *region_idx = side->RegionIdx; return side->Instance; } +void UDI_int_ChannelSetContext(udi_channel_t channel, void *context) +{ + struct sUDI_ChannelSide *side = UDI_int_ChannelGetSide(channel, false); + side->Context = context; +} + /** * \brief Prepare a cb for a channel call * \param gcb Generic control block for this request diff --git a/KernelLand/Modules/Interfaces/UDI/main.c b/KernelLand/Modules/Interfaces/UDI/main.c index e9dffc5e..51e04b32 100644 --- a/KernelLand/Modules/Interfaces/UDI/main.c +++ b/KernelLand/Modules/Interfaces/UDI/main.c @@ -783,44 +783,6 @@ tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index) return NULL; } -void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel) -{ - const udi_cb_init_t *cb_init; - LOG("Inst=%p, bind_cb_idx=%i, channel=%p", Inst, bind_cb_idx, channel); - if(Inst) { - ASSERT(Inst->Module); - ASSERT(Inst->Module->InitInfo); - ASSERT(Inst->Module->InitInfo->cb_init_list); - } - 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 ) - { - // TODO: Get base size using meta/cbnum - tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst, cb_init->meta_idx); - if( !metalang ) { - Log_Warning("UDI", "Metalang referenced in %s CB %i is invalid (%i)", - Inst->Module->ModuleName, bind_cb_idx, cb_init->meta_idx); - return NULL; - } - ASSERTC(cb_init->meta_cb_num, <, metalang->nCbTypes); - size_t base = metalang->CbTypes[cb_init->meta_cb_num].Size; - ASSERTC(base, >=, sizeof(udi_cb_t)); - base -= sizeof(udi_cb_t); - LOG("+ %i + %i + %i", base, cb_init->inline_size, cb_init->scratch_requirement); - udi_cb_t *ret = NEW(udi_cb_t, + base - + 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; - -} - const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name) { //extern tUDI_MetaLang cMetaLang_Management; diff --git a/KernelLand/Modules/Interfaces/UDI/management_agent.c b/KernelLand/Modules/Interfaces/UDI/management_agent.c index eb441aa4..f9d60418 100644 --- a/KernelLand/Modules/Interfaces/UDI/management_agent.c +++ b/KernelLand/Modules/Interfaces/UDI/management_agent.c @@ -46,7 +46,7 @@ tUDI_DriverInstance *UDI_MA_CreateInstance(tUDI_DriverModule *DriverModule) inst->ManagementChannel = UDI_CreateChannel_Blank(&cMetaLang_Management); UDI_BindChannel_Raw(inst->ManagementChannel, true, - inst, 0, inst->Regions[0]->InitContext, pri_init->mgmt_ops); + inst, 0, 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? @@ -111,6 +111,7 @@ void UDI_MA_BeginEnumeration(tUDI_DriverInstance *Inst) int UDI_MA_CheckDeviceMatch(int nDevAttr, udi_instance_attr_list_t *DevAttrs, int nEnumAttr, udi_instance_attr_list_t *EnumAttrs) { + // TODO: Ask metalangauge instead int n_matches = 0; for( int i = 0; i < nDevAttr; i ++ ) { @@ -149,7 +150,8 @@ int UDI_MA_CheckDeviceMatch(int nDevAttr, udi_instance_attr_list_t *DevAttrs, 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 ); + // TODO: Get region index too? + tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance( UDI_GCB(cb), true, NULL ); //LOG("inst = %p", inst); // Search for existing child with same child_ID and ops @@ -249,6 +251,8 @@ tUDI_DriverInstance *UDI_MA_CreateChildInstance(tUDI_DriverModule *Module, // Found a match, so create an instance and bind it tUDI_DriverInstance *inst = UDI_MA_CreateInstance(Module); ChildBinding->BoundInstance = inst; + inst->Parent = ParentInstance; + inst->ParentChildBinding = ChildBinding; // TODO: Handle multi-parent drivers ASSERTC(Module->nParents, ==, 1); @@ -257,9 +261,10 @@ tUDI_DriverInstance *UDI_MA_CreateChildInstance(tUDI_DriverModule *Module, 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,true, inst, parent->ops_idx, parent->region_idx, NULL,false,0); UDI_BindChannel(channel,false, - ParentInstance, ChildBinding->Ops->ops_idx, ChildBinding->BindOps->region_idx); + ParentInstance, ChildBinding->Ops->ops_idx, ChildBinding->BindOps->region_idx, + NULL, true, ChildBinding->ChildID); udi_channel_event_cb_t ev_cb; memset(&ev_cb, 0, sizeof(ev_cb)); diff --git a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c index 32f2eea7..1c3a7c13 100644 --- a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c +++ b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c @@ -10,6 +10,7 @@ #include #include #include // acess +#include "../udi_internal.h" // === MACROS === /* Copied from http://projectudi.cvs.sourceforge.net/viewvc/projectudi/udiref/driver/udi_dpt/udi_dpt.h */ @@ -58,6 +59,8 @@ 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); +// - Hook to physio (UDI doesn't define these) + int pci_pio_get_regset(udi_cb_t *gcb, udi_ubit32_t regset_idx, void **baseptr, size_t *lenptr); // === CODE === void pci_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level) @@ -110,7 +113,7 @@ void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level) PCI_GetDeviceSubsys(rdata->cur_iter, &sven, &sdev); udi_strcpy(attr_list->attr_name, "identifier"); - attr_list->attr_length = snprintf(attr_list->attr_value, + attr_list->attr_length = sprintf((char*)attr_list->attr_value, "%04x%04x%02x%04x%04x", ven, dev, revision, sven, sdev); attr_list ++; @@ -154,6 +157,8 @@ void pci_unbind_req(udi_bus_bind_cb_t *cb) } void pci_intr_attach_req(udi_intr_attach_cb_t *cb) { + // Create a channel + //udi_channel_spawn(, UCI_GCB(cb), cb->gcb.channel, 0, PCI_OPS_IRQ, NULL); UNIMPLEMENTED(); } void pci_intr_detach_req(udi_intr_detach_cb_t *cb) @@ -161,6 +166,51 @@ void pci_intr_detach_req(udi_intr_detach_cb_t *cb) UNIMPLEMENTED(); } +// - physio hooks +udi_status_t pci_pio_do_io(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit32_t ofs, udi_ubit8_t len, + void *data, bool isOutput) +{ + tPCIDev pciid = child_ID; + // TODO: Cache child mappings + + switch(regset_idx) + { + case UDI_PCI_CONFIG_SPACE: + // TODO: + return UDI_STAT_NOT_SUPPORTED; + case UDI_PCI_BAR_0 ... UDI_PCI_BAR_5: { + Uint64 bar = PCI_GetBAR(pciid, regset_idx); + if(bar & 1) + { + // IO BAR + bar &= ~3; + #define _IO(fc, type) do {\ + if( isOutput ) out##fc(bar+ofs, *(type*)data); \ + else *(type*)data = in##fc(bar+ofs); \ + } while(0) + switch(len) + { + case UDI_PIO_1BYTE: _IO(b, udi_ubit8_t); return UDI_OK; + case UDI_PIO_2BYTE: _IO(w, udi_ubit16_t); return UDI_OK; + case UDI_PIO_4BYTE: _IO(d, udi_ubit32_t); return UDI_OK; + //case UDI_PIO_8BYTE: _IO(q, uint64_t); return UDI_OK; + default: + return UDI_STAT_NOT_SUPPORTED; + } + #undef _IO + } + else + { + // Memory BAR + bar = PCI_GetValidBAR(pciid, regset_idx, PCI_BARTYPE_MEM); + return UDI_STAT_NOT_SUPPORTED; + } + break; } + default: + return UDI_STAT_NOT_UNDERSTOOD; + } +} + // === UDI Functions === udi_mgmt_ops_t pci_mgmt_ops = { pci_usage_ind, @@ -189,7 +239,7 @@ udi_primary_init_t pci_pri_init = { udi_ops_init_t pci_ops_list[] = { { 1, 1, UDI_BUS_BRIDGE_OPS_NUM, - 0, + sizeof(udi_child_chan_context_t), (udi_ops_vector_t*)&pci_bridge_ops, pci_bridge_op_flags }, diff --git a/KernelLand/Modules/Interfaces/UDI/udi_internal.h b/KernelLand/Modules/Interfaces/UDI/udi_internal.h index b2089303..9cc835a5 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_internal.h +++ b/KernelLand/Modules/Interfaces/UDI/udi_internal.h @@ -72,7 +72,7 @@ struct sUDI_MetaLang const char *Name; int nCbTypes; struct { - size_t Size; + udi_size_t Size; udi_layout_t *Layout; } CbTypes[]; }; @@ -140,6 +140,9 @@ struct sUDI_DriverInstance struct sUDI_DriverInstance *Next; tUDI_DriverModule *Module; udi_channel_t ManagementChannel; + tUDI_DriverInstance *Parent; + tUDI_ChildBinding *ParentChildBinding; + tUDI_ChildBinding *FirstChild; tUDI_DriverRegion *Regions[]; }; @@ -174,9 +177,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, 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 udi_channel_t UDI_CreateChannel_Linked(udi_channel_t orig, udi_ubit8_t spawn_idx); +extern int UDI_BindChannel_Raw(udi_channel_t channel, bool other_side, tUDI_DriverInstance *inst, udi_index_t region_idx, 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, void *context, bool is_child_bind, udi_ubit32_t child_ID); +extern tUDI_DriverInstance *UDI_int_ChannelGetInstance(udi_cb_t *gcb, bool other_side, udi_index_t *region_idx); +extern void UDI_int_ChannelSetContext(udi_channel_t channel, void *context); 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); @@ -201,6 +206,8 @@ extern void UDI_int_MakeDeferredCbS(udi_cb_t *cb, udi_op_t *handler, udi_status_ // --- CBs --- extern void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel); +// --- Attribute Management --- +extern udi_instance_attr_type_t udi_instance_attr_get_internal(udi_cb_t *gcb, const char *attr_name, udi_ubit32_t child_ID, void *attr_value, udi_size_t attr_length, udi_size_t *actual_length); #endif diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/attr.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/attr.c new file mode 100644 index 00000000..7268d07d --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/attr.c @@ -0,0 +1,73 @@ +/** + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * udi_lib/attr.c + * - Instance Attribute Management + */ +#include +#include +#include "../udi_internal.h" + +// Notes: +// - Prefixes: +// > '%': Private persistent +// > '$': Private Volatile +// > '': Enumeration +// > '^': Sibling group +// > '@': parent-visible (persistent) + +// === CODE === +udi_instance_attr_type_t udi_instance_attr_get_internal(udi_cb_t *gcb, const char *attr_name, udi_ubit32_t child_ID, void *attr_value, udi_size_t attr_length, udi_size_t *actual_length) +{ + // Get instance + tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance(gcb, false, NULL); + + const tUDI_ChildBinding *bind = inst->ParentChildBinding; + + // Search + switch(*attr_name) + { + // Private Persistent + case '%': + // Read cached from tUDI_DriverModule + // Write to permanent storage? + break; + // Private Volatile + case '$': + // Read from tUDI_DriverInstance + break; + // Sibling group + case '^': + // Read from parent's tUDI_DriverInstance + break; + // Parent-Visible + case '@': + // Read from tUDI_ChildBinding + break; + // Enumeration + default: + // Check associated tUDI_ChildBinding + if( !inst->ParentChildBinding ) { + return UDI_ATTR_NONE; + } + + for( int i = 0; i < bind->nAttribs; i ++ ) + { + const udi_instance_attr_list_t *at = &bind->Attribs[i]; + if( strcmp(at->attr_name, attr_name) == 0 ) + { + if( actual_length ) + *actual_length = at->attr_length; + udi_size_t len = (at->attr_length < attr_length) ? at->attr_length : attr_length; + memcpy(attr_value, at->attr_value, len); + return at->attr_type; + } + } + break; + } + // - Priv + // - enumeration attributes + // - set attributes + return UDI_ATTR_NONE; +} diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/cb.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/cb.c index b615dfeb..7d05768c 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/cb.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/cb.c @@ -3,10 +3,50 @@ * \author John Hodge (thePowersGang) * \brief Control block code */ -#include +#define DEBUG 1 #include +#include +#include "../udi_internal.h" +#include "../udi_ma.h" // for cUDI_MgmtCbInitList // === CODE === +void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel) +{ + const udi_cb_init_t *cb_init; + LOG("Inst=%p, bind_cb_idx=%i, channel=%p", Inst, bind_cb_idx, channel); + if(Inst) { + ASSERT(Inst->Module); + ASSERT(Inst->Module->InitInfo); + ASSERT(Inst->Module->InitInfo->cb_init_list); + } + 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 ) + { + // TODO: Get base size using meta/cbnum + tUDI_MetaLang *metalang = UDI_int_GetMetaLang(Inst, cb_init->meta_idx); + if( !metalang ) { + Log_Warning("UDI", "Metalang referenced in %s CB %i is invalid (%i)", + Inst->Module->ModuleName, bind_cb_idx, cb_init->meta_idx); + return NULL; + } + ASSERTC(cb_init->meta_cb_num, <, metalang->nCbTypes); + size_t base = metalang->CbTypes[cb_init->meta_cb_num].Size; + ASSERTC(base, >=, sizeof(udi_cb_t)); + base -= sizeof(udi_cb_t); + LOG("+ %i + %i + %i", base, cb_init->inline_size, cb_init->scratch_requirement); + udi_cb_t *ret = NEW(udi_cb_t, + base + + 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; +} + void udi_cb_alloc ( udi_cb_alloc_call_t *callback, //!< Function to be called when the CB is allocated udi_cb_t *gcb, //!< Parent Control Block @@ -14,7 +54,9 @@ void udi_cb_alloc ( udi_channel_t default_channel ) { - UNIMPLEMENTED(); + tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance(gcb, false, NULL); + void *ret = udi_cb_alloc_internal(inst, cb_idx, default_channel); + callback(gcb, ret); } void udi_cb_alloc_dynamic( diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/imc.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/imc.c index ce646dfc..31fd6e2d 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/imc.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/imc.c @@ -5,7 +5,6 @@ #define DEBUG 1 #include #include -//#include "internal/channels.h" #include "../udi_internal.h" // === EXPORTS === @@ -25,7 +24,7 @@ void udi_channel_anchor( udi_channel_t channel, udi_index_t ops_idx, void *channel_context ) { - Warning("%s Unimplemented", __func__); + UNIMPLEMENTED(); } /** @@ -36,7 +35,24 @@ extern void udi_channel_spawn( udi_index_t ops_idx, void *channel_context ) { - Warning("%s Unimplemented", __func__); + LOG("gcb=%p,channel=%p", gcb, channel, spawn_idx, ops_idx, channel_context); + + // Search existing channel for a matching spawn_idx + udi_channel_t ret = UDI_CreateChannel_Linked(channel, spawn_idx); + + // Bind local end of channel to ops_idx (with channel_context) + if( ops_idx != 0 ) + { + udi_index_t region_idx; + tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance(gcb, false, ®ion_idx); + UDI_BindChannel(ret, false, inst, ops_idx, region_idx, channel_context, false,0); + } + else + { + // leave unbound + } + + callback(gcb, ret); } /** @@ -46,14 +62,19 @@ void udi_channel_set_context( udi_channel_t target_channel, void *channel_context ) { - Warning("%s Unimplemented", __func__); + LOG("target_channel=%p,channel_context=%p", target_channel, channel_context); + UDI_int_ChannelSetContext(target_channel, channel_context); } void udi_channel_op_abort( udi_channel_t target_channel, udi_cb_t *orig_cb ) { - Warning("%s Unimplemented", __func__); + udi_channel_event_cb_t cb; + cb.gcb.channel = target_channel; + cb.event = UDI_CHANNEL_CLOSED; + cb.params.orig_cb = orig_cb; + udi_channel_event_ind(&cb); } void udi_channel_close(udi_channel_t channel) diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c index 6a80292d..6e6ec42c 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c @@ -2,7 +2,7 @@ * \file meta_mgmt.c * \author John Hodge (thePowersGang) */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include "../udi_internal.h" diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio.c index 5d136a14..ed47c157 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio.c @@ -5,6 +5,15 @@ #include #include #include +#include "../udi_internal.h" +//#include + +struct udi_dma_constraints_s +{ + udi_ubit16_t size; + udi_ubit16_t n_attrs; + udi_dma_constraints_attr_spec_t attrs[]; +}; // === EXPORTS === EXPORT(udi_dma_constraints_attr_set); @@ -17,7 +26,79 @@ void udi_dma_constraints_attr_set(udi_dma_constraints_attr_set_call_t *callback, const udi_dma_constraints_attr_spec_t *attr_list, udi_ubit16_t list_length, udi_ubit8_t flags) { - UNIMPLEMENTED(); + udi_dma_constraints_t ret; + if( !src_constraints ) + { + // Allocate new + ret = NEW_wA(struct udi_dma_constraints_s, attrs, list_length); + if(!ret) goto alloc_error; + ret->size = list_length; + ret->n_attrs = 0; + } + else + { + udi_ubit8_t bm[256/8] = {0}; + // Calculate new size + for( int i = 0; i < src_constraints->n_attrs; i ++ ) { + int idx = src_constraints->attrs[i].attr_type; + bm[idx/8] |= 1 << (idx%8); + } + udi_ubit16_t count = src_constraints->n_attrs; + for( int i = 0; i < list_length; i ++ ) { + int idx = attr_list[i].attr_type; + if(bm[idx/8] & 1 << (idx%8)) + ; + else { + count ++; + bm[idx/8] |= 1 << (idx%8); + } + } + + if( flags & UDI_DMA_CONSTRAINTS_COPY ) + { + // Duplicate + ret = NEW_wA(struct udi_dma_constraints_s, attrs, count); + if(!ret) goto alloc_error; + ret->size = count; + ret->n_attrs = src_constraints->n_attrs; + memcpy(ret->attrs, src_constraints->attrs, + src_constraints->n_attrs*sizeof(ret->attrs[0])); + } + else + { + // Expand + ret = realloc(src_constraints, sizeof(*ret) + + count*sizeof(ret->attrs[0])); + if(!ret) goto alloc_error; + ret->size = count; + } + } + + // Begin populating + for( int i = 0; i < list_length; i ++ ) + { + int j; + for( j = 0; j < ret->n_attrs; j ++ ) + { + if( ret->attrs[j].attr_type == attr_list[i].attr_type ) { + ret->attrs[j].attr_value = attr_list[i].attr_value; + break; + } + } + if( j == ret->n_attrs ) + { + ASSERTC(ret->n_attrs, !=, ret->size); + ret->attrs[j].attr_type = attr_list[i].attr_type; + ret->attrs[j].attr_value = attr_list[i].attr_value; + ret->n_attrs ++; + } + + } + + callback(gcb, ret, UDI_OK); + return ; +alloc_error: + callback(gcb, NULL, UDI_STAT_RESOURCE_UNAVAIL); } void udi_dma_constraints_attr_reset( @@ -30,5 +111,5 @@ void udi_dma_constraints_attr_reset( void udi_dma_constraints_free(udi_dma_constraints_t constraints) { - UNIMPLEMENTED(); + free(constraints); } diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/dma.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/dma.c index 1b1eecdb..03ba1bf8 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/dma.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/dma.c @@ -6,6 +6,11 @@ #include #include +struct udi_dma_handle_s +{ + +}; + // === EXPORTS === EXPORT(udi_dma_prepare); EXPORT(udi_dma_buf_map); diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_bus.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_bus.c index dadb4421..c0631f21 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_bus.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_bus.c @@ -71,6 +71,7 @@ struct marshalled_bus_bind_ack static void _unmarshal_bus_bind_ack(tUDI_DeferredCall *Call) { + LOG("Call=%p", Call); struct marshalled_bus_bind_ack *info = (void*)Call; ((udi_bus_bind_ack_op_t*)Call->Handler)( UDI_MCB(Call->cb, udi_bus_bind_cb_t), diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_intr.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_intr.c index 0c0ef6cb..38c263e6 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_intr.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_intr.c @@ -5,14 +5,15 @@ #include #include #include +#include "../../udi_internal.h" // === EXPORTS === EXPORT(udi_intr_attach_req); EXPORT(udi_intr_attach_ack); -//EXPORT(udi_intr_attach_ack_unused); +EXPORT(udi_intr_attach_ack_unused); EXPORT(udi_intr_detach_req); EXPORT(udi_intr_detach_ack); -//EXPORT(udi_intr_detach_ack_unused); +EXPORT(udi_intr_detach_ack_unused); EXPORT(udi_intr_event_ind); EXPORT(udi_intr_event_rdy); @@ -25,10 +26,12 @@ void udi_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t stat { UNIMPLEMENTED(); } -//void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) -//{ -// UNIMPLEMENTED(); -//} +void udi_intr_attach_ack_unused(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status) +{ + Log_Error("UDI", "Driver %s caused %s to be called", + UDI_int_ChannelGetInstance(UDI_GCB(intr_attach_cb), false, NULL)->Module->ModuleName, + __func__); +} void udi_intr_detach_req(udi_intr_detach_cb_t *intr_detach_cb) { @@ -38,10 +41,12 @@ void udi_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb) { UNIMPLEMENTED(); } -//void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb) -//{ -// UNIMPLEMENTED(); -//} +void udi_intr_detach_ack_unused(udi_intr_detach_cb_t *intr_detach_cb) +{ + Log_Error("UDI", "Driver %s caused %s to be called", + UDI_int_ChannelGetInstance(UDI_GCB(intr_detach_cb), false, NULL)->Module->ModuleName, + __func__); +} void udi_intr_event_ind(udi_intr_event_cb_t *intr_event_cb, udi_ubit8_t flags) { diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/pio.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/pio.c index b70861bd..2fa39eea 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/pio.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/physio/pio.c @@ -1,10 +1,38 @@ /** - * \file physio/pio.c + * \file udi_lib/physio/pio.c * \author John Hodge (thePowersGang) */ +#define DEBUG 1 #include #include #include +#include "../../udi_internal.h" + +typedef void _udi_pio_do_io_op_t(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit32_t ofs, size_t len, + void *data, bool isOutput); + +// === STRUCTURES === +struct udi_pio_handle_s +{ + tUDI_DriverInstance *Inst; + udi_index_t RegionIdx; + + _udi_pio_do_io_op_t *IOFunc; + udi_ubit32_t Offset; + udi_ubit32_t Length; + + size_t nTransOps; + udi_pio_trans_t *TransOps; + + udi_ubit16_t PIOAttributes; + udi_ubit32_t Pace; + udi_index_t Domain; + + // TODO: Cached labels +}; + +// === IMPORTS === +extern _udi_pio_do_io_op_t pci_pio_do_io; // === EXPORTS === EXPORT(udi_pio_map); @@ -20,22 +48,43 @@ void udi_pio_map(udi_pio_map_call_t *callback, udi_cb_t *gcb, udi_pio_trans_t *trans_list, udi_ubit16_t list_length, udi_ubit16_t pio_attributes, udi_ubit32_t pace, udi_index_t serialization_domain) { + LOG("gcb=%p,regset_idx=%i,base_offset=0x%x,length=0x%x,trans_list=%p,list_length=%i,...", + gcb, regset_idx, base_offset, length, trans_list, list_length); char bus_type[16]; udi_instance_attr_type_t type; type = udi_instance_attr_get_internal(gcb, "bus_type", 0, bus_type, sizeof(bus_type), NULL); if(type != UDI_ATTR_STRING) { + Log_Warning("UDI", "No/invalid bus_type attribute"); callback(gcb, UDI_NULL_PIO_HANDLE); return ; } - + + + _udi_pio_do_io_op_t *io_op; if( strcmp(bus_type, "pci") == 0 ) { // Ask PCI binding + io_op = pci_pio_do_io; } else { // Oops, unknown callback(gcb, UDI_NULL_PIO_HANDLE); return ; } + + udi_pio_handle_t ret = malloc( sizeof(struct udi_pio_handle_s) ); + ret->Inst = UDI_int_ChannelGetInstance(gcb, false, &ret->RegionIdx); + ret->IOFunc = io_op; + ret->Offset = base_offset; + ret->Length = length; + ret->TransOps = trans_list; + // TODO: Pre-scan to get labels + ret->nTransOps = list_length; + ret->PIOAttributes = pio_attributes; + ret->Pace = pace; + // TODO: Validate serialization_domain + ret->Domain = serialization_domain; + + callback(gcb, ret); } void udi_pio_unmap(udi_pio_handle_t pio_handle) -- 2.20.1