From: John Hodge Date: Tue, 8 Oct 2013 15:10:48 +0000 (+0800) Subject: Modules/UDI - NSR layer and fixes to enumeration X-Git-Tag: rel0.15~126 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=e2ff5722101ae7dbb10f51f1477eac625fa30c1e;p=tpg%2Facess2.git Modules/UDI - NSR layer and fixes to enumeration --- diff --git a/KernelLand/Modules/Interfaces/UDI/Makefile b/KernelLand/Modules/Interfaces/UDI/Makefile index 4d90a1a8..1f99c954 100644 --- a/KernelLand/Modules/Interfaces/UDI/Makefile +++ b/KernelLand/Modules/Interfaces/UDI/Makefile @@ -11,7 +11,7 @@ LIB_OBJS += physio.o physio/meta_bus.o physio/pio.o physio/dma.o LIB_OBJS += scsi.o LIB_OBJS += udi_nic.o # - UDI->Acess Translation Layer -TRANS_OBJS := bus_pci.o +TRANS_OBJS := bus_pci.o nsr.o OBJ = main.o channels.o deferred_calls.o management_agent.o OBJ += $(LIB_OBJS:%=udi_lib/%) $(TRANS_OBJS:%=trans/%) diff --git a/KernelLand/Modules/Interfaces/UDI/channels.c b/KernelLand/Modules/Interfaces/UDI/channels.c index bb723a2e..993308b6 100644 --- a/KernelLand/Modules/Interfaces/UDI/channels.c +++ b/KernelLand/Modules/Interfaces/UDI/channels.c @@ -103,7 +103,7 @@ int UDI_BindChannel(udi_channel_t channel, bool other_side, tUDI_DriverInstance return 1; } - tUDI_MetaLang *ops_ml = UDI_int_GetMetaLang(inst, ops->meta_idx); + tUDI_MetaLang *ops_ml = UDI_int_GetMetaLang(inst->Module, ops->meta_idx); if( ops_ml != ch->MetaLang ) { Log_Warning("UDI", "Attempt by %s to bind with mismatched channel '%s' op '%s' channel", inst->Module, ops_ml->Name, ch->MetaLang->Name); diff --git a/KernelLand/Modules/Interfaces/UDI/include/trans_nsr.h b/KernelLand/Modules/Interfaces/UDI/include/trans_nsr.h new file mode 100644 index 00000000..dcfbec81 --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/include/trans_nsr.h @@ -0,0 +1,16 @@ +/* + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * trans_nsr.h + * - Acess IPStack to UDI Network Service Requester + */ +#ifndef _TRANS_NSR_H_ +#define _TRANS_NSR_H_ + +extern const udi_init_t acessnsr_init; +extern const char acessnsr_udiprops[]; +extern size_t acessnsr_udiprops_size; + +#endif + diff --git a/KernelLand/Modules/Interfaces/UDI/include/udi_internal.h b/KernelLand/Modules/Interfaces/UDI/include/udi_internal.h index e07b8d41..7bebc2fb 100644 --- a/KernelLand/Modules/Interfaces/UDI/include/udi_internal.h +++ b/KernelLand/Modules/Interfaces/UDI/include/udi_internal.h @@ -107,7 +107,7 @@ struct sUDI_DriverModule tUDI_DriverModule *Next; void *Base; - udi_init_t *InitInfo; + const udi_init_t *InitInfo; // Counts of arrays in InitInfo int nCBInit; @@ -174,7 +174,7 @@ extern tUDI_MetaLang cMetaLang_Management; // --- Index to pointer translation --- extern udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index); -extern tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t meta_idx); +extern tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverModule *Inst, udi_index_t meta_idx); // --- Channels --- extern udi_channel_t UDI_CreateChannel_Blank(tUDI_MetaLang *metalang); diff --git a/KernelLand/Modules/Interfaces/UDI/main.c b/KernelLand/Modules/Interfaces/UDI/main.c index bb24d19c..fabdcbbe 100644 --- a/KernelLand/Modules/Interfaces/UDI/main.c +++ b/KernelLand/Modules/Interfaces/UDI/main.c @@ -13,12 +13,13 @@ #include #include #include +#include // === PROTOTYPES === int UDI_Install(char **Arguments); int UDI_DetectDriver(void *Base); int UDI_LoadDriver(void *Base); -tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size); +tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size); const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name); // === GLOBALS === @@ -40,6 +41,7 @@ int UDI_Install(char **Arguments) Proc_SpawnWorker(UDI_int_DeferredThread, NULL); UDI_int_LoadDriver(NULL, &pci_init, pci_udiprops, pci_udiprops_size); + UDI_int_LoadDriver(NULL, &acessnsr_init, acessnsr_udiprops, acessnsr_udiprops_size); return MODULE_ERR_OK; } @@ -318,7 +320,7 @@ const char *caUDI_UdipropsNames[] = { }; #undef _defpropname -tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const char *udiprops, size_t udiprops_size) +tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, const udi_init_t *info, const char *udiprops, size_t udiprops_size) { //UDI_int_DumpInitInfo(info); @@ -664,6 +666,10 @@ tUDI_DriverModule *UDI_int_LoadDriver(void *LoadBase, udi_init_t *info, const ch } } free(udipropsptrs); + + for( int i = 0; i < driver_module->nDevices; i ++ ) + driver_module->Devices[i]->Metalang = UDI_int_GetMetaLang(driver_module, + driver_module->Devices[i]->MetaIdx); // Sort message list // TODO: Sort message list @@ -767,15 +773,15 @@ udi_ops_init_t *UDI_int_GetOps(tUDI_DriverInstance *Inst, udi_index_t index) return ops; } -tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverInstance *Inst, udi_index_t index) +tUDI_MetaLang *UDI_int_GetMetaLang(tUDI_DriverModule *Module, udi_index_t index) { if( index == 0 ) return &cMetaLang_Management; - ASSERT(Inst); - for( int i = 0; i < Inst->Module->nMetaLangs; i ++ ) + ASSERT(Module); + for( int i = 0; i < Module->nMetaLangs; i ++ ) { - if( Inst->Module->MetaLangs[i].meta_idx == index ) - return Inst->Module->MetaLangs[i].metalang; + if( Module->MetaLangs[i].meta_idx == index ) + return Module->MetaLangs[i].metalang; } return NULL; } @@ -784,8 +790,10 @@ const tUDI_MetaLang *UDI_int_GetMetaLangByName(const char *Name) { //extern tUDI_MetaLang cMetaLang_Management; extern tUDI_MetaLang cMetaLang_BusBridge; + extern tUDI_MetaLang cMetaLang_NIC; const tUDI_MetaLang *langs[] = { &cMetaLang_BusBridge, + &cMetaLang_NIC, NULL }; for( int i = 0; langs[i]; i ++ ) diff --git a/KernelLand/Modules/Interfaces/UDI/management_agent.c b/KernelLand/Modules/Interfaces/UDI/management_agent.c index 512fda3c..536c28ff 100644 --- a/KernelLand/Modules/Interfaces/UDI/management_agent.c +++ b/KernelLand/Modules/Interfaces/UDI/management_agent.c @@ -49,9 +49,11 @@ tUDI_DriverInstance *UDI_MA_CreateInstance(tUDI_DriverModule *DriverModule, // UDI_BindChannel_Raw(inst->ManagementChannel, false, // NULL, 1, inst, &cUDI_MgmtOpsList); // TODO: ops list for management agent? - for( int i = 0; i < DriverModule->nRegions; i ++ ) - Log("Rgn %i: %p", i, inst->Regions[i]); +// for( int i = 0; i < DriverModule->nRegions; i ++ ) +// Log("Rgn %i: %p", i, inst->Regions[i]); + LOG("Inst %s %p MA state =%i", + inst->Module->ModuleName, inst, UDI_MASTATE_USAGEIND); inst->CurState = UDI_MASTATE_USAGEIND; // Next State: _SECBIND @@ -132,7 +134,7 @@ int UDI_MA_CheckDeviceMatch(int nDevAttr, udi_instance_attr_list_t *DevAttrs, else { // Attribute desired is missing, error? - //LOG("attr '%s' missing", dev_attr->attr_name); + LOG("attr '%s' missing", dev_attr->attr_name); } } //LOG("n_matches = %i", n_matches); @@ -184,13 +186,16 @@ void UDI_MA_AddChild(udi_enumerate_cb_t *cb, udi_index_t ops_idx) inst->FirstChild = child; // and search for a handler - tUDI_MetaLang *metalang = UDI_int_GetMetaLang(inst, child->Ops->meta_idx); + tUDI_MetaLang *metalang = UDI_int_GetMetaLang(inst->Module, child->Ops->meta_idx); int best_level = 0; tUDI_DriverModule *best_module = NULL; for( tUDI_DriverModule *module = gpUDI_LoadedModules; module; module = module->Next ) { for( int i = 0; i < module->nDevices; i ++ ) { + //LOG("%s:%i %p ?== %p", + // module->ModuleName, i, + // module->Devices[i]->Metalang, metalang); if( module->Devices[i]->Metalang != metalang ) continue ; @@ -223,6 +228,7 @@ void UDI_MA_BindParents(tUDI_DriverModule *Module) { if( child->BoundInstance ) continue ; + // TODO: Check metalangs // Check for match int level = UDI_MA_CheckDeviceMatch( Module->Devices[i]->nAttribs, Module->Devices[i]->Attribs, @@ -244,6 +250,9 @@ void UDI_MA_TransitionState(tUDI_DriverInstance *Inst, enum eUDI_MAState Src, en if( Inst->CurState != Src ) return ; + LOG("Inst %s %p MA state %i->%i", + Inst->Module->ModuleName, Inst, Src, Dst); + switch(Dst) { case UDI_MASTATE_USAGEIND: @@ -270,7 +279,7 @@ void UDI_MA_TransitionState(tUDI_DriverInstance *Inst, enum eUDI_MAState Src, en // Bind to parent tUDI_BindOps *parent = &Module->Parents[0]; - udi_channel_t channel = UDI_CreateChannel_Blank(UDI_int_GetMetaLang(Inst, parent->meta_idx)); + udi_channel_t channel = UDI_CreateChannel_Blank(UDI_int_GetMetaLang(Inst->Module, parent->meta_idx)); UDI_BindChannel(channel,true, Inst, parent->ops_idx, parent->region_idx, NULL,false,0); UDI_BindChannel(channel,false, diff --git a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c index e51db758..daf07f27 100644 --- a/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c +++ b/KernelLand/Modules/Interfaces/UDI/trans/bus_pci.c @@ -285,8 +285,8 @@ void pci_intr_handle__trans_done(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t 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) { - LOG("child_ID=%i, regset_idx=%i,ofs=0x%x,len=%i,data=%p,isOutput=%b", - child_ID, regset_idx, ofs, len, data, isOutput); +// LOG("child_ID=%i, regset_idx=%i,ofs=0x%x,len=%i,data=%p,isOutput=%b", +// child_ID, regset_idx, ofs, len, data, isOutput); tPCIDev pciid = child_ID; // TODO: Cache child mappings diff --git a/KernelLand/Modules/Interfaces/UDI/trans/nsr.c b/KernelLand/Modules/Interfaces/UDI/trans/nsr.c new file mode 100644 index 00000000..a6135711 --- /dev/null +++ b/KernelLand/Modules/Interfaces/UDI/trans/nsr.c @@ -0,0 +1,199 @@ +/* + * Acess2 UDI Layer + * - By John Hodge (thePowersGang) + * + * trans/nsr.c + * - "Network Service Requester" (UDI->IP Translation) + */ +#define DEBUG 1 +#include +#include +#include +#include +#include + +enum { + ACESSNSR_OPS_CTRL = 1, + ACESSNSR_OPS_TX, + ACESSNSR_OPS_RX, +}; +enum { + ACESSNSR_META_NIC = 1 +}; +enum { + ACESSNSR_CB_CTRL = 1 +}; + +// === TYPES === +typedef struct +{ + udi_init_context_t init_context; +} acessnsr_rdata_t; + +// === PROTOTYPES === +// --- Management metalang +void acessnsr_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level); +void acessnsr_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID); +void acessnsr_final_cleanup_req(udi_mgmt_cb_t *cb); +// --- NSR Control +void acessnsr_ctrl_channel_event_ind(udi_channel_event_cb_t *cb); +void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status); +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); +void acessnsr_ctrl_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status); +void acessnsr_ctrl_status_ind(udi_nic_status_cb_t *cb); +void acessnsr_ctrl_info_ack(udi_nic_info_cb_t *cb); +// --- NSR TX +void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb); +void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb); +// --- NSR RX +void acessnsr_rx_channel_event_ind(udi_channel_event_cb_t *cb); +void acessnsr_rx_ind(udi_nic_rx_cb_t *cb); +void acessnsr_rx_exp_ind(udi_nic_rx_cb_t *cb); + +// === CODE === +// --- Management metalang +void acessnsr_usage_ind(udi_usage_cb_t *cb, udi_ubit8_t resource_level) +{ +} +void acessnsr_devmgmt_req(udi_mgmt_cb_t *cb, udi_ubit8_t mgmt_op, udi_ubit8_t parent_ID) +{ +} +void acessnsr_final_cleanup_req(udi_mgmt_cb_t *cb) +{ +} +// --- NSR Control +void acessnsr_ctrl_channel_event_ind(udi_channel_event_cb_t *cb) +{ + //acessnsr_rdata_t *rdata = UDI_GCB(cb)->context; + switch(cb->event) + { + + } +} +void acessnsr_ctrl_bind_ack(udi_nic_bind_cb_t *cb, udi_status_t status) +{ +} +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) +{ +} +void acessnsr_ctrl_ctrl_ack(udi_nic_ctrl_cb_t *cb, udi_status_t status) +{ +} +void acessnsr_ctrl_status_ind(udi_nic_status_cb_t *cb) +{ +} +void acessnsr_ctrl_info_ack(udi_nic_info_cb_t *cb) +{ +} +// --- NSR TX +void acessnsr_tx_channel_event_ind(udi_channel_event_cb_t *cb) +{ +} +void acessnsr_tx_rdy(udi_nic_tx_cb_t *cb) +{ +} +// --- NSR RX +void acessnsr_rx_channel_event_ind(udi_channel_event_cb_t *cb) +{ +} +void acessnsr_rx_ind(udi_nic_rx_cb_t *cb) +{ +} +void acessnsr_rx_exp_ind(udi_nic_rx_cb_t *cb) +{ +} + +// === UDI Bindings === +udi_mgmt_ops_t acessnsr_mgmt_ops = { + acessnsr_usage_ind, + udi_enumerate_no_children, + acessnsr_devmgmt_req, + acessnsr_final_cleanup_req +}; +udi_ubit8_t acessnsr_mgmt_ops_flags[4] = {0,0,0,0}; + +udi_primary_init_t acessnsr_pri_init = { + .mgmt_ops = &acessnsr_mgmt_ops, + .mgmt_op_flags = acessnsr_mgmt_ops_flags, + .mgmt_scratch_requirement = 0, + .enumeration_attr_list_length = 4, + .rdata_size = sizeof(acessnsr_rdata_t), + .child_data_size = 0, + .per_parent_paths = 0 +}; + +udi_nsr_ctrl_ops_t acessnsr_ctrl_ops = { + acessnsr_ctrl_channel_event_ind, + acessnsr_ctrl_bind_ack, + acessnsr_ctrl_unbind_ack, + acessnsr_ctrl_enable_ack, + acessnsr_ctrl_ctrl_ack, + acessnsr_ctrl_info_ack, + acessnsr_ctrl_status_ind +}; +udi_ubit8_t acessnsr_ctrl_op_flags[7] = {0}; + +udi_nsr_tx_ops_t acessnsr_tx_ops = { + acessnsr_tx_channel_event_ind, + acessnsr_tx_rdy +}; +udi_ubit8_t acessnsr_tx_ops_flags[2] = {0}; + +udi_nsr_rx_ops_t acessnsr_rx_ops = { + acessnsr_rx_channel_event_ind, + acessnsr_rx_ind, + acessnsr_rx_exp_ind +}; +udi_ubit8_t acessnsr_rx_ops_flags[3] = {0}; + +udi_ops_init_t acessnsr_ops_list[] = { + { + ACESSNSR_OPS_CTRL, ACESSNSR_META_NIC, UDI_NSR_CTRL_OPS_NUM, + 0, (udi_ops_vector_t*)&acessnsr_ctrl_ops, acessnsr_ctrl_op_flags + }, + { + ACESSNSR_OPS_TX, ACESSNSR_META_NIC, UDI_NSR_TX_OPS_NUM, + 0, (udi_ops_vector_t*)&acessnsr_tx_ops, acessnsr_tx_ops_flags + }, + { + ACESSNSR_OPS_RX, ACESSNSR_META_NIC, UDI_NSR_RX_OPS_NUM, + 0, (udi_ops_vector_t*)&acessnsr_rx_ops, acessnsr_rx_ops_flags + }, + {0} +}; +udi_cb_init_t acessnsr_cb_init_list[] = { + {ACESSNSR_CB_CTRL, ACESSNSR_META_NIC, UDI_NIC_BIND_CB_NUM, 0, 0,NULL}, + {0} +}; +const udi_init_t acessnsr_init = { + .primary_init_info = &acessnsr_pri_init, + .ops_init_list = acessnsr_ops_list, + .cb_init_list = acessnsr_cb_init_list, +}; +const char acessnsr_udiprops[] = + "properties_version 0x101\0" + "message 1 Acess2 Kernel\0" + "message 2 John Hodge (acess@mutabah.net)\0" + "message 3 Acess2 NSR\0" + "supplier 1\0" + "contact 2\0" + "name 3\0" + "module acess_nsr\0" + "shortname acessnsr\0" + "requires udi 0x101\0" + "requires udi_nic 0x101\0" + "meta 1 udi_nic\0" + "message 101 Ethernet Adapter\0" + "device 101 1 if_media string eth\0" + "parent_bind_ops 1 0 1 1\0" + "\0"; +size_t acessnsr_udiprops_size = sizeof(acessnsr_udiprops); + diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c index ae8c155d..14bcd326 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c @@ -37,7 +37,7 @@ void *udi_cb_alloc_internal(tUDI_DriverInstance *Inst, udi_ubit8_t bind_cb_idx, 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); + 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, bind_cb_idx, cb_init->meta_idx); @@ -103,7 +103,8 @@ void udi_cb_alloc_batch( void udi_cb_free(udi_cb_t *cb) { - UNIMPLEMENTED(); + // TODO: Ensure that cb is inactive + free(cb); } void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb) diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/meta_mgmt.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/meta_mgmt.c index ab8f68a5..865ace44 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/meta_mgmt.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/meta_mgmt.c @@ -91,13 +91,16 @@ void udi_enumerate_ack(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_result, u switch(at->attr_type) { case UDI_ATTR_STRING: - LOG("[%i] String '%.*s'", i, at->attr_length, at->attr_value); + LOG("[%i] %s String '%.*s'", i, at->attr_name, + at->attr_length, at->attr_value); break; case UDI_ATTR_UBIT32: - LOG("[%i] UBit32 0x%08x", i, UDI_ATTR32_GET(at->attr_value)); + LOG("[%i] %s UBit32 0x%08x", i, at->attr_name, + UDI_ATTR32_GET(at->attr_value)); break; default: - LOG("[%i] %i", i, at->attr_type); + LOG("[%i] %s %i", i, at->attr_name, + at->attr_type); break; } } diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c index 6bf636bb..00790f03 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/udi_nic.c @@ -2,9 +2,10 @@ * \file physio.c * \author John Hodge (thePowersGang) */ -#include #include #include +#include // for EXPORT +#include // === EXPORTS === EXPORT(udi_nd_bind_req); @@ -28,6 +29,29 @@ EXPORT(udi_nsr_rx_ind); EXPORT(udi_nsr_exp_rx_ind); EXPORT(udi_nd_rx_rdy); +#define UDI_NIC_STD_CB_NUM 1 +#define UDI_NIC_BIND_CB_NUM 2 +#define UDI_NIC_CTRL_CB_NUM 3 +#define UDI_NIC_STATUS_CB_NUM 4 +#define UDI_NIC_INFO_CB_NUM 5 +#define UDI_NIC_TX_CB_NUM 6 +#define UDI_NIC_RX_CB_NUM 7 +// === 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 --- void udi_nd_bind_req(udi_nic_bind_cb_t *cb, udi_index_t tx_chan_index, udi_index_t rx_chan_index)