+ for (;;) {
+ /* Block if there is nothing to do.
+ * Wake up if an TX interrupt occured.
+ */
+ xSemaphoreTake(hdkif->goTX, portMAX_DELAY);
+
+ next_bd_to_process = txch->next_bd_to_process;
+ curr_bd = next_bd_to_process;
+
+ /* Traverse the list of BDs used for transmission --
+ * stop on the first unused
+ */
+ while (curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP) {
+ /* Make sure the transmission is over */
+ while (curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER)
+ ;
+
+ /* Find the last chunk of the packet */
+ while (!(curr_bd->flags_pktlen & EMAC_DSC_FLAG_EOP))
+ curr_bd = curr_bd->next;
+
+ /* Remove flags for the transmitted BDs */
+ next_bd_to_process->flags_pktlen &= (~EMAC_DSC_FLAG_SOP);
+ curr_bd->flags_pktlen &= (~EMAC_DSC_FLAG_EOP);
+
+ /* Point the txch->next_bd_to_process to the BDs
+ * following the 'last BD belonging to the packet
+ * being processed'
+ */
+ if (curr_bd->next == NULL)
+ txch->next_bd_to_process = txch->free_head;
+ else
+ txch->next_bd_to_process = curr_bd->next;
+
+ /* Ack the Interrupt in the EMAC peripheral */
+ EMACTxCPWrite(hdkif->emac_base, CHANNEL,
+ (uint32_t)curr_bd);
+
+ /* Free the corresponding pbuf
+ * Sidenote: Each fragment of the single packet points
+ * to the same pbuf // FIXME is it true?
+ */
+ pbuf_free(curr_bd->pbuf);
+
+ LINK_STATS_INC(link.xmit);
+
+ /* Move to the next packet */
+ next_bd_to_process = txch->next_bd_to_process;
+ curr_bd = next_bd_to_process;
+ }
+
+ /* Ack the Interrupt in the EMAC peripheral */
+ EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
+ //EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX); // Proc?
+ /* Enable the interrupt in the VIM */
+ vim_mask_set(TXinterruptVectorNumber);
+ }