X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FInterfaces%2FUDI%2Fudi_lib%2Fcore%2Fcb.c;h=9bf8f118528f3f648139198d0c625e69744b577c;hb=3bbdda25a43af7c2c97719ff7ebd9fd2187ae272;hp=c9399348ad6da993c93809bd1de8fdb12b77ca88;hpb=6c17bdc4f8dee5d2a9c97f1db2cd9b85eefa9b8e;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c index c9399348..9bf8f118 100644 --- a/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c +++ b/KernelLand/Modules/Interfaces/UDI/udi_lib/core/cb.c @@ -32,14 +32,14 @@ udi_cb_t *udi_cb_alloc_internal_v(tUDI_MetaLang *Meta, udi_index_t MetaCBNum, 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) @@ -106,7 +106,102 @@ void udi_cb_alloc_batch( 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 = metalang->CbTypes[cb_init->meta_cb_num].ChainOfs; + { + 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, %s:%i)", + metalang->Name, cb_init->meta_cb_num, + inst->Module->ModuleName, cb_idx); + } + buf_ofs = cur_ofs; + } + else { + // No-op + } + + size_t sz = _udi_marshal_step(NULL, 0, &layout, NULL); + if( sz == 0 ) { + Log_Warning("UDI", "Metalang CB %s:%i has an invalid layout", + metalang->Name, cb_init->meta_cb_num); + callback(gcb, NULL); + return ; + } + cur_ofs += sz; + } + } + + // 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); + } + LOG("buf_ofs = %i", buf_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 ) { + 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); + *prevptr = cur_cb; + prevptr = (void*)cur_cb + chain_ofs; + } + *prevptr = NULL; + + callback(gcb, first_cb); } void udi_cb_free(udi_cb_t *cb)