# - 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
#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;
};
tUDI_MetaLang *MetaLang;
bool Locked;
struct sUDI_ChannelSide Side[2];
+ struct sUDI_Channel *SpawnBinds[MAX_SPAWN_IDX];
} tUDI_Channel;
// === CODE ===
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;
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;
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
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;
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?
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 ++ )
{
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
// 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);
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));
#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 */
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)
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 ++;
}
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)
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,
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
},
const char *Name;
int nCbTypes;
struct {
- size_t Size;
+ udi_size_t Size;
udi_layout_t *Layout;
} CbTypes[];
};
struct sUDI_DriverInstance *Next;
tUDI_DriverModule *Module;
udi_channel_t ManagementChannel;
+ tUDI_DriverInstance *Parent;
+ tUDI_ChildBinding *ParentChildBinding;
+
tUDI_ChildBinding *FirstChild;
tUDI_DriverRegion *Regions[];
};
// --- 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);
// --- 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
--- /dev/null
+/**
+ * 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;
+}
* \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
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(
#define DEBUG 1
#include <acess.h>
#include <udi.h>
-//#include "internal/channels.h"
#include "../udi_internal.h"
// === EXPORTS ===
udi_channel_t channel, udi_index_t ops_idx, void *channel_context
)
{
- Warning("%s Unimplemented", __func__);
+ UNIMPLEMENTED();
}
/**
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);
}
/**
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)
* \file meta_mgmt.c
* \author John Hodge (thePowersGang)
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <udi.h>
#include "../udi_internal.h"
#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);
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(
void udi_dma_constraints_free(udi_dma_constraints_t constraints)
{
- UNIMPLEMENTED();
+ free(constraints);
}
#include <udi.h>
#include <udi_physio.h>
+struct udi_dma_handle_s
+{
+
+};
+
// === EXPORTS ===
EXPORT(udi_dma_prepare);
EXPORT(udi_dma_buf_map);
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),
#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);
{
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)
{
{
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)
{
/**
- * \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);
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)