Modules/UDI - Attributes, PIO, CB allocation and channel_spawn
authorJohn Hodge <[email protected]>
Sun, 6 Oct 2013 11:13:14 +0000 (19:13 +0800)
committerJohn Hodge <[email protected]>
Sun, 6 Oct 2013 11:13:14 +0000 (19:13 +0800)
15 files changed:
KernelLand/Modules/Interfaces/UDI/Makefile
KernelLand/Modules/Interfaces/UDI/channels.c
KernelLand/Modules/Interfaces/UDI/main.c
KernelLand/Modules/Interfaces/UDI/management_agent.c
KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c
KernelLand/Modules/Interfaces/UDI/udi_internal.h
KernelLand/Modules/Interfaces/UDI/udi_lib/attr.c [new file with mode: 0644]
KernelLand/Modules/Interfaces/UDI/udi_lib/cb.c
KernelLand/Modules/Interfaces/UDI/udi_lib/imc.c
KernelLand/Modules/Interfaces/UDI/udi_lib/meta_mgmt.c
KernelLand/Modules/Interfaces/UDI/udi_lib/physio.c
KernelLand/Modules/Interfaces/UDI/udi_lib/physio/dma.c
KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_bus.c
KernelLand/Modules/Interfaces/UDI/udi_lib/physio/meta_intr.c
KernelLand/Modules/Interfaces/UDI/udi_lib/physio/pio.c

index a895de4..886674b 100644 (file)
@@ -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
index c5ad096..6e59594 100644 (file)
 #include <udi.h>
 #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
index e9dffc5..51e04b3 100644 (file)
@@ -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;
index eb441aa..f9d6041 100644 (file)
@@ -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));
index 32f2eea..1c3a7c1 100644 (file)
@@ -10,6 +10,7 @@
 #include <udi_pci.h>
 #include <acess.h>
 #include <drv_pci.h>   // 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
        },
index b208930..9cc835a 100644 (file)
@@ -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 (file)
index 0000000..7268d07
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * Acess2 UDI Layer
+ * - By John Hodge (thePowersGang)
+ *
+ * udi_lib/attr.c
+ * - Instance Attribute Management
+ */
+#include <acess.h>
+#include <udi.h>
+#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;
+}
index b615dfe..7d05768 100644 (file)
@@ -3,10 +3,50 @@
  * \author John Hodge (thePowersGang)
  * \brief Control block code
  */
-#include <acess.h>
+#define DEBUG  1
 #include <udi.h>
+#include <acess.h>
+#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(
index ce646df..31fd6e2 100644 (file)
@@ -5,7 +5,6 @@
 #define DEBUG  1
 #include <acess.h>
 #include <udi.h>
-//#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, &region_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)
index 6a80292..6e6ec42 100644 (file)
@@ -2,7 +2,7 @@
  * \file meta_mgmt.c
  * \author John Hodge (thePowersGang)
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <acess.h>
 #include <udi.h>
 #include "../udi_internal.h"
index 5d136a1..ed47c15 100644 (file)
@@ -5,6 +5,15 @@
 #include <acess.h>
 #include <udi.h>
 #include <udi_physio.h>
+#include "../udi_internal.h"
+//#include <udi_internal/physio.h>
+
+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);
 }
index 1b1eecd..03ba1bf 100644 (file)
@@ -6,6 +6,11 @@
 #include <udi.h>
 #include <udi_physio.h>
 
+struct udi_dma_handle_s
+{
+       
+};
+
 // === EXPORTS ===
 EXPORT(udi_dma_prepare);
 EXPORT(udi_dma_buf_map);
index dadb442..c0631f2 100644 (file)
@@ -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),
index 0c0ef6c..38c263e 100644 (file)
@@ -5,14 +5,15 @@
 #include <acess.h>
 #include <udi.h>
 #include <udi_physio.h>
+#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)
 {
index b70861b..2fa39ee 100644 (file)
@@ -1,10 +1,38 @@
 /**
- * \file physio/pio.c
+ * \file udi_lib/physio/pio.c
  * \author John Hodge (thePowersGang)
  */
+#define DEBUG  1
 #include <acess.h>
 #include <udi.h>
 #include <udi_physio.h>
+#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)

UCC git Repository :: git.ucc.asn.au