/********************************************************************************* File: eth_stub.c Date: 22.1.2004 Version: 0.1 Author: Jari Lahti (jari.lahti@violasystems.com) Description: Wrapper functions betw. Motorola fec, nif & nbuf code and OpenTCP internals Version Info: 22.1.2004 - First version (JaL) 26.3.2004 - Check for Ethernet rx frame length (JaL) *********************************************************************************/ #include "rtxcapi.h" #include "mcf5xxx.h" #include "enable.h" #include "nif.h" #include "fec.h" #include "debug.h" #include "eth_stub.h" /* structure we use to keep track on tx & rx stuff */ /* this is needed for easy integration of opentcp principles */ /* and Motorola eth drivers without lot of re-code */ struct { INT16 unprocessed; /* Number of unprocessed rx packets */ INT16 next_receive; /* The entry in RxNBUF we receive */ NBUF* cur_rxframe; /* current nbuf entry we are using */ NBUF* cur_txframe; /* current nbuf entry we are using */ UINT8* rxp; /* Read pointer */ UINT8* txp; /* Write pointer */ } eth_wrapper; /* Frame we receive */ struct otcp_ethframe otcp_rxframe; /* Frame we send */ struct otcp_ethframe otcp_txframe; /******************************************************************************** Function: eth_stub_init Parameters: void Return val: void Date: 22.1.2004 Desc: Call this function on init before entering to main loop. Just initializes the eth_wrapper *********************************************************************************/ void eth_stub_init (void) { eth_wrapper.unprocessed = 0; eth_wrapper.next_receive = 0; eth_wrapper.cur_rxframe = NULL; eth_wrapper.cur_txframe = NULL; eth_wrapper.rxp = NULL; eth_wrapper.txp = NULL; } /******************************************************************************** Function: opentcp_fechandler Parameters: NIF *nif - network interface Return val: void Date: 22.1.2004 Desc: This function is called by nif_protocol_handler in order to supply received Ethernet packet. We just increase the number of unprocessed packets OpenTCP to poll. *********************************************************************************/ void opentcp_fechandler (NIF *nif) { if( (eth_wrapper.unprocessed + 1) > eth_wrapper.unprocessed ) eth_wrapper.unprocessed++; } /******************************************************************************** Function: eth_stub_isframe Parameters: NIF *nif - network interface Return val: INT16 : (<0) - Error (0) - No pending frames (>0) - There are pending frames Date: 22.1.2004 Desc: Checks do we have any pending frame *********************************************************************************/ INT16 eth_stub_isframe (NIF *nif) { NBUF* fr; eth_frame_hdr *ethframe; int i; if(eth_wrapper.unprocessed == 0) return(0); for(i=0; i< NUM_RXBDS; i++) { fr = nbuf_give_frame(eth_wrapper.next_receive); if(fr != NULL) break; if(eth_wrapper.next_receive++ >= NUM_RXBDS) eth_wrapper.next_receive = 0; } if(fr == NULL) return(0); eth_wrapper.cur_rxframe = fr; /* Store packet info for OpenTCP internals */ /* Point to the ethernet header of this packet */ ethframe = (eth_frame_hdr *)&fr->data[ETH_HDR_OFFSET]; /* Check for errors */ if(fr->status & RX_BD_TR) { /* Truncated */ DEBUGOUT("Received truncated packet\n"); eth_stub_dumpframe(nif); return(-1); } if (fr->status & RX_BD_L) { if(fr->status & RX_BD_OV) { /* Receive FIFO overrun */ DEBUGOUT("Receive FIFO overrun\n"); eth_stub_dumpframe(nif); return(-1); } if(fr->status & RX_BD_NO) { /* Non-octet aligned frame */ DEBUGOUT("Received non-octet aligned frame\n"); eth_stub_dumpframe(nif); return(-1); } if(fr->status & RX_BD_LG) { /* Frame length violation */ //DEBUGOUT("Frame length violation\n"); //eth_stub_dumpframe(nif); //return(-1); } if(fr->status & RX_BD_CR) { /* CRC Fail */ DEBUGOUT("Received CRC failed\n"); eth_stub_dumpframe(nif); return(-1); } } /* Too big? */ if(fr->length > ETH_MAX_SIZE) { DEBUGOUT("Too big Ethernet Frame\r\n"); eth_stub_dumpframe(nif); return(-1); } for(i=0; idest[i]; for(i=0; isrc[i]; otcp_rxframe.framesize = fr->length; otcp_rxframe.protocol = ethframe->type; otcp_rxframe.bufindex = ETH_HDR_SIZE; eth_wrapper.rxp = fr->data; return(1); } /******************************************************************************** Function: eth_stub_dumpframe Parameters: NIF *nif - network interface Return val: INT16 : (<0) - Error (=>0) - OK, frame released Date: 22.1.2004 Desc: Releases the frame and decreases the number of pending packets *********************************************************************************/ INT16 eth_stub_dumpframe (NIF *nif) { /* int old_ipl; */ PPL_TYPE ppl; NBUF* fr; if(eth_wrapper.cur_rxframe == NULL) { return(0); } /* This routine alters shared data. Disable interrupts! */ /* old_ipl = asm_set_ipl(6); */ PUSHPPL(ppl); fr = eth_wrapper.cur_rxframe; eth_wrapper.cur_rxframe = NULL; if(eth_wrapper.unprocessed) eth_wrapper.unprocessed--; eth_wrapper.next_receive++; if(eth_wrapper.next_receive >= NUM_RXBDS) eth_wrapper.next_receive = 0; eth_wrapper.rxp = NULL; /* Release buffer */ nif->rx_free(fr); /* Restore previous IPL */ /* asm_set_ipl(old_ipl); */ POPPPL(ppl); return(1); } /******************************************************************************** Function: eth_stub_seekread Parameters: NIF *nif - network interface UINT16 pos - position from the start of read buffer Return val: INT16 : (<0) - Error (=>0) - OK Date: 22.1.2004 Desc: Moves the read pointer to the given position from start *********************************************************************************/ INT16 eth_stub_seekread (NIF *nif, UINT16 pos) { if(eth_wrapper.rxp == NULL) return(-1); eth_wrapper.rxp = eth_wrapper.cur_rxframe->data; eth_wrapper.rxp += pos; return(0); } /******************************************************************************** Function: eth_stub_read Parameters: NIF *nif - network interface Return val: UINT8 - read data Date: 22.1.2004 Desc: Return one byte of data from rx buffer and advances read pointer. TODO:More efficient to make this a MACRO *********************************************************************************/ UINT8 eth_stub_read (NIF *nif) { //TODO:overflow check return(*eth_wrapper.rxp++); } /******************************************************************************** Function: eth_stub_read_buf Parameters: NIF *nif - network interface UINT8* buf - buffer for data UINT16 buflen - number of bytes requested Return val: INT16: (-1) - Error (>=0) - Number of bytes read Date: 22.1.2004 Desc: Reads multiple bytes from rx buffer and advances read pointer *********************************************************************************/ INT16 eth_stub_read_buf (NIF *nif, UINT8* buf, UINT16 buflen) { //TODO:overflow check memcpy(buf, eth_wrapper.rxp, buflen); eth_wrapper.rxp += buflen; return(buflen); } /******************************************************************************** Function: eth_stub_skip_buf Parameters: NIF *nif - network interface UINT16 len - number of bytes requested Return val: INT16: (-1) - Error (>=0) - Number of bytes skipped Author: Ilya A Sukhanov (dotCOMmie.net) Date: 05.07.2006 Desc: Advances read pointer *********************************************************************************/ INT16 eth_stub_skip_buf (NIF *nif, UINT16 len) { //TODO:overflow check eth_wrapper.rxp += len; return(len); } /******************************************************************************** Function: eth_stub_txalloc Parameters: NIF *nif - network interface Return val: INT16: (-1) - Error (>=0) - OK, tx buffer allocated Date: 22.1.2004 Desc: Allocates tx buffer from nbuf *********************************************************************************/ INT16 eth_stub_txalloc (NIF *nif) { /* Are we already assembling a frame? */ if(eth_wrapper.cur_txframe != NULL) { /* yep, release it */ nif->tx_free(eth_wrapper.cur_txframe); eth_wrapper.cur_txframe = NULL; } /* try to get the buffer */ //TODO: try few times eth_wrapper.cur_txframe = nif->tx_alloc(); /* how it went? */ if(eth_wrapper.cur_txframe == NULL) { DEBUGOUT("Error allocating Ethernet TX Buffer\r\n"); return(-1); } eth_wrapper.txp = eth_wrapper.cur_txframe->data + ETH_HDR_SIZE; /* it's now allocated, next assemble data and send */ return(1); } /******************************************************************************** Function: eth_stub_writeheader Parameters: NIF *nif - network interface struct otcp_ethframe* frame - ethernet header info Return val: INT16: (-1) - Error (>=0) - OK Date: 22.1.2004 Desc: Writes ethernet header to tx buffer *********************************************************************************/ INT16 eth_stub_writeheader (NIF *nif, struct otcp_ethframe* frame) { /* Are we having a buffer? */ if(eth_wrapper.cur_txframe == NULL) return(-1); /* Write destination ethernet address */ eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 0] = frame->destination[0]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 1] = frame->destination[1]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 2] = frame->destination[2]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 3] = frame->destination[3]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 4] = frame->destination[4]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 5] = frame->destination[5]; /* Write source ethernet address. */ eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 6] = frame->source[0]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 7] = frame->source[1]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 8] = frame->source[2]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 9] = frame->source[3]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 10] = frame->source[4]; eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 11] = frame->source[5]; /* Write frame type */ eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 12] = (uint8)((frame->protocol & 0xFF00) >> 8); eth_wrapper.cur_txframe->data[ETH_HDR_OFFSET + 13] = (uint8)(frame->protocol & 0x00FF); return(1); } /******************************************************************************** Function: eth_stub_send Parameters: NIF *nif - network interface UINT16 len - length of packet without the eth header & CRR Return val: INT16: (-1) - Error (>=0) - OK (number of bytes written) Date: 22.1.2004 Desc: Sends the ethernet frame *********************************************************************************/ INT16 eth_stub_send (NIF *nif, UINT16 len) { int i; if(eth_wrapper.cur_txframe == NULL) return(-1); //TODO: Insert pad bytes? eth_wrapper.cur_txframe->length = len + ETH_HDR_SIZE; i = nif->send(nif, eth_wrapper.cur_txframe); /* The nif->send releases buffer */ eth_wrapper.cur_txframe = NULL; if(!i) return(-1); return(len); } /******************************************************************************** Function: eth_stub_write Parameters: NIF *nif - network interface UINT8 dat - data byte to write Return val: INT16: (-1) - Error (>=0) - OK (number of bytes written) Date: 22.1.2004 Desc: Writes single byte to tx buffer and increases write pointer *********************************************************************************/ INT16 eth_stub_write (NIF *nif, UINT8 dat) { if(eth_wrapper.cur_txframe == NULL) return(-1); //TODO: Check overflow *eth_wrapper.txp++ = dat; return(1); } /******************************************************************************** Function: eth_stub_write_buf Parameters: NIF *nif - network interface UINT8* buf - data to write UINT16 buflen - number of bytes to write Return val: INT16: (-1) - Error (>=0) - OK (number of bytes written) Date: 22.1.2004 Desc: Writes multiple bytes to tx buffer and increases write pointer *********************************************************************************/ INT16 eth_stub_write_buf (NIF *nif, UINT8* buf, UINT16 buflen) { if(eth_wrapper.cur_txframe == NULL) return(-1); //TODO: Check overflow memcpy(eth_wrapper.txp, buf, buflen); eth_wrapper.txp += buflen; return(buflen); } /* EOF */