+ acessnsr_rdata_t *rdata = Card;
+ udi_nic_tx_cb_t *cb = Workqueue_GetWork(&rdata->TXWorkQueue);
+ ASSERT(cb);
+ acessnsr_txdesc_t *tx = UDI_GCB(cb)->scratch;
+ ASSERT(tx);
+
+ Mutex_Acquire(&tx->CompleteMutex);
+ tx->IPBuffer = Buffer;
+ tx->BufIdx = -1;
+ acessnsr_SendPacket__buf_write_complete(UDI_GCB(cb), NULL);
+
+ // Double lock is resolved once TX is complete
+ Mutex_Acquire(&tx->CompleteMutex);
+ Mutex_Release(&tx->CompleteMutex);
+ // TODO: TX status
+
+ Workqueue_AddWork(&rdata->TXWorkQueue, tx);
+ return 0;
+}
+void acessnsr_SendPacket__buf_write_complete(udi_cb_t *gcb, udi_buf_t *buf)
+{
+ acessnsr_txdesc_t *tx = gcb->scratch;
+ udi_nic_tx_cb_t *cb = UDI_MCB(gcb, udi_nic_tx_cb_t);
+ if( tx->BufIdx >= 0 ) {
+ cb->tx_buf = buf;
+ }
+ size_t buflen;
+ const void *bufptr;
+ if( (tx->BufIdx = IPStack_Buffer_GetBuffer(tx->IPBuffer, tx->BufIdx, &buflen, &bufptr )) != -1 )
+ {
+ 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
+ return ;
+ }
+
+ udi_nd_tx_req(cb);
+ // continued in acessnsr_tx_rdy