diff --git a/drivers/net/mmnif.c b/drivers/net/mmnif.c index 3b1679be..80acc0e3 100644 --- a/drivers/net/mmnif.c +++ b/drivers/net/mmnif.c @@ -1,1139 +1,2081 @@ -/* - * mmnif.c --- memmory mapped interface - * - * Virutal IP Interface for the concept processor SCC - * - * virutally tested under Windows 7 - * - * Carl-Benedikt Krüger 2011 - * - * - * EXPERIMENTAL VERSION - */ - - -#include "mmnif.h" /* definitions */ - -#include /* lwip netif */ -#include /* inteface stats */ -#include /* ethernet arp packets */ -#include /* struct iphdr*/ -#include /* tcpip_input()*/ -#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) - -#ifdef WIN32 - -#define kmalloc malloc -#define kfree(x,y) free(x) -#define RCCE_shfree(x) VirtualFree(x,NULL,NULL); -#define RCCE_shmalloc(x) VirtualAlloc((char*)0x41000000,x,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); -#include "mailbox.h" /* mailbox_ptr_t */ -#define WIN32_LEAN_AND_MEAN -#include -#include -typedef bthread_sem_t sem_t; -typedef bthread_t tid_t; -/* "interrupt" of the other virutal network card*/ -extern HANDLE remote_process_event; -extern HANDLE remote_process_mutex; -extern HANDLE own_process_mutex; -/* HANDLE to the other Process (for WPM and RPM)*/ -extern HANDLE hProc; -#define DEBUGPRINTF(x,...) printf(x,__VA_ARGS__) - -#else - -#include /* mailbox_ptr_t */ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#define DEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__) - -#endif - - - -#define DEBUG_MMNIF -//#define DEBUG_MMNIF_PACKET - -#ifdef DEBUG_MMNIF -#include "util.h" /* hex dump */ -#endif - -/* define constants - * regarding the driver & its configuration - */ - -#define MMNIF_TX_BUFFERLEN 1792 -#define MMNIF_TX_QUEUELEN 4 - -#define MMNIF_RX_BUFFERLEN 8192 -#define MMNIF_MAX_DESCRIPTORS 32 - -#define MMNIF_CORES 48 - -#define MMNIF_POLL_BUDGET 0x100000 - -#define MMNIF_STATUS_FREE 0x00 -#define MMNIF_STATUS_PENDING 0x01 -#define MMNIF_STATUS_RDY 0x02 -#define MMNIF_STATUS_INPROC 0x03 -#define MMNIF_STATUS_PROC 0x04 - - -/* decide whether it's polling mode or not - */ -static int no_irq = 0; - -/* this will be set by open() and close() and shows wether the driver is running or not -*/ -static int active = 0; - -/* decide wheter it's uses locking or not - */ -static int disable_locking = 0; - -/* decide whether deliver work to a worker thread or instantly process all packets - */ -static int instant_process = 1; - -/* IP address of the local core and the router core to get packets forwarded - */ -static unsigned int own_ip_address = 0xC0A80000; /* 192.168.0.0 */ - -static unsigned int router_ip_address = 0xC0A80001; /* 192.168.0.1 */ - -/* "message passing buffer" specific constants: - * - start address - * - size - */ -char* mpb_start_address = NULL; -unsigned int mpb_size = NULL; - -/* - * the memory mapped network device - */ -static struct netif* mmnif_dev = NULL; - -/* thread variables */ -static tid_t worker_thread; -static tid_t polling_thread; - -typedef struct mmnif_device_stats -{ - /* device stats (granularity in packets): - * - recieve errors - * - recieve successes - * - recieved bytes - * - transmit errors - * - transmit successes - * - transmitted bytes - */ - unsigned int rx_err; - unsigned int rx; - - unsigned int rx_bytes; - - unsigned int tx_err; - unsigned int tx; - - unsigned int tx_bytes; - - /* Heuristics : - * - how many times an budget overflow occured - * - how many times the polling thread polled without recieving a new message - * - how many messages are recieved via interrupt - * - how many messages are recieved via the polling thread - */ - unsigned int bdg_overflow; - unsigned int pll_empty; - unsigned int rx_intr; - unsigned int rx_poll; - -} mmnif_device_stats_t; - -/* receive descror structure */ -typedef struct rx_desc -{ - uint8_t stat; - uint16_t len; - uint32_t addr; - -} rx_desc_t; - -/* receive ring buffer structure */ -typedef struct mm_rx_buffer -{ - /* iv_intr: inform via interrupt - * states whether the interface wants to recieve an interrupt for - * incoming packet - */ - uint16_t iv_intr; - /* memory "pseudo-ring/heap" - * packets are always in one single chunk of memory - * head : head of allocated memory region - * tail : tail of allocated memory region - */ - uint16_t head; - uint16_t tail; - spinlock_t rlock; - /* descritpor queue - * desc_table : descriptor table - * dcount : descriptor's free in queue - * dread : next descriptor to read - * dwrite : next descriptor to write - * dlock : lock to protect these members - */ - rx_desc_t desc_table[MMNIF_MAX_DESCRIPTORS]; - uint8_t dcount; - uint8_t dread; - uint8_t dwrite; - spinlock_t dlock; -} mm_rx_buffer_t; - -typedef struct mmnif -{ - struct mmnif_device_stats stats; - - /* Interface constants: - * - ehternet address - * - local ip address - */ - struct eth_addr* ethaddr; - uint32_t ipaddr; - - /* memory interaction variables: - * - transmit queue - * - pointer to transmit buffer - * - pointer to recive buffer - */ - uint8_t tx_queue; - uint8_t* tx_buff[MMNIF_TX_QUEUELEN]; - mm_rx_buffer_t* rx_buff; - - /* lock to protect members - */ - spinlock_t lock; - - /* - */ - sem_t com_poll; - -}mmnif_t; - - -#ifdef WIN32 -__inline int RCCE_ue(void){ -#ifndef RECV - return 1; -#else - return 0; -#endif -} -#endif - -/* - * memory maped interface helper functions - */ -#ifdef WIN32 -#define __MEMCPY(x,y,z) memcpy(x,y,z) -#else -#define __MEMCPY(x,y,z) memcpy(x,y,z) -#endif - -/* mmnif_device_schedule() : - * if there is no interupt used to indicate new packets - * this creates a polling thread which looks for data - * itself - */ -__inline int mmnif_device_schedule() -{ -#ifdef WIN32 - bthread_create(&polling_thread,NULL,mmnif_poll,NULL); - return NULL; -#else - create_kernel_task(&polling_thread,mmnif_poll,NULL, NORMAL_PRIO); - return NULL; -#endif -} - -/* trigger an interrupt on the remote processor - * so he knows there is a packet to read - */ -__inline int mmnif_trigger_irq(dest_ip) -{ -#ifdef WIN32 - return SetEvent(remote_process_event); -#else - int tmp, x, y, z, addr; - - int ue = dest_ip -1; - - z = Z_PID(RC_COREID[ue]); - x = X_PID(RC_COREID[ue]); - y = Y_PID(RC_COREID[ue]); - addr = CRB_ADDR(x,y) + (z==0 ? GLCFG0 : GLCFG1); - - // send interrupt to ue - do { - NOP1; - tmp=ReadConfigReg(addr); - } while(tmp & 2); - tmp |= 2; - SetConfigReg(addr, tmp); - - return 0; -#endif -} - -/* mmnif_get_device_stats(): Returns a copy of the - * current device - */ -mmnif_device_stats_t mmnif_get_device_stats(void) -{ - mmnif_device_stats_t stats = {0}; - - if(!mmnif_dev) - DEBUGPRINTF("mmnif_get_device_stats(): the device is not initialized yet.\n"); - else - stats = ((mmnif_t*)mmnif_dev->state)->stats; - - return stats; -} - -/* mmnif_print_stats(): Print the devices stats of the - * current device - */ -void mmnif_print_stats(void) -{ - mmnif_t* mmnif; - - if (!mmnif_dev) - { - DEBUGPRINTF("mmnif_print_stats(): the device is not initialized yet.\n"); - return; - } - - mmnif = (mmnif_t*)mmnif_dev->state; - - DEBUGPRINTF("/dev/mmnif - stats:\n"); - DEBUGPRINTF("Received: %d packets successfull\n",mmnif->stats.rx); - DEBUGPRINTF("Received: %d bytes\n",mmnif->stats.rx_bytes); - DEBUGPRINTF("interrupts: %d\n",mmnif->stats.rx_intr); - DEBUGPRINTF("polling: %d\n",mmnif->stats.rx_poll); - DEBUGPRINTF("Received: %d packets containuing errors\n",mmnif->stats.rx_err); - DEBUGPRINTF("Transmitted: %d packests successfull\n",mmnif->stats.tx); - DEBUGPRINTF("Transmitted: %d bytes\n",mmnif->stats.tx_bytes); - DEBUGPRINTF("Transmitted: %d packests were dropped due to errors\n",mmnif->stats.tx_err); - -} - - -/* - * memory maped interface main functions - */ - -/* mmnif_get_destination(): low level transmid helper function - * this function deals with some HW details, it checks to wich core this packet - * should be routed and returns the destination - */ - -uint8_t mmnif_get_destination(struct netif* netif, struct pbuf* p) -{ - struct ip_hdr* iphdr; - uint8_t core; - uint8_t* ip4addr; - uint8_t addr[4]; - uint32_t netmask = 0xFFFFFF00; - - /* grab the destination ip address out of the ip header - * for internal routing the last ocet is interpreted as core ID. - */ - - iphdr = (struct ip_hdr*)(p->payload); - ip4addr = &iphdr->dest.addr; - - /* revert the address to host format */ - addr[3] = ip4addr[0]; addr[2] = ip4addr[1]; - addr[1] = ip4addr[2]; addr[0] = ip4addr[3]; - - /* check if the ip address is in the Local Area Network of the 48 cores */ - - /* if it's not the same network the router core is addressed - * Note: the router core is core 1 - */ - - if (!((netmask & *(uint32_t*)addr) == (netmask & own_ip_address) )) - return 1; - - core = addr[0]; - - /* check if the address is legitimata else return router core again */ - if ((core) < 1 || (core > MMNIF_CORES)) - core = 1; - - return core; -} - -/* mmnif_rxbuff_alloc(): - * this function allocates a continues chunk of memory - * right inside of the buffer which is used for communication - * with the remote end - */ -uint32_t mmnif_rxbuff_alloc(uint8_t dest,uint16_t len) -{ - mm_rx_buffer_t* rb = (mm_rx_buffer_t*)((char*)mpb_start_address + ( dest -1 ) * mpb_size); - char* memblock = (char*)rb + sizeof(mm_rx_buffer_t); - - uint32_t ret; - - spinlock_lock(&rb->dlock); - - if (rb->dcount) - { - if (rb->tail > rb->head) - { - if (MMNIF_RX_BUFFERLEN - rb->tail > len) - { - rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; - ret = memblock + rb->tail; - rb->desc_table[rb->dwrite].addr = ret; - rb->desc_table[rb->dwrite].len = len; - rb->dcount--; - rb->dwrite = (++rb->dwrite)%MMNIF_MAX_DESCRIPTORS; - - rb->tail = (rb->tail + len); - spinlock_unlock(&rb->dlock); - return ret; - } - else if (rb->head > len) - { - rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; - ret = memblock; - rb->desc_table[rb->dwrite].addr = ret; - rb->desc_table[rb->dwrite].len = len; - rb->dcount--; - rb->dwrite = (++rb->dwrite)%MMNIF_MAX_DESCRIPTORS; - - rb->tail = len; - spinlock_unlock(&rb->dlock); - return ret; - } - else - { - spinlock_unlock(&rb->dlock); - return NULL; - } - } - else - { - if (rb->head - rb->tail > len) - { - rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; - ret = memblock + rb->tail; - rb->desc_table[rb->dwrite].addr = ret; - rb->desc_table[rb->dwrite].len = len; - rb->dcount--; - rb->dwrite = (++rb->dwrite)%MMNIF_MAX_DESCRIPTORS; - - rb->tail = (rb->tail + len); - spinlock_unlock(&rb->dlock); - return ret; - } - else if (rb->tail == rb->head) - { - if (MMNIF_RX_BUFFERLEN - rb->tail < len) - { - rb->tail = 0; - if (rb->dread == rb->dwrite) - rb->head = 0; - } - - rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; - ret = memblock + rb->tail; - rb->desc_table[rb->dwrite].addr = ret; - rb->desc_table[rb->dwrite].len = len; - rb->dcount--; - rb->dwrite = (++rb->dwrite)%MMNIF_MAX_DESCRIPTORS; - - rb->tail = (rb->tail + len); - spinlock_unlock(&rb->dlock); - return ret; - } - else - { - spinlock_unlock(&rb->dlock); - return NULL; - } - } - } - else - { - spinlock_unlock(&rb->dlock); - return NULL; - } -} - -/* mmnif_commit_packet: this function set the state of the (in advance) - * allocated packet to RDY so the recieve queue knows that it can be - * processed further - */ -int mmnif_commit_packet(uint8_t dest,uint32_t addr) -{ - mm_rx_buffer_t* rb = (mm_rx_buffer_t*)((char*)mpb_start_address + ( dest -1 ) * mpb_size); - uint32_t i; - - for (i = 0; i < MMNIF_MAX_DESCRIPTORS; i++) - { - if (rb->desc_table[i].addr == addr && rb->desc_table[i].stat == MMNIF_STATUS_PENDING) - { - rb->desc_table[i].stat = MMNIF_STATUS_RDY; - return 0; - } - } - return -1; -} - -/* mmnif_rxbuff_free() : the opposite to mmnif_rxbuff_alloc() a from the receiver - * already processed chunk of memory is freed so that it can be allocated again - */ -void mmnif_rxbuff_free(void) -{ - mmnif_t* mmnif = mmnif_dev->state; - mm_rx_buffer_t* b = mmnif->rx_buff; - uint32_t i,j; - uint32_t rpos; - - spinlock_lock(&b->dlock); - - rpos = b->dread; - - for (i = 0, j = rpos; i < MMNIF_MAX_DESCRIPTORS; i++) - { - j = (j+i)%MMNIF_MAX_DESCRIPTORS; - - if (b->desc_table[j].stat == MMNIF_STATUS_PROC) - { - b->dcount++; - b->dread = (b->dread +1)%MMNIF_MAX_DESCRIPTORS; - b->desc_table[j].stat = MMNIF_STATUS_FREE; - - if (b->tail > b->head) - { - b->head += b->desc_table[j].len; - } - else - { - if ( (b->desc_table[(j+1)%MMNIF_MAX_DESCRIPTORS].stat != MMNIF_STATUS_FREE ) - && ( b->desc_table[j].addr > b->desc_table[(j+1)%MMNIF_MAX_DESCRIPTORS].addr)) - { - b->head = 0; - - } - else - { - b->head += b->desc_table[j].len; - } - } - } - else - break; - } - - spinlock_unlock(&b->dlock); -} -/* - * Transmid a packet (called by the lwip) - */ -err_t mmnif_tx(struct netif* netif, struct pbuf* p) -{ - mmnif_t* mmnif = netif->state; - uint8_t slot = mmnif->tx_queue; - - uint32_t write_address; - uint32_t i; - struct pbuf* q; /* interator */ - - uint8_t build_buff = TRUE; - uint32_t dest_ip = mmnif_get_destination(netif,p); - - mm_rx_buffer_t* rb = (mm_rx_buffer_t*)((char*)mpb_start_address + ( dest_ip -1 ) * mpb_size); - -#ifdef WIN32 - ReadProcessMemory(hProc, (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size, (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,mpb_size,NULL); - WaitForSingleObject(remote_process_mutex,INFINITE); -#endif - - spinlock_lock(&mmnif->lock); - mmnif->tx_queue++; - spinlock_unlock(&mmnif->lock); - - - /* Perform serveral sanity checks on the packet and the buffers: - * - is the queue full? - * - is the output packet to big? - */ - - if (mmnif->tx_queue > MMNIF_TX_QUEUELEN) - { - DEBUGPRINTF("mmnif_tx(): too many packets at once for tx_queue\n"); - goto drop_packet; - } - - if (p->tot_len > MMNIF_TX_BUFFERLEN) - { - DEBUGPRINTF("mmnif_tx(): packet is longer than %d bytes\n",MMNIF_TX_BUFFERLEN); - goto drop_packet; - } - - /* check if the pbuf consists only of one element - * if that is the case it would be much overhead - * copying that packet again - */ - if (!p->next) - build_buff = FALSE; - - if (build_buff) - { - /* build the payload out of the p's - * ensure that the packet is in one memory chunk stored in the transmid buffer - */ - for (q = p, i = 0; q != 0; q = q->next) - { - memcpy(mmnif->tx_buff[slot] + i, q->payload, q->len); - i += q->len; - } - } - - /* allocate memory for the packet in the remote buffer */ - - write_address = mmnif_rxbuff_alloc(dest_ip,p->tot_len); - - if (!write_address) - goto drop_packet; - - /* write buffer to buffer & increment the queued packet count - * this can be safely done without locking because this place is - * reserved for us because it has the status "pending" - */ - if (build_buff) - memcpy(write_address,mmnif->tx_buff[slot],p->tot_len); - else - memcpy(write_address,p->payload,p->tot_len); - - - if (mmnif_commit_packet(dest_ip,write_address)) - { - DEBUGPRINTF("mmnif_tx(): packet somehow lost during commit\n"); - } - -#ifdef DEBUG_MMNIF_PACKET - DEBUGPRINTF("\n SEND 0x%.8X with length: %d\n",(char*)mpb_start_address + (dest_ip -1)*mpb_size + pos * 1792,p->tot_len +2); - hex_dump(p->tot_len, p->payload); -#endif - - /* release the tx_queue because it's finished */ - spinlock_lock(&mmnif->lock); - mmnif->tx_queue--; - spinlock_unlock(&mmnif->lock); - - /* just gather some stats */ - LINK_STATS_INC(link.xmit); - - mmnif->stats.tx++; - mmnif->stats.tx_bytes += p->tot_len; - -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size, (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,mpb_size,NULL); - SetEvent(remote_process_event); - ReleaseMutex(remote_process_mutex); -#endif - - if (rb->iv_intr) - mmnif_trigger_irq(dest_ip); - - return ERR_OK; - -drop_packet: - /* drop packet for one or another reason - */ - spinlock_lock(&mmnif->lock); - mmnif->tx_queue--; - spinlock_unlock(&mmnif->lock); - - LINK_STATS_INC(link.drop); - mmnif->stats.tx_err++; - -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,mpb_size,NULL); -#endif - - return ERR_IF; -} - -/* mmnif_link_layer(): wrapper function called by ip_output() - * adding all needed headers for the link layer - * because we have no link layer and everything is reliable we don't need - * to add anything so we just pass it to our tx function - */ -static void mmnif_link_layer(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) -{ - netif->linkoutput(netif,q); -} - -/* - * Init the device (called from lwip) - * It's invoked in netif_add - */ -err_t mmnif_init(struct netif* netif) -{ - mmnif_t* mmnif; - uint32_t i; - int num = 0; - - /* Alloc and clear memory for the device struct - */ - mmnif = kmalloc(sizeof(mmnif_t)); - - if (!mmnif) - { - DEBUGPRINTF("mmnif init():out of memory\n"); - return ERR_MEM; - } - memset(mmnif, 0, sizeof(mmnif_t)); - - /* Alloc and clear shared memory for rx_buff - */ - mpb_size = (sizeof(mm_rx_buffer_t) + MMNIF_RX_BUFFERLEN); - // align mpb size to the granularity of a page size - mpb_size = (mpb_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - mpb_start_address = RCCE_shmalloc(mpb_size*MMNIF_CORES); - // map physical address in the virtual address space - mpb_start_address = map_region(0, mpb_start_address, mpb_size >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_NO_CACHE); - - mmnif->rx_buff = mpb_start_address + (mpb_size) * (own_ip_address - router_ip_address); - if (!(mpb_start_address)) - { - DEBUGPRINTF("mmnif init(): allocating shared memory failed\n"); - return ERR_MEM; - } - memset(mmnif->rx_buff, 0, mpb_size); - - /* set initial values - */ - mmnif->rx_buff->dcount = MMNIF_MAX_DESCRIPTORS; - - /* init the lock's for the hdr - */ - - spinlock_init(&mmnif->rx_buff->rlock); - spinlock_init(&mmnif->rx_buff->dlock); - - spinlock_init(&mmnif->lock); - - /* init the sems for communication art - */ - sem_init(&mmnif->com_poll,1); - - /* since there is no possibilty to create a full semaphore we just block it manually - */ - sem_wait(&mmnif->com_poll,0); - - /* inform via interrupt should be the dafault - */ - if (!no_irq) - mmnif->rx_buff->iv_intr = TRUE; - - /* Alloc and clear internal memory for tx_buff - */ - mmnif->tx_buff[0] = kmalloc(MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); - - if (!(mmnif->tx_buff[0])) - { - DEBUGPRINTF("mmnif init: out of memory tx\n"); - return ERR_MEM; - } - mmnif->tx_queue = 0; - memset(mmnif->tx_buff[0], 0, MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); - - for (i = 0; i < MMNIF_TX_QUEUELEN -1 ; i++) - mmnif->tx_buff[i+1] = mmnif->tx_buff[i] + MMNIF_TX_BUFFERLEN; - - /* pass the device state to lwip */ - netif->state = mmnif; - mmnif_dev = netif; - - /* administrative details */ - netif->name[0] = 'e'; - netif->name[1] = 'n'; - netif->num = num; - num++; - /* downward functions */ - netif->output = mmnif_link_layer; - /* there is no special link layer just the ip layer */ - netif->linkoutput = mmnif_tx; - /* maximum transfer unit */ - netif->mtu = 1500; - /* broadcast capability, keep all default flags*/ - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP; - /* hardware address length */ - netif->hwaddr_len = 6; - - active = TRUE; - -#ifdef MMNIF_DEBUG - DEBUGPRINTF("mmnif init complete\n"); -#endif - - return NULL; -} - -/* - * Receive a packet : recieve, pack it up and pass over to higher levels - */ -static void mmnif_rx(struct netif* netif) -{ - mmnif_t* mmnif = netif->state; - mm_rx_buffer_t* b = mmnif->rx_buff; - - uint16_t length; - struct pbuf* p = NULL; - struct pbuf* q; - char* packet; - - uint32_t i,j; - uint8_t rdesc = 0xFF; - - err_t err = NULL; - -#ifdef WIN32 - ReadProcessMemory(hProc, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size,mpb_size,NULL); - WaitForSingleObject(own_process_mutex,INFINITE); -#endif - - spinlock_lock(&b->rlock); - - /* check if this call to mmnif_rx makes any sense - */ - if (b->desc_table[b->dread].stat == MMNIF_STATUS_FREE) - { - spinlock_unlock(&b->rlock); -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size,mpb_size,NULL); -#endif - return; - } - - /* search the packet whose transmission is finished - */ - for (i = 0,j = b->dread; i < MMNIF_MAX_DESCRIPTORS; i++) - { - if (b->desc_table[(j + i)% MMNIF_MAX_DESCRIPTORS].stat == MMNIF_STATUS_RDY) - { - rdesc = (j + i)% MMNIF_MAX_DESCRIPTORS; - b->desc_table[rdesc].stat = MMNIF_STATUS_INPROC; - packet = (char*)b->desc_table[rdesc].addr; - length = b->desc_table[rdesc].len; - break; - } - } - - spinlock_unlock(&b->rlock); - - /* if there is no packet finished we encountered a random error - */ - if (rdesc == 0xFF) - { -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size,mpb_size,NULL); -#endif - return; - } - - /* If length is zero return silently - */ - if (length == 0) - { - DEBUGPRINTF("mmnif_rx(): empty packet error\n"); - return; - } - if (length < sizeof(struct ip_hdr) ||length > netif->mtu) - { - DEBUGPRINTF("mmnif_rx(): illegal packet length %d => drop the packet\n",length); - goto drop_packet; - } - - /* From now on there is a real packet and it - * has to be worked on - */ - - #ifdef DEBUG_MMNIF_PACKET - DEBUGPRINTF("\n RECIEVED - 0x%.8X with legth: %d\n",packet,length); - hex_dump(length,packet); - #endif - - /* Build the pbuf for the packet so the lwip - * and other higher layer can handle it - */ - p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); - if (!p) - { - DEBUGPRINTF("mmnif_rx(): low on mem - packet dropped\n"); - goto drop_packet; - } - - /* copy packet to pbuf structure going through linked list */ - for (q=p, i = 0; q!=NULL; q=q->next) - { - memcpy((uint8_t*)q->payload,&packet[i],q->len); - i +=q->len; - } - - /* indicate that the copy process is done and the packet can be freed - * note that we did not lock here because we are the only one editing this value - */ - mmnif->rx_buff->desc_table[rdesc].stat = MMNIF_STATUS_PROC; - - /* everything is copied to a new buffer so it's save to release - * the old one for new incoming packets - */ - - mmnif_rxbuff_free(); - - /* full packet send to tcpip_thread to process */ - if ((err = mmnif_dev->input(p, mmnif_dev)) != ERR_OK) - { - DEBUGPRINTF("mmnif_rx: IP input error\n"); - pbuf_free(p); - } - - /* gather some stats and leave the rx handler */ - LINK_STATS_INC(link.xmit); - mmnif->stats.rx++; - - mmnif->stats.rx_bytes += p->tot_len; - - if (mmnif->rx_buff->iv_intr) - mmnif->stats.rx_intr++; - else - mmnif->stats.rx_poll++; - -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size,mpb_size,NULL); - ReleaseMutex(own_process_mutex); -#endif - - return; - -drop_packet: - - spinlock_lock(&mmnif->rx_buff->rlock); - /*error handling*/ - spinlock_unlock(&mmnif->rx_buff->rlock); - - LINK_STATS_INC(link.drop); - mmnif->stats.rx_err++; - -#ifdef WIN32 - WriteProcessMemory(hProc, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size, (char*)mpb_start_address + ( !((own_ip_address && 0xFF)-1) ) * mpb_size,mpb_size,NULL); -#endif - return; -} -/* mmnif_irqhandler(): - * handles the incomint interrupts - */ -void mmnif_irqhandler(void) -{ - mmnif_t* mmnif; - - /* return if mmnif_dev is not yet initialized*/ - if (!mmnif_dev) - { - DEBUGPRINTF("mmnif_irqhandler(): the driver is not initialized yet\n"); - return; - } - - mmnif = (mmnif_t*) mmnif_dev->state; - - while (mmnif->rx_buff->dcount < MMNIF_MAX_DESCRIPTORS) - { - mmnif_rx(mmnif_dev); - -// if (instant_process) -// mmnif_wait(mmnif_dev,1,MMNIF_WORKER_BUDGET); - } -} -/* - * the poll function wich is used if no interrupt wake up our mmnif_rx functions - */ -int mmnif_poll(void* e) -{ - mmnif_t* mmnif; - - if (!mmnif_dev) - { - DEBUGPRINTF("mmnif_poll(): the driver is not initialized yet\n"); - return -1; - } - - mmnif = (mmnif_t*) mmnif_dev->state; - -#ifdef DEBUG_MMNIF - DEBUGPRINTF("mmnif_poll(): polling thread launched",mmnif->rx_buff); -#endif - - if (!no_irq) - { - sem_wait(&mmnif->com_poll,0); - } - - /*run while driver is up*/ - while (active) - { - while (!mmnif->rx_buff->dcount == MMNIF_MAX_DESCRIPTORS) - { - mmnif->stats.pll_empty++; - if (mmnif->stats.pll_empty >= MMNIF_POLL_BUDGET) - { - /* enable interrupts and suspend polling - * - */ - mmnif->rx_buff->iv_intr = TRUE; - mmnif->stats.pll_empty = 0; -#ifdef DEBUG_MMNIF - DEBUGPRINTF("mmnif_poll(): heuristical interrupts enabled\n"); -#endif - sem_wait(&mmnif->com_poll,0); - } - /* uncomment this to test only polling - */ - // mmnif->stats.pll_empty = 0; - } - - mmnif->stats.pll_empty=0; - mmnif_rx(mmnif_dev); - - } - - return NULL; -} -/* - * Open the interface should be called by kernel to use this network interface - */ -int mmnif_open(void) -{ - struct ip_addr ipaddr; - struct ip_addr netmask; - struct ip_addr gw; - - /* calculate my own ip address from core number - * Note: core 1 is the router core - */ - IP4_ADDR(&gw, 0,0,0,0); - IP4_ADDR(&ipaddr, 192,168,0,RCCE_ue() +1); - IP4_ADDR(&netmask, 255,255,255,0); - - own_ip_address+= RCCE_ue() +1; - - mmnif_dev = kmalloc(sizeof(struct netif)); - - /* register our Memory Mapped Virtual IP interface in the lwip stack - * and tell him how to use the interface: - * - mmnif_dev : the device data storage - * - ipaddr : the ip address wich should be used - * - gw : the gateway wicht should be used - * - mmnif_init : the initialization which has to be done in order to use our interface - * - ethernet_input : tells him that he should get ethernet input (inclusice ARP) - * - * Note: Ethernet Input will be removed because its NOT needed and will - * be replaced with ip_input - */ - if (!netif_add(mmnif_dev, &ipaddr, &netmask, &gw, NULL,(netif_init_fn)mmnif_init, tcpip_input)) - { - DEBUGPRINTF("mmnif_open() : unable to add network interface\n"); - return -1; - } - - /* set our network interface to the default interface for lwip*/ - //netif_set_default(mmnif_dev); - /* tell lwip all initialization is done and we want to set it ab*/ - netif_set_up(mmnif_dev); - - /* test if interface is really up */ - if (!netif_is_up(mmnif_dev)) - { - DEBUGPRINTF("mmnif_open(): network interface is not up\n"); - return -2; - } - - /* indicate that the driver is active now*/ - active = TRUE; - - /* If interrupts are not used we immediately add the polling function - * to the queue which would otherwise be done through the IRQ handler. - */ - mmnif_device_schedule(); - - /* Start the device worker thread wich actually processes the incoming - * packet's this is not done in the "interrupt handler" to shorten them up - */ -// if (!instant_process) -// mmnif_worker_schedule(); - - - // mmnif_retrigger_schedule(); - -#ifdef DEBUG_MMNIF - DEBUGPRINTF("mmnif_dev is open\n"); -#endif - - return 0; - -} - -/* - * close the interface should be called by kernel to close this interface and release resources - * Note: it's temporarly empty. Support will be added. - */ -int mmnif_close(void) -{ - size_t phyaddr; - - mmnif_t* mmnif; - - if (!mmnif_dev) - { - DEBUGPRINTF("mmnif_close(): you closed the device before it was properly opened -.-* \n"); - } - - mmnif = (mmnif_t*)mmnif_dev->state; - /* indicate that the driver is not active anymore - * - this will stop the polling thread i.e. - */ - - active = FALSE; - - kfree(mmnif->tx_buff[0],MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); - kfree(mmnif_dev,sizeof(mmnif_t)); - - // determine physical address - phyaddr = virt_to_phys(mpb_start_address); - // unmap shared memory regeion - unmap_region(mpb_start_address, mpb_size >> PAGE_SHIFT); - RCCE_shfree(phyaddr); - - return NULL; -} - -#endif +/* + * Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + * + * mmnif.c --- memmory mapped interface + * + * Virutal IP Interface for the concept processor SCC + * + */ + +#include "mmnif.h" /* definitions */ + +#include /* lwip netif */ +#include /* inteface stats */ +#include /* ethernet arp packets */ +#include /* struct iphdr */ +#include /* tcpip_input() */ +#include + +//#include + +#include /* mailbox_ptr_t */ +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#define TRUE 1 +#define FALSE 0 + +#define DEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__) + +#define DEBUG_MMNIF +//#define DEBUG_MMNIF_PACKET + +// set to 1 if you want to enable the L1 cache for the receive buffers +#define USE_CACHE 0 + +// set to 1 if you want to use the message passing buffer +#define MMNIF_USE_MPB 0 + +/* Cache line wrappers */ +#define CLINE_SHIFT 5 +#define CLINE_SIZE (1UL << CLINE_SHIFT) +#define CLINE_MASK (~(CLINE_SIZE - 1)) +#define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK) +//#define CLINE_ALIGN(_x) (_x) + +#define MMNIF_AUTO_SOCKET_TIMEOUT 500 + +#define MMNIF_FAST_SOCKET_BLOCK 0 + +#ifdef DEBUG_MMNIF +#include "util.h" /* hex dump */ +#endif + +/* define constants + * regarding the driver & its configuration + */ + +#define MMNIF_TX_BUFFERLEN 2048 +#define MMNIF_TX_QUEUELEN 4 + +#define MMNIF_RX_BUFFERLEN 7*1024 +#define MMNIF_MAX_DESCRIPTORS 64 + +#define MMNIF_CORES 2 + +#define MMNIF_POLL_BUDGET 0x100000 +#define MMNIF_INTR_BUDGET 0x10 + +#define MMNIF_STATUS_FREE 0x00 +#define MMNIF_STATUS_PENDING 0x01 +#define MMNIF_STATUS_RDY 0x02 +#define MMNIF_STATUS_INPROC 0x03 +#define MMNIF_STATUS_INPROC_BYPASS 0x04 +#define MMNIF_STATUS_PROC 0x05 + +#define MMNIF_MAX_ACCEPTORS 0x20 +#define MMNIF_ACC_STAT_CLOSED 0x00 +#define MMNIF_ACC_STAT_ACCEPTING 0x01 +#define MMNIF_ACC_STAT_ACCEPT_ME 0x02 +#define MMNIF_ACC_STAT_ACCEPTED 0x03 + +#define MMNIF_HASHTABLE_SIZE 0x20 + +#define MMNIF_PSEUDO_SOCKET_START 0x31337 + +static int npseudosocket = MMNIF_PSEUDO_SOCKET_START; +static spinlock_t pseudolock; + +/* decide whether it's polling mode or not + */ +static int reduce_irq = 0; + +/* this will be set by open() and close() and shows wether the driver is running or not +*/ +static int active = 0; + +/* IP address of the local core and the router core to get packets forwarded + */ +static unsigned int own_ip_address = 0xC0A80000; /* 192.168.0.0 */ +static unsigned int router_ip_address = 0xC0A80001; /* 192.168.0.1 */ +//static unsigned int budget_overflow_count = 0; + +/* "message passing buffer" specific constants: + * - start address + * - size + */ +static char* header_start_address = NULL; +static unsigned int header_size = 0; +static char* heap_start_address = NULL; +static unsigned int heap_size = 0; + +/* + * the memory mapped network device + */ +static struct netif* mmnif_dev = NULL; + +/* thread variables */ +static tid_t polling_thread; + +/* accept struct + */ +typedef struct acceptor { + + /* stat: status of the acceptor + * src_ip: where did the connect request came from + * port: port on which the acceptor is listening + * alock : acceptor lock + * nsock : next pseudo socket which is used in further connection + * rsock : remote socket which has to be assosicated with the nsock + */ + uint8_t stat; + uint8_t src_ip; + uint16_t port; + spinlock_t alock; + int nsock; + int rsock; +} acceptor_t; + +/* bypass descriptor struct + */ +typedef struct bypass_rxdesc { + + /* socket : hashtarget + * remote_socket: socket on the remote end + * cnt : atomic counter for the recv function + * dest_ip : associated destination ip/core + */ + int socket; + int remote_socket; + sem_t sem; + atomic_int32_t cnt; + uint8_t dest_ip; +} bypass_rxdesc_t; + +/* + */ +static bypass_rxdesc_t mmnif_hashtable[MMNIF_HASHTABLE_SIZE]; +typedef struct mmnif_device_stats { + + /* device stats (granularity in packets): + * - recieve errors + * - recieve successes + * - recieved bytes + * - transmit errors + * - transmit successes + * - transmitted bytes + */ + unsigned int rx_err; + unsigned int rx; + unsigned int rx_bytes; + unsigned int tx_err; + unsigned int tx; + unsigned int tx_bytes; + + /* Heuristics : + * - how many times an budget overflow occured + * - how many times the polling thread polled without recieving a new message + * - how many messages are recieved via interrupt + * - how many messages are recieved via the polling thread + */ + unsigned int bdg_overflow; + unsigned int pll_empty; + unsigned int rx_intr; + unsigned int rx_poll; +} mmnif_device_stats_t; + +/* receive descror structure */ +typedef struct rx_desc { + + /* stat : status of the descriptor + * len : length of the packet + * addr : memory address of the packet + * fast_sock: (-1) if no socket is associated + * else the socket n of the fast socket + */ + uint8_t stat; + uint16_t len; + uint32_t addr; + uint32_t fast_sock; +} rx_desc_t; + +/* receive ring buffer structure */ +typedef struct mm_rx_buffer { + + /* iv_intr: inform via interrupt + * states whether the interface wants to recieve an interrupt for + * incoming packet + */ + uint16_t iv_intr; + + /* memory "pseudo-ring/heap" + * packets are always in one single chunk of memory + * head : head of allocated memory region + * tail : tail of allocated memory region + */ + uint16_t head; + uint16_t tail; + spinlock_t rlock; + + /* descritpor queue + * desc_table : descriptor table + * dcount : descriptor's free in queue + * dread : next descriptor to read + * dwrite : next descriptor to write + * dlock : lock to protect these members + */ + rx_desc_t desc_table[MMNIF_MAX_DESCRIPTORS]; + uint8_t dcount; + uint8_t dread; + uint8_t dwrite; + spinlock_t dlock; + + /* acceptors + * shared memory "hashtable" to realize + * fast socket accept/connect + */ + acceptor_t acceptors[MMNIF_MAX_ACCEPTORS]; +} mm_rx_buffer_t; + +typedef struct mmnif { + struct mmnif_device_stats stats; + + /* Interface constants: + * - ehternet address + * - local ip address + */ + struct eth_addr *ethaddr; + uint32_t ipaddr; + + /* memory interaction variables: + * - transmit queue + * - pointer to transmit buffer + * - pointer to recive buffer + */ + uint8_t tx_queue; + uint8_t *tx_buff[MMNIF_TX_QUEUELEN]; + mm_rx_buffer_t *rx_buff; + uint8_t *rx_heap; + + /* lock to protect members + */ + spinlock_t lock; + + /* semaphore to regulate polling vs. interrupts + */ + sem_t com_poll; +} mmnif_t; + +/* + * A write access, which cache line is not present, doesn't perform (on the + * current SCC architecture) a cache line fill. Therefore, the core writes + * in this case directly to the memory. + * + * The following function copies from the on-die memory (MPB) to the off-die + * memory and prefetchs its destintation. Therefore, the function avoids the + * bad behavior of a "write miss". + */ +inline static void *memcpy_get(void *dest, const void *src, size_t count) +{ + int h, i, j, k, l, m; + asm volatile ("cld;\n\t" + "1: cmpl $0, %%eax ; je 2f\n\t" + "movl (%%edi), %%edx\n\t" + "movl 0(%%esi), %%ecx\n\t" + "movl 4(%%esi), %%edx\n\t" + "movl %%ecx, 0(%%edi)\n\t" + "movl %%edx, 4(%%edi)\n\t" + "movl 8(%%esi), %%ecx\n\t" + "movl 12(%%esi), %%edx\n\t" + "movl %%ecx, 8(%%edi)\n\t" + "movl %%edx, 12(%%edi)\n\t" + "movl 16(%%esi), %%ecx\n\t" + "movl 20(%%esi), %%edx\n\t" + "movl %%ecx, 16(%%edi)\n\t" + "movl %%edx, 20(%%edi)\n\t" + "movl 24(%%esi), %%ecx\n\t" + "movl 28(%%esi), %%edx\n\t" + "movl %%ecx, 24(%%edi)\n\t" + "movl %%edx, 28(%%edi)\n\t" + "addl $32, %%esi\n\t" + "addl $32, %%edi\n\t" + "dec %%eax ; jmp 1b\n\t" + "2: movl %%ebx, %%ecx\n\t" + "movl (%%edi), %%edx\n\t" + "andl $31, %%ecx\n\t" + "rep ; movsb\n\t":"=&a" (h), "=&D"(i), "=&S"(j), + "=&b"(k), "=&c"(l), "=&d"(m):"0"(count / 32), + "1"(dest), "2"(src), "3"(count):"memory", "cc"); + return dest; +} + +/* + * In our kernel, we didn't want to use FPU registers. + * Therefore, we use standard memcpy routine + */ +inline static void *memcpy_put(void *dest, const void *src, size_t count) +{ + int32_t i, j, k; + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + asm volatile ("cld; rep movsl\n\t" + "movl %4, %%ecx\n\t" + "andl $3, %%ecx\n\t" + "rep movsb\n\t":"=&c" (i), "=&D"(j), + "=&S"(k):"0"(count / 4), "g"(count), "1"(dest), + "2"(src):"memory", "cc"); + return dest; +} + +/* + * memory maped interface helper functions + */ + +/* mmnif_device_schedule() : + * if there is no interupt used to indicate new packets + * this creates a polling thread which looks for data + * itself + */ +inline int mmnif_device_schedule() +{ + return create_kernel_task(&polling_thread, mmnif_poll, NULL, NORMAL_PRIO); +} + +/* trigger an interrupt on the remote processor + * so he knows there is a packet to read + */ +inline int mmnif_trigger_irq(dest_ip) +{ + int tmp, x, y, z, addr; + int ue = dest_ip - 1; + z = Z_PID(RC_COREID[ue]); + x = X_PID(RC_COREID[ue]); + y = Y_PID(RC_COREID[ue]); + addr = CRB_ADDR(x, y) + (z == 0 ? GLCFG0 : GLCFG1); + + // send interrupt to ue + do { + NOP1; + tmp = ReadConfigReg(addr); + } + while (tmp & 2); + tmp |= 2; + SetConfigReg(addr, tmp); + return 0; +} + +/* mmnif_get_device_stats(): Returns a copy of the + * current device + */ +mmnif_device_stats_t mmnif_get_device_stats() +{ + mmnif_device_stats_t stats = { + 0 + }; + if (!mmnif_dev) + DEBUGPRINTF + ("mmnif_get_device_stats(): the device is not initialized yet.\n"); + + else + stats = ((mmnif_t *) mmnif_dev->state)->stats; + return stats; +} + +/* mmnif_print_stats(): Print the devices stats of the + * current device + */ +void mmnif_print_stats() +{ + mmnif_t *mmnif; + if (!mmnif_dev) + { + DEBUGPRINTF + ("mmnif_print_stats(): the device is not initialized yet.\n"); + return; + } + mmnif = (mmnif_t *) mmnif_dev->state; + DEBUGPRINTF("/dev/mmnif - stats:\n"); + DEBUGPRINTF("Received: %d packets successfull\n", mmnif->stats.rx); + DEBUGPRINTF("Received: %d bytes\n", mmnif->stats.rx_bytes); + DEBUGPRINTF("interrupts: %d\n", mmnif->stats.rx_intr); + DEBUGPRINTF("polling: %d\n", mmnif->stats.rx_poll); + DEBUGPRINTF("Received: %d packets containuing errors\n", + mmnif->stats.rx_err); + DEBUGPRINTF("Transmitted: %d packests successfull\n", mmnif->stats.tx); + DEBUGPRINTF("Transmitted: %d bytes\n", mmnif->stats.tx_bytes); + DEBUGPRINTF("Transmitted: %d packests were dropped due to errors\n", + mmnif->stats.tx_err); +} + +/* mmnif_print_driver_status + * + */ +void mmnif_print_driver_status() +{ + mmnif_t *mmnif; + int i; + if (!mmnif_dev) + { + DEBUGPRINTF + ("mmnif_print_driver_status(): the device is not initialized yet.\n"); + return; + } + mmnif = (mmnif_t *) mmnif_dev->state; + DEBUGPRINTF("/dev/mmnif driver status: \n\n"); + DEBUGPRINTF("rx_buf: 0x%.8X\n", mmnif->rx_buff); + DEBUGPRINTF("free descriptors : %d\n\n", mmnif->rx_buff->dcount); + DEBUGPRINTF("descriptor table: (only print descriptors in use)\n"); + DEBUGPRINTF("status\taddr\tsize\n"); + for (i = 0; i < MMNIF_MAX_DESCRIPTORS; i++) + { + if (mmnif->rx_buff->desc_table[i].stat != 0) + DEBUGPRINTF("0x%.2X\t0x%.8X\t%X\t\n", + mmnif->rx_buff->desc_table[i].stat, + mmnif->rx_buff->desc_table[i].addr, + mmnif->rx_buff->desc_table[i].len); + } + DEBUGPRINTF("\n\nretrive via interrupt : %d\n", + mmnif->rx_buff->iv_intr); + DEBUGPRINTF("ring heap start addr: 0x%.8X\n", + mmnif->rx_buff + sizeof(mm_rx_buffer_t)); + DEBUGPRINTF("head: 0x%X\ttail: 0x%X\n", mmnif->rx_buff->head, + mmnif->rx_buff->tail); + mmnif_print_stats(); +} + +/* + * memory maped interface main functions + */ + +/* mmnif_get_destination(): low level transmid helper function + * this function deals with some HW details, it checks to wich core this packet + * should be routed and returns the destination + */ +uint8_t mmnif_get_destination(struct netif *netif, struct pbuf *p) +{ + struct ip_hdr *iphdr; + uint8_t core; + uint8_t *ip4addr; + uint8_t addr[4]; + uint32_t netmask = 0xFFFFFF00; + + /* grab the destination ip address out of the ip header + * for internal routing the last ocet is interpreted as core ID. + */ + iphdr = (struct ip_hdr *)(p->payload); + ip4addr = (uint8_t*) &iphdr->dest.addr; + + /* revert the address to host format */ + addr[3] = ip4addr[0]; + addr[2] = ip4addr[1]; + addr[1] = ip4addr[2]; + addr[0] = ip4addr[3]; + + /* check if the ip address is in the Local Area Network of the 48 cores */ + + /* if it's not the same network the router core is addressed + * Note: the router core is core 1 + */ + if (!((netmask & *(uint32_t *) addr) == (netmask & own_ip_address))) + return 1; + core = addr[0]; + + /* check if the address is legitimata else return router core again */ + if ((core) < 1 || (core > MMNIF_CORES)) + core = 1; + return core; +} + +/* mmnif_rxbuff_alloc(): + * this function allocates a continues chunk of memory + * right inside of the buffer which is used for communication + * with the remote end + */ +uint32_t mmnif_rxbuff_alloc(uint8_t dest, uint16_t len) +{ + mm_rx_buffer_t *rb = (mm_rx_buffer_t *) ((char *)header_start_address + (dest - 1) * header_size); + +#if MMNIF_USE_MPB + char *memblock = (char *)heap_start_address + (dest - 1) * 0x2000; +#else + char *memblock = (char *)heap_start_address + (dest - 1) * heap_size; +#endif + +// memblock = 0xC0000000 + ( dest -1 ) * heap_size; + uint32_t ret; + +// if (rb->tail > rb->head) +// if ((MMNIF_RX_BUFFERLEN - rb->tail < len)&&(rb->head < len)) +// return NULL; +// else +// if ((rb->head - rb->tail < len)&&(rb->tail != rb->head)) +// return NULL; + spinlock_lock(&rb->dlock); + if (rb->dcount) + { + if (rb->tail > rb->head) + { + if (MMNIF_RX_BUFFERLEN - rb->tail > len) + { + rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; + ret = (uint32_t) (memblock + rb->tail); + rb->desc_table[rb->dwrite].addr = ret; + rb->desc_table[rb->dwrite].len = len; + rb->dcount--; + rb->dwrite = (rb->dwrite + 1) % MMNIF_MAX_DESCRIPTORS; + rb->tail = (rb->tail + len); + spinlock_unlock(&rb->dlock); + return ret; + } else if (rb->head > len) { + rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; + ret = (uint32_t) memblock; + rb->desc_table[rb->dwrite].addr = ret; + rb->desc_table[rb->dwrite].len = len; + rb->dcount--; + rb->dwrite = (rb->dwrite + 1) % MMNIF_MAX_DESCRIPTORS; + rb->tail = len; + spinlock_unlock(&rb->dlock); + return ret; + } else { + spinlock_unlock(&rb->dlock); + return 0; + } + } else { + if (rb->head - rb->tail > len) + { + rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; + ret = (uint32_t) (memblock + rb->tail); + rb->desc_table[rb->dwrite].addr = ret; + rb->desc_table[rb->dwrite].len = len; + rb->dcount--; + rb->dwrite = (rb->dwrite + 1) % MMNIF_MAX_DESCRIPTORS; + rb->tail = (rb->tail + len); + spinlock_unlock(&rb->dlock); + return ret; + } else if (rb->tail == rb->head) { + if (MMNIF_RX_BUFFERLEN - rb->tail < len) + { + rb->tail = 0; + if (rb->dread == rb->dwrite) + rb->head = 0; + } + rb->desc_table[rb->dwrite].stat = MMNIF_STATUS_PENDING; + ret = (uint32_t) (memblock + rb->tail); + rb->desc_table[rb->dwrite].addr = ret; + rb->desc_table[rb->dwrite].len = len; + rb->dcount--; + rb->dwrite = (rb->dwrite + 1) % MMNIF_MAX_DESCRIPTORS; + rb->tail = (rb->tail + len); + spinlock_unlock(&rb->dlock); + return ret; + } else { + spinlock_unlock(&rb->dlock); + return 0; + } + } + } else { + spinlock_unlock(&rb->dlock); + return 0; + } +} + +/* mmnif_commit_packet: this function set the state of the (in advance) + * allocated packet to RDY so the recieve queue knows that it can be + * processed further + */ +int mmnif_commit_packet(uint8_t dest, uint32_t addr) +{ + mm_rx_buffer_t *rb = (mm_rx_buffer_t *) ((char *)header_start_address + (dest - 1) * header_size); + uint32_t i; + + for (i = 0; i < MMNIF_MAX_DESCRIPTORS; i++) + { + if (rb->desc_table[i].addr == addr + && rb->desc_table[i].stat == MMNIF_STATUS_PENDING) + { + rb->desc_table[i].stat = MMNIF_STATUS_RDY; + rb->desc_table[i].fast_sock = -1; + return 0; + } + } + + return -1; +} + +/* mmnif_commit_packet: this function set the state of the (in advance) + * allocated packet to RDY so the recieve queue knows that it can be + * processed further + */ +int mmnif_commit_packet_bypass(uint8_t dest, uint32_t addr, int dest_socket) +{ + mm_rx_buffer_t *rb = + (mm_rx_buffer_t *) ((char *)header_start_address + + (dest - 1) * header_size); + uint32_t i; + for (i = 0; i < MMNIF_MAX_DESCRIPTORS; i++) + { + if (rb->desc_table[i].addr == addr + && rb->desc_table[i].stat == MMNIF_STATUS_PENDING) + { + rb->desc_table[i].stat = MMNIF_STATUS_RDY; + rb->desc_table[i].fast_sock = dest_socket; + return 0; + } + } + return -1; +} + +/* mmnif_rxbuff_free() : the opposite to mmnif_rxbuff_alloc() a from the receiver + * already processed chunk of memory is freed so that it can be allocated again + */ +void mmnif_rxbuff_free() +{ + mmnif_t *mmnif = mmnif_dev->state; + mm_rx_buffer_t *b = mmnif->rx_buff; + uint32_t i, j; + uint32_t rpos; + spinlock_lock(&b->dlock); + rpos = b->dread; + for (i = 0, j = rpos; i < MMNIF_MAX_DESCRIPTORS; i++) + { + j = (j + i) % MMNIF_MAX_DESCRIPTORS; + if (b->desc_table[j].stat == MMNIF_STATUS_PROC) + { + b->dcount++; + b->dread = (b->dread + 1) % MMNIF_MAX_DESCRIPTORS; + b->desc_table[j].stat = MMNIF_STATUS_FREE; + if (b->tail > b->head) + { + b->head += b->desc_table[j].len; + } + + else + { + if ((b-> + desc_table[(j + + 1) % + MMNIF_MAX_DESCRIPTORS].stat != + MMNIF_STATUS_FREE) + && (b->desc_table[j].addr > + b->desc_table[(j + 1) % + MMNIF_MAX_DESCRIPTORS]. + addr)) + { + b->head = 0; + } + + else + { + b->head += b->desc_table[j].len; + } + } + } + + else + break; + } + spinlock_unlock(&b->dlock); +} + +/* + * Transmid a packet (called by the lwip) + */ +err_t mmnif_tx(struct netif *netif, struct pbuf *p) +{ + mmnif_t *mmnif = netif->state; + uint8_t slot = mmnif->tx_queue; + uint32_t write_address; + uint32_t i; + struct pbuf *q; /* interator */ + uint8_t build_buff = TRUE; + uint32_t dest_ip = mmnif_get_destination(netif, p); + //uint8_t chances = 20; + mm_rx_buffer_t *rb = (mm_rx_buffer_t *) ((char *)header_start_address + (dest_ip - 1) * header_size); + + spinlock_lock(&mmnif->lock); + mmnif->tx_queue++; + spinlock_unlock(&mmnif->lock); + + /* Perform serveral sanity checks on the packet and the buffers: + * - is the queue full? + * - is the output packet to big? + */ + if (mmnif->tx_queue > MMNIF_TX_QUEUELEN) + { + DEBUGPRINTF("mmnif_tx(): too many packets at once for tx_queue\n"); + goto drop_packet; + } + if (p->tot_len > MMNIF_TX_BUFFERLEN) + { + DEBUGPRINTF("mmnif_tx(): packet is longer than %d bytes\n",MMNIF_TX_BUFFERLEN); + goto drop_packet; + } + + /* check if the pbuf consists only of one element + * if that is the case it would be much overhead + * copying that packet again + */ + if (!p->next) + build_buff = FALSE; + + if (build_buff) + { + + /* build the payload out of the p's + * ensure that the packet is in one memory chunk stored in the transmid buffer + */ + for (q = p, i = 0; q != 0; q = q->next) + { + memcpy(mmnif->tx_buff[slot] + i, q->payload, q->len); + i += q->len; + } + } + + /* allocate memory for the packet in the remote buffer */ +realloc: + write_address = mmnif_rxbuff_alloc(dest_ip, CLINE_ALIGN(p->tot_len)); + if (!write_address) + { + +// DEBUGPRINTF("mmnif_tx(): concurrency"); + +// if (!chances) +// goto drop_packet; + +// chances--; +// // udelay(exp_delay); +// // exp_delay << 1; +// // reschedule(); +// // NOP8;NOP8;NOP8;NOP8;NOP8;NOP8;NOP8;NOP8; +// udelay(20000); +// mmnif_trigger_irq(dest_ip); + goto realloc; + } + if (!write_address) + goto drop_packet; + + /* write buffer to buffer & increment the queued packet count + * this can be safely done without locking because this place is + * reserved for us because it has the status "pending" + */ + +#if MMNIF_USE_MPB + asm volatile (".byte 0x0f; .byte 0x0a;\n"); + +#endif + if (build_buff) +#if MMNIF_USE_MPB + memcpy_put(write_address, mmnif->tx_buff[slot], CLINE_ALIGN(p->tot_len)); +#else + memcpy((void*)write_address, mmnif->tx_buff[slot], CLINE_ALIGN(p->tot_len)); + +#endif + else +#if MMNIF_USE_MPB + memcpy_put(write_address, p->payload, CLINE_ALIGN(p->tot_len)); + +#else + memcpy((void*)write_address, p->payload, CLINE_ALIGN(p->tot_len)); + +#endif + + *((int *)RCCE_fool_write_combine_buffer) = 1; +#if USE_CACHE +#if MMNIF_USE_MPB + asm volatile (".byte 0x0f; .byte 0x0a;\n"); + +#endif +#endif + if (mmnif_commit_packet(dest_ip, write_address)) + { + DEBUGPRINTF("mmnif_tx(): packet somehow lost during commit\n"); + } +#ifdef DEBUG_MMNIF_PACKET +// DEBUGPRINTF("\n SEND 0x%.8X with length: %d\n",(char*)heap_start_address + (dest_ip -1)*mpb_size + pos * 1792,p->tot_len +2); +// hex_dump(p->tot_len, p->payload); +#endif + + /* release the tx_queue because it's finished */ + spinlock_lock(&mmnif->lock); + mmnif->tx_queue--; + spinlock_unlock(&mmnif->lock); + + /* just gather some stats */ + LINK_STATS_INC(link.xmit); + mmnif->stats.tx++; + mmnif->stats.tx_bytes += p->tot_len; + if (rb->iv_intr) + mmnif_trigger_irq(dest_ip); + return ERR_OK; + +drop_packet: + /* drop packet for one or another reason + */ +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif_tx(): packet dropped"); + +#endif /* */ + spinlock_lock(&mmnif->lock); + mmnif->tx_queue--; + spinlock_unlock(&mmnif->lock); + LINK_STATS_INC(link.drop); + mmnif->stats.tx_err++; + return ERR_IF; +} + +/* mmnif_hashlookup(): looks up a bypass descriptor by + * the associated socket + */ +bypass_rxdesc_t *mmnif_hashlookup(int s) +{ + int i; + bypass_rxdesc_t *p; + + for (i=0, p = &mmnif_hashtable[s % MMNIF_HASHTABLE_SIZE]; isocket == s) + return p; + p = &mmnif_hashtable[(s + i + 1) % MMNIF_HASHTABLE_SIZE]; + } + return 0; +} + +/* mmnif_hashadd(): adds a entry to the hashtable + * by the socket + */ +int mmnif_hashadd(int sock, int rsock, uint8_t dest_ip) +{ + bypass_rxdesc_t *p; + int i; + p = mmnif_hashlookup(sock); + if (p != 0) + return -1; + for (i = 0; i < MMNIF_HASHTABLE_SIZE; i++) + { + p = &mmnif_hashtable[(sock + i) % MMNIF_HASHTABLE_SIZE]; + if (p->socket == -1) + { + p->socket = sock; + p->remote_socket = rsock; + p->dest_ip = dest_ip; + return 0; + } + } + return -1; +} + +/* mmnif_hashdelete(): deletes an entry from the + * hashtable + */ +int mmnif_hashdelete(int sock) +{ + bypass_rxdesc_t *p; + int i; + p = mmnif_hashlookup(sock); + if (p != 0) + return -1; + for (i = 0; i < MMNIF_HASHTABLE_SIZE; i++) + { + p = &mmnif_hashtable[(sock + i) % MMNIF_HASHTABLE_SIZE]; + if (p->socket == sock) + { + p->socket = -1; + p->remote_socket = 0; + p->dest_ip = 0; + return 0; + } + } + return -1; +} + +/* + * Transmid a packet (with insane speed) + */ +err_t mmnif_tx_bypass(struct netif * netif, void *pbuff, uint16_t size, int s) +{ + mmnif_t *mmnif = netif->state; + uint32_t write_address; + bypass_rxdesc_t *dest = mmnif_hashlookup(s); + //uint32_t exp_delay = 2; + mm_rx_buffer_t *rb = + (mm_rx_buffer_t *) ((char *)header_start_address + + (dest->dest_ip - 1) * header_size); + + /* Perform serveral sanity checks on the packet and the buffers: + * - is the output packet to big? + */ + +// if (size > MMNIF_TX_BUFFERLEN) +// { +// DEBUGPRINTF("mmnif_tx(): packet is longer than %d bytes\n",MMNIF_TX_BUFFERLEN); +// goto drop_packet; +// } + + /* allocate memory for the packet in the remote buffer */ + realloc:write_address = + mmnif_rxbuff_alloc(dest->dest_ip, CLINE_ALIGN(size)); + if (!write_address) + { + + // DEBUGPRINTF("mmnif_tx_bypass(): concurrency"); + // udelay(exp_delay); + // exp_delay << 1; + // reschedule(); + NOP8; + NOP8; + NOP8; + NOP8; + NOP8; + NOP8; + NOP8; + NOP8; + goto realloc; + } + + /* write buffer to buffer & increment the queued packet count + * this can be safely done without locking because this place is + * reserved for us because it has the status "pending" + */ + +#if MMNIF_USE_MPB + asm volatile (".byte 0x0f; .byte 0x0a;\n"); +#endif + +#if MMNIF_USE_MPB + memcpy_put(write_address, pbuff, CLINE_ALIGN(size)); +#else + memcpy((void*) write_address, pbuff, CLINE_ALIGN(size)); +#endif + *((int *)RCCE_fool_write_combine_buffer) = 1; + +#if USE_CACHE +#if MMNIF_USE_MPB + asm volatile (".byte 0x0f; .byte 0x0a;\n"); + +#endif +#endif + if (mmnif_commit_packet_bypass(dest->dest_ip, write_address, dest->remote_socket)) + { + DEBUGPRINTF("mmnif_tx(): packet somehow lost during commit\n"); + } +#ifdef DEBUG_MMNIF_PACKET + // DEBUGPRINTF("\n SEND 0x%.8X with length: %d\n",(char*)mpb_start_address + (dest_ip -1)*mpb_size + pos * 1792,p->tot_len +2); + // hex_dump(p->tot_len, p->payload); +#endif + + /* just gather some stats */ + LINK_STATS_INC(link.xmit); + mmnif->stats.tx++; + mmnif->stats.tx_bytes += size; + if (rb->iv_intr) + mmnif_trigger_irq(dest->dest_ip); + return ERR_OK; +//drop_packet: + /* drop packet for one or another reason + */ + LINK_STATS_INC(link.drop); + mmnif->stats.tx_err++; + return ERR_IF; +} + +/* mmnif_send(): is going to be used as replacement of + * lwip_send with fast_sockets + */ +int mmnif_send(int s, void *data, size_t size, int flags) +{ + bypass_rxdesc_t *p = mmnif_hashlookup(s); + uint32_t i, j, k, ret; + if (p != 0) + { + if (size < ((MMNIF_RX_BUFFERLEN / 2) - 1)) + return mmnif_tx_bypass(mmnif_dev, data, size, s); + + else + { + j = size / (((MMNIF_RX_BUFFERLEN / 2) - 1)); + k = size - (j * (((MMNIF_RX_BUFFERLEN / 2) - 1))); + for (i = 0; i < j; i++) + { + ret = + mmnif_tx_bypass(mmnif_dev, + data + + i * + ((MMNIF_RX_BUFFERLEN / 2) - + 1), + ((MMNIF_RX_BUFFERLEN / 2) - + 1), s); + if (ret < 0) + return ret; + } + ret = + mmnif_tx_bypass(mmnif_dev, + data + (j - + 1) * ((MMNIF_RX_BUFFERLEN / + 2) - 1), k, s); + return ret; + } + } + return lwip_send(s, data, size, flags); +} + +/* mmnif_link_layer(): wrapper function called by ip_output() + * adding all needed headers for the link layer + * because we have no link layer and everything is reliable we don't need + * to add anything so we just pass it to our tx function + */ +static err_t +mmnif_link_layer(struct netif *netif, struct pbuf *q, ip_addr_t * ipaddr) +{ + return netif->linkoutput(netif, q); +} + +/* + * Init the device (called from lwip) + * It's invoked in netif_add + */ +err_t mmnif_init(struct netif *netif) +{ + mmnif_t *mmnif; + uint32_t i; + int num = 0; + int tmp1, tmp2, n; + +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif init attempt\n"); + +#endif /* */ + + /* Alloc and clear memory for the device struct + */ + mmnif = kmalloc(sizeof(mmnif_t)); + if (!mmnif) + { + DEBUGPRINTF("mmnif init():out of memory\n"); + return ERR_MEM; + } + memset(mmnif, 0, sizeof(mmnif_t)); + + /* Alloc and clear shared memory for rx_buff + */ + header_size = (sizeof(mm_rx_buffer_t)); + DEBUGPRINTF("mmnif_init() : size of mm_rx_buffer_t : %d", + sizeof(mm_rx_buffer_t)); + + // align mpb size to the granularity of a page size + header_size = (header_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + header_start_address = (void*) RCCE_shmalloc(header_size * MMNIF_CORES); + DEBUGPRINTF("RCCE_shmalloc : 0x%.8X", header_start_address); + + // map physical address in the virtual address space + header_start_address = (void*) map_region(0, (size_t) header_start_address, (MMNIF_CORES * header_size) >> PAGE_SHIFT, MAP_KERNEL_SPACE | MAP_NO_CACHE); + DEBUGPRINTF("map_region : 0x%.8X", header_start_address); + mmnif->rx_buff = (mm_rx_buffer_t *) (header_start_address + (header_size) * (own_ip_address - router_ip_address)); + + /* Alloc and clear shared memory for rx_buff + */ + heap_size = (MMNIF_RX_BUFFERLEN); + + // align mpb size to the granularity of a page size + heap_size = (heap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + +#if MMNIF_USE_MPB + heap_start_address = RCCE_malloc(RCCE_LINE_SIZE); + DEBUGPRINTF("MessagePassingBuffer allocated @ : 0x%.8X\n", heap_start_address); + for (i = heap_size / RCCE_LINE_SIZE; i > 0; i--) + { + if (!RCCE_malloc(RCCE_LINE_SIZE)) ; + + { + + // DEBUGPRINTF("mmnif init(): allocating shared memory failed\n"); + // return ERR_MEM; + } + } + +#else /* */ + heap_start_address = (void*) RCCE_shmalloc(heap_size * MMNIF_CORES); + n = (int) heap_start_address; + DEBUGPRINTF("RCCE_shmalloc : 0x%.8X", header_start_address); + + // map physical address in the virtual address space +#if USE_CACHE + //heap_start_address = map_region(0, heap_start_address, (MMNIF_CORES*heap_size) >> PAGE_SHIFT, MAP_KERNEL_SPACE|MAP_MPE); + heap_start_address = map_region(0, heap_start_address, (MMNIF_CORES * heap_size) >> PAGE_SHIFT, MAP_KERNEL_SPACE | MAP_NO_CACHE | MAP_MPE); + remap_region(heap_start_address + + (heap_size) * (own_ip_address - router_ip_address), + n + (heap_size) * (own_ip_address - router_ip_address), 1, + MAP_KERNEL_SPACE | MAP_MPE); + +#else + heap_start_address = (void*) map_region(0, (size_t) heap_start_address, (MMNIF_CORES * heap_size) >> PAGE_SHIFT, MAP_KERNEL_SPACE | MAP_NO_CACHE | MAP_MPE); + +#endif // USE_CAHCE +#endif // MMNIF_USE_MPB + DEBUGPRINTF("map_region : 0x%.8X", header_start_address); + +#if MMNIF_USE_MPB + mmnif->rx_heap = heap_start_address; + heap_start_address = + heap_start_address - (own_ip_address - router_ip_address) * 0x2000; + DEBUGPRINTF("heap_start_address : 0x%.8X", heap_start_address); + +// heap_start_address = 0xC0000000; +// mmnif->rx_heap = heap_start_address + (heap_size) * (own_ip_address - router_ip_address); +#else /* */ + mmnif->rx_heap = + heap_start_address + (heap_size) * (own_ip_address - + router_ip_address); + +#endif /* */ + if (!(heap_start_address)) + { + DEBUGPRINTF("mmnif init(): allocating shared memory failed\n"); + return ERR_MEM; + } + memset(mmnif->rx_buff, 0, header_size); + memset(mmnif->rx_heap, 0, heap_size); + +#if USE_CACHE + *((int *)RCCE_fool_write_combine_buffer) = 1; + +#endif /* */ + if (own_ip_address == router_ip_address) + { + kprintf("Test0: MEMCPY 2048B"); + tmp1 = get_clock_tick(); + for (n = 0; n < 4096; n++) + { + memcpy(mmnif->rx_heap + heap_size, mmnif->rx_heap, + 2048); + +#if USE_CACHE + *((int *)RCCE_fool_write_combine_buffer) = 1; + flush_cache(); + +#endif /* */ + memcpy(mmnif->rx_heap, mmnif->rx_heap, 2048); + } tmp2 = get_clock_tick(); + kprintf("memcpy'd' %d bytes in %d ticks", n * 2048, + (tmp2 - tmp1)); + } + + /* set initial values + */ + mmnif->rx_buff->dcount = MMNIF_MAX_DESCRIPTORS; + + /* init the lock's for the hdr + */ + spinlock_init(&mmnif->rx_buff->rlock); + spinlock_init(&mmnif->rx_buff->dlock); + spinlock_init(&pseudolock); + spinlock_init(&mmnif->lock); + + /* init the sems for communication art + */ + sem_init(&mmnif->com_poll, 0); + + /* inform via interrupt should be the dafault + */ + if (!reduce_irq) + mmnif->rx_buff->iv_intr = TRUE; + + /* Alloc and clear internal memory for tx_buff + */ + mmnif->tx_buff[0] = kmalloc(MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); + if (!(mmnif->tx_buff[0])) + { + DEBUGPRINTF("mmnif init: out of memory tx\n"); + return ERR_MEM; + } + mmnif->tx_queue = 0; + memset(mmnif->tx_buff[0], 0, MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); + for (i = 0; i < MMNIF_TX_QUEUELEN - 1; i++) + mmnif->tx_buff[i + 1] = mmnif->tx_buff[i] + MMNIF_TX_BUFFERLEN; + for (i = 0; i < MMNIF_HASHTABLE_SIZE; i++) + { + mmnif_hashtable[i].socket = -1; + mmnif_hashtable[i].remote_socket = -1; + mmnif_hashtable[i].dest_ip = 0; + +#if MMNIF_FAST_SOCKET_BLOCK + sem_init(&mmnif_hashtable[i].sem, 0); + +#endif /* */ + } + for (i = 0; i < MMNIF_MAX_ACCEPTORS; i++) + { + mmnif->rx_buff->acceptors[i].stat = MMNIF_ACC_STAT_CLOSED; + mmnif->rx_buff->acceptors[i].nsock = -1; + mmnif->rx_buff->acceptors[i].rsock = -1; + mmnif->rx_buff->acceptors[i].src_ip = 0; + mmnif->rx_buff->acceptors[i].port = 0; + spinlock_init(&mmnif->rx_buff->acceptors[i].alock); + spinlock_lock(&mmnif->rx_buff->acceptors[i].alock); + spinlock_unlock(&mmnif->rx_buff->acceptors[i].alock); + } + + /* pass the device state to lwip */ + netif->state = mmnif; + mmnif_dev = netif; + + /* administrative details */ + netif->name[0] = 'e'; + netif->name[1] = 'n'; + netif->num = num; + num++; + + /* downward functions */ + netif->output = mmnif_link_layer; + + /* there is no special link layer just the ip layer */ + netif->linkoutput = mmnif_tx; + + /* maximum transfer unit */ + netif->mtu = MMNIF_TX_BUFFERLEN; + + /* broadcast capability, keep all default flags */ + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP; + + /* hardware address length */ + netif->hwaddr_len = 0; + active = TRUE; + +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif init complete\n"); +#endif + return ERR_OK; +} + +/* + * Receive a packet : recieve, pack it up and pass over to higher levels + */ +static void mmnif_rx(struct netif *netif) +{ + mmnif_t *mmnif = netif->state; + mm_rx_buffer_t *b = mmnif->rx_buff; + uint16_t length = 0; + struct pbuf *p = NULL; + struct pbuf *q; + char *packet = NULL; + uint32_t i, j; + uint8_t rdesc = 0xFF; + err_t err = ERR_OK; + bypass_rxdesc_t *bp; + +anotherpacket: + spinlock_lock(&b->rlock); + + /* check if this call to mmnif_rx makes any sense + */ + if (b->desc_table[b->dread].stat == MMNIF_STATUS_FREE) + { + spinlock_unlock(&b->rlock); + return; + } + + /* search the packet whose transmission is finished + */ + for (i = 0, j = b->dread; i < MMNIF_MAX_DESCRIPTORS; i++) + { + if (b->desc_table[(j + i) % MMNIF_MAX_DESCRIPTORS].stat == + MMNIF_STATUS_RDY) + { + rdesc = (j + i) % MMNIF_MAX_DESCRIPTORS; + if (b->desc_table[(j + i) % MMNIF_MAX_DESCRIPTORS]. + fast_sock == -1) + { + b->desc_table[rdesc].stat = MMNIF_STATUS_INPROC; + packet = (char *)b->desc_table[rdesc].addr; + length = b->desc_table[rdesc].len; + break; + } + + else + { + bp = mmnif_hashlookup(b->desc_table[rdesc]. + fast_sock); + if (!bp) + { + DEBUGPRINTF + ("mmnif_rx(): no fast socket associated with %d", + b->desc_table[rdesc].fast_sock); + mmnif->rx_buff->desc_table[rdesc].stat = MMNIF_STATUS_PROC; + mmnif_rxbuff_free(); + } + + else + { + b->desc_table[rdesc].stat = MMNIF_STATUS_INPROC; + +#if MMNIF_FAST_SOCKET_BLOCK + sem_post(&bp->sem); + +#else + atomic_int32_inc(&bp->cnt); + +#endif + } + spinlock_unlock(&b->rlock); + return; + } + } + if (b->desc_table[(j + i) % MMNIF_MAX_DESCRIPTORS].stat == MMNIF_STATUS_FREE) + { + spinlock_unlock(&b->rlock); + return; + } + } + spinlock_unlock(&b->rlock); + + /* if there is no packet finished we encountered a random error + */ + if (rdesc == 0xFF) + return; + + /* If length is zero return silently + */ + if (length == 0) + { + DEBUGPRINTF("mmnif_rx(): empty packet error\n"); + return; + } + if (length < sizeof(struct ip_hdr) || length > netif->mtu) + { + DEBUGPRINTF("mmnif_rx(): illegal packet length %d => drop the packet\n", length); + goto drop_packet; + } + + /* From now on there is a real packet and it + * has to be worked on + */ + +#ifdef DEBUG_MMNIF_PACKET + DEBUGPRINTF("\n RECIEVED - 0x%.8X with legth: %d\n", packet, length); + hex_dump(length, packet); + +#endif + + /* Build the pbuf for the packet so the lwip + * and other higher layer can handle it + */ + p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); + if (!p) + { + DEBUGPRINTF("mmnif_rx(): low on mem - packet dropped\n"); + goto drop_packet; + } +#if USE_CACHE + asm volatile (".byte 0x0f; .byte 0x0a;\n"); + +#endif /* */ + + /* copy packet to pbuf structure going through linked list */ + for (q = p, i = 0; q != NULL; q = q->next) + { + +#if MMNIF_USE_MPB + memcpy_get((uint8_t *) q->payload, &packet[i], q->len); + +#else /* */ + memcpy((uint8_t *) q->payload, &packet[i], q->len); + +#endif /* */ + i += q->len; + } + + /* indicate that the copy process is done and the packet can be freed + * note that we did not lock here because we are the only one editing this value + */ + mmnif->rx_buff->desc_table[rdesc].stat = MMNIF_STATUS_PROC; + + /* everything is copied to a new buffer so it's save to release + * the old one for new incoming packets + */ + mmnif_rxbuff_free(); + + /* full packet send to tcpip_thread to process */ + if ((err = mmnif_dev->input(p, mmnif_dev)) != ERR_OK) + { + DEBUGPRINTF("mmnif_rx: IP input error\n"); + pbuf_free(p); + } + + /* gather some stats and leave the rx handler */ + LINK_STATS_INC(link.xmit); + mmnif->stats.rx++; + mmnif->stats.rx_bytes += p->tot_len; + if (mmnif->rx_buff->iv_intr) + mmnif->stats.rx_intr++; + + else + mmnif->stats.rx_poll++; + goto anotherpacket; + return; + drop_packet:spinlock_lock(&mmnif->rx_buff->rlock); + + /*error handling */ + spinlock_unlock(&mmnif->rx_buff->rlock); + LINK_STATS_INC(link.drop); + mmnif->stats.rx_err++; + return; +} + +/* mmnif_rx_bypass(): recieve packets + * with insane speed ;) + */ +int mmnif_rx_bypass(struct netif *netif, int s, void *data, uint32_t len) +{ + mmnif_t *mmnif = netif->state; + mm_rx_buffer_t *b = mmnif->rx_buff; + uint16_t length; + char *packet; + uint32_t i, j; + uint8_t rdesc = 0xFF; + + // spinlock_lock(&b->rlock); + + /* check if this call to mmnif_rx makes any sense + */ + if (b->desc_table[b->dread].stat == MMNIF_STATUS_FREE) + { + + // spinlock_unlock(&b->rlock); + return -1; + } + + /* search the packet whose transmission is finished + */ + for (i = 0, j = b->dread; i < MMNIF_MAX_DESCRIPTORS; i++) + { + if (b->desc_table[(j + i) % MMNIF_MAX_DESCRIPTORS].stat == + MMNIF_STATUS_INPROC + && b->desc_table[(j + i) % + MMNIF_MAX_DESCRIPTORS].fast_sock != -1) + { + rdesc = (j + i) % MMNIF_MAX_DESCRIPTORS; + packet = (char *)b->desc_table[rdesc].addr; + length = b->desc_table[rdesc].len; + b->desc_table[rdesc].stat = MMNIF_STATUS_INPROC_BYPASS; + break; + } + } + + // spinlock_unlock(&b->rlock); + + /* if there is no packet finished we encountered a random error + */ + if (rdesc == 0xFF) + { + return -1; + } + + /* If length is zero return silently + */ + if (length == 0) + { + DEBUGPRINTF("mmnif_rx(): empty packet error\n"); + return -1; + } + + /* From now on there is a real packet and it + * has to be worked on + */ + +#ifdef DEBUG_MMNIF_PACKET + DEBUGPRINTF("\n RECIEVED - 0x%.8X with legth: %d\n", packet, length); + hex_dump(length, packet); + +#endif /* */ + if (len >= length) + memcpy(data, (void*) mmnif->rx_buff->desc_table[rdesc].addr, mmnif->rx_buff->desc_table[rdesc].len); + + else + goto drop_packet; + + /* indicate that the copy process is done and the packet can be freed + * note that we did not lock here because we are the only one editing this value + */ + b->desc_table[rdesc].stat = MMNIF_STATUS_PROC; + + /* everything is copied to a new buffer so it's save to release + * the old one for new incoming packets + */ + mmnif_rxbuff_free(); + + /* gather some stats and leave the rx handler */ + LINK_STATS_INC(link.xmit); + mmnif->stats.rx++; + mmnif->stats.rx_bytes += length; + if (mmnif->rx_buff->iv_intr) + mmnif->stats.rx_intr++; + + else + mmnif->stats.rx_poll++; + return length; + drop_packet:spinlock_lock(&mmnif->rx_buff->rlock); + + /*error handling */ + spinlock_unlock(&mmnif->rx_buff->rlock); + LINK_STATS_INC(link.drop); + mmnif->stats.rx_err++; + return -1; +} + +/* mmnif_recv(): replacement of lwip_recv + * for fast sockets + */ +int mmnif_recv(int s, void *data, uint32_t len, int flags) +{ + bypass_rxdesc_t *p = mmnif_hashlookup(s); + int ret; + if (p == 0) + return lwip_recv(s, data, len, flags); + +#if MMNIF_FAST_SOCKET_BLOCK + sem_wait(&p->sem, 0); + +#else /* */ + while (!atomic_int32_read(&p->cnt)) + { + + //reschedule(); + NOP8; + } + +#endif /* */ + ret = mmnif_rx_bypass(mmnif_dev, s, data, len); + atomic_int32_dec(&p->cnt); + return ret; +} + +/* mmnif_socket(): replacement of lwip_socket for + * fast sockets + */ +int mmnif_socket(int domain, int type, int protocol) +{ + int ret = 0; + if (domain == AF_MMNIF_NET) + { + spinlock_lock(&pseudolock); + ret = npseudosocket++; + spinlock_unlock(&pseudolock); + return ret; + } + return lwip_socket(domain, type, protocol); +} + +/* mmnif_accept(): replacement of lwip_accept for + * fast sockets + */ +int mmnif_accept(int s, struct sockaddr *addr, socklen_t * addrlen) +{ + struct sockaddr_in *bp = (struct sockaddr_in*)addr; + uint16_t port = bp->sin_port; + mm_rx_buffer_t *b = ((mmnif_t *) mmnif_dev->state)->rx_buff; + int i; + bypass_rxdesc_t *p; + int tmp1 = get_clock_tick(); + int tmp2 = 0; + if ((unsigned int)s >= MMNIF_PSEUDO_SOCKET_START) + { + for (i = 0; i < MMNIF_MAX_ACCEPTORS; i++) + { + if (b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS]. + stat == MMNIF_ACC_STAT_CLOSED) + { + spinlock_lock(&b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].port = port; + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat = + MMNIF_ACC_STAT_ACCEPTING; + spinlock_lock(&pseudolock); + mmnif_hashadd(npseudosocket, -1, 0); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].nsock = + npseudosocket++; + spinlock_unlock(&pseudolock); + spinlock_unlock(&b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + while (b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat != + MMNIF_ACC_STAT_ACCEPT_ME) + NOP8; + p = mmnif_hashlookup(b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + nsock); + p->dest_ip = + b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].src_ip; + p->remote_socket = + b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].rsock; + spinlock_lock(&b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat = + MMNIF_ACC_STAT_ACCEPTED; + i = b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].nsock; + spinlock_unlock(&b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + return i; + } + } + return -1; + } + + else + { + for (i = 0; i < MMNIF_MAX_ACCEPTORS; i++) + { + if (b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS]. + stat == MMNIF_ACC_STAT_CLOSED) + { + spinlock_lock(&b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].port = port; + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat = + MMNIF_ACC_STAT_ACCEPTING; + spinlock_lock(&pseudolock); + mmnif_hashadd(npseudosocket, -1, 0); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].nsock = + npseudosocket++; + spinlock_unlock(&pseudolock); + spinlock_unlock(&b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + while (b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat != + MMNIF_ACC_STAT_ACCEPT_ME) + { + tmp2 = get_clock_tick(); + if (tmp2 - tmp1 > + MMNIF_AUTO_SOCKET_TIMEOUT) + { + spinlock_lock(&b->acceptors[(i + + port) + % + MMNIF_MAX_ACCEPTORS].alock); + if (b->acceptors + [(i + + port) % + MMNIF_MAX_ACCEPTORS]. + stat == + MMNIF_ACC_STAT_ACCEPT_ME) + { + spinlock_unlock(&b-> + acceptors + [(i + + port) + % + MMNIF_MAX_ACCEPTORS]. + alock); + break; + } +#ifdef DEBUG_MMNIF + DEBUGPRINTF + ("mmnif_accept(): Timout occoured, switching to normal accept()"); + +#endif /* */ + mmnif_hashdelete(b-> + acceptors[(i + + port) + % + MMNIF_MAX_ACCEPTORS]. + nsock); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + stat = + MMNIF_ACC_STAT_CLOSED; + spinlock_unlock(&b-> + acceptors[(i + + port) + % + MMNIF_MAX_ACCEPTORS].alock); + goto normalaccept; + } + NOP8; + } + p = mmnif_hashlookup(b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + nsock); + p->dest_ip = + b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].src_ip; + p->remote_socket = + b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].rsock; + spinlock_lock(&b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + b->acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS].stat = + MMNIF_ACC_STAT_ACCEPTED; + i = b->acceptors[(i + port) % + MMNIF_MAX_ACCEPTORS].nsock; + spinlock_unlock(&b-> + acceptors[(i + + port) % + MMNIF_MAX_ACCEPTORS]. + alock); + return i; + } + } + return -1; + } + normalaccept:return lwip_accept(s, addr, addrlen); +} + +/* mmnif_connect(): replacement of lwip_connect for + * fast sockets + */ +int mmnif_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct sockaddr_in *p = (struct sockaddr_in*) name; + uint16_t port = p->sin_port; + mm_rx_buffer_t *b; + int i; + //int tmp1 = get_clock_tick(); + //int tmp2 = 0; + uint8_t core; + uint8_t *ip4addr; + uint8_t addr[4]; + //uint32_t netmask = 0xFFFFFF00; + + /* grab the destination ip address out of the ip header + * for internal routing the last ocet is interpreted as core ID. + */ + ip4addr = (uint8_t*) &p->sin_addr.s_addr; + + /* revert the address to host format */ + addr[3] = ip4addr[0]; + addr[2] = ip4addr[1]; + addr[1] = ip4addr[2]; + addr[0] = ip4addr[3]; + + /* check if the ip address is in the Local Area Network of the 48 cores */ + // if (!((netmask & *(uint32_t*)addr) == (netmask & own_ip_address) )) + // return -1; + + core = addr[0]; + if ((core) < 1 || (core > MMNIF_CORES)) + return lwip_connect(s, name, namelen); + + b = (mm_rx_buffer_t *) ((char *)header_start_address + + (core - 1) * header_size); + for (i = 0; i < MMNIF_MAX_ACCEPTORS; i++) + { + if (b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].stat == MMNIF_ACC_STAT_ACCEPTING + && b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].port == port) + { + spinlock_lock(&b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].alock); + b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].stat = MMNIF_ACC_STAT_ACCEPT_ME; + b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].rsock = s; + b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].src_ip = own_ip_address & 0xFF; + mmnif_hashadd(s, + b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].nsock, core); + spinlock_unlock(&b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].alock); + while (b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].stat != MMNIF_ACC_STAT_ACCEPTED) + { + +// tmp2 = get_clock_tick(); +// if (tmp2 - tmp1 > MMNIF_AUTO_SOCKET_TIMEOUT) +// { +//#ifdef DEBUG_MMNIF +// DEBUGPRINTF("mmnif_connect(): Timout occoured, switching to normal connect()"); +//#endif +// mmnif_hashdelete(s); +// goto normalsend; +// } + NOP8; + } + spinlock_lock(&b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].alock); + b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].stat = MMNIF_ACC_STAT_CLOSED; + spinlock_unlock(&b->acceptors[(i + port) % MMNIF_MAX_ACCEPTORS].alock); + return 0; + } + } + +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif_connect(): no acceptor found"); + +#endif + + return -1; +} + +int mmnif_listen(int s, int backlog) +{ + if ((unsigned int)s < MMNIF_PSEUDO_SOCKET_START) + return lwip_listen(s, backlog); + return 0; +} + +int mmnif_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + if ((unsigned int)s < MMNIF_PSEUDO_SOCKET_START) + return lwip_bind(s, name, namelen); + return 0; +} + +/* mmnif_closesocket(): replacement if lwip_close for + * fast_sockets + */ +int mmnif_closesocket(int s) +{ + bypass_rxdesc_t *p = mmnif_hashlookup(s); + + if (p == 0) + return -1; + mmnif_hashdelete(s); + if ((unsigned int)s < MMNIF_PSEUDO_SOCKET_START) + return lwip_close(s); + return 0; +} + +/* mmnif_irqhandler(): + * handles the incomint interrupts + */ +void mmnif_irqhandler() +{ + mmnif_t *mmnif; + + /* return if mmnif_dev is not yet initialized */ + if (!mmnif_dev) + { + DEBUGPRINTF + ("mmnif_irqhandler(): the driver is not initialized yet\n"); + return; + } + mmnif = (mmnif_t *) mmnif_dev->state; + mmnif_rx(mmnif_dev); + +// while (mmnif->rx_buff->dcount < MMNIF_MAX_DESCRIPTORS) +// { +// mmnif_rx(mmnif_dev); + +// if (mmnif->rx_buff->dcount < MMNIF_MAX_DESCRIPTORS/2) +// { +// budget_overflow_count++; +// if (budget_overflow_count >= MMNIF_INTR_BUDGET) +// { +// mmnif->rx_buff->iv_intr = FALSE; +// budget_overflow_count = 0; +// sem_post(&mmnif->com_poll); +// break; +// } +// } +// else +// budget_overflow_count = 0; + +// } +} + +/* + * the poll function wich is used if no interrupt wake up our mmnif_rx functions + */ +int mmnif_poll(void *e) +{ + mmnif_t *mmnif; + if (!mmnif_dev) + { + DEBUGPRINTF + ("mmnif_poll(): the driver is not initialized yet\n"); + return -1; + } + mmnif = (mmnif_t *) mmnif_dev->state; + if (!reduce_irq) + { + sem_wait(&mmnif->com_poll, 0); + } +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif_poll(): polling thread launched", mmnif->rx_buff); + +#endif /* */ + + /*run while driver is up */ + while (active) + { + while (mmnif->rx_buff->desc_table[mmnif->rx_buff->dread].stat != + MMNIF_STATUS_RDY) + { + mmnif->stats.pll_empty++; + if (mmnif->stats.pll_empty >= MMNIF_POLL_BUDGET) + { + + /* enable interrupts and suspend polling + * + */ + mmnif->rx_buff->iv_intr = TRUE; + mmnif->stats.pll_empty = 0; + +#ifdef DEBUG_MMNIF + DEBUGPRINTF + ("mmnif_poll(): heuristical interrupts enabled\n"); + +#endif /* */ + sem_wait(&mmnif->com_poll, 0); + } + + /* uncomment this to test only polling + */ + // mmnif->stats.pll_empty = 0; + } + mmnif->stats.pll_empty = 0; + mmnif_rx(mmnif_dev); + } + + return 0; +} + +/* + * Open the interface should be called by kernel to use this network interface + */ +int mmnif_open() +{ + struct ip_addr ipaddr; + struct ip_addr netmask; + struct ip_addr gw; + + /* calculate my own ip address from core number + * Note: core 1 is the router core + */ + IP4_ADDR(&gw, 0, 0, 0, 0); + IP4_ADDR(&ipaddr, 192, 168, 0, RCCE_ue() + 1); + IP4_ADDR(&netmask, 255, 255, 255, 0); + own_ip_address += RCCE_ue() + 1; + mmnif_dev = kmalloc(sizeof(struct netif)); + + /* register our Memory Mapped Virtual IP interface in the lwip stack + * and tell him how to use the interface: + * - mmnif_dev : the device data storage + * - ipaddr : the ip address wich should be used + * - gw : the gateway wicht should be used + * - mmnif_init : the initialization which has to be done in order to use our interface + * - ethernet_input : tells him that he should get ethernet input (inclusice ARP) + * + * Note: Ethernet Input will be removed because its NOT needed and will + * be replaced with ip_input + */ + if (!netif_add + (mmnif_dev, &ipaddr, &netmask, &gw, NULL, + (netif_init_fn) mmnif_init, tcpip_input)) + { + DEBUGPRINTF("mmnif_open() : unable to add network interface\n"); + return -1; + } + + /* set our network interface to the default interface for lwip */ + netif_set_default(mmnif_dev); + + /* tell lwip all initialization is done and we want to set it ab */ + netif_set_up(mmnif_dev); + + /* test if interface is really up */ + if (!netif_is_up(mmnif_dev)) + { + DEBUGPRINTF("mmnif_open(): network interface is not up\n"); + +// return -2; + } + + /* indicate that the driver is active now */ + active = TRUE; + + /* If interrupts are not used we immediately add the polling function + * to the queue which would otherwise be done through the IRQ handler. + */ + if (reduce_irq) + mmnif_device_schedule(); + +#ifdef DEBUG_MMNIF + DEBUGPRINTF("mmnif_dev is open\n"); + +#endif /* */ + return 0; +} + +/* + * close the interface should be called by kernel to close this interface and release resources + * Note: it's temporarly empty. Support will be added. + */ +int mmnif_close() +{ + mmnif_t *mmnif; + if (!mmnif_dev) + { + DEBUGPRINTF + ("mmnif_close(): you closed the device before it was properly opened -.-* \n"); + } + mmnif = (mmnif_t *) mmnif_dev->state; + + /* indicate that the driver is not active anymore + * - this will stop the polling thread i.e. + */ + active = FALSE; + kfree(mmnif->tx_buff[0], MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); + kfree(mmnif_dev, sizeof(mmnif_t)); + + //RCCE_shfree(mpb_start_address); + return 0; +} diff --git a/drivers/net/mmnif.h b/drivers/net/mmnif.h index 012e8109..97305344 100644 --- a/drivers/net/mmnif.h +++ b/drivers/net/mmnif.h @@ -1,51 +1,48 @@ -/* - * Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems, - * RWTH Aachen University - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of MetalSVM. - */ - -#ifndef __MMNIF_H__ -#define __MMNIF_H__ - -#ifdef WIN32 - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -typedef char int8_t; -typedef short int16_t; -typedef int int32_t; - -#else - -#define TRUE 1 -#define FALSE 0 - -#endif - -/* - * Initialize the network driver for mmn - */ -int mmnif_open(void); -int mmnif_close(void); - -int mmnif_poll(void* e); -int mmnif_worker(void* e); - -void mmnif_irqhandler(void); - -#endif +/* + * Copyright 2011 Carl-Benedikt Krueger, Chair for Operating Systems, + * RWTH Aachen University + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of MetalSVM. + */ + +#ifndef __MMNIF_H__ +#define __MMNIF_H__ + +#define AF_MMNIF_NET 0x1337 + +#define MMNIF_AUTOACTIVATE_FAST_SOCKETS 0 + +#if MMNIF_AUTOACTIVATE_FAST_SOCKETS +#define accept(a,b,c) mmnif_accept(a,b,c) +#define closesocket(s) mmnif_closesocket(s) +#define connect(a,b,c) mmnif_connect(a,b,c) +#define recv(a,b,c,d) mmnif_recv(a,b,c,d) +#define send(a,b,c,d) mmnif_send(a,b,c,d) +#define socket(a,b,c) mmnif_socket(a,b,c) +#define bind(a,b,c) mmnif_bind(a,b,c) +#define listen(a,b) mmnif_listen(a,b) +#endif + +/* + * Initialize the network driver for mmn + */ +int mmnif_open(void); +int mmnif_close(void); +int mmnif_poll(void *e); +int mmnif_worker(void *e); +void mmnif_irqhandler(void); +void mmnif_print_driver_status(); + +#endif