int ethernet_send() { #if NEW_LOGIC if(tx_produce_offset < 0) { // no buffer active return -1; } // ensure there is a link if(!ethernet_link()) { return -2; } // we have been writing in to a buffer, so finalise it int size = tx_produce_offset; int index = LPC_EMAC->TxProduceIndex; txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST); // Increment ProduceIndex to allow it to be sent // We can only do this if the next slot is free int next = rinc(index, NUM_TX_FRAG); while(next == LPC_EMAC->TxConsumeIndex) { for(int i=0; i<1000; i++) { __NOP(); } } LPC_EMAC->TxProduceIndex = next; tx_produce_offset = -1; return size; #else int s = send_size; txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST); send_idx = rinc(send_idx, NUM_TX_FRAG); LPC_EMAC->TxProduceIndex = send_idx; send_doff = 0; send_idx = -1; send_size = 0; return s; #endif }
int ethernet_read(char *data, int dlen) { #if NEW_LOGIC // Check we have a valid buffer to read if(rx_consume_offset < 0) { return 0; } // Assume 1 fragment block uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info; int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum int remaining = size - rx_consume_offset; int requested = dlen; int ncopy = min(remaining, requested); void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset); void *pdst = (void *)(data); if(data != NULL && ncopy > 0) { memcpy(pdst, psrc, ncopy); } rx_consume_offset += ncopy; return ncopy; #else int slen; int copy = 0; unsigned int more; unsigned int info; void *pdst, *psrc; int doff = 0; if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) { return 0; } do { info = rxstat[receive_idx].Info; more = !(info & RINFO_LAST_FLAG); slen = (info & RINFO_SIZE) + 1; if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) { /* Invalid frame, ignore it and free buffer. */ receive_idx = rinc(receive_idx, NUM_RX_FRAG); } else { copy = min(slen - receive_soff, dlen - doff); psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff); pdst = (void *)(data + doff); if(data != NULL) { /* check if Buffer available */ memcpy(pdst, psrc, copy); } receive_soff += copy; doff += copy; if((more && (receive_soff == slen))) { receive_idx = rinc(receive_idx, NUM_RX_FRAG); receive_soff = 0; } } } while(more && !(doff == dlen) && !receive_soff); return doff; #endif }
int ethernet_write(const char *data, int slen) { #if NEW_LOGIC if(tx_produce_offset < 0) { // mark as active if not already tx_produce_offset = 0; } int index = LPC_EMAC->TxProduceIndex; int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum int requested = slen; int ncopy = min(remaining, requested); void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset); void *psrc = (void *)(data); if(ncopy > 0 ){ if(data != NULL) { memcpy(pdst, psrc, ncopy); } else { memset(pdst, 0, ncopy); } } tx_produce_offset += ncopy; return ncopy; #else void *pdst, *psrc; const int dlen = ETH_FRAG_SIZE; int copy = 0; int soff = 0; if(send_idx == -1) { send_idx = LPC_EMAC->TxProduceIndex; } if(slen + send_doff > ethernet_MTU_SIZE) { return -1; } do { copy = min(slen - soff, dlen - send_doff); pdst = (void *)(txdesc[send_idx].Packet + send_doff); psrc = (void *)(data + soff); if(send_doff + copy > ETH_FRAG_SIZE) { txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT); send_idx = rinc(send_idx, NUM_TX_FRAG); send_doff = 0; } if(data != NULL) { memcpy(pdst, psrc, copy); } else { memset(pdst, 0, copy); } soff += copy; send_doff += copy; send_size += copy; } while(soff != slen); return soff; #endif }