int nCbTypes;
struct {
udi_size_t Size;
+ udi_size_t ChainOfs;
udi_layout_t *Layout;
} CbTypes[];
};
tIPStackBuffer *ret = IPStack_Buffer_CreateBuffer(1);
void *data = malloc( cb->rx_buf->buf_size );
udi_buf_read(cb->rx_buf, 0, cb->rx_buf->buf_size, data);
+ Debug_HexDump("NSR WaitForPacket", data, cb->rx_buf->buf_size);
IPStack_Buffer_AppendSubBuffer(ret, cb->rx_buf->buf_size, 0, data, _FreeHeapSubBuf, data);
udi_nd_rx_rdy(cb);
newsect->Length = data_len;
newsect->Space = space_atom;
newsect->Data = newsect+1;
- memcpy(newsect->Data, data, data_len);
+ if( !data )
+ memset(newsect->Data, 0xFF, data_len);
+ else
+ memcpy(newsect->Data, data, data_len);
newsect->Next = *prevptr;
*prevptr = newsect;
dst_buf = &dst->buf;
}
+ // Find dst_off segment
tUDI_BufSect **prevptr = &dst->Sections;
tUDI_BufSect *sect = dst->Sections;
for( ; sect; prevptr = §->Next, sect = sect->Next )
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 )
+ // Overwrite MIN(src_len,dst_len) bytes
+ // then delete/append remainder
+ size_t len = MIN(src_len,dst_len);
+ src_len -= len;
+ dst_len -= len;
+ while( len > 0 )
+ {
+ // Create new section
+ if( !sect || sect->RelOfs > dst_off ) {
+ size_t newsize = MIN(sect->RelOfs - dst_off, len);
+ sect = UDI_int_BufAddSect(len, dst_off, prevptr, src_mem, path_handle);
+ len -= newsize;
+ src_mem += newsize;
+ prevptr = §->Next;
+ sect = sect->Next;
+ dst_off = 0;
+ }
+ if( len == 0 )
+ break;
+
+ // Update existing section
+ size_t bytes = MIN(len, sect->Length - dst_off);
+ memcpy(sect->Data + dst_off, src_mem, bytes);
+ len -= bytes;
+ src_mem += bytes;
+
+ prevptr = §->Next;
+ sect = sect->Next;
+ }
+
+ if( dst_len > 0 )
{
- // Insert / Initialise
- if( src_len > 0 )
+ ASSERT(src_len == 0);
+ // Delete
+ while( dst_len > 0 )
{
- 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;
+ if( !sect ) {
+ dst_buf->buf_size = dst_off;
+ dst_len = 0;
+ }
+ else if( sect->RelOfs > dst_off ) {
+ size_t bytes = MIN(dst_len, sect->RelOfs - dst_off);
+ dst_len -= bytes;
+ dst_buf->buf_size -= bytes;
+ sect->RelOfs -= bytes;
}
- 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 if( dst_off == 0 && sect->Length <= dst_len ) {
+ // Remove entire section
+ dst_len -= sect->Length;
+ dst_buf->buf_size -= sect->Length;
+ *prevptr = sect->Next;
+ free(sect);
+
+ // Next block
+ sect = *prevptr;
+ }
+ else if( dst_off + dst_len >= sect->Length ) {
+ // block truncate
+ size_t bytes = MIN(dst_len, sect->Length - dst_off);
+ dst_len -= bytes;
+ dst_buf->buf_size -= bytes;
+ sect->Length -= bytes;
+
+ // Next block
+ prevptr = §->Next;
+ sect = sect->Next;
}
else {
- // Complex: Need to handle mid-section inserts
- Log_Warning("UDI", "TODO: udi_buf_write - mid-section inserts");
+ // in-block removal (must be last)
+ ASSERTC(dst_off + dst_len, <, sect->Length);
+ size_t tail = sect->Length - (dst_off + dst_len);
+ memmove(sect->Data+dst_off, sect->Data+dst_off+dst_len, tail);
+ dst_buf->buf_size -= dst_len;
+ sect->Length -= dst_len;
+ dst_len = 0;
}
}
- // no-op
- else
- {
- }
}
- else
+ else if( src_len > 0 )
{
- // Delete
- if( src_len == 0 )
- {
- Log_Warning("UDI", "TODO: udi_buf_write - delete");
+ ASSERT(dst_len == 0);
+ // 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;
}
- // Overwrite
- else
- {
- Log_Warning("UDI", "TODO: udi_buf_write - overwrite");
+ 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");
}
}
+ else
+ {
+ // No-op
+ }
- callback(gcb, &dst->buf);
+ // HACK: udi_pio_trans calls this with a NULL cb, so handle that
+ if( callback ) {
+ callback(gcb, &dst->buf);
+ }
}
void udi_buf_read(
// Get chain offset and buffer offset
size_t buf_ofs = 0; // TODO: Multiple buffers are to be supported
- size_t chain_ofs = 0;
+ size_t chain_ofs = metalang->CbTypes[cb_init->meta_cb_num].ChainOfs;
{
udi_layout_t *layout = metalang->CbTypes[cb_init->meta_cb_num].Layout;
if( !layout ) {
}
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 ++;
}
}
else {
LOG("chain_ofs = %i", chain_ofs);
}
+ LOG("buf_ofs = %i", buf_ofs);
udi_cb_t *first_cb = NULL, *cur_cb;
udi_cb_t **prevptr = &first_cb;
// Allocate buffer
if( with_buf && buf_ofs ) {
- *(void**)((char*)cur_cb + buf_ofs) =_udi_buf_allocate(NULL, buf_size, path_handle);
+ udi_buf_t *buf = _udi_buf_allocate(NULL, buf_size, path_handle);
+ LOG("buf +%i = %p", buf_ofs, buf);
+ *(void**)((char*)cur_cb + buf_ofs) = buf;
}
LOG("*%p = %p", prevptr, cur_cb);
// Check call type
udi_op_t *const*ops = UDI_int_ChannelPrepForCall(gcb, metalang, meta_ops_num);
udi_op_t *op = ops[vec_idx];
+
+ // Change ownership of chained cbs
+ size_t chain_ofs = metalang->CbTypes[cb_type].ChainOfs;
+ if( chain_ofs )
+ {
+ udi_cb_t *chained_cb = gcb;
+ while( (chained_cb = *(udi_cb_t**)((void*)chained_cb + chain_ofs)) )
+ UDI_int_ChannelFlip(chained_cb);
+ }
+
if( indirect_call )
{
va_list args;
NULL,
3,
{
- {sizeof(udi_enumerate_cb_t), NULL},
- {sizeof(udi_usage_cb_t), NULL},
- {sizeof(udi_channel_event_cb_t), NULL},
+ {sizeof(udi_enumerate_cb_t), 0, NULL},
+ {sizeof(udi_usage_cb_t), 0, NULL},
+ {sizeof(udi_channel_event_cb_t), 0, NULL},
}
};
5,
{
{0}, // 0: Empty
- {sizeof(udi_bus_bind_cb_t), udi_meta_info__bridge__bus_bind_cb},
- {sizeof(udi_intr_attach_cb_t), udi_meta_info__bridge__intr_attach_cb},
- {sizeof(udi_intr_detach_cb_t), udi_meta_info__bridge__intr_detach_cb},
- {sizeof(udi_intr_event_cb_t), NULL}
+ {sizeof(udi_bus_bind_cb_t), 0, udi_meta_info__bridge__bus_bind_cb},
+ {sizeof(udi_intr_attach_cb_t), 0, udi_meta_info__bridge__intr_attach_cb},
+ {sizeof(udi_intr_detach_cb_t), 0, udi_meta_info__bridge__intr_detach_cb},
+ {sizeof(udi_intr_event_cb_t), 0, NULL}
}
};
//LOG("scr %p+%i => %i %x,...", gcb->scratch, ofs, size, val->words[0]);
break;
case UDI_PIO_BUF:
+ ASSERT(buf);
udi_buf_read(buf, ofs, size, val);
//LOG("buf %p+%i => %i %x,...", buf, ofs, size, val->words[0]);
break;
switch(op)
{
case UDI_PIO_DIRECT:
+ //LOG("reg %p = %i %x,...", reg, size, val->words[0]);
memcpy(reg, val, size);
_zero_upper(sizelog2, reg);
break;
case UDI_PIO_SCRATCH:
ASSERTCR( (ofs & (size-1)), ==, 0, 1);
- LOG("scr %p+%i = %i %x,...", gcb->scratch, ofs, size, val->words[0]);
+ //LOG("scr %p+%i = %i %x,...", gcb->scratch, ofs, size, val->words[0]);
memcpy(gcb->scratch + ofs, val, size);
break;
case UDI_PIO_BUF:
- LOG("buf %p+%i = %i %x,...", buf, ofs, size, val->words[0]);
+ ASSERT(buf);
+ //LOG("buf %p+%i = %i %x,...", buf, ofs, size, val->words[0]);
udi_buf_write(NULL,NULL, val, size, buf, ofs, size, UDI_NULL_BUF_PATH);
break;
case UDI_PIO_MEM:
ASSERTCR( (ofs & (size-1)), ==, 0, 1);
- LOG("mem %p+%i = %i %x,...", mem_ptr, ofs, size, val->words[0]);
+ //LOG("mem %p+%i = %i %x,...", mem_ptr, ofs, size, val->words[0]);
memcpy(mem_ptr + ofs, val, size);
break;
}
break;
case UDI_PIO_OUT:
_read_mem(gcb, buf, mem_ptr, (pio_op&0x18), tran_size, reg, &tmpval);
+ LOG("OUT %x = %i %x", operand, tran_size, tmpval.words[0]);
pio_handle->IOFunc(pio_handle->ChildID, pio_handle->RegSet,
operand, tran_size, &tmpval, true);
break;
switch(operand)
{
case UDI_PIO_NZ:
- LOG("CSKIP NZ R%i", reg_num);
+ LOG("CSKIP NZ R%i (%i %x)", reg_num, tran_size, reg->words[0]);
if( !(cnd & 1) )
ip ++;
break;
case UDI_PIO_Z:
- LOG("CSKIP Z R%i", reg_num);
+ LOG("CSKIP Z R%i (%i %x)", reg_num, tran_size, reg->words[0]);
if( cnd & 1 )
ip ++;
break;
case UDI_PIO_NNEG:
- LOG("CSKIP NNEG R%i", reg_num);
+ LOG("CSKIP NNEG R%i (%i %x)", reg_num, tran_size, reg->words[0]);
if( !(cnd & 2) )
ip ++;
+ break;
case UDI_PIO_NEG:
- LOG("CSKIP NEG R%i", reg_num);
+ LOG("CSKIP NEG R%i (%i %x)", reg_num, tran_size, reg->words[0]);
if( cnd & 2 )
ip ++;
break;
_operation_xor(tran_size, reg, ®isters[operand]);
break;
case UDI_PIO_ADD:
+ LOG("ADD R%i += R%i", reg_num, operand);
+ ASSERTC(operand, <, 8);
_operation_add(tran_size, reg, ®isters[operand]);
break;
case UDI_PIO_ADD_IMM:
else {
_zero_upper(UDI_PIO_4BYTE, &tmpval);
}
+ LOG("ADD R%i += 0x%x", reg_num, tmpval.words[0]);
_operation_add(tran_size, reg, &tmpval);
break;
case UDI_PIO_SUB:
+ LOG("SUB R%i -= R%i", reg_num, operand);
+ ASSERTC(operand, <, 8);
_operation_sub(tran_size, reg, ®isters[operand]);
break;
default:
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},
+ {sizeof(udi_nic_cb_t), 0, _NIC_STD_cb_layout},
+ {sizeof(udi_nic_bind_cb_t), 0, _NIC_BIND_cb_layout},
+ {sizeof(udi_nic_ctrl_cb_t), 0, _NIC_CTRL_cb_layout},
+ {sizeof(udi_nic_status_cb_t), 0, _NIC_STATUS_cb_layout},
+ {sizeof(udi_nic_info_cb_t), 0, _NIC_INFO_cb_layout},
+ {sizeof(udi_nic_tx_cb_t), offsetof(udi_nic_tx_cb_t, chain), _NIC_TX_cb_layout},
+ {sizeof(udi_nic_rx_cb_t), offsetof(udi_nic_rx_cb_t, chain), _NIC_RX_cb_layout},
}
};