if( other_side )
side_idx = 1 - side_idx;
- LOG("side_idx = %i, other_side=%b", side_idx, other_side);
-
return &ch->Side[side_idx];
}
if( context ) {
// Use provided context pointer
+ LOG("context = provided %p", context);
}
else if( ops->chan_context_size )
{
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 );
+ context = calloc( 1, 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;
+ LOG("context = allocated %p", context);
// 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;
+ LOG("context = region %p", context);
}
UDI_BindChannel_Raw(channel, other_side, inst, region, ops->meta_ops_num, context, ops->ops_vector);
void UDI_int_AddDeferred(tUDI_DeferredCall *Call)
{
+ LOG("Added deferred %p{um=%p,cb=%p,handler=%p}",
+ Call, Call->Unmarshal, Call->cb, Call->Handler);
Workqueue_AddWork(&gUDI_DeferredWorkQueue, Call);
}
struct sUDI_MetaLang
{
const char *Name;
- //void *MeiInfo;
+ const void *MeiInfo;
int nCbTypes;
struct {
udi_size_t Size;
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);
// --- Layout ---
+extern size_t _udi_marshal_step(void *buf, size_t cur_ofs, udi_layout_t **layoutp, va_list *values);
extern size_t _udi_marshal_values(void *buf, udi_layout_t *layout, va_list values);
+// --- Buffers ---
+extern udi_buf_t *_udi_buf_allocate(const void *data, udi_size_t length, udi_buf_path_t path_handle);
+
#endif
int interrupt_handle;
- udi_pio_handle_t intr_preprocessing;
+ udi_pio_handle_t intr_preprocessing;
udi_intr_event_cb_t *event_cbs[PCI_MAX_EVENT_CBS];
- int event_cb_wr_ofs;
- int event_cb_rd_ofs;
+ udi_index_t event_cb_wr_ofs;
+ udi_index_t event_cb_rd_ofs;
+ int bIntrEnabled;
} pci_child_chan_context_t;
// === PROTOTYPES ===
void pci_intr_ch_event_ind(udi_channel_event_cb_t *cb);
void pci_intr_event_rdy(udi_intr_event_cb_t *cb);
+void pci_intr_event_rdy__irqs_enabled(udi_cb_t *gcb, udi_buf_t *newbuf, udi_status_t status, udi_ubit16_t result);
void pci_intr_handler(int irq, void *void_context);
void pci_intr_handle__trans_done(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result);
context->interrupt_handle = IRQ_AddHandler(
PCI_GetIRQ(context->child_chan_context.child_ID),
- pci_intr_handler, new_channel);
+ pci_intr_handler, context);
udi_intr_attach_ack(cb, UDI_OK);
}
void pci_intr_event_rdy(udi_intr_event_cb_t *cb)
{
pci_child_chan_context_t *context = UDI_GCB(cb)->context;
+
+ ASSERTC(context->event_cb_rd_ofs, <, PCI_MAX_EVENT_CBS);
+ ASSERTC(context->event_cb_wr_ofs, <, PCI_MAX_EVENT_CBS);
+
+ LOG("Rd %i, Wr %i [WR %p]", context->event_cb_rd_ofs, context->event_cb_wr_ofs, cb);
if( context->event_cbs[context->event_cb_wr_ofs] )
{
// oops, overrun.
context->event_cbs[context->event_cb_wr_ofs++] = cb;
if( context->event_cb_wr_ofs == PCI_MAX_EVENT_CBS )
context->event_cb_wr_ofs = 0;
+
+ // TODO: Fire once >= min_event_pend CBs are recieved
+ if( !context->bIntrEnabled )
+ {
+ context->bIntrEnabled = 1;
+ udi_pio_trans(pci_intr_event_rdy__irqs_enabled, NULL, context->intr_preprocessing, 0, NULL, NULL);
+ }
+}
+void pci_intr_event_rdy__irqs_enabled(udi_cb_t *gcb, udi_buf_t *newbuf, udi_status_t status, udi_ubit16_t result)
+{
+ // nothing
}
void pci_intr_handler(int irq, void *void_context)
{
pci_child_chan_context_t *context = void_context;
+ LOG("irq=%i, context=%p", irq, context);
+
if( context->event_cb_rd_ofs == context->event_cb_wr_ofs ) {
// Dropped
return ;
}
+ ASSERTC(context->event_cb_rd_ofs, <, PCI_MAX_EVENT_CBS);
+ ASSERTC(context->event_cb_wr_ofs, <, PCI_MAX_EVENT_CBS);
+
udi_intr_event_cb_t *cb = context->event_cbs[context->event_cb_rd_ofs];
+ LOG("Rd %i, Wr %i [RD %p]", context->event_cb_rd_ofs, context->event_cb_wr_ofs, cb);
context->event_cbs[context->event_cb_rd_ofs] = NULL;
context->event_cb_rd_ofs ++;
if( context->event_cb_rd_ofs == PCI_MAX_EVENT_CBS )
context->event_cb_rd_ofs = 0;
+ ASSERT(cb);
if( UDI_HANDLE_IS_NULL(context->intr_preprocessing, udi_pio_handle_t) )
{
bar &= ~3;
#define _IO(fc, type) do {\
if( isOutput ) { \
- LOG("out"#fc"(0x%x, 0x%x)",bar+ofs,*(type*)data);\
+ /*LOG("out"#fc"(0x%x, 0x%x)",bar+ofs,*(type*)data);*/\
out##fc(bar+ofs, *(type*)data); \
} \
else { \
*(type*)data = in##fc(bar+ofs); \
- LOG("in"#fc"(0x%x) = 0x%x",bar+ofs,*(type*)data);\
+ /*LOG("in"#fc"(0x%x) = 0x%x",bar+ofs,*(type*)data);*/\
}\
} while(0)
switch(len)
enum {
ACESSNSR_CB_CTRL = 1,
ACESSNSR_CB_RX,
- ACESSNSR_CB_TX
+ ACESSNSR_CB_TX,
+ ACESSNSR_CB_STD,
};
// === TYPES ===
{
udi_init_context_t init_context;
udi_cb_t *active_cb;
-
- udi_index_t init_idx;
- udi_buf_t *rx_buffers[NUM_RX_BUFFERS];
- udi_nic_rx_cb_t *rx_cbs[NUM_RX_BUFFERS];
+ udi_channel_t saved_active_channel;
tWorkqueue RXQueue;
void acessnsr_ctrl_ch_ev_ind__rx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
void acessnsr_ctrl_ch_ev_ind__tx_channel_spawned(udi_cb_t *gcb, udi_channel_t channel);
void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status);
-void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf);
-void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
-void acessnsr_ctrl_bind_ack__tx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
+void acessnsr_ctrl_bind_ack__rx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb);
+void acessnsr_ctrl_bind_ack__tx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb);
+void acessnsr_ctrl_bind_ack__std_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb);
void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status);
void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status);
void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status);
break;
}
+ // - Register with IPStack
if(cb->capabilities & UDI_NIC_CAP_TX_IP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_IP4;
if(cb->capabilities & UDI_NIC_CAP_TX_TCP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_TCP;
if(cb->capabilities & UDI_NIC_CAP_TX_UDP_CKSUM)
rdata->AdapterType.Flags |= ADAPTERFLAG_OFFLOAD_UDP;
-
rdata->AdapterType.Name = "udi";
rdata->AdapterType.SendPacket = acessnsr_SendPacket;
rdata->AdapterType.WaitForPacket = acessnsr_WaitForPacket;
-
rdata->ipstack_handle = IPStack_Adapter_Add(&rdata->AdapterType, rdata, cb->mac_addr);
// Allocate RX CBs and buffers
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__rx_buf_allocated(rdata->active_cb, NULL);
+ // EVIL: Save and change channel of event CB
+ rdata->saved_active_channel = rdata->active_cb->channel;
+ rdata->active_cb->channel = rdata->rx_channel;
+ udi_cb_alloc_batch( acessnsr_ctrl_bind_ack__rx_cbs_allocated, rdata->active_cb,
+ ACESSNSR_CB_RX, NUM_RX_BUFFERS, TRUE, 0, NULL);
// V V V V
}
-void acessnsr_ctrl_bind_ack__rx_buf_allocated(udi_cb_t *gcb, udi_buf_t *new_buf)
+void acessnsr_ctrl_bind_ack__rx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb)
{
acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- rdata->rx_buffers[rdata->init_idx] = new_buf;
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_RX_BUFFERS )
- {
- UDI_BUF_ALLOC(acessnsr_ctrl_bind_ack__rx_buf_allocated, gcb, NULL, 0, NULL);
- // A A A A
- return ;
- }
+ // Send of the entire list
+ ASSERT(first_new_cb);
+ udi_nd_rx_rdy( UDI_MCB(first_new_cb, udi_nic_rx_cb_t) );
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__rx_cb_allocated(gcb, NULL);
+ // Allocate batch (no buffers)
+ gcb->channel = rdata->tx_channel;
+ udi_cb_alloc_batch( acessnsr_ctrl_bind_ack__tx_cbs_allocated, gcb,
+ ACESSNSR_CB_TX, NUM_TX_DESCS, FALSE, 0, NULL);
+ // V V V V
}
-void acessnsr_ctrl_bind_ack__rx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
+void acessnsr_ctrl_bind_ack__tx_cbs_allocated(udi_cb_t *gcb, udi_cb_t *first_new_cb)
{
acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- udi_nic_rx_cb_t *cb = UDI_MCB(new_cb, udi_nic_rx_cb_t);
- rdata->rx_cbs[rdata->init_idx] = cb;
- cb->rx_buf = rdata->rx_buffers[rdata->init_idx];
- udi_nd_rx_rdy(cb);
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_RX_BUFFERS )
+ ASSERT(first_new_cb);
+
{
- udi_cb_alloc(acessnsr_ctrl_bind_ack__rx_cb_allocated, gcb, ACESSNSR_CB_RX, rdata->rx_channel);
- // A A A A
- return ;
+ udi_nic_tx_cb_t *cb, *next_cb;
+ cb = UDI_MCB(first_new_cb, udi_nic_tx_cb_t);
+ ASSERT(cb);
+ do {
+ next_cb = cb->chain;
+ cb->chain = NULL;
+ Workqueue_AddWork( &rdata->TXWorkQueue, cb );
+ } while(next_cb);
}
- rdata->init_idx = -1;
- acessnsr_ctrl_bind_ack__tx_cb_allocated(gcb, NULL);
+
+ // Allocate standard control CB (for enable/disable)
+ udi_cb_alloc(acessnsr_ctrl_bind_ack__std_cb_allocated, gcb,
+ ACESSNSR_CB_STD, rdata->saved_active_channel);
// V V V V
}
-void acessnsr_ctrl_bind_ack__tx_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
+void acessnsr_ctrl_bind_ack__std_cb_allocated(udi_cb_t *gcb, udi_cb_t *new_cb)
{
- acessnsr_rdata_t *rdata = gcb->context;
- if( rdata->init_idx != (udi_index_t)-1 )
- {
- //udi_assert(new_cb);
- ASSERT(new_cb);
- Workqueue_AddWork( &rdata->TXWorkQueue, UDI_MCB(new_cb, udi_nic_tx_cb_t) );
- }
- rdata->init_idx ++;
- if( rdata->init_idx < NUM_TX_DESCS )
- {
- udi_cb_alloc(acessnsr_ctrl_bind_ack__tx_cb_allocated, gcb, ACESSNSR_CB_TX, rdata->tx_channel);
- // A A A A
- return ;
- }
- udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
- // = = = =
+ // Final Operations:
+ // - Enable card (RX won't happen until this is called)
+ udi_nd_enable_req( UDI_MCB(new_cb, udi_nic_cb_t) );
+ // Continued in acessnsr_ctrl_enable_ack
}
void acessnsr_ctrl_unbind_ack(udi_nic_cb_t *cb, udi_status_t status)
{
}
void acessnsr_ctrl_enable_ack(udi_nic_cb_t *cb, udi_status_t status)
{
- UNIMPLEMENTED();
+ udi_cb_t *gcb = UDI_GCB(cb);
+ acessnsr_rdata_t *rdata = gcb->context;
+
+ rdata->active_cb->channel = rdata->saved_active_channel;
+ udi_channel_event_complete( UDI_MCB(rdata->active_cb,udi_channel_event_cb_t), UDI_OK );
+ // = = = =
}
void acessnsr_ctrl_disable_ack(udi_nic_cb_t *cb, udi_status_t status)
{
int acessnsr_SendPacket(void *Card, tIPStackBuffer *Buffer)
{
acessnsr_rdata_t *rdata = Card;
+ LOG("Card=%p,Buffer=%p", Card, Buffer);
udi_nic_tx_cb_t *cb = Workqueue_GetWork(&rdata->TXWorkQueue);
ASSERT(cb);
acessnsr_txdesc_t *tx = UDI_GCB(cb)->scratch;
ASSERT(tx);
-
+
+ LOG("Mutex acquire #1 %p", cb);
Mutex_Acquire(&tx->CompleteMutex);
tx->IPBuffer = Buffer;
tx->BufIdx = -1;
Mutex_Release(&tx->CompleteMutex);
// TODO: TX status
- Workqueue_AddWork(&rdata->TXWorkQueue, tx);
+ LOG("Release %p", cb);
+ Workqueue_AddWork(&rdata->TXWorkQueue, cb);
return 0;
}
void acessnsr_SendPacket__buf_write_complete(udi_cb_t *gcb, udi_buf_t *buf)
const void *bufptr;
if( (tx->BufIdx = IPStack_Buffer_GetBuffer(tx->IPBuffer, tx->BufIdx, &buflen, &bufptr )) != -1 )
{
+ Debug_HexDump("NSR", bufptr, buflen);
udi_buf_write(acessnsr_SendPacket__buf_write_complete, gcb,
bufptr, buflen, cb->tx_buf, (cb->tx_buf ? cb->tx_buf->buf_size : 0), 0, NULL);
// A A A A
{ACESSNSR_CB_CTRL, ACESSNSR_META_NIC, UDI_NIC_BIND_CB_NUM, 0, 0,NULL},
{ACESSNSR_CB_RX, ACESSNSR_META_NIC, UDI_NIC_RX_CB_NUM, 0, 0,NULL},
{ACESSNSR_CB_TX, ACESSNSR_META_NIC, UDI_NIC_TX_CB_NUM, sizeof(acessnsr_txdesc_t), 0,NULL},
+ {ACESSNSR_CB_STD, ACESSNSR_META_NIC, UDI_NIC_TX_CB_NUM, 0, 0,NULL},
{0}
};
const udi_init_t acessnsr_init = {
*
* Buffer Manipulation
*/
+#define DEBUG 0
#include <acess.h>
#include <udi.h>
#include <udi_internal.h>
typedef struct sUDI_BufSect
{
struct sUDI_BufSect *Next;
- size_t Offset;
+ size_t RelOfs;
size_t Length;
size_t Space;
+ void *Data;
// data
} tUDI_BufSect;
udi_buf_t *dst_buf,
udi_size_t dst_off,
udi_size_t dst_len,
- udi_buf_path_t path_handle
+ udi_buf_path_t path_handle
)
{
UNIMPLEMENTED();
}
+tUDI_BufSect *UDI_int_BufAddSect(size_t data_len, size_t relofs, tUDI_BufSect **prevptr, const void *data,
+ udi_buf_path_t path_handle
+ )
+{
+ const int space_atom = 1<<7;
+ size_t space = (data_len + space_atom-1) & ~(space_atom-1);
+ tUDI_BufSect *newsect = NEW(tUDI_BufSect, + space);
+ newsect->RelOfs = relofs;
+ newsect->Length = data_len;
+ newsect->Space = space_atom;
+ newsect->Data = newsect+1;
+ memcpy(newsect->Data, data, data_len);
+
+ newsect->Next = *prevptr;
+ *prevptr = newsect;
+ LOG("@0x%x : %p <= %p+%i", relofs, newsect->Data, data, data_len);
+
+ return newsect;
+}
+
+udi_buf_t *_udi_buf_allocate(const void *data, udi_size_t length, udi_buf_path_t path_handle)
+{
+ tUDI_BufInt *buf = NEW(tUDI_BufInt,);
+ udi_buf_t *ret = &buf->buf;
+
+ if( data ) {
+ UDI_int_BufAddSect(length, 0, &buf->Sections, data, path_handle);
+ }
+ ret->buf_size = length;
+
+ return ret;
+}
+
/**
* \brief Write to a buffer
* \param callback Function to call once the write has completed
* \param src_len Length of source data
* \param dst_buf Destination buffer
* \param dst_off Destination offset in the buffer
- * \param dst_len Length of destination area
+ * \param dst_len Length of area to be replaced
* \param path_handle ???
*/
void udi_buf_write(
tUDI_BufInt *dst = (void*)dst_buf;
if( !dst ) {
dst = NEW(tUDI_BufInt,);
+ dst_buf = &dst->buf;
}
-
+
+ tUDI_BufSect **prevptr = &dst->Sections;
+ tUDI_BufSect *sect = dst->Sections;
+ for( ; sect; prevptr = §->Next, sect = sect->Next )
+ {
+ if(sect->RelOfs >= dst_off)
+ break;
+ if(sect->RelOfs + sect->Length > dst_off)
+ break ;
+ dst_off -= sect->RelOfs + sect->Length;
+ }
+
+ // Find dst_off segment (or create one if src_len>0)
+ // Copy in src data
+ // or (if src_len==0) delete dst_len bytes
if( dst_len == 0 )
{
// Insert / Initialise
if( src_len > 0 )
{
- Log_Warning("UDI", "TODO: udi_buf_write - insert");
+ if( !sect || sect->RelOfs > dst_off ) {
+ // Simple: Just add a new section
+ UDI_int_BufAddSect(src_len, dst_off, prevptr, src_mem, path_handle);
+ dst_buf->buf_size += src_len;
+ }
+ else if( sect->RelOfs + sect->Length == dst_off ) {
+ // End of block inserts
+ size_t avail = sect->Space - sect->Length;
+ if( avail ) {
+ size_t bytes = MIN(avail, src_len);
+ memcpy(sect->Data + sect->Length, src_mem, bytes);
+ src_mem += bytes;
+ src_len -= bytes;
+ }
+ if( src_len ) {
+ // New block(s)
+ UDI_int_BufAddSect(src_len, 0, prevptr, src_mem, path_handle);
+ }
+ dst_buf->buf_size += src_len;
+ }
+ else {
+ // Complex: Need to handle mid-section inserts
+ Log_Warning("UDI", "TODO: udi_buf_write - mid-section inserts");
+ }
}
// no-op
else
}
else
{
- // Overwrite
- if( src_len > 0 )
+ // Delete
+ if( src_len == 0 )
{
- Log_Warning("UDI", "TODO: udi_buf_write - overwrite");
+ Log_Warning("UDI", "TODO: udi_buf_write - delete");
}
- // Delete
+ // Overwrite
else
{
- Log_Warning("UDI", "TODO: udi_buf_write - delete");
+ Log_Warning("UDI", "TODO: udi_buf_write - overwrite");
}
}
udi_size_t src_len,
void *dst_mem )
{
- UNIMPLEMENTED();
+ ENTER("psrc_buf isrc_off isrc_len pdst_mem",
+ src_buf, src_off, src_len, dst_mem);
+ tUDI_BufInt *src = (void*)src_buf;
+
+ tUDI_BufSect *sect = src->Sections;
+ while( src_len )
+ {
+ for( ; sect; sect = sect->Next )
+ {
+ LOG("%x <= %x <= +%x", sect->RelOfs, src_off, sect->Length);
+ if(sect->RelOfs >= src_off)
+ break;
+ if(sect->RelOfs + sect->Length > src_off)
+ break;
+ src_off -= sect->RelOfs + sect->Length;
+ }
+ if( !sect ) {
+ LOG("no section");
+ break;
+ }
+ if( src_off < sect->RelOfs ) {
+ size_t undef_len = MIN(src_len, sect->RelOfs - src_off);
+ LOG("%i undef", undef_len);
+ memset(dst_mem, 0xFF, undef_len);
+ dst_mem += undef_len;
+ src_len -= undef_len;
+ src_off += undef_len;
+ }
+ if( src_len == 0 )
+ break;
+ ASSERTC(src_off, >=, sect->RelOfs);
+ size_t ofs = src_off - sect->RelOfs;
+ size_t len = MIN(src_len, sect->Length - ofs);
+ LOG("%i data from %p + %i", len, sect->Data, ofs);
+ memcpy(dst_mem, sect->Data+ofs, len);
+ dst_mem += len;
+ src_len -= len;
+
+ src_off -= sect->RelOfs + sect->Length;
+ sect = sect->Next;
+ }
+ LEAVE('-');
}
void udi_buf_free(udi_buf_t *buf)
size_t base = Meta->CbTypes[MetaCBNum].Size;
ASSERTC(base, >=, sizeof(udi_cb_t));
base -= sizeof(udi_cb_t);
- LOG("(%s) udi_cb_t + %i + %i + %i",
- Meta->Name, base, inline_size, scratch_size);
tUDI_CBHeader *cbhdr = NEW(tUDI_CBHeader, + base + inline_size + scratch_size);
cbhdr->Metalang = Meta;
cbhdr->MetaCBNum = MetaCBNum;
udi_cb_t *ret = &cbhdr->cb;
ret->channel = channel;
ret->scratch = (void*)(ret + 1) + base + inline_size;
+ LOG("(%s) udi_cb_t + %i + %i + %i = %p",
+ Meta->Name, base, inline_size, scratch_size, ret);
return ret;
}
void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, udi_channel_t channel)
udi_buf_path_t path_handle
)
{
- UNIMPLEMENTED();
+ tUDI_DriverInstance *inst = UDI_int_ChannelGetInstance(gcb, false, NULL);
+ udi_cb_init_t *cb_init;
+ for( cb_init = inst->Module->InitInfo->cb_init_list; cb_init->cb_idx; cb_init ++ )
+ {
+ if( cb_init->cb_idx == cb_idx )
+ break;
+ }
+ if( cb_init->cb_idx == 0 ) {
+ callback(gcb, NULL);
+ return ;
+ }
+ tUDI_MetaLang *metalang = UDI_int_GetMetaLang(inst->Module, cb_init->meta_idx);
+ if( !metalang ) {
+ Log_Warning("UDI", "Metalang referenced in %s CB %i is invalid (%i)",
+ inst->Module->ModuleName, cb_idx, cb_init->meta_idx);
+ callback(gcb, NULL);
+ return ;
+ }
+
+ if( cb_init->meta_cb_num >= metalang->nCbTypes ) {
+ Log_Warning("UDI", "Metalang CB referenced in %s CB %i is invalid (%s %i>=%i)",
+ inst->Module->ModuleName, cb_idx,
+ metalang->Name, cb_init->meta_cb_num, metalang->nCbTypes);
+ callback(gcb, NULL);
+ return ;
+ }
+
+ // Get chain offset and buffer offset
+ size_t buf_ofs = 0; // TODO: Multiple buffers are to be supported
+ size_t chain_ofs = 0;
+ {
+ udi_layout_t *layout = metalang->CbTypes[cb_init->meta_cb_num].Layout;
+ if( !layout ) {
+ Log_Warning("UDI", "Metalang CB %s:%i does not define a layout. Bulk alloc impossible",
+ metalang->Name, cb_init->meta_cb_num);
+ callback(gcb, NULL);
+ return ;
+ }
+
+ size_t cur_ofs = sizeof(udi_cb_t);
+ while( *layout != UDI_DL_END )
+ {
+ if( *layout == UDI_DL_BUF ) {
+ if( buf_ofs ) {
+ Log_Notice("UDI", "TODO Multiple buffers in cb_alloc_batch (%s:%i)",
+ metalang->Name, cb_init->meta_cb_num);
+ }
+ buf_ofs = cur_ofs;
+ }
+ else if( *layout == UDI_DL_CB ) {
+ if( chain_ofs ) {
+ Log_Warning("UDI", "Cb %s:%i has multiple DL_CB entries",
+ metalang->Name, cb_init->meta_cb_num);
+ }
+ chain_ofs = cur_ofs;
+ }
+ else {
+ // No-op
+ }
+
+ cur_ofs += _udi_marshal_step(NULL, 0, &layout, NULL);
+ layout ++;
+ }
+ }
+
+ // Use initiator context if there's no chain
+ if( !chain_ofs ) {
+ chain_ofs = offsetof(udi_cb_t, initiator_context);
+ LOG("chain_ofs = %i (initiator_context)", chain_ofs);
+ }
+ else {
+ LOG("chain_ofs = %i", chain_ofs);
+ }
+
+ udi_cb_t *first_cb = NULL, *cur_cb;
+ udi_cb_t **prevptr = &first_cb;
+ for( int i = 0; i < count; i ++ )
+ {
+ cur_cb = udi_cb_alloc_internal_v(metalang, cb_init->meta_cb_num,
+ cb_init->inline_size, cb_init->scratch_requirement, gcb->channel);
+
+ // Allocate buffer
+ if( with_buf && buf_ofs ) {
+ *(void**)((char*)cur_cb + buf_ofs) =_udi_buf_allocate(NULL, buf_size, path_handle);
+ }
+
+ LOG("*%p = %p", prevptr, cur_cb);
+ *prevptr = cur_cb;
+ prevptr = (void*)cur_cb + chain_ofs;
+ }
+ *prevptr = NULL;
+
+ callback(gcb, first_cb);
}
void udi_cb_free(udi_cb_t *cb)
#define _PUT(type,vtype) do{\
ofs = alignto(ofs,type); \
if(buf){\
- *(type*)(buf+ofs) = va_arg(values,vtype);\
+ *(type*)(buf+ofs) = va_arg(*values,vtype);\
LOG(#type" %p %x", buf+ofs, *(type*)(buf+ofs));\
}\
- else va_arg(values,vtype); \
+ else if(values) \
+ va_arg(*values,vtype); \
ofs += sizeof(type); \
}while(0)
+size_t _udi_marshal_step(void *buf, size_t cur_ofs, udi_layout_t **layoutp, va_list *values)
+{
+ size_t ofs = cur_ofs;
+ udi_layout_t *layout = *layoutp;
+ switch(*layout++)
+ {
+ case UDI_DL_UBIT8_T: _PUT(udi_ubit8_t, UDI_VA_UBIT8_T); break;
+ case UDI_DL_SBIT8_T: _PUT(udi_sbit8_t, UDI_VA_SBIT8_T); break;
+ case UDI_DL_UBIT16_T: _PUT(udi_ubit16_t, UDI_VA_UBIT16_T); break;
+ case UDI_DL_SBIT16_T: _PUT(udi_sbit16_t, UDI_VA_SBIT16_T); break;
+ case UDI_DL_UBIT32_T: _PUT(udi_ubit32_t, UDI_VA_UBIT32_T); break;
+ case UDI_DL_SBIT32_T: _PUT(udi_sbit32_t, UDI_VA_SBIT16_T); break;
+ case UDI_DL_BOOLEAN_T: _PUT(udi_boolean_t, UDI_VA_BOOLEAN_T); break;
+ case UDI_DL_STATUS_T: _PUT(udi_status_t, UDI_VA_STATUS_T); break;
+
+ case UDI_DL_INDEX_T: _PUT(udi_index_t, UDI_VA_INDEX_T); break;
+
+ case UDI_DL_CHANNEL_T: _PUT(udi_channel_t, UDI_VA_CHANNEL_T); break;
+ case UDI_DL_ORIGIN_T: _PUT(udi_origin_t, UDI_VA_ORIGIN_T); break;
+
+ case UDI_DL_BUF:
+ _PUT(udi_buf_t*,UDI_VA_POINTER);
+ layout += 3;
+ break;
+ case UDI_DL_CB:
+ _PUT(udi_cb_t*,UDI_VA_POINTER);
+ break;
+
+ default:
+ Log_Error("UDI", "_udi_marshal_values - Unknown layout code %i", layout[-1]);
+ return 0;
+ }
+ *layoutp = layout;
+ return ofs;
+}
+
size_t _udi_marshal_values(void *buf, udi_layout_t *layout, va_list values)
{
size_t ofs = 0;
while( *layout != UDI_DL_END )
{
- switch(*layout++)
- {
- case UDI_DL_UBIT8_T: _PUT(udi_ubit8_t, UDI_VA_UBIT8_T); break;
- case UDI_DL_SBIT8_T: _PUT(udi_sbit8_t, UDI_VA_SBIT8_T); break;
- case UDI_DL_UBIT16_T: _PUT(udi_ubit16_t, UDI_VA_UBIT16_T); break;
- case UDI_DL_SBIT16_T: _PUT(udi_sbit16_t, UDI_VA_SBIT16_T); break;
- case UDI_DL_UBIT32_T: _PUT(udi_ubit32_t, UDI_VA_UBIT32_T); break;
- case UDI_DL_SBIT32_T: _PUT(udi_sbit32_t, UDI_VA_SBIT16_T); break;
- case UDI_DL_BOOLEAN_T: _PUT(udi_boolean_t, UDI_VA_BOOLEAN_T); break;
- case UDI_DL_STATUS_T: _PUT(udi_status_t, UDI_VA_STATUS_T); break;
-
- case UDI_DL_INDEX_T: _PUT(udi_index_t, UDI_VA_INDEX_T); break;
-
- case UDI_DL_CHANNEL_T: _PUT(udi_channel_t, UDI_VA_CHANNEL_T); break;
- case UDI_DL_ORIGIN_T: _PUT(udi_origin_t, UDI_VA_ORIGIN_T); break;
-
- default:
- Log_Error("UDI", "_udi_marshal_values - Unknown layout code %i", layout[-1]);
- return -1;
- }
+ ofs = _udi_marshal_step(buf, ofs, &layout, &values);
+ if( ofs == 0 )
+ return 0;
}
return ofs;
}
{
tUDI_MeiCall *Call = (void*)DCall;
const udi_mei_op_template_t *mei_op = Call->mei_op;
+ LOG("%s backend", mei_op->op_name);
mei_op->backend_stub(Call->DCall.Handler, Call->DCall.cb, Call+1);
}
void udi_mei_call(udi_cb_t *gcb, udi_mei_init_t *meta_info, udi_index_t meta_ops_num, udi_index_t vec_idx, ...)
{
- ENTER("pgcb pmeta_info imeta_ops_num ivec_idx",
- gcb, meta_info, meta_ops_num, vec_idx);
+// ENTER("pgcb pmeta_info imeta_ops_num ivec_idx",
+// gcb, meta_info, meta_ops_num, vec_idx);
const udi_mei_op_template_t *mei_op;
{
mei_op = &ops->op_template_list[vec_idx-1];
}
- LOG("%s", mei_op->op_name);
-
// Check CB type
udi_index_t cb_type;
tUDI_MetaLang *metalang = UDI_int_GetCbType(gcb, &cb_type);
- //if( metalang->MeiInfo != meta_info )
- // return ;
- if( mei_op->meta_cb_num != cb_type ) {
- LEAVE('-');
+ if( meta_info != metalang->MeiInfo && mei_op->meta_cb_num != cb_type ) {
+ Log_Warning("UDI", "%s meta cb mismatch want %p:%i got %p:%i",
+ mei_op->op_name,
+ meta_info, mei_op->meta_cb_num,
+ metalang->MeiInfo, cb_type
+ );
+ ASSERTC(meta_info, ==, metalang->MeiInfo);
+ ASSERTC(mei_op->meta_cb_num, ==, cb_type);
+// LEAVE('-');
return ;
}
- // Check call type
- udi_op_t *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
- udi_op_t *op = ops[vec_idx];
- // Start va_args
// Determine if indirect call is needed
// > check stack depth?
// > Direction?
int indirect_call = (mei_op->op_category == UDI_MEI_OPCAT_REQ)
|| (mei_op->op_category == UDI_MEI_OPCAT_IND);
+
+ LOG("%s %sdirect", mei_op->op_name, (indirect_call ? "in" : ""));
+
+ // Check call type
+ udi_op_t *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
+ udi_op_t *op = ops[vec_idx];
if( indirect_call )
{
va_list args;
mei_op->direct_stub( op, gcb, args );
va_end(args);
}
- LEAVE('-');
+// LEAVE('-');
}
tUDI_MetaLang cMetaLang_Management = {
"udi_mgmt",
-
+ NULL,
3,
{
{sizeof(udi_enumerate_cb_t), NULL},
UDI_DL_END
};
+udi_layout_t _BUS_BIND_cb_layout[] = {
+ UDI_DL_END
+};
+
#if USE_MEI
udi_layout_t _noargs_marshal[] = {
UDI_DL_END
#endif
tUDI_MetaLang cMetaLang_BusBridge = {
"udi_bridge",
+ #if USE_MEI
+ &udi_meta_info__bridge,
+ #else
+ NULL,
+ #endif
// CB Types
5,
{
* \file udi_lib/physio/pio.c
* \author John Hodge (thePowersGang)
*/
-#define DEBUG 0
+#define DEBUG 1
#include <udi.h>
#include <udi_physio.h>
#include <acess.h>
case UDI_PIO_SCRATCH:
ASSERTCR( (ofs & (size-1)), ==, 0, 1);
memcpy(val, gcb->scratch + ofs, size);
+ //LOG("scr %p+%i => %i %x,...", gcb->scratch, ofs, size, val->words[0]);
break;
case UDI_PIO_BUF:
udi_buf_read(buf, ofs, size, val);
+ //LOG("buf %p+%i => %i %x,...", buf, ofs, size, val->words[0]);
break;
case UDI_PIO_MEM:
ASSERTCR( (ofs & (size-1)), ==, 0, 1 );
memcpy(val, mem_ptr + ofs, size);
+ //LOG("mem %p+%i => %i %x,...", mem_ptr, ofs, size, val->words[0]);
break;
}
return 0;
EXPORT(udi_nsr_exp_rx_ind);
EXPORT(udi_nd_rx_rdy);
-// === GLOBALS ===
-tUDI_MetaLang cMetaLang_NIC = {
- "udi_nic",
- 8,
- {
- {0},
- {sizeof(udi_nic_cb_t), NULL},
- {sizeof(udi_nic_bind_cb_t), NULL},
- {sizeof(udi_nic_ctrl_cb_t), NULL},
- {sizeof(udi_nic_status_cb_t), NULL},
- {sizeof(udi_nic_info_cb_t), NULL},
- {sizeof(udi_nic_tx_cb_t), NULL},
- {sizeof(udi_nic_rx_cb_t), NULL},
- }
-};
-
// === CODE ===
// --- Control Ops ---
+// ND - Network Device
UDI_MEI_STUBS(udi_nd_bind_req, udi_nic_bind_cb_t,
- 2,
- (tx_chan_index, rx_chan_index),
- (udi_index_t, udi_index_t),
- (UDI_VA_INDEX_T, UDI_VA_INDEX_T),
+ 2, (tx_chan_index, rx_chan_index), (udi_index_t, udi_index_t), (UDI_VA_INDEX_T, UDI_VA_INDEX_T),
UDI_ND_CTRL_OPS_NUM, 1)
udi_layout_t _udi_nd_bind_req_marshal_layout[] = { UDI_DL_INDEX_T, UDI_DL_INDEX_T, UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nd_unbind_req, udi_nic_cb_t,
+ 0, (), (), (),
+ UDI_ND_CTRL_OPS_NUM, 2)
+udi_layout_t _udi_nd_unbind_req_marshal_layout[] = { UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nd_enable_req, udi_nic_cb_t,
+ 0, (), (), (),
+ UDI_ND_CTRL_OPS_NUM, 3)
+udi_layout_t _udi_nd_enable_req_marshal_layout[] = { UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nd_disable_req, udi_nic_cb_t,
+ 0, (), (), (),
+ UDI_ND_CTRL_OPS_NUM, 4)
+udi_layout_t _udi_nd_disable_req_marshal_layout[] = { UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nd_ctrl_req, udi_nic_ctrl_cb_t,
+ 0, (), (), (),
+ UDI_ND_CTRL_OPS_NUM, 5)
+udi_layout_t _udi_nd_ctrl_req_marshal_layout[] = { UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nd_info_req, udi_nic_info_cb_t,
+ 1, (reset_statistics), (udi_boolean_t), (UDI_VA_BOOLEAN_T),
+ UDI_ND_CTRL_OPS_NUM, 6)
+udi_layout_t _udi_nd_info_req_marshal_layout[] = { UDI_DL_BOOLEAN_T, UDI_DL_END };
+
+// NSR - Network Service Requester
UDI_MEI_STUBS(udi_nsr_bind_ack, udi_nic_bind_cb_t,
1, (status), (udi_status_t), (UDI_VA_STATUS_T),
UDI_NSR_CTRL_OPS_NUM, 1)
udi_layout_t _udi_nsr_bind_ack_marshal_layout[] = { UDI_DL_STATUS_T, UDI_DL_END };
-void udi_nd_unbind_req(udi_nic_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nsr_unbind_ack(udi_nic_cb_t *cb, udi_status_t status)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nd_enable_req(udi_nic_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nsr_enable_ack(udi_nic_cb_t *cb, udi_status_t status)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nd_disable_req(udi_nic_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nd_ctrl_req(udi_nic_ctrl_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nsr_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nsr_status_ind(udi_nic_status_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nd_info_req(udi_nic_info_cb_t *cb, udi_boolean_t reset_statistics)
-{
- UNIMPLEMENTED();
-}
-
-void udi_nsr_info_ack(udi_nic_info_cb_t *cb)
-{
- UNIMPLEMENTED();
-}
+UDI_MEI_STUBS(udi_nsr_unbind_ack, udi_nic_cb_t,
+ 1, (status), (udi_status_t), (UDI_VA_STATUS_T),
+ UDI_NSR_CTRL_OPS_NUM, 2)
+udi_layout_t _udi_nsr_unbind_ack_marshal_layout[] = { UDI_DL_STATUS_T, UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nsr_enable_ack, udi_nic_cb_t,
+ 1, (status), (udi_status_t), (UDI_VA_STATUS_T),
+ UDI_NSR_CTRL_OPS_NUM, 3)
+udi_layout_t _udi_nsr_enable_ack_marshal_layout[] = { UDI_DL_STATUS_T, UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nsr_ctrl_ack, udi_nic_ctrl_cb_t,
+ 1, (status), (udi_status_t), (UDI_VA_STATUS_T),
+ UDI_NSR_CTRL_OPS_NUM, 4)
+udi_layout_t _udi_nsr_ctrl_ack_marshal_layout[] = { UDI_DL_STATUS_T, UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nsr_status_ind, udi_nic_status_cb_t,
+ 0, (), (), (),
+ UDI_NSR_CTRL_OPS_NUM, 5)
+udi_layout_t _udi_nsr_status_ind_marshal_layout[] = { UDI_DL_END };
+
+UDI_MEI_STUBS(udi_nsr_info_ack, udi_nic_info_cb_t,
+ 0, (), (), (),
+ UDI_NSR_CTRL_OPS_NUM, 6)
+udi_layout_t _udi_nsr_info_ack_marshal_layout[] = { UDI_DL_END };
// --- TX ---
UDI_MEI_STUBS(udi_nsr_tx_rdy, udi_nic_tx_cb_t, 0, (), (), (), UDI_NSR_TX_OPS_NUM, 1);
UDI_##rsp_ops##_OPS_NUM,rsp_idx,UDI_##err_ops##_OPS_NUM,err_idx, \
name##_direct, name##_backend, _##cbtype##_cb_layout, _##name##_marshal_layout }
+// 1: UDI_NIC_STD_CB_NUM
+udi_layout_t _NIC_STD_cb_layout[] = {
+ UDI_DL_END
+};
+// 2: UDI_NIC_BIND_CB_NUM
udi_layout_t _NIC_BIND_cb_layout[] = {
UDI_DL_UBIT8_T, // media_type
UDI_DL_UBIT32_T, // min_pdu_size
UDI_DL_END,
UDI_DL_END
};
+// 3: UDI_NIC_CTRL_CB_NUM
+udi_layout_t _NIC_CTRL_cb_layout[] = {
+ UDI_DL_UBIT8_T, // command
+ UDI_DL_UBIT32_T, // indicator
+ UDI_DL_BUF, 0,0,0, // data_buf
+ UDI_DL_END
+
+};
+// 4: UDI_NIC_STATUS_CB_NUM
+udi_layout_t _NIC_STATUS_cb_layout[] = {
+ UDI_DL_UBIT8_T,
+ UDI_DL_END
+};
+// 5: UDI_NIC_INFO_CB_NUM
+udi_layout_t _NIC_INFO_cb_layout[] = {
+ UDI_DL_BOOLEAN_T, // interface_is_active
+ UDI_DL_BOOLEAN_T, // link_is_active
+ UDI_DL_BOOLEAN_T, // is_full_duplex
+ UDI_DL_UBIT32_T, // link_mbps
+ UDI_DL_UBIT32_T, // link_bps
+ UDI_DL_UBIT32_T, // tx_packets
+ UDI_DL_UBIT32_T, // rx_packets
+ UDI_DL_UBIT32_T, // tx_errors
+ UDI_DL_UBIT32_T, // rx_errors
+ UDI_DL_UBIT32_T, // tx_discards
+ UDI_DL_UBIT32_T, // rx_discards
+ UDI_DL_UBIT32_T, // tx_underrun
+ UDI_DL_UBIT32_T, // rx_underrun
+ UDI_DL_UBIT32_T, // collisions
+ UDI_DL_END
+};
+// 6: UDI_NIC_RX_CB_NUM
udi_layout_t _NIC_RX_cb_layout[] = {
UDI_DL_CB, // chain
UDI_DL_BUF, 0, 0, 0, // rx_buf
UDI_DL_UBIT8_T, // rx_valid
UDI_DL_END
};
+// 7: UDI_NIC_TX_CB_NUM
udi_layout_t _NIC_TX_cb_layout[] = {
UDI_DL_CB, // chain
UDI_DL_BUF, 0, 0, 0, // tx_buf
udi_mei_op_template_t udi_mei_info__nic__nd_ctrl_ops[] = {
MEI_OPINFO(udi_nd_bind_req, REQ, 0, NIC_BIND, NSR_CTRL,1, ,0),
+ MEI_OPINFO(udi_nd_unbind_req, REQ, 0, NIC_STD, NSR_CTRL,2, ,0),
+ MEI_OPINFO(udi_nd_enable_req, REQ, 0, NIC_STD, NSR_CTRL,3, ,0),
+ MEI_OPINFO(udi_nd_disable_req, REQ, 0, NIC_STD, ,0, ,0),
+ MEI_OPINFO(udi_nd_ctrl_req, REQ, 0, NIC_CTRL, NSR_CTRL,4, ,0),
+ MEI_OPINFO(udi_nd_info_req, REQ, 0, NIC_INFO, NSR_CTRL,5, ,0),
{0}
};
udi_mei_op_template_t udi_mei_info__nic__nsr_ctrl_ops[] = {
MEI_OPINFO(udi_nsr_bind_ack, ACK, 0, NIC_BIND, ,0, ,0),
+ MEI_OPINFO(udi_nsr_unbind_ack, ACK, 0, NIC_STD, ,0, ,0),
+ MEI_OPINFO(udi_nsr_enable_ack, ACK, 0, NIC_STD, ,0, ,0),
+ MEI_OPINFO(udi_nsr_ctrl_ack, ACK, 0, NIC_CTRL, ,0, ,0),
+ MEI_OPINFO(udi_nsr_info_ack, ACK, 0, NIC_INFO, ,0, ,0),
+ MEI_OPINFO(udi_nsr_status_ind, IND, 0, NIC_INFO, ,0, ,0),
{0}
};
udi_mei_op_template_t udi_mei_info__nic__nd_tx_ops[] = {
udi_mei_info__nic_ops,
NULL
};
+
+tUDI_MetaLang cMetaLang_NIC = {
+ "udi_nic",
+ &udi_mei_info__nic,
+ 8,
+ {
+ {0},
+ {sizeof(udi_nic_cb_t), _NIC_STD_cb_layout},
+ {sizeof(udi_nic_bind_cb_t), _NIC_BIND_cb_layout},
+ {sizeof(udi_nic_ctrl_cb_t), _NIC_CTRL_cb_layout},
+ {sizeof(udi_nic_status_cb_t), _NIC_STATUS_cb_layout},
+ {sizeof(udi_nic_info_cb_t), _NIC_INFO_cb_layout},
+ {sizeof(udi_nic_tx_cb_t), _NIC_TX_cb_layout},
+ {sizeof(udi_nic_rx_cb_t), _NIC_RX_cb_layout},
+ }
+};