diff --git a/drivers/net/mmnif.c b/drivers/net/mmnif.c index 18c126d2..5dd5d1c0 100644 --- a/drivers/net/mmnif.c +++ b/drivers/net/mmnif.c @@ -1,72 +1,51 @@ -/* - * 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 * - * Carl-Benedikt Krueger 2011 + * virutally tested under Windows 7 * + * Carl-Benedikt Krüger 2011 + * + * + * EXPERIMENTAL VERSION */ + #include "mmnif.h" /* definitions */ -#ifdef WIN32 -#include "mailbox.h" /* mailbox_ptr_t */ -#else -#include /* mailbox_ptr_t */ -#endif - -#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) - #include /* lwip netif */ #include /* inteface stats */ #include /* ethernet arp packets */ #include /* struct iphdr*/ #include /* tcpip_input()*/ -//#define DEBUG_MMNIF - -#ifdef DEBUG_MMNIF -#include "util.h" /* hex dump */ -#endif - #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 -#define DEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__) + +#include /* mailbox_ptr_t */ #include +#include #include #include @@ -77,18 +56,39 @@ extern HANDLE hProc; #include +#define DEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__) #endif -#define MMNIF_TX_QUEUELEN 4 -#define MMNIF_RX_QUEUELEN 8 -#define MMNIF_RX_BUFFERLEN 1792 + +#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_CORES 2 +#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 -#define MMNIF_WORKER_BUDGET 5 /* decide whether it's polling mode or not */ @@ -102,6 +102,10 @@ static int active = 0; */ 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 */ @@ -112,29 +116,9 @@ static unsigned int router_ip_address = 0xC0A80001; /* 192.168.0.1 */ * - start address * - size */ -char* mpb_start_address = NULL; +char* mpb_start_address = NULL; unsigned int mpb_size = NULL; - -/* Register offset for the CONFIG and LOCK registers */ -#define RCK_GLCFG0 0x10 -#define RCK_GLCFG1 0x18 -#define RCK_TILEID 0x100 - -#define RCK_TILE_SIZE 0x01000000 - -/* Start address of the local register bank */ -static int local_crb = 0xF8000000; - -/* just set and reset the irq */ -static int pulse_irq = 0; - -/* Mask of the interrupt bits */ -#define RCK_INTR_MASK 0x00000002 -#define RCK_NMI_MASK 0x00000001 - - - /* * the memory mapped network device */ @@ -149,8 +133,10 @@ 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; @@ -163,7 +149,10 @@ typedef struct mmnif_device_stats 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; @@ -172,275 +161,119 @@ typedef struct mmnif_device_stats } 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 { - /* memory rx buffer build - * - queued : how many packets are in the queue - * - pos : which is the next packet to be worked on - * - pending : how many packets are pending - * - iv_intr : inform via interrupt or not - * - lock: semaphore to lock the local variables to be multi access save - * - * Note: this section will soon be complexer. - * I won't use a single buffer the whole time. I think i will use an descripor table - * and a table which descriptor is in use and use the buffer space dynamically with - * descriptors - * - * And this buffer needs a lock as soon as more as cores are availible =/ + /* 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 */ - uint8_t queued; - uint8_t pos; - uint8_t pending; - - uint8_t iv_intr; - - sem_t lock; - -// void* rx_desc[MMNIF_CORES * MMNIF_RX_QUEUELEN]; -// uint8_t rx_inuse[MMNIF_CORES * MMNIF_RX_QUEUELEN]; /* bits 1: pending 2: finished 3: free ...*/ -// uint8_t fin; -// uint8_t* data[MMNIF_RX_QUEUELEN]; + 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; + struct mmnif_device_stats stats; /* Interface constants: * - ehternet address - * - local ip address + * - local ip address */ - struct eth_addr* ethaddr; - uint32_t ipaddr; + 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 tx_queue; + uint8_t* tx_buff[MMNIF_TX_QUEUELEN]; + mm_rx_buffer_t* rx_buff; - sem_t com_poll; + /* lock to protect members + */ + spinlock_t lock; + + /* + */ + sem_t com_poll; - /* comunication mailbox - */ - mailbox_ptr_t mbox; }mmnif_t; #ifdef WIN32 - -__inline int RCCE_ue(void) -{ +__inline int RCCE_ue(void){ #ifndef RECV - return 1; + return 1; #else - return 0; + 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 -/* read the queue value from the remote buffer - * and return it. +/* mmnif_device_schedule() : + * if there is no interupt used to indicate new packets + * this creates a polling thread which looks for data + * itself */ -__inline uint8_t mmnif_read_rx_queue(uint32_t dest_ip) +__inline int mmnif_device_schedule() { #ifdef WIN32 - /* Read the value of the forgein process - * form rx_buff->queued - */ - mm_rx_buffer_t hdr; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - return hdr.queued; + bthread_create(&polling_thread,NULL,mmnif_poll,NULL); + return NULL; #else - mm_rx_buffer_t hdr; - memcpy(&hdr,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,sizeof(hdr)); - return hdr.queued; + create_kernel_task(&polling_thread,mmnif_poll,NULL); + return NULL; #endif -}; - -/* read the pos value from the remote buffer - * and return it. - */ -__inline uint8_t mmnif_read_rx_pos(uint32_t dest_ip) -{ -#ifdef WIN32 - /* Read the value of the forgein process - * form rx_buff->pos - */ - mm_rx_buffer_t hdr; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - return hdr.pos; -#else - mm_rx_buffer_t hdr; - memcpy(&hdr,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,sizeof(hdr)); - return hdr.pos; -#endif -}; - -/* read the inv_intr from the remote buffer - * and return it. - */ -__inline uint8_t mmnif_read_rx_inv_intr(uint32_t dest_ip) -{ -#ifdef WIN32 - /* Read the value of the forgein process - * form rx_buff->inv_intr - */ - mm_rx_buffer_t hdr; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - return hdr.iv_intr; -#else - mm_rx_buffer_t hdr; - memcpy(&hdr,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,sizeof(hdr)); - return hdr.iv_intr; -#endif -}; - -/* read the pending value from the remote buffer - * and return it. - */ -__inline uint8_t mmnif_read_rx_pending(uint32_t dest_ip) -{ -#ifdef WIN32 - /* Read the value of the forgein process - * form rx_buff->pending - */ - mm_rx_buffer_t hdr; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - return hdr.pending; -#else - mm_rx_buffer_t hdr; - memcpy(&hdr,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,sizeof(hdr)); - return hdr.pending; -#endif -}; - -/* write data to the remote buffer - * - */ -__inline int mmnif_write_rx_buff(uint32_t dest_ip, uint32_t pos,void* data) -{ -#ifdef WIN32 - /* we assume this is a correct buffer - * therefore here is no further error checking - */ - uint32_t nr_of_bytes_written = 0; - uint16_t length = *((uint16_t*)data); - while(!WriteProcessMemory(hProc,(char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN,data,length+2,&nr_of_bytes_written)); - return nr_of_bytes_written; -#else - uint16_t length = *((uint16_t*)data); - memcpy((char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN,data,length+2); - return 1; -#endif -}; - -__inline int mmnif_write_rx_buffl(uint32_t dest_ip, uint32_t pos,void* data,uint16_t length) -{ -#ifdef WIN32 - /* we assume this is a correct buffer - * therefore here is no further error checking - */ - uint32_t nr_of_bytes_written = 0; - while(!WriteProcessMemory(hProc,(char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN,&length,2,&nr_of_bytes_written)); - while(!WriteProcessMemory(hProc,(char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN + 2,data,length,&nr_of_bytes_written)); - return nr_of_bytes_written+2; -#else -// uint16_t length = *((uint16_t*)data); - memcpy((char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN,&length,2); - memcpy((char*)mpb_start_address +(dest_ip -1 ) * mpb_size + sizeof(mm_rx_buffer_t)+ pos * MMNIF_RX_BUFFERLEN + 2,data,length); - return 1; -#endif -}; - -/* write the new queue value to the remote buffer - * - */ -__inline int mmnif_write_rx_queue(uint32_t dest_ip,uint8_t queue) -{ - /* tell the remote buffer/process - * that there is another packet in the queue - */ -#ifdef WIN32 - uint32_t nr_of_bytes_written = 0; - while(!WriteProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size ,&queue,1,&nr_of_bytes_written)); - return nr_of_bytes_written; -#else - - memcpy((char*)mpb_start_address + ( dest_ip -1 ) * mpb_size ,&queue,1); - - return 1; -#endif -}; - -/* write the new queue value to the remote buffer - * - */ -__inline int mmnif_write_rx_pending(uint32_t dest_ip,uint8_t pending) -{ - /* tell the remote buffer/process - * that there is another packet in the queue - */ -#ifdef WIN32 - uint32_t nr_of_bytes_written = 0; - while(!WriteProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size + 2 ,&pending,1,&nr_of_bytes_written)); - return nr_of_bytes_written; -#else - - memcpy((char*)mpb_start_address + ( dest_ip -1 ) * mpb_size + 2 , &pending,1); - - return 1; -#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 PulseEvent(remote_process_event); + return SetEvent(remote_process_event); #else -#if 0 - /* NOTE: have to check how the remote interrupt managment works - * on the SCC - */ - mmnif_t* mmnif = mmnif_dev->state; - int core = (dest_ip - 1) % 2; - int irq_address = mmnif->crb[dest_ip-1]; - unsigned int value; - - if (core == 0) irq_address += RCK_GLCFG0; - else irq_address += RCK_GLCFG1; - - /**/ - value = ReadConfigReg((void*)irq_address); - - if ((!pulse_irq) && (value & RCK_INTR_MASK)) - { - value &= (~(RCK_INTR_MASK|RCK_NMI_MASK)); - SetConfigReg((void*)irq_address,value); - } - - value |= RCK_INTR_MASK; - SetConfigReg((void*) irq_address,value); - - /**/ - if (pulse_irq) - { - value &= (~(RCK_INTR_MASK|RCK_NMI_MASK)); - SetConfigReg((void*)irq_address,value); - } -#endif - int tmp, x, y, z, addr; int ue = dest_ip -1; @@ -460,118 +293,7 @@ __inline int mmnif_trigger_irq(dest_ip) return 0; #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); - return NULL; -#endif } -/* mmnif_worker_schedule() : - * if there is no interupt used to indicate new packets - * this creates a polling thread which looks for data - * itself - */ -__inline int mmnif_worker_schedule() -{ -#ifdef WIN32 - bthread_create(&worker_thread,NULL,mmnif_worker,NULL); - return NULL; -#else - create_kernel_task(&worker_thread,mmnif_worker,NULL); - return NULL; -#endif -} -/* Allocate Shared Memory for communication this could be: - * - in Message Passing Buffer - * - Shared Memory Address Space (0x8000000 + ) - * - * Note: under windows this is kernel space so we take arbitrary 0x41000000 here - */ -__inline void* mmnif_shmalloc() -{ - /* Right now every core has the same buffer for every incoming packet - * this will be removed and a buffer for each Core will be implemented - * - * but i'm first testing with two cores/processes. - */ -#ifdef WIN32 - mpb_size = sizeof(mm_rx_buffer_t) + MMNIF_RX_QUEUELEN* MMNIF_RX_BUFFERLEN; - mpb_start_address = VirtualAlloc((char*)0x41000000 /*+ - (mpb_size) * (own_ip_address - router_ip_address)*/, - mpb_size *MMNIF_CORES,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); - - return (char*)0x41000000 + (mpb_size) * (own_ip_address - router_ip_address); -#else - mpb_size = (sizeof(mm_rx_buffer_t) + MMNIF_RX_QUEUELEN* MMNIF_RX_BUFFERLEN); - /* We choose a arbitrary address first - * until i know how to properly allocate shared memory - */ -// RCCE_shmalloc_init(0x80000000,48*8192); - mpb_start_address = RCCE_shmalloc(mpb_size*MMNIF_CORES); - //mpb_start_address = 0x8000000+ mpb_size * (own_ip_address - router_ip_address); - //SHMalloc(&mpb_start_address); - //mpb_start_address = kmalloc(mpb_size*MMNIF_CORES); -// mpb_start_address = 0xC0000000; - return mpb_start_address + (mpb_size) * (own_ip_address - router_ip_address); -#endif -} - -/* mmnif_lock_rx_hdr(): lock the header of mm_rx_buffer - * so there is no race condition on the variables - */ -__inline void mmnif_lock_rx_hdr(int dest_ip) -{ -#ifdef WIN32 - mm_rx_buffer_t hdr; - if(disable_locking) return; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - sem_wait(&hdr.lock); -#else - if(disable_locking) return; - mm_rx_buffer_t* hdr = (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size; - sem_wait(&hdr->lock, 0); -#endif -} -/* mmnif_unlock_rx_hdr(): unlock the header - * again - */ -__inline void mmnif_unlock_rx_hdr(int dest_ip) -{ -#ifdef WIN32 - mm_rx_buffer_t hdr; - if(disable_locking) return; - while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); - sem_post(&hdr.lock); -#else - if(disable_locking) return; - mm_rx_buffer_t* hdr = (char*)mpb_start_address + ( dest_ip -1 ) * mpb_size; - sem_post(&hdr->lock); -#endif -} - -/* mmnif_timestamp(): genereate a timestamp for the - * packets - */ -__inline int mmnif_timestamp() -{ -#ifdef WIN32 - return GetTickCount(); -#else - return get_clock_tick(); -#endif -} - /* mmnif_get_device_stats(): Returns a copy of the * current device @@ -588,7 +310,6 @@ mmnif_device_stats_t mmnif_get_device_stats() return stats; } - /* mmnif_print_stats(): Print the devices stats of the * current device */ @@ -634,7 +355,6 @@ uint8_t mmnif_get_destination(struct netif* netif, struct pbuf* p) 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. */ @@ -655,8 +375,6 @@ uint8_t mmnif_get_destination(struct netif* netif, struct pbuf* p) 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 */ @@ -664,47 +382,217 @@ uint8_t mmnif_get_destination(struct netif* netif, struct pbuf* p) 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() +{ + 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; - uint8_t queued; - uint8_t pos; - uint8_t pending; - uint32_t i; - struct pbuf* q; /* interator */ - uint8_t build_buff = TRUE; - uint8_t dest_intr = FALSE; - uint32_t dest_ip = mmnif_get_destination(netif,p); + mmnif_t* mmnif = netif->state; + uint8_t slot = mmnif->tx_queue; - /* take a place in the 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? - * - * - * HINT: MMNIF_TX_QUEUELEN should be 1 as long there is no mutex availible to ensure - * just one thread is writing to pos and queue of the mm_rx_buff */ - if (mmnif->tx_queue >= MMNIF_TX_QUEUELEN) + if (mmnif->tx_queue > MMNIF_TX_QUEUELEN) { - DEBUGPRINTF("mmnif_tx(): too many packets at once for tx_queue\n"); - goto drop_packet; + 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 1792 bytes\n"); - goto drop_packet; + 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 @@ -714,114 +602,82 @@ err_t mmnif_tx(struct netif* netif, struct pbuf* p) if (!p->next) build_buff = FALSE; - if (build_buff) { - /* write packet length to start transmit buffer */ - *((unsigned short*)mmnif->tx_buff[slot]) = p->tot_len; - /* 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 = 2; q != 0; q = q->next) + for (q = p, i = 0; q != 0; q = q->next) { memcpy(mmnif->tx_buff[slot] + i, q->payload, q->len); i += q->len; } } - else - { - /* because there is no copy operation to the tx_slots - * we don't need a place in the queue anymore - */ - mmnif->tx_queue--; - } - /* get the palce the router core is looking for the packet */ - /* lock the dest_ip mm_rx_buffer_hdr */ - mmnif_lock_rx_hdr(dest_ip); + /* allocate memory for the packet in the remote buffer */ - /* read and edit needed values */ - queued = mmnif_read_rx_queue(dest_ip); - pos = mmnif_read_rx_pos(dest_ip); + write_address = mmnif_rxbuff_alloc(dest_ip,p->tot_len); - pending = mmnif_read_rx_pending(dest_ip); - - pending++; - mmnif_write_rx_pending(dest_ip,pending); - - /* and unlock the dest_ip mm_rx_buffer_hdr */ - mmnif_unlock_rx_hdr(dest_ip); - - /* check if there is a space in the queue without overwriting another packet */ - if ((queued + pending) > MMNIF_RX_QUEUELEN) - { - DEBUGPRINTF("mmnif_tx(): too many packet's at once for the remote queue : q:%d p:%d\n",queued , pending); + if (!write_address) goto drop_packet; - } - - pos = (pos + queued + pending -1) % MMNIF_RX_QUEUELEN; /* 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) - mmnif_write_rx_buff(dest_ip, pos, mmnif->tx_buff[slot]); + memcpy(write_address,mmnif->tx_buff[slot],p->tot_len); else - mmnif_write_rx_buffl(dest_ip, pos, p->payload,p->tot_len); + memcpy(write_address,p->payload,p->tot_len); -// udelay(50000); - /* like above ensure we are the only ones editing the hdr */ - mmnif_lock_rx_hdr(dest_ip); - - queued = mmnif_read_rx_queue(dest_ip); - pending = mmnif_read_rx_pending(dest_ip); - queued++; - pending--; - - dest_intr = mmnif_read_rx_inv_intr(dest_ip); - -#ifdef DEBUG_MMNIF + 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 - mmnif_write_rx_queue(dest_ip, queued); - mmnif_write_rx_pending(dest_ip, pending); + /* release the tx_queue because it's finished */ + spinlock_lock(&mmnif->lock); + mmnif->tx_queue--; + spinlock_unlock(&mmnif->lock); - mmnif_unlock_rx_hdr(dest_ip); - - /* if driver is not in polling mode inform core that a message has arrived */ - if (dest_intr) - mmnif_trigger_irq(dest_ip); - - /* free the transmid queue*/ - if(build_buff) - mmnif->tx_queue--; - - /* gather stats: - * - firstly for lwip - * - secondly for us - */ - + /* 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: /* packet is lost. clean up and gather stats */ - +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++; - return ERR_IF; +#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() @@ -834,7 +690,6 @@ static void mmnif_link_layer(struct netif *netif, struct pbuf *q, ip_addr_t *ipa netif->linkoutput(netif,q); } - /* * Init the device (called from lwip) * It's invoked in netif_add @@ -843,17 +698,12 @@ err_t mmnif_init(struct netif* netif) { mmnif_t* mmnif; uint32_t i; - static int num = 0; - uint16_t speed = 4000; - + int num = 0; /* Alloc and clear memory for the device struct */ -#ifdef WIN32 - mmnif = malloc(sizeof(mmnif_t)); -#else mmnif = kmalloc(sizeof(mmnif_t)); -#endif + if (!mmnif) { DEBUGPRINTF("mmnif init():out of memory\n"); @@ -863,22 +713,35 @@ err_t mmnif_init(struct netif* netif) /* Alloc and clear shared memory for rx_buff */ - mmnif->rx_buff = mmnif_shmalloc(); - if (!(mmnif->rx_buff)) + mpb_size = (sizeof(mm_rx_buffer_t) + MMNIF_RX_BUFFERLEN); + mpb_start_address = RCCE_shmalloc(mpb_size*MMNIF_CORES); + + 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); - /* init the lock for the hdr + /* set initial values + */ + mmnif->rx_buff->dcount = MMNIF_MAX_DESCRIPTORS; + + /* init the lock's for the hdr */ - sem_init(&mmnif->rx_buff->lock,1); + + 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 @@ -888,21 +751,11 @@ err_t mmnif_init(struct netif* netif) /* Alloc and clear internal memory for tx_buff */ -#ifdef WIN32 - mmnif->tx_buff[0] = malloc(MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); -#else mmnif->tx_buff[0] = kmalloc(MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); -#endif + if (!(mmnif->tx_buff[0])) { DEBUGPRINTF("mmnif init: out of memory tx\n"); -#ifdef WIN32 - free(mmnif->rx_buff); - free(mmnif); -#else -// kfree(mmnif->rx_buff); -// kfree(mmnif); -#endif return ERR_MEM; } mmnif->tx_queue = 0; @@ -911,26 +764,12 @@ err_t mmnif_init(struct netif* netif) for (i = 0; i < MMNIF_TX_QUEUELEN -1 ; i++) mmnif->tx_buff[i+1] = mmnif->tx_buff[i] + MMNIF_TX_BUFFERLEN; - /* initialize the mailbox system */ - mailbox_ptr_init(&mmnif->mbox); - /* pass the device state to lwip */ netif->state = mmnif; mmnif_dev = netif; - /* Generate MAC address */ - mmnif_dev->hwaddr[0] = 0x11;mmnif_dev->hwaddr[1] = 0x22;mmnif_dev->hwaddr[2] = 0x33; - mmnif_dev->hwaddr[3] = 0x44;mmnif_dev->hwaddr[4] = 0x55;mmnif_dev->hwaddr[5] = RCCE_ue()*0x11 +0x66; - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, speed); - /* administrative details */ - netif->name[0] = 'm'; + netif->name[0] = 'e'; netif->name[1] = 'n'; netif->num = num; num++; @@ -941,12 +780,10 @@ err_t mmnif_init(struct netif* netif) /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability, keep all default flags*/ - netif->flags |= NETIF_FLAG_BROADCAST /*| NETIF_FLAG_ETHARP*/ | NETIF_FLAG_LINK_UP; + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP; /* hardware address length */ netif->hwaddr_len = 6; - mmnif->ethaddr = (struct eth_addr *)netif->hwaddr; - active = TRUE; #ifdef MMNIF_DEBUG @@ -961,30 +798,68 @@ err_t mmnif_init(struct netif* netif) */ static void mmnif_rx(struct netif* netif) { - mmnif_t* mmnif = netif->state; - uint16_t length,i; + mmnif_t* mmnif = netif->state; + mm_rx_buffer_t* b = mmnif->rx_buff; + + uint16_t length; struct pbuf* p = NULL; struct pbuf* q; - char* data; - uint32_t pos; - uint8_t queued; + char* packet; - /* retrieve pointer to actual data array */ - data = (char*) mmnif->rx_buff + sizeof(mm_rx_buffer_t); - /* retrice position wich is needed to be worked on */ - pos = (mmnif->rx_buff->pos % MMNIF_RX_QUEUELEN) * MMNIF_RX_BUFFERLEN; + uint32_t i,j; + uint8_t rdesc = 0xFF; - /* The packet length is stored in the first 2 bytes but does not include - * the header. Check for reasonable sizes before processing the data to - * prevent nasty memory overflow errors. - */ - length = *((uint16_t*) (data + pos)); + err_t err = NULL; - /* If length is zero return silently */ +#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) { -// mmnif->rx_buff->pos++; -// mmnif->rx_buff->queued--; + DEBUGPRINTF("mmnif_rx(): empty packet error\n"); return; } if (length < sizeof(struct ip_hdr) ||length > netif->mtu) @@ -997,16 +872,11 @@ static void mmnif_rx(struct netif* netif) * 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 -#ifdef DEBUG_MMNIF - DEBUGPRINTF("\n RECIEVED - 0x%.8X with legth: %d\n",data + pos,length+2); - hex_dump(length+2,data + pos); -#endif - - /* drop the length word of the packet data since it's no longer needed*/ - pos += 2; - - /* Build the pbuf for the packet so the lwip * and other higher layer can handle it */ @@ -1016,29 +886,31 @@ static void mmnif_rx(struct netif* netif) 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 + i,&data[pos+i],q->len); + 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_lock_rx_hdr(own_ip_address & 0xFF); + mmnif_rxbuff_free(); - mmnif->rx_buff->pos++; - mmnif->rx_buff->queued--; - - mmnif_unlock_rx_hdr(own_ip_address & 0xFF); - - /* using the mailbox to hand the buffer to the incoming packet thread - * so the "interrupt" itself is not taking to long - */ - mailbox_ptr_post(&mmnif->mbox, (void*)p); + /* 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); @@ -1051,170 +923,34 @@ static void mmnif_rx(struct netif* netif) 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: - /* packet is lost so gather stats and leave the rx handler*/ - mmnif->rx_buff->pos++; - mmnif->rx_buff->queued--; - LINK_STATS_INC(link.drop); + + 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; } - -/* - * The wait implementation which is processing all incoming packets +/* mmnif_irqhandler(): + * handles the incomint interrupts */ -static int mmnif_wait(struct netif* netif, uint32_t poll, int budget) -{ - mmnif_t* mmnif = netif->state; - struct eth_hdr * ethhdr; - struct pbuf* p = NULL; - int err = ERR_OK; - unsigned int npackets = 0; - unsigned int quota = 0; - - if (budget > mmnif->rx_buff->queued) - { - quota = mmnif->rx_buff->queued; - } - else - { - quota = budget; - - mmnif->stats.bdg_overflow++; - if (mmnif->stats.bdg_overflow >= 0x10) - { - /* enable polling and disable interrupts - * - - */ - mmnif_lock_rx_hdr(own_ip_address && 0xff); - mmnif->rx_buff->iv_intr = FALSE; - mmnif_unlock_rx_hdr(own_ip_address && 0xff); -#ifdef DEBUG_MMNIF - DEBUGPRINTF("mmnif_wait(): heuristical polling enables\n"); -#endif - sem_post(&mmnif->com_poll); - mmnif->stats.bdg_overflow = 0; - } - - } - - /* process up to quota packets from the receive queue */ - while (npackets <= quota) - { - /* fetch new data from mmnif_rx() if there is any */ - if (poll) - { - /* if there is no data return immeadieatly*/ - if (mailbox_ptr_tryfetch(&(mmnif->mbox), (void**) &p)) - return err; - } - else - { - mailbox_ptr_fetch(&(mmnif->mbox), (void**) &p,0); - } - - /* if there is data, pass it up to the lwip - * so he can handle it properly - */ - - /* full packet send to tcpip_thread to process */ - if ((err = mmnif_dev->input(p, mmnif_dev)) != ERR_OK) - { - DEBUGPRINTF("mmnif_poll: IP input error\n"); - pbuf_free(p); - } - - npackets++; - } - - /* Note : i will add an return error wich indicates that - * there is no budget left but messages in the queue - */ - return err; - -} - -/* - * worker thread - */ -int mmnif_worker(void* e) -{ -#ifdef DEBUG_MMNIF - DEBUGPRINTF("Waiting for work to do!!!\n"); -#endif - while (active) - mmnif_wait(mmnif_dev,0,MMNIF_WORKER_BUDGET); - - return NULL; -} - -/* - * the poll function wich is used if no interrupt wake up our mmnif_rx functions - */ -int mmnif_poll(void* e) +void mmnif_irqhandler() { mmnif_t* mmnif; - unsigned int diff = mmnif_timestamp(); - unsigned int tmp32 = 0; - 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("Polling for work to do!!!! ONBBBB 0x%.8X BBBB\n\n",mmnif->rx_buff); -#endif - - if (!no_irq) - { - sem_wait(&mmnif->com_poll,0); - } - - /*run while driver is up*/ - while (active) - { - while (!mmnif->rx_buff->queued) - { - tmp32 = mmnif_timestamp(); - diff = diff - tmp32 > 0 ? diff - tmp32 : tmp32 - diff; - mmnif->stats.pll_empty++; - if (mmnif->stats.pll_empty >= 0x100000) - { - /* enable interrupts and suspend polling - * - */ - mmnif_lock_rx_hdr(own_ip_address && 0xff); - mmnif->rx_buff->iv_intr = TRUE; - mmnif_unlock_rx_hdr(own_ip_address && 0xff); -#ifdef DEBUG_MMNIF - DEBUGPRINTF("mmnif_poll(): heuristical interrupts enabled\n"); -#endif - sem_wait(&mmnif->com_poll,0); - mmnif->stats.pll_empty = 1; - } - } - mmnif->stats.pll_empty--; -// udelay(30000); - mmnif_rx(mmnif_dev); -// mmnif_wait(mmnif_dev,0,MMNIF_WORKER_BUDGET); - } - - return NULL; -} - -/* mmnif_irqhandler(): handles incoming interrupts - * its just a local wrapper for mmnif_rx() - */ -void mmnif_irqhandler(void) -{ - mmnif_t* mmnif; /* return if mmnif_dev is not yet initialized*/ if (!mmnif_dev) { @@ -1224,14 +960,72 @@ void mmnif_irqhandler(void) mmnif = (mmnif_t*) mmnif_dev->state; - while (mmnif->rx_buff->queued) + 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) +int mmnif_open() { struct ip_addr ipaddr; struct ip_addr netmask; @@ -1240,17 +1034,14 @@ int mmnif_open(void) /* 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(&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; + own_ip_address+= RCCE_ue() +1; -#ifdef WIN32 - mmnif_dev = malloc(sizeof(struct netif)); -#else mmnif_dev = kmalloc(sizeof(struct netif)); -#endif + /* 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 @@ -1262,14 +1053,14 @@ int mmnif_open(void) * 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/*ethernet_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); + netif_set_default(mmnif_dev); /* tell lwip all initialization is done and we want to set it ab*/ netif_set_up(mmnif_dev); @@ -1284,15 +1075,18 @@ int mmnif_open(void) 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 (no_irq) - mmnif_device_schedule(); + * 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 */ - mmnif_worker_schedule(); +// if (!instant_process) +// mmnif_worker_schedule(); + + + // mmnif_retrigger_schedule(); #ifdef DEBUG_MMNIF DEBUGPRINTF("mmnif_dev is open\n"); @@ -1306,7 +1100,7 @@ int mmnif_open(void) * 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) +int mmnif_close() { mmnif_t* mmnif; @@ -1320,19 +1114,11 @@ int mmnif_close(void) * - this will stop the polling thread i.e. */ - /* resources has to be freed here - * will be added soon ;) - */ - active = FALSE; -#ifdef WIN32 - free(mmnif->tx_buff); - free(mmnif_dev); -#else -// kfree(mmnif->tx_buff); -// kfree(mmnif_dev); -#endif + + kfree(mmnif->tx_buff[0],MMNIF_TX_QUEUELEN * MMNIF_TX_BUFFERLEN); + kfree(mmnif_dev,sizeof(mmnif_t)); + RCCE_shfree(mpb_start_address); + return NULL; } - -#endif diff --git a/kernel/Makefile b/kernel/Makefile index fdddee71..a5aa5b13 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,4 +1,4 @@ -C_source := main.c tasks.c syscall.c tests.c echo.c ping.c init.c +C_source := main.c tasks.c syscall.c tests.c echo.c ping.c init.c server.c client.c shell.c MODULE := kernel include $(TOPDIR)/Makefile.inc diff --git a/kernel/client.c b/kernel/client.c new file mode 100644 index 00000000..386e69a7 --- /dev/null +++ b/kernel/client.c @@ -0,0 +1,120 @@ +#include "client.h" + +#include "../drivers/net/util.h" + +#define SOCKET_ERROR -1 + +int cli_sendBuffer(Client* cli,void* pBuffer, unsigned int bufferlen) +{ + int iResult; + ClientEventArgs e; + //abfragen ob client existiert!! wichtig + if (cli->sSocket != SOCKET_ERROR) + { + iResult= send(cli->sSocket,(char*)pBuffer,bufferlen,0); + if (cli->_OnWrite != 0) + { + e.dwLen = iResult; + e.pBuffer = pBuffer; + cli->_OnWrite(&e); + } + return iResult; + } + else + return -3; +} + +int cli_ConnectTo(Client* cli,char * pAdresse,unsigned short Port,int webAdresse) +{ + ClientEventArgs e; + cli->sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Einen Socket erstellen + cli->wPort=Port; + cli->adAddr.sin_port = htons(cli->wPort); + + if (cli->sSocket == SOCKET_ERROR) + return -2; + + if (webAdresse) //Fall es sich um eine Internet Adresse Handelt + return -1; + else //Fall es sich um eine LAN Adresse im 127.0.0.1 Stil handelt + cli->adAddr.sin_addr.s_addr = inet_addr(pAdresse); + + if (connect(cli->sSocket,(const struct sockaddr*)&cli->adAddr, sizeof(cli->adAddr))==0) + { + + create_kernel_task(&cli->bThread,cli_WaitForPacket,cli); + + if (cli->_OnConnect != 0) + { + e.dwLen = 0; + e.pBuffer = 0; + cli->_OnConnect(&e); + } + return 0; + } + else + return -1; +}; + +int cli_DisconnectFrom(Client* cli) +{ + shutdown(cli->sSocket,2); + closesocket(cli->sSocket); + cli->sSocket = SOCKET_ERROR; + return 0; +} + +void cli_WaitForPacket(Client* cli) +{ + int iResult=1; + char pTmpBuffer[DEF_BUFFERSIZE+1]; + ClientEventArgs e; + + while (iResult > 0) + { + iResult = recv(cli->sSocket ,pTmpBuffer, DEF_BUFFERSIZE, 0); + if (iResult > 0) + { + pTmpBuffer[iResult]='\0'; + if (cli->_OnRead != 0) + { + e.dwLen = iResult; + e.pBuffer = pTmpBuffer; + cli->_OnRead( &e); + } + } + else //Verbindung geschlossen + { + cli->sSocket=SOCKET_ERROR; + if (cli->_OnDisconnect != 0) + { + e.dwLen = 0; + e.pBuffer = 0; + cli->_OnDisconnect( &e); + } + } + + } +}; + + +int cli_init(Client* cli) +{ + + cli->_OnConnect = 0; + cli->_OnWrite = 0; + cli->_OnRead = 0; + cli->_OnDisconnect = 0; + + cli->adAddr.sin_addr.s_addr = INADDR_ANY; // IP'S die der Client annehmen soll + cli->adAddr.sin_family = AF_INET; // AdressFamilie (TCP/IP) +// adAddr.sin_port = htons(iPort); // Port auf dem der Client erreichbar seien soll + + return NULL; +} + +int cli_destroy(Client* cli) +{ + closesocket(cli->sSocket);; + return NULL; +} diff --git a/kernel/client.h b/kernel/client.h new file mode 100644 index 00000000..1c686c4d --- /dev/null +++ b/kernel/client.h @@ -0,0 +1,56 @@ +#ifndef __CLIENT__ +#define __CLIENT__ + +#define DEF_BUFFERSIZE 2048 // Buffergröße für ein Packet + +#ifndef LWIP_SOCKET +#include +#endif + +#ifndef SOCKET +#define SOCKET int +#endif + + +#include + + +typedef struct _ClientEventArgs +{ + unsigned int dwLen; + void* pBuffer; +} ClientEventArgs; + + +typedef void (*ClientEventHandler)(ClientEventArgs*); + + +typedef struct _Client +{ +//Connection Handling +SOCKET sSocket; + +struct sockaddr_in adAddr; + +//Output Interfacte +unsigned short wPort; + +tid_t bThread; + +// Eventhandling +ClientEventHandler _OnConnect; +ClientEventHandler _OnDisconnect; +ClientEventHandler _OnRead; +ClientEventHandler _OnWrite; +} Client; + +int cli_sendBuffer(Client* cli,void* pBuffer, unsigned int bufferlen); +int cli_ConnectTo(Client* cli,char * pAdresse,unsigned short Port,int webAdresse); +int cli_DisconnectFrom(Client* cli); +void cli_WaitForPacket(Client* cli); + +cli_init(Client* cli); +cli_destroy(Client* cli); + + +#endif diff --git a/kernel/init.c b/kernel/init.c index 39274ebb..6ada0799 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -157,7 +157,7 @@ int network_init(void) // start echo and ping server echo_init(); - ping_init(); + //ping_init(); #endif return 0; diff --git a/kernel/server.c b/kernel/server.c new file mode 100644 index 00000000..bd5c441a --- /dev/null +++ b/kernel/server.c @@ -0,0 +1,199 @@ +#include "server.h" + +typedef int UINT_PTR; +#define SOCKET_ERROR -1 + + +int srv_sendBuffer(Server* srv, unsigned int cli,void* pBuffer, unsigned int dwLen) +{ + int result; + ServerEventArgs e; + //abfragen ob client existiert!! wichtig + if (srv->sConnections[cli] != SOCKET_ERROR) + { + result= send(srv->sConnections[cli],(char*)pBuffer,dwLen,0); + if (srv->_OnWrite!=0) + { + e.ClientID = cli; + e.dwLen = dwLen; + e.pBuffer = pBuffer; + srv->_OnWrite(&e); + } + + return result; + } + else + return -1; +} + +void srv_DisconnectClient(Server* srv, unsigned int cli) +{ + ServerEventArgs e; + closesocket(srv->sConnections[cli]); + srv->sConnections[cli]=SOCKET_ERROR; + srv->dwConnections--; + if (srv->_OnDisconnect!=0) + { + e.ClientID = cli; + e.dwLen = 0; + e.pBuffer = 0; + srv->_OnDisconnect(&e); + } + + memset(&srv->ConnectionsAddr[cli],0,sizeof(struct sockaddr_in)); +} +void* srv_WaitForConnection(Server* srv) +{ + SOCKET tmpClient; + struct sockaddr_in tmpAddr; + int tmpAddrLen; + ServerEventArgs e; + ServerThreadArgs* t; + unsigned int i; + + + do + { + if (srv->dwConnections < srv->dwMaximumConnections) + { + tmpAddrLen = sizeof(struct sockaddr); + if ((tmpClient=accept(srv->sSocket,(struct sockaddr*)&tmpAddr,&tmpAddrLen)) != SOCKET_ERROR) + { + for(i=0;idwMaximumConnections;i++) + { + if (srv->sConnections[i] == SOCKET_ERROR) + { + srv->sConnections[i] = tmpClient; + srv->ConnectionsAddr[i] = tmpAddr; + srv->dwConnections++; + + if(srv->_OnConnect!=0) + { + e.ClientID = i; + e.dwLen = 0; + e.pBuffer =0; + srv->_OnConnect(&e); + } + + t = (ServerThreadArgs*) kmalloc(sizeof(ServerThreadArgs)); + t->ID = i; + t->srv = srv; + create_kernel_task(&srv->bThreads[i],srv_WaitForPacket,t); + + break; + } + } + } + } + else + { + } + }while(1); + + return NULL; + +} +void* srv_WaitForPacket(ServerThreadArgs* t) +{ + int iResult=1; + char pTmpBuffer[DEF_BUFFERSIZE+1]; + ServerEventArgs e; + Server* srv = t->srv; + int cli = t->ID; + + while (iResult > 0) + { + iResult = recv(srv->sConnections[cli] ,pTmpBuffer, DEF_BUFFERSIZE, 0); + if (iResult > 0) + { + pTmpBuffer[iResult]='\0'; + if(srv->_OnRead!=0) + { + e.ClientID = cli; + e.dwLen = iResult; + e.pBuffer = pTmpBuffer; + srv->_OnRead(&e); + } + } + else //Verbindung geschlossen + { + closesocket(srv->sConnections[cli]); + srv->sConnections[cli]=SOCKET_ERROR; + if(srv->_OnDisconnect!=0) + { + e.ClientID = cli; + e.dwLen = 0; + e.pBuffer = 0; + srv->_OnDisconnect(&e); + } + memset(&srv->ConnectionsAddr[cli],0,sizeof(struct sockaddr_in)); + srv->dwConnections--; + iResult=-1; + } + } + return NULL; +} + +int server_init(Server* srv, unsigned short Port, unsigned int dwMaxConnections) +{ + struct sockaddr_in tmpAddr; + int tmpAddrLen; + ServerThreadArgs t; + tmpAddrLen = sizeof(struct sockaddr); + + // Unregister Events + srv->_OnConnect=0; + srv->_OnRead=0; + srv->_OnDisconnect=0; + srv->_OnWrite=0; + + // Allocate needed Memory + srv->sConnections=(SOCKET*)kmalloc(sizeof(SOCKET)*dwMaxConnections); + srv->ConnectionsAddr =(struct sockaddr_in*) kmalloc(sizeof(struct sockaddr_in)*dwMaxConnections); + srv->bThreads = (tid_t*)kmalloc(sizeof(tid_t)*dwMaxConnections); + + if (!srv->sConnections || !srv->ConnectionsAddr || !srv->bThreads) + { + kprintf("low on mem -%d- -%d- -%d-",srv->sConnections ,srv->ConnectionsAddr,srv->bThreads); + return -1; + } + + srv->dwMaximumConnections=dwMaxConnections; + + memset(srv->sConnections,0xFF,sizeof(SOCKET)*dwMaxConnections); + memset(srv->ConnectionsAddr,0x00,sizeof(struct sockaddr_in)*dwMaxConnections); + + srv->dwConnections=0; + srv->wPort = Port; + + srv->adAddr.sin_addr.s_addr = INADDR_ANY; // IP'S die der Server annehmen soll + srv->adAddr.sin_family = AF_INET; // AdressFamilie (TCP/IP) + srv->adAddr.sin_port = htons(srv->wPort); // Port auf dem der server erreichbar seien soll + + srv->sSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Einen Socket erstellen + + bind( srv->sSocket,(const struct sockaddr *) &srv->adAddr, sizeof(srv->adAddr)); // Der Server an die Adresse binden; + listen(srv->sSocket,srv->dwMaximumConnections); // Den Server in listenig State versetzen + + create_kernel_task(&srv->bThread_listen,srv_WaitForConnection,srv); +// sConnections[0] = accept(sSocket,(struct sockaddr*)&tmpAddr,&tmpAddrLen); +// t.ID = 0; +// bthread_create(&bThreads[0],NULL,(start_routine) srv_WaitForPacket,&t); +} + +int server_destroy(Server* srv) +{ + unsigned int i; + for (i=0;idwMaximumConnections;i++) + { + if (srv->sConnections[i] != SOCKET_ERROR)closesocket(srv->sConnections[i]); + //bthread_terminate(&srv->bThreads[i],0x00); + } + closesocket(srv->sSocket); + //bthread_terminate(&srv->bThread_listen,0x00); + +// free(srv->sConnections); +// free(srv->ConnectionsAddr); +// free(srv->bThreads); + +} diff --git a/kernel/server.h b/kernel/server.h new file mode 100644 index 00000000..c0ad344e --- /dev/null +++ b/kernel/server.h @@ -0,0 +1,67 @@ +#ifndef __SERVER__ +#define __SERVER__ + + +#ifdef WIN32 +#include +#else +#include +#endif + +#ifndef LWIP_SOCKET +#include +#endif + + +typedef struct _ServerEventArgs +{ + unsigned int ClientID; + unsigned int dwLen; + void* pBuffer; +} ServerEventArgs; + +#define DEF_BUFFERSIZE 2048 + +typedef void (*ServerEventHandler)(ServerEventArgs*); + +#ifndef SOCKET +#define SOCKET int +#endif + + +typedef struct _Server +{ + SOCKET sSocket; + unsigned int* sConnections; + struct sockaddr_in adAddr; + unsigned short wPort; + unsigned int dwConnections; + unsigned int dwMaximumConnections; + + struct sockaddr_in* ConnectionsAddr; + + tid_t bThread_listen; + tid_t* bThreads; + + ServerEventHandler _OnConnect; + ServerEventHandler _OnDisconnect; + ServerEventHandler _OnRead; + ServerEventHandler _OnWrite; +} Server; + +typedef struct _ServerThreadArgs +{ + Server* srv; + unsigned int ID; +} ServerThreadArgs; + + +int srv_sendBuffer(Server* srv,unsigned int cli,void* pBuffer, unsigned int dwLen); +void srv_DisconnectClient(Server* srv,unsigned int cli); +void* srv_WaitForConnection(Server* srv); +void* srv_WaitForPacket(ServerThreadArgs* t); + +int server_init(Server* srv,unsigned short Port, unsigned int dwMaxConnections); +int server_destroy(Server* srv); + +#endif diff --git a/kernel/shell.c b/kernel/shell.c new file mode 100644 index 00000000..b7df2362 --- /dev/null +++ b/kernel/shell.c @@ -0,0 +1,76 @@ +#include "shell.h" + +#include "server.h" +#include "client.h" + +#include + +static Server srv; +static int emac_id = -1; + +static Client cli; + +static int iamsrv = 0; + +char shellbuffer[512]; + + +void shelldebugprint(char* x) +{ + kprintf("debugprinting : %s",x); + if (iamsrv) + srv_sendBuffer(&srv,emac_id,x,strlen(x)); + else + cli_sendBuffer(&cli,x,strlen(x)); +} + +void shell_on_connect(ServerEventArgs* e) +{ + kprintf("connection from %s:%d",inet_ntoa(srv.ConnectionsAddr[e->ClientID].sin_addr),ntohs(srv.ConnectionsAddr[e->ClientID].sin_port)); + kprintf("connehx: 0x%.8X",srv.ConnectionsAddr[e->ClientID].sin_addr); + // if (srv.ConnectionsAddr[e->ClientID].sin_addr.s_addr > 0xC0A80031 || srv.ConnectionsAddr[e->ClientID].sin_addr.s_addr < 0xC0A80001) + if (srv.ConnectionsAddr[e->ClientID].sin_addr.s_addr == 0xFE04A8C0) + { + emac_id = e->ClientID; + kprintf("bmc connected"); + } + else + kprintf("link engaged\n"); +} + +void shell_on_disconnect(ServerEventArgs* e) +{ + kprintf("connection lost from %s:%d",inet_ntoa(srv.ConnectionsAddr[e->ClientID].sin_addr),ntohs(srv.ConnectionsAddr[e->ClientID].sin_port)); +} + +void shell_on_read(ServerEventArgs* e) +{ + if (emac_id != -1 && e->ClientID != emac_id) + srv_sendBuffer(&srv,emac_id,e->pBuffer,e->dwLen); + else + // else commandos oder so + srv_sendBuffer(&srv,emac_id,e->pBuffer,e->dwLen); +} + +void shell_init(int srv_or_cli) +{ + if (!srv_or_cli) + { + iamsrv = 1; + kprintf("server init"); + server_init(&srv,23,49); + srv._OnConnect = shell_on_connect; + srv._OnDisconnect = shell_on_disconnect; + srv._OnRead = shell_on_read; + } + else + { + sleep(3); + kprintf("client init"); + cli_init(&cli); + while (cli_ConnectTo(&cli,"192.168.0.1",23,0)); + sleep(1); + + } + +} diff --git a/kernel/shell.h b/kernel/shell.h new file mode 100644 index 00000000..6924c567 --- /dev/null +++ b/kernel/shell.h @@ -0,0 +1,14 @@ +#ifndef SHELL_H +#define SHELL_H + +#include + +void shelldebugprint(char* x); + +void shell_init(int srv_or_cli); + +extern char shellbuffer[512]; + +#define SHELLDEBUGPRINTF(x,...) ksnprintf(shellbuffer,sizeof(shellbuffer),x,##__VA_ARGS__);shelldebugprint(shellbuffer); + +#endif // SHELL_H diff --git a/kernel/tests.c b/kernel/tests.c index 989dfe51..0bd523d0 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -33,6 +33,12 @@ #include #include + +#include "client.h" +#include "server.h" + +#include "shell.h" + #endif static sem_t consuming, producing; @@ -121,129 +127,139 @@ static int join_test(void* arg) kprintf("Child %u finished: result = %d\n", id, result); - dump_scheduling_statistics(); - return 0; } #if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) -static int server_task(void* e) + + +#define SHELLDEBUGPRINTF(x,...) kprintf(x,##__VA_ARGS__); + +static int srv_cnt = 0; +static Server srv; +void srv_on_read(ServerEventArgs* e) { - int sockfd, newsockfd, portno, clilen; - char buffer[256]; - struct sockaddr_in serv_addr, cli_addr; - int n; - - /* First call to socket() function */ - sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sockfd < 0) - { - kprintf("ERROR opening socket"); - return -1; - } - /* Initialize socket structure */ - memset((char *) &serv_addr,0, sizeof(serv_addr)); - portno = 5001; - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(portno); - - kprintf("binding"); - /* Now bind the host address using bind() call.*/ - if (bind(sockfd, (struct sockaddr *) &serv_addr, - sizeof(serv_addr)) < 0) - { - kprintf("ERROR on binding"); - return -1; - } - - /* Now start listening for the clients, here process will - * go in sleep mode and will wait for the incoming connection - */ - kprintf("listening"); - listen(sockfd,5); - clilen = sizeof(cli_addr); - - /* Accept actual connection from the client */ - kprintf("accepting"); - newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); - if (newsockfd < 0) - { - kprintf("ERROR on accept"); - return -1; - } - /* If connection is established then start communicating */ - memset(buffer,0,256); - kprintf("recieving"); - n = read( newsockfd,buffer, 255); - if (n < 0) - { - kprintf("ERROR reading from socket"); - return -1; - } - kprintf("Here is the message: %s\n",buffer); - - /* Write a response to the client */ - kprintf("writing"); - n = write(newsockfd,"I got your message",18); - if (n < 0) - { - kprintf("ERROR writing to socket"); - return -1; - } - - return 0; + // kprintf("%i:",srv_cnt); + // hex_dump(e->dwLen,e->pBuffer); + // srv_cnt++; +/* printf("%i:",cnt); + puts(e->pBuffer); + puts("\n"); + cnt++; + */ } -static int client_task(void* e) +void srv_on_disc(ServerEventArgs*e ) { - char dir[256]; - int sd; - struct sockaddr_in pin; + kprintf("connection lost!!!\n"); +} - sleep(1); +void srv_on_conn(ServerEventArgs* e) +{ + int i = 0, err = 0; + int tmp1,tmp2; + char buff[1024]; - /* fill in the socket structure with host information */ - memset(&pin, 0, sizeof(pin)); - pin.sin_family = AF_INET; - pin.sin_addr.s_addr = inet_addr("192.168.0.1"); - pin.sin_port = htons(5001); + SHELLDEBUGPRINTF("someone finally connected\n"); - /* grab an Internet domain socket */ - if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - kprintf("socketfail"); - return -1; - } + tmp1 = get_clock_tick(); + for (i = 0; i < 1024*4; i++) + { + err = srv_sendBuffer(&srv,e->ClientID,buff,sizeof(buff)); + if ( err < 0) + { + SHELLDEBUGPRINTF("err: %d", err); + } - kprintf("connecting with socket nr : %d",sd); - /* connect to PORT on HOST */ + if (!(i%10)) + { + SHELLDEBUGPRINTF("\r-%d-",i); + } - if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) { - kprintf("connectfail"); - return -1; - } - kprintf("sending"); - /* send a message to the server PORT on machine HOST */ - if (send(sd, "HELLO THERE", strlen("HELLO THERE"), 0) == -1) { - kprintf("sendfail"); - return -1; - } - kprintf("recieving"); - /* wait for a message to come back from the server */ - if (recv(sd, dir, 256, 0) == -1) { - kprintf("recvfail"); - return -1; - } + } + tmp2 = get_clock_tick(); - /* spew-out the results and bail out of here! */ - kprintf("%s\n", dir); +// SHELLDEBUGPRINTF("send with %f kb/s",((float)i*sizeof(buff))/(tmp2-tmp1)); + SHELLDEBUGPRINTF("send %d bytes in %d ticks",i*sizeof(buff),(tmp2-tmp1)); +} - close(sd); +void* server_task(void* e) +{ + SHELLDEBUGPRINTF("created server\n"); - return 0; + server_init(&srv,5555,2); + + srv._OnRead = srv_on_read; + srv._OnDisconnect = srv_on_disc; + srv._OnConnect = srv_on_conn; + + while(1) + sleep(2); + + return NULL; +} + +static int cli_cnt = 0; +void cli_on_read(ClientEventArgs* e) +{ + kprintf("\r-%d-",cli_cnt); + cli_cnt++; +// printf("%i:",cnt); +// hex_dump(e->dwLen,e->pBuffer); +// cnt++; +/* puts(e->pBuffer); + puts("\n"); + cnt++; +*/ +} + +void cli_on_disc(ClientEventArgs*e ) +{ + kprintf("connection lost!!!\n"); +} + + +void* client_task(void* e) +{ + int err = -2; + Client cli; + char netbuffer[256]; + kprintf("created client"); + cli_init(&cli); + cli._OnRead = cli_on_read; + cli._OnDisconnect = cli_on_disc; + sleep(2); + + SHELLDEBUGPRINTF("Client is ready...\n"); + while (err) + { + sleep(1); + err = cli_ConnectTo(&cli,"192.168.0.1",5555,0); + SHELLDEBUGPRINTF("retry connect err = %d socket: %d\n",err,cli.sSocket); + } + SHELLDEBUGPRINTF("connected\n"); + + sleep(1); + err = cli_sendBuffer(&cli,"Hallo Welt",sizeof("Hallo Welt")); + SHELLDEBUGPRINTF("send message err = %d\n",err); + + + while(1) + sleep(2); + +return NULL; } #endif +void* alive(void*e) +{ + while (1) + { + kprintf("IM ALIVE"); + sleep(2); + } +} + int test_init(void) { char* argv[] = {"/bin/tests", NULL}; @@ -252,20 +268,29 @@ int test_init(void) sem_init(&consuming, 0); mailbox_int32_init(&mbox); -#if 0 //defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) - if (!RCCE_ue()) - create_kernel_task(NULL,server_task,NULL); - else - create_kernel_task(NULL,client_task,NULL); +#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK) + +// shell_init(RCCE_ue()); +// +// sleep(10); +// SHELLDEBUGPRINTF("hello World! I AM CORE NO. %d =) \n",RCCE_ue()); + + create_kernel_task(NULL,alive,NULL); + + if (!RCCE_ue()) + create_kernel_task(NULL,server_task,NULL); + else + create_kernel_task(NULL,client_task,NULL); + #endif - create_kernel_task(NULL, foo, "Hello from foo1"); - create_kernel_task(NULL, join_test, NULL); +// create_kernel_task(NULL, foo, "Hello from foo1"); +// create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); //create_kernel_task(NULL, mail_ping, NULL); //create_user_task(NULL, "/bin/hello", argv); - create_user_task(NULL, "/bin/tests", argv); +// create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); diff --git a/newlib/net/accept.c b/newlib/net/accept.c new file mode 100644 index 00000000..2b092f68 --- /dev/null +++ b/newlib/net/accept.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (accept, (s, addr, addrlen), + int s _AND void *addr _AND void *addrlen) +{ + int ret; + + ret = SYSCALL3(__NR_accept, s, addr, addrlen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/bind.c b/newlib/net/bind.c new file mode 100644 index 00000000..9c02b834 --- /dev/null +++ b/newlib/net/bind.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (bind, (s, name, namelen), + int s _AND void *name _AND int namelen) +{ + int ret; + + ret = SYSCALL3(__NR_bind, s, name, namelen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/closesocket.c b/newlib/net/closesocket.c new file mode 100644 index 00000000..e24ce3c6 --- /dev/null +++ b/newlib/net/closesocket.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (closesocket, (s), + int s) +{ + int ret; + + ret = SYSCALL1(__NR_closesocket, s); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/connect.c b/newlib/net/connect.c new file mode 100644 index 00000000..ba3408e8 --- /dev/null +++ b/newlib/net/connect.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (connect, (s, name, namelen), + int s _AND void *name _AND int namelen) +{ + int ret; + + ret = SYSCALL3(__NR_connect, s, name, namelen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/listen.c b/newlib/net/listen.c new file mode 100644 index 00000000..7d75dfc2 --- /dev/null +++ b/newlib/net/listen.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (listen, (s, backlog), + int s _AND int backlog) +{ + int ret; + + ret = SYSCALL2(__NR_listen, s, backlog); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/recv.c b/newlib/net/recv.c new file mode 100644 index 00000000..d6159fbb --- /dev/null +++ b/newlib/net/recv.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (recv, (s, data, size,flags), + int s _AND void *data _AND int size _AND int flags) +{ + int ret; + + ret = SYSCALL4(__NR_recv, s, data, size, flags); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/send.c b/newlib/net/send.c new file mode 100644 index 00000000..4da06e06 --- /dev/null +++ b/newlib/net/send.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (send, (s, data, size,flags), + int s _AND void *data _AND int size _AND int flags) +{ + int ret; + + ret = SYSCALL4(__NR_send, s, data, size, flags); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/socket.c b/newlib/net/socket.c new file mode 100644 index 00000000..8aae8f67 --- /dev/null +++ b/newlib/net/socket.c @@ -0,0 +1,25 @@ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (socket, (domain, type, protocol), + int domain _AND int type _AND int protocol) +{ + int ret; + + ret = SYSCALL3(__NR_socket, domain, type, protocol); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/syscall.h b/newlib/net/syscall.h new file mode 100644 index 00000000..6d137508 --- /dev/null +++ b/newlib/net/syscall.h @@ -0,0 +1,78 @@ +/* + * Copyright 2010 Stefan Lankes, 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. + * + * Standard x86 syscalls for user programs running under MetalSVM + */ + +#ifndef __SYSCALL_H__ +#define __SYSCALL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NR_exit 0 +#define __NR_write 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_read 4 +#define __NR_lseek 6 +#define __NR_unlink 7 +#define __NR_getpid 8 +#define __NR_kill 9 +#define __NR_fstat 10 +#define __NR_sbrk 11 +#define __NR_fork 12 +#define __NR_wait 13 +#define __NR_execve 14 +#define __NR_times 15 + +#define _STR(token) #token +#define _SYSCALLSTR(x) "int $" _STR(x) " " +#define INT_SYSCALL 0x80 + +inline static long +syscall(int nr, unsigned long arg0, unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4) +{ + long res; + + asm volatile (_SYSCALLSTR(INT_SYSCALL) + : "=a" (res) + : "0" (nr), "b" (arg0), "c" (arg1), "d" (arg2), "S" (arg3), "D" (arg4) + : "memory", "cc"); + + return res; +} + +#define SYSCALL0(NR) \ + syscall(NR, 0, 0, 0, 0, 0) +#define SYSCALL1(NR, ARG1) \ + syscall(NR, (unsigned long)ARG1, 0, 0, 0, 0) +#define SYSCALL2(NR, ARG1, ARG2) \ + syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, 0, 0, 0) +#define SYSCALL3(NR, ARG1, ARG2, ARG3) \ + syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, 0, 0) +#define SYSCALL4(NR, ARG1, ARG2, ARG3, ARG4) \ + syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, (unsigned long) ARG4, 0) +#define SYSCALL5(NR, ARG1, ARG2, ARG3, ARG4) \ + syscall(NR, (unsigned long)ARG1, (unsigned long)ARG2, (unsigned long)ARG3, (unsigned long) ARG4, (unsigned long) ARG5) + +#ifdef __cplusplus +} +#endif + +#endif