diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index 81e3dd4c..093fb61f 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -75,6 +75,21 @@ inline static void irq_nested_enable(uint32_t flags) { irq_enable(); } +/** @brief Determines, if the interrupt flags (IF) is ser + * + * @return + * - 1 interrupt flag is set + * - 0 interrupt flag is cleared + */ +inline static uint32_t is_irq_enabled(void) +{ + uint32_t flags; + asm volatile("pushf; popl %0": "=r"(flags) : : "memory"); + if (flags & (1 << 9)) + return 1; + return 0; +} + #ifdef __cplusplus } #endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ad962757..ad9e9f36 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -272,22 +272,42 @@ static inline uint32_t read_eflags(void) return result; } -/** @brief search the first bit, which is set +/** @brief search the first most significant bit * * @param i source operand - * @return first bit, which is set in the source operand + * @return + * - first bit, which is set in the source operand + * - invalid value, if not bit ist set */ -static inline uint32_t last_set(uint32_t i) +static inline size_t msb(size_t i) { - uint32_t ret; + size_t ret; if (!i) - return 0; + return (sizeof(size_t)*8); asm volatile ("bsr %1, %0" : "=r"(ret) : "r"(i) : "cc"); return ret; } +/** @brief search the least significant bit + * + * @param i source operand + * @return + * - first bit, which is set in the source operand + * - invalid value, if not bit ist set + */ +static inline size_t lsb(size_t i) +{ + size_t ret; + + if (!i) + return (sizeof(size_t)*8); + asm volatile ("bsf %1, %0" : "=r"(ret) : "r"(i) : "cc"); + + return ret; +} + /** @brief Read extended instruction pointer * @return The EIP's value */ diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index d93b2a55..f0f7d130 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -237,8 +237,7 @@ void irq_handler(struct state *s) // evaluate only irq status register if int_no = 124 if( s->int_no == 124 ) { check_workqueues_rem_irq(); - } - else { + } else { check_workqueues(); } @@ -283,4 +282,6 @@ leave_handler: // timer interrupt? if ((s->int_no == 32) || (s->int_no == 123)) scheduler(); // switch to a new task + else if ((s->int_no >= 32) && (get_highest_priority() > per_core(current_task)->prio)) + scheduler(); } diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index cecbab61..b2cfaad4 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -367,6 +367,9 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag if (flags & MAP_NO_ACCESS) pgt->entries[index] &= ~PG_PRESENT; + if (flags & MAP_WT) + pgt->entries[index] |= PG_PWT; + if (flags & MAP_USER_SPACE) atomic_int32_inc(&task->user_usage); @@ -801,8 +804,9 @@ int arch_paging_init(void) npages = bootinfo->size >> PAGE_SHIFT; if (bootinfo->size & (PAGE_SIZE-1)) npages++; - bootinfo->addr = map_region(0, bootinfo->addr, npages, MAP_KERNEL_SPACE); - kprintf("Map initrd at 0x%x (size %u bytes)\n", bootinfo->addr, bootinfo->size); + viraddr = map_region(0, bootinfo->addr, npages, MAP_KERNEL_SPACE); + kprintf("Map initrd from 0x%x to 0x%x (size %u bytes)\n", bootinfo->addr, viraddr, bootinfo->size); + bootinfo->addr = viraddr; #endif /* diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index f0b772d4..588618bd 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -132,7 +132,7 @@ int svm_access_request(size_t addr) icc_mail_check(0); while (page_owner[pageid] != my_ue) { - check_workqueues_rem_irq(); + check_workqueues(); } return change_page_permissions(addr, addr+PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 2bd5141f..065c086f 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -257,7 +257,7 @@ int icc_halt(void) return 0; } -#define ROUNDS 100000 +#define ROUNDS 1000 #define CORE_A 0 // sender #define CORE_B 1 // receiver @@ -425,7 +425,7 @@ int icc_mail_ping_irq(void) kprintf( "timer = %d\n", timer ); kprintf( "mail_pingpong needs in average %d nsec (%d ticks)!\n", - timer*1000/(2*ROUNDS*533), timer/(2*ROUNDS) ); + timer*1000/(2*ROUNDS*get_cpu_frequency()), timer/(2*ROUNDS) ); irq_nested_enable(flags); diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 69f4bdba..a7188f2a 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -101,9 +101,6 @@ #define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK) #define CLINE_PACKETS(_x) (CLINE_ALIGN(_x) >> CLINE_SHIFT) -/* Flush */ -#define CL1FLUSH __asm__ volatile (".byte 0x0F; .byte 0x0A;\n") - /* Read 16bit from buffer */ #define U16(_addr) (256 * (*((uint8_t*) (_addr + 1))) + (*((uint8_t*)(_addr)))) @@ -111,8 +108,80 @@ #define MAC_HI(_x) ((((_x) >> 32)) & 0xFFFF) #define MAC_LO(_x) (((_x) ) & 0xFFFFFFFF) +#define MIN(a, b) (a) < (b) ? (a) : (b) + static struct netif* mynetif; +inline static void* memcpy_from_nc(void *dest, const void *src, size_t count) +{ +#if 0 + size_t i; + + for(i=0; inext) { - memcpy(((uint8_t*)addr) + 2 + i, q->payload, q->len); + memcpy_to_nc(((uint8_t*)addr) + 2 + i, q->payload, q->len); i += q->len; } @@ -207,12 +276,12 @@ again: if (bytes_left < bytes_to_copy) bytes_to_copy = bytes_left; - LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy)); + //LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy)); q = p; i = 0; while ((q != 0) && (i < bytes_to_copy)) { sz = q->len > bytes_to_copy-i ? bytes_to_copy-i : q->len; - memcpy(((uint8_t*) addr) + 2 + i, q->payload, sz); + memcpy_to_nc(((uint8_t*) addr) + 2 + i, q->payload, sz); bytes_left -= sz; i += sz; if (i < bytes_to_copy) @@ -222,16 +291,16 @@ again: if (bytes_left != 0) { rckemacif->tx_write_offset = 1; addr = rckemacif->tx_buffer + 32; - LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left)); + //LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left)); i = 0; if (sz < q->len) { - memcpy((uint8_t*) addr, q->payload + sz, q->len - sz); + memcpy_to_nc((uint8_t*) addr, q->payload + sz, q->len - sz); bytes_left -= (q->len - sz); i = q->len - sz; } for(q=q->next; (q != 0); q = q->next) { - memcpy(((uint8_t*) addr) + i, q->payload, q->len); + memcpy_to_nc(((uint8_t*) addr) + i, q->payload, q->len); i += q->len; } @@ -239,13 +308,16 @@ again: if (rest != 0) rest = 32 - rest; - LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest)); + //LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest)); rckemacif->tx_write_offset += CLINE_PACKETS(bytes_left + rest) - 1; } } *((volatile int*) rckemacif->tx_buffer) = 2; + // flush write combining buffers + *(int *)RCCE_fool_write_combine_buffer = 1; + /* set new write offset */ //LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset)); write_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_WRITE_OFFSET, rckemacif->core, rckemacif->tx_write_offset); @@ -292,7 +364,7 @@ static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset) { rckemacif_t* rckemacif = netif->state; unsigned short read_offset = rckemacif->rx_read_offset; - unsigned int counter; + //unsigned int counter; volatile void *addr = NULL; uint16_t i, length = 0; uint32_t packets = 0; @@ -353,7 +425,7 @@ again: if (read_offset < write_offset) { for (q=p, i/*counter=0*/; q!=NULL; q=q->next) { - memcpy((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len); + memcpy_from_nc((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len); //for(i=0; ilen; i++, counter++) { // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; //} @@ -364,33 +436,52 @@ again: int rest; int bytesLeft = length; int bytesToCopy = length; + int counter = 0; /* rest to the end of buffer - 2 bytes length information */ rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2; if (length > rest) bytesToCopy = rest; - LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft)); + //LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft)); - for (q=p, counter=0; q!=NULL; q=q->next) { - for(i=0; ilen; i++, counter++) { + q = p; + i = /*counter =*/ 0; + while ((q != NULL) && (counter < bytesToCopy)) { + i = MIN(q->len, bytesToCopy - counter); + memcpy_from_nc(q->payload, (uint8_t*) addr + 2 + counter, i); + counter += i; + if (counter >= bytesToCopy) + goto out; + else + q = q->next; + /*for(i=0; ilen; i++, counter++) { if (counter < bytesToCopy) ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; else goto out; - } + }*/ } out: bytesLeft -= bytesToCopy; if (bytesLeft != 0) { addr = rckemacif->rx_buffer + 0x20; - LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0])); - for(counter=0; (ilen) && (counter < bytesLeft); i++, counter++) - ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + counter = 0; + //LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0])); + + if (i < q->len) { + counter = MIN(q->len - i, bytesLeft); + memcpy_from_nc((uint8_t*)q->payload + i, (uint8_t*) addr, counter); + } + //for(counter=0; (ilen) && (counter < bytesLeft); i++, counter++) + // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) { - for(i=0; (ilen) && (counter < bytesLeft); i++, counter++) { - ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; - } + i = MIN(q->len, bytesLeft - counter); + memcpy_from_nc((uint8_t*)q->payload, (uint8_t*)addr + counter, i); + counter += i; + //for(i=0; (ilen) && (counter < bytesLeft); i++, counter++) { + // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + //} } read_offset = CLINE_PACKETS(bytesLeft); } else { @@ -439,7 +530,6 @@ static void rckemacif_handler(struct state* s) nexttry: /* check for updated write offset */ - CL1FLUSH; write_offset = *((volatile unsigned int*) (rckemacif->rx_buffer)) & 0xFFFF; //write_offset = read_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, rckemacif->core); if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) { @@ -500,7 +590,7 @@ err_t rckemacif_init(struct netif* netif) rckemacif->rx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; /* allocate the send buffers */ - rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE); + rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE|MAP_WT|MAP_MPE); if (!(rckemacif->tx_buffer)) { LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); kfree(rckemacif->rx_buffer, BUFFER_SIZE); @@ -762,7 +852,8 @@ err_t rckemacif_init(struct netif* netif) rckemacif->ethaddr = (struct eth_addr *)netif->hwaddr; - tcpip_callback(netif_set_link_up, netif); + // flush write combining buffers + *(int *)RCCE_fool_write_combine_buffer = 1; return ERR_OK; } diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index cc3ab28d..df5d7ce6 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -441,14 +441,12 @@ err_t rtl8139if_init(struct netif* netif) /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability */ - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; /* hardware address length */ netif->hwaddr_len = 6; rtl8139if->ethaddr = (struct eth_addr *)netif->hwaddr; - tcpip_callback(netif_set_link_up, netif); - return ERR_OK; } #endif diff --git a/include/metalsvm/init.h b/include/metalsvm/init.h index 02f97091..8ca4a89a 100644 --- a/include/metalsvm/init.h +++ b/include/metalsvm/init.h @@ -36,11 +36,8 @@ extern "C" { * initialize the VGA output. If configured.*/ int lowlevel_init(void); -/** @brief Initialize LWIP stack and start a networking task. */ -int network_init(void); - -/** @brief Shutdown the networking subsystem. */ -int network_shutdown(void); +/** @brief Shutdown the system */ +int shutdown(void); /** @brief Entry point of the init task */ int initd(void* arg); diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index 15d0961e..0a568204 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -41,7 +41,7 @@ extern "C" { #define MAP_USER_SPACE (1 << 1) #define MAP_PAGE_TABLE (1 << 2) #define MAP_NO_CACHE (1 << 3) -//#define MAP_STACK (1 << 4) +#define MAP_WT (1 << 5) //#define MAP_HEAP (1 << 5) #define MAP_CODE (1 << 6) #define MAP_READONLY (1 << 7) diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index 7f3c7221..3f4589cb 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -176,12 +176,17 @@ size_t get_idle_task(uint32_t id); */ int sys_execve(const char* fname, char** argv, char** env); -/** @brief determines the highest priority of all ready tasks on core core_id - * - * @param core_id core id - * @return highest priority +/** @brief if a task exists with higher priority, MetalSVM switch to it. */ -uint32_t get_highest_priority(uint32_t core_id); +void check_scheduling(void); + +/** @brief determine the highest priority of all tasks, which are ready + * + * @return + * - return highest priority + * - if no task is ready, the function returns an invalid value (> MAX_PRIO) + */ +uint32_t get_highest_priority(void); /** @brief Call to rescheduling * @@ -194,6 +199,7 @@ static inline void check_workqueues(void) #ifdef CONFIG_ROCKCREEK icc_mail_check(0); #endif + check_scheduling(); } static inline void check_workqueues_rem_irq(void) diff --git a/kernel/init.c b/kernel/init.c index eaf1f904..fb13ff9c 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -72,30 +72,14 @@ int lowlevel_init(void) #if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) static struct netif* default_netif = NULL; -static volatile uint32_t lwip_initialized = 0; -static void tcp_init_ok(void* e) +static int init_netifs(void) { - kputs("TCP/IP init COMPLETE!!\n"); - lwip_initialized = 1; -} -#endif - -int network_init(void) -{ -#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; - kputs("Initialize network...\n"); - - // Initialize lwIP modules - tcpip_init(tcp_init_ok, NULL); - - while(!lwip_initialized) { - reschedule(); - } + kputs("Initialize NICs...\n"); // Set up the lwIP network interface // Allocate and configure netif @@ -109,12 +93,20 @@ int network_init(void) memset(default_netif, 0x00, sizeof(struct netif)); #ifdef CONFIG_ROCKCREEK /* Set network address variables */ - IP4_ADDR(&gw, 192,168,4,254); - IP4_ADDR(&ipaddr, 192,168,4,RCCE_ue()+1); + IP4_ADDR(&gw, 192,168,28,254); + IP4_ADDR(&ipaddr, 192,168,28,RCCE_ue()+1); IP4_ADDR(&netmask, 255,255,255,0); /* Bring up the network interface */ if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, tcpip_input)) { + kputs("Unable to add network interface\n"); + return -ENODEV; + } + + netif_set_default(default_netif); + netif_set_up(default_netif); + + //mmnif_open(); #else /* Clear network address because we use DHCP to get an ip address */ IP4_ADDR(&gw, 0,0,0,0); @@ -123,63 +115,63 @@ int network_init(void) /* Bring up the network interface */ if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, tcpip_input)) { -#endif kputs("Unable to add network interface\n"); return -ENODEV; } netif_set_default(default_netif); - netif_set_up(default_netif); - /* test if interface is really up */ - if (!netif_is_up(default_netif)) { - kputs("network interface is not up\n"); - return -ENODEV; - } - -#ifndef CONFIG_ROCKCREEK kprintf("Starting DHCPCD...\n"); dhcp_start(default_netif); - - int mscnt = 0; - /* wait for ip address */ - while(!default_netif->ip_addr.addr) { - sys_msleep(DHCP_FINE_TIMER_MSECS); - dhcp_fine_tmr(); - mscnt += DHCP_FINE_TIMER_MSECS; - if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { - dhcp_coarse_tmr(); - mscnt = 0; - } - } -#else - //mmnif_open(); -#endif - - // start echo and ping server - echo_init(); - //ping_init(); - netio_init(); #endif return 0; } +#endif -int network_shutdown(void) -{ #ifdef CONFIG_LWIP +static void tcpip_init_done(void* arg) +{ + sys_sem_t* sem = (sys_sem_t*)arg; + +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) + init_netifs(); +#endif + sys_sem_signal(sem); +} +#endif + +#ifdef CONFIG_LWIP +static int network_shutdown(void) +{ #ifdef CONFIG_ROCKCREEK + if (default_netif) { + netif_set_link_down(default_netif); + mem_free(default_netif); + default_netif = NULL; + } //mmnif_close(); #elif defined(CONFIG_PCI) - dhcp_release(default_netif); - dhcp_stop(default_netif); + if (default_netif) { + dhcp_release(default_netif); + dhcp_stop(default_netif); + mem_free(default_netif); + default_netif = NULL; + } #endif - mem_free(default_netif); - default_netif = NULL; -#endif return 0; } +#endif + +int shutdown(void) +{ +#ifdef CONFIG_LWIP + return network_shutdown(); +#else + return 0; +#endif +} static void list_fs(vfs_node_t* node, uint32_t depth) { @@ -225,7 +217,45 @@ static void list_root(void) { int initd(void* arg) { - network_init(); +#ifdef CONFIG_LWIP + sys_sem_t sem; + + // Initialize lwIP modules + if(sys_sem_new(&sem, 0) != ERR_OK) + LWIP_ASSERT("Failed to create semaphore", 0); + tcpip_init(tcpip_init_done, &sem); + sys_sem_wait(&sem); + kprintf("TCP/IP initialized.\n"); + sys_sem_free(&sem); + +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) + /* test if interface is really up */ + if (!netif_is_up(default_netif)) { + kputs("network interface is not up\n"); + return -ENODEV; + } +#endif + +#ifndef CONFIG_ROCKCREEK + int mscnt = 0; + /* wait for ip address */ + while(default_netif && !default_netif->ip_addr.addr) { + sys_msleep(DHCP_FINE_TIMER_MSECS); + dhcp_fine_tmr(); + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { + dhcp_coarse_tmr(); + mscnt = 0; + } + } +#endif + + // start echo and ping server + echo_init(); + //ping_init(); + netio_init(); +#endif + list_root(); test_init(); diff --git a/kernel/main.c b/kernel/main.c index 6a18cdc8..c458c3aa 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -94,12 +94,9 @@ int main(void) create_kernel_task(NULL, initd, NULL, NORMAL_PRIO); reschedule(); - while(1) { -#ifdef CONFIG_ROCKCREEK - //icc_halt(); -#else + while(1) { + check_workqueues(); HALT; -#endif } return 0; diff --git a/kernel/netio.c b/kernel/netio.c index 166bbc18..e6c55ef8 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -1,50 +1,354 @@ -/* - * this example is derived from the netio example of the contrib-1.4.0 +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. * - * see http://download.savannah.gnu.org/releases/lwip/ */ - -#include -#include +#include +#include #if defined(CONFIG_LWIP) #include + +#if LWIP_TCP #include +/* + * This implements a netio server. + * The client sends a command word (4 bytes) then a data length word (4 bytes). + * If the command is "receive", the server is to consume "data length" bytes into + * a circular buffer until the first byte is non-zero, then it is to consume + * another command/data pair. + * If the command is "send", the server is to send "data length" bytes from a circular + * buffer with the first byte being zero, until "some time" and then send one final buffer with + * the first byte being non-zero. Then it is to consume another command/data pair. + */ + /* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ -#if LWIP_TCP -static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +/* implementation options */ +#define NETIO_BUF_SIZE (4 * 1024) +#define NETIO_USE_STATIC_BUF 0 + +/* NetIO server state definition */ +#define NETIO_STATE_WAIT_FOR_CMD 0 +#define NETIO_STATE_RECV_DATA 1 +#define NETIO_STATE_SEND_DATA 2 +#define NETIO_STATE_SEND_DATA_LAST 3 +#define NETIO_STATE_DONE 4 + +struct netio_state { + u32_t state; + u32_t cmd; + u32_t data_len; + u32_t cntr; + u8_t * buf_ptr; + u32_t buf_pos; + u32_t first_byte; + u64_t time_stamp; +}; + +/* NetIO command protocol definition */ +#define NETIO_CMD_QUIT 0 +#define NETIO_CMD_C2S 1 +#define NETIO_CMD_S2C 2 +#define NETIO_CMD_RES 3 + +static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); + +static void +netio_close(void *arg, struct tcp_pcb *pcb) { + err_t err; - LWIP_UNUSED_ARG(arg); + struct netio_state *ns = arg; + ns->state = NETIO_STATE_DONE; + tcp_recv(pcb, NULL); + err = tcp_close(pcb); + + if (err != ERR_OK) { + /* closing failed, try again later */ + tcp_recv(pcb, netio_recv); + } else { + /* closing succeeded */ +#if NETIO_USE_STATIC_BUF != 1 + if(ns->buf_ptr != NULL){ + mem_free(ns->buf_ptr); + } +#endif + tcp_arg(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_sent(pcb, NULL); + if (arg != NULL) { + mem_free(arg); + } + } +} + +static err_t +netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netio_state *ns = arg; + u8_t * data_ptr; + u32_t data_cntr; + struct pbuf *q = p; + u16_t len; + + if (err == ERR_OK && q != NULL) { + + while (q != NULL) { + data_cntr = q->len; + data_ptr = q->payload; + while (data_cntr--) { + if (ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + break; + } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { + if (ns->cntr < 4) { + /* build up the CMD field */ + ns->cmd <<= 8; + ns->cmd |= *data_ptr++; + ns->cntr++; + } else if (ns->cntr < 8) { + /* build up the DATA field */ + ns->data_len <<= 8; + ns->data_len |= *data_ptr++; + ns->cntr++; + + if (ns->cntr == 8) { + /* now we have full command and data words */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + if (ns->cmd == NETIO_CMD_C2S) { + ns->state = NETIO_STATE_RECV_DATA; + } else if (ns->cmd == NETIO_CMD_S2C) { + ns->state = NETIO_STATE_SEND_DATA; + /* start timer */ + ns->time_stamp = rdtsc(); + /* send first round of data */ + + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + //kprintf("data length: %d, len: %d\n", ns->data_len, len); + + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + ns->cntr += len; + + } else { + /* unrecognized command, punt */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + netio_close(ns, pcb); + break; + } + } + } else { + /* in trouble... shouldn't be in this state! */ + kputs("netio is in trouble\n"); + } + + } else if (ns->state == NETIO_STATE_RECV_DATA) { + + if(ns->cntr == 0){ + /* save the first byte of this new round of data + * this will not match ns->buf_ptr[0] in the case that + * NETIO_BUF_SIZE is less than ns->data_len. + */ + ns->first_byte = *data_ptr; + } + + ns->buf_ptr[ns->buf_pos++] = *data_ptr++; + ns->cntr++; + + if (ns->buf_pos == NETIO_BUF_SIZE) { + /* circularize the buffer */ + ns->buf_pos = 0; + } + + if(ns->cntr == ns->data_len){ + ns->cntr = 0; + if (ns->first_byte != 0) { + /* if this last round did not start with 0, + * go look for another command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ + } else { + /* stay here and wait on more data */ + } + } + + } else if (ns->state == NETIO_STATE_SEND_DATA + || ns->state == NETIO_STATE_SEND_DATA_LAST) { + /* I don't think this should happen... */ + } else { + /* done / quit */ + netio_close(ns, pcb); + break; + } /* end of ns->state condition */ + } /* end of while data still in this pbuf */ + + q = q->next; + } - if (err == ERR_OK && p != NULL) { tcp_recved(pcb, p->tot_len); pbuf_free(p); + } else { - pbuf_free(p); + + /* error or closed by other side */ + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + + /* close the connection */ + netio_close(ns, pcb); + + } + return ERR_OK; + +} + +static err_t +netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netio_state *ns = arg; + err_t err = ERR_OK; + + if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { + u64_t now = rdtsc(); + u64_t time = (now - ns->time_stamp) / get_cpu_frequency(); + + /* done with this round of sending */ + ns->buf_pos = 0; + ns->cntr = 0; + ns->buf_ptr[0] = 1; + ns->state = NETIO_STATE_SEND_DATA_LAST; + + kprintf("consumed time: %llu usec (%llu ticks)\n", time, now - ns->time_stamp); + kprintf("throughput: %llu KByte/s\n", (ns->data_len * 1000000ULL) / (time*1024)); } - if (err == ERR_OK && p == NULL) { - tcp_arg(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_close(pcb); + if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + + if(ns->cntr < ns->data_len){ + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + if(ns->buf_pos >= NETIO_BUF_SIZE){ + ns->buf_pos = 0; + } + + ns->cntr += len; + } + } + + if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ + /* we have buffered up all our data to send this last round, go look for a command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->cntr = 0; + ns->buf_ptr[0] = 0; } return ERR_OK; } -static err_t netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) +static err_t +netio_poll(void *arg, struct tcp_pcb *pcb) { - LWIP_UNUSED_ARG(arg); + struct netio_state * ns = arg; + + if(ns->state == NETIO_STATE_SEND_DATA) { + + } else if(ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + } + + return ERR_OK; + +} + +#if NETIO_USE_STATIC_BUF == 1 +static u8_t netio_buf[NETIO_BUF_SIZE]; +#endif + +static err_t +netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netio_state * ns; + LWIP_UNUSED_ARG(err); - tcp_arg(pcb, NULL); - tcp_sent(pcb, NULL); + ns = mem_malloc(sizeof(struct netio_state)); + + if(ns == NULL){ + return ERR_MEM; + } + + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + ns->cntr = 0; + ns->buf_pos = 0; +#if NETIO_USE_STATIC_BUF == 1 + ns->buf_ptr = netio_buf; +#else + ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE); + + if(ns->buf_ptr == NULL){ + mem_free(ns); + return ERR_MEM; + } +#endif + + memset(ns->buf_ptr, 0x00, NETIO_BUF_SIZE); + + tcp_arg(pcb, ns); + tcp_sent(pcb, netio_sent); tcp_recv(pcb, netio_recv); + tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ + //tcp_nagle_disable(pcb); return ERR_OK; } @@ -57,6 +361,7 @@ void netio_init(void) pcb = tcp_listen(pcb); tcp_accept(pcb, netio_accept); } + #endif /* LWIP_TCP */ #endif diff --git a/kernel/ping.c b/kernel/ping.c index 7d81500f..af661b79 100644 --- a/kernel/ping.c +++ b/kernel/ping.c @@ -55,7 +55,7 @@ #include #if LWIP_SOCKET -#define PING_USE_SOCKETS 1 +#define PING_USE_SOCKETS 0 #endif #if PING_USE_SOCKETS @@ -102,7 +102,7 @@ #endif /* ping variables */ -static u16_t ping_seq_num; +static u16_t ping_seq_num = 0; static u32_t ping_time; #if !PING_USE_SOCKETS static struct raw_pcb *ping_pcb; @@ -216,7 +216,7 @@ ping_thread(void *arg) ping_target = PING_TARGET; if (ping_send(s, &ping_target) == ERR_OK) { - LWIP_DEBUGF( PING_DEBUG, ("ping: send on core %d to " , CORE_ID)); + LWIP_DEBUGF( PING_DEBUG, ("ping: send to ")); ip_addr_debug_print(PING_DEBUG, &ping_target); LWIP_DEBUGF( PING_DEBUG, ("\n")); @@ -293,6 +293,7 @@ ping_send(struct raw_pcb *raw, ip_addr_t *addr) static void ping_timeout(void *arg) { + static unsigned counter = 0; struct raw_pcb *pcb = (struct raw_pcb*)arg; ip_addr_t ping_target = PING_TARGET; @@ -300,7 +301,9 @@ ping_timeout(void *arg) ping_send(pcb, &ping_target); - sys_timeout(PING_DELAY, ping_timeout, pcb); + counter++; + if (counter < 5) + sys_timeout(PING_DELAY, ping_timeout, pcb); } static void @@ -314,13 +317,15 @@ ping_raw_init(void) sys_timeout(PING_DELAY, ping_timeout, ping_pcb); } +#if 0 void -ping_send_now() +ping_send_now(void) { ip_addr_t ping_target = PING_TARGET; LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL); ping_send(ping_pcb, &ping_target); } +#endif #endif /* PING_USE_SOCKETS */ diff --git a/kernel/syscall.c b/kernel/syscall.c index adf0cd84..bb0dc6b2 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -193,7 +193,7 @@ int syscall_handler(uint32_t sys_nr, ...) int ret = -EINVAL; va_list vl; - check_workqueues_rem_irq(); + check_workqueues(); va_start(vl, sys_nr); diff --git a/kernel/tasks.c b/kernel/tasks.c index 94ec5022..e8f62d16 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -69,8 +69,16 @@ task_t* get_current_task(void) { return per_core(current_task); } -uint32_t get_highest_priority(uint32_t core_id) { - return last_set(runqueues[core_id].prio_bitmap); +void check_scheduling(void) { + if (!is_irq_enabled()) + return; + if (msb(runqueues[CORE_ID].prio_bitmap) > per_core(current_task)->prio) + reschedule(); +} + +uint32_t get_highest_priority(void) +{ + return msb(runqueues[CORE_ID].prio_bitmap); } int multitasking_init(void) { @@ -1244,20 +1252,15 @@ void scheduler(void) } runqueues[core_id].old_task = NULL; // reset old task - prio = last_set(runqueues[core_id].prio_bitmap); // determines highest priority + prio = msb(runqueues[core_id].prio_bitmap); // determines highest priority #if MAX_CORES > 1 - if (!prio) { + if (prio >= sizeof(size_t)*8) { load_balancing(); - prio = last_set(runqueues[core_id].prio_bitmap); // retry... + prio = msb(runqueues[core_id].prio_bitmap); // retry... } #endif - if (BUILTIN_EXPECT(prio > MAX_PRIO, 0)) { - kprintf("Invalid priority %u by bitmap 0x%x\n", prio, runqueues[core_id].prio_bitmap); - prio = 0; - } - - if (!prio) { + if (prio >= sizeof(size_t)*8) { if ((curr_task->status == TASK_RUNNING) || (curr_task->status == TASK_IDLE)) goto get_task_out; curr_task = per_core(current_task) = runqueues[core_id].idle; diff --git a/lwip/src/arch/sys_arch.c b/lwip/src/arch/sys_arch.c index 88b9e26b..5b90bf66 100644 --- a/lwip/src/arch/sys_arch.c +++ b/lwip/src/arch/sys_arch.c @@ -167,7 +167,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t * mbox, void **msg, u32_t timeout) int err; err = mailbox_ptr_fetch(&mbox->mailbox, msg, timeout); - LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: %d\n", err)); + //LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: %d\n", err)); if (!err) return 0; @@ -216,7 +216,7 @@ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) int err; err = mailbox_ptr_trypost(&mbox->mailbox, msg); - LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: %d"\n, err)); + //LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: %d"\n, err)); return err; } diff --git a/lwip/src/include/arch/cc.h b/lwip/src/include/arch/cc.h index 3474f573..d4b637cc 100644 --- a/lwip/src/include/arch/cc.h +++ b/lwip/src/include/arch/cc.h @@ -48,6 +48,8 @@ typedef uint16_t u16_t; typedef int16_t s16_t; typedef uint32_t u32_t; typedef int32_t s32_t; +typedef uint64_t u64_t; +typedef int64_t s64_t; typedef size_t mem_ptr_t; @@ -70,7 +72,7 @@ typedef size_t mem_ptr_t; #define MEM_ALIGNMENT 4 #define ETH_PAD_SIZE 2 -#define LWIP_CHKSUM_ALGORITHM 2 +#define LWIP_CHKSUM_ALGORITHM 2 /* prototypes for printf() and abort() */ #include diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 0e1b40c7..d21fe32c 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -3,6 +3,8 @@ #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H_ +#include + /** * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain * critical regions during buffer allocation, deallocation and memory @@ -59,10 +61,19 @@ */ #define LWIP_TCP 1 +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#define TCP_MSS 1460 + /** * TCP_SND_BUF: TCP sender buffer space (bytes). */ -#define TCP_SND_BUF (16*1024) +#define TCP_SND_BUF (16*TCP_WND) /** * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) @@ -118,15 +129,6 @@ */ #define DEFAULT_THREAD_PRIO NORMAL_PRIO -/** - * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, - * you might want to increase this.) - * For the receive side, this MSS is advertised to the remote side - * when opening a connection. For the transmit size, this MSS sets - * an upper limit on the MSS advertised by the remote host. - */ -#define TCP_MSS 2048 - /** * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ @@ -171,12 +173,36 @@ */ #define MEMP_NUM_TCPIP_MSG_INPKT 0x40 +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN + +// On the SCC, we have not to check incoming messages from the trusted MCPC +#ifdef CONFIG_ROCKCREEK +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#define CHECKSUM_CHECK_IP 0 + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#define CHECKSUM_CHECK_UDP 0 + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#define CHECKSUM_CHECK_TCP 0 +#endif + /* DEBUG options */ #define LWIP_DEBUG 1 #define DHCP_DEBUG LWIP_DBG_OFF #define ETHARP_DEBUG LWIP_DBG_OFF #define TCPIP_DEBUG LWIP_DBG_OFF -#define SYS_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_ON #define RAW_DEBUG LWIP_DBG_OFF #define MEM_DEBUG LWIP_DBG_OFF #define IP_DEBUG LWIP_DBG_OFF diff --git a/newlib/net/Makefile b/newlib/net/Makefile index 4d8e4bce..9a0ea2e6 100644 --- a/newlib/net/Makefile +++ b/newlib/net/Makefile @@ -7,7 +7,7 @@ LDFLAGS = LIBNAME = libsocket.a ARFLAGS = ruv CP = cp -OBJS = accept.o bind.o closesocket.o connect.o listen.o recv.o send.o socket.o ip_addr.o +OBJS = accept.o bind.o closesocket.o connect.o listen.o recv.o send.o socket.o ip_addr.o gethostbyname.o #setsockopt.o getsockopt.o sendto.o select.o # other implicit rules %.o : %.c @@ -23,6 +23,7 @@ $(LIBNAME): $(OBJS) socket.h $(CP) socket.h $(NEWLIB)/include/sys $(CP) in.h $(NEWLIB)/include/netinet $(CP) inet.h $(NEWLIB)/include/arpa + $(CP) netdb.h $(NEWLIB)/include clean: $(RM) $(LIBNAME) *.o *~ diff --git a/newlib/net/gethostbyname.c b/newlib/net/gethostbyname.c new file mode 100644 index 00000000..a42e4037 --- /dev/null +++ b/newlib/net/gethostbyname.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +struct hostent; + +struct hostent* +_DEFUN (gethostbyname, (name), + const char *name) +{ + struct hostent* ret; + + ret = (struct hostent*) SYSCALL1(__NR_gethostbyname, name); + //if (ret == NULL) + // errno = -EINVAL; + + return ret; +} diff --git a/newlib/net/getsockopt.c b/newlib/net/getsockopt.c new file mode 100644 index 00000000..2684ecc0 --- /dev/null +++ b/newlib/net/getsockopt.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +int +_DEFUN (getsockopt, (s, level, optname, optval, optlen), + int s _AND int level _AND int optname _AND void *optval _AND uint32_t optlen) +{ + int ret; + + ret = SYSCALL6(__NR_getsockopt, s, level, optname, optval, optlen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/inet.h b/newlib/net/inet.h index 39bbc745..8d2cbf42 100644 --- a/newlib/net/inet.h +++ b/newlib/net/inet.h @@ -106,4 +106,4 @@ char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); } #endif -#endif /* __NETINET_IN_H__ */ +#endif /* __ARPA_INET_H__ */ diff --git a/newlib/net/netdb.h b/newlib/net/netdb.h new file mode 100644 index 00000000..d4086a07 --- /dev/null +++ b/newlib/net/netdb.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, Stefan Lankes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The kernel of MetalSVM uses LwIP as lightweight TCP/IP stack. + * This header defines only a small wrapper to use LwIP functions + * from user space. + */ + +#ifndef __NETDB_H__ +#define __NETDB_H__ + +#include +#include + +#ifdef __cplusplus +{ +#endif + +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct hostent *gethostbyname(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETDB_H__ */ diff --git a/newlib/net/select.c b/newlib/net/select.c new file mode 100644 index 00000000..862cd467 --- /dev/null +++ b/newlib/net/select.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (select, (maxfdp1, readset, writeset, exceptset, timeout), + int maxfdp1 _AND fd_set *readset _AND fd_set *writeset _AND fd_set *exceptset _AND struct timeval *timeout) +{ + int ret; + + ret = SYSCALL6(__NR_select, maxfdp1, readset, writeset, exceptset, timeout); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/sendto.c b/newlib/net/sendto.c new file mode 100644 index 00000000..a4730cbc --- /dev/null +++ b/newlib/net/sendto.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +struct sockaddr; + +int +_DEFUN (sendto, (s, dataptr, size, flags, to, tolen), + int s _AND const void *dataptr _AND size_t size _AND int flags _AND const struct sockaddr *to _AND uint32_t tolen) +{ + int ret; + + ret = SYSCALL7(__NR_sendto, s, dataptr, size, flags, to, tolen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/setsockopt.c b/newlib/net/setsockopt.c new file mode 100644 index 00000000..b650da0a --- /dev/null +++ b/newlib/net/setsockopt.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * RWTH Aachen University + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen University + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (setsockopt, (s, level, optname, optval, optlen), + int s _AND int level _AND int optname _AND const void *optval _AND uint32_t optlen) +{ + int ret; + + ret = SYSCALL6(__NR_setsockopt, s, level, optname, optval, optlen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/socket.h b/newlib/net/socket.h index 92d9ad0f..da6b1d11 100644 --- a/newlib/net/socket.h +++ b/newlib/net/socket.h @@ -311,8 +311,8 @@ int send(int s, const void *dataptr, size_t size, int flags); int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); int socket(int domain, int type, int protocol); -//int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, -// struct timeval *timeout); +int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); //int ioctl(int s, long cmd, void *argp); //int fcntl(int s, int cmd, int val); diff --git a/newlib/net/syscall.h b/newlib/net/syscall.h index 5bd58118..26acb507 100644 --- a/newlib/net/syscall.h +++ b/newlib/net/syscall.h @@ -63,6 +63,12 @@ extern "C" { #define __NR_recv 21 #define __NR_send 22 #define __NR_socket 23 +#define __NR_getsockopt 24 +#define __NR_setsockopt 25 +#define __NR_gethostbyname 26 +#define __NR_sendto 27 +#define __NR_recvfrom 28 +#define __NR_select 29 #define _STR(token) #token #define _SYSCALLSTR(x) "int $" _STR(x) " " diff --git a/tools/Makefile b/tools/Makefile index ecec5ec0..ee97610b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -36,7 +36,7 @@ reset_vector.bin: reset_vector.o ld --oformat binary -Ttext 0 -melf_i386 -o $@ $< scc_bootinfo.asm: bootinfo.sh - ./bootinfo.sh 0x00400000 initrd.img 1 533 0 > scc_bootinfo.asm + ./bootinfo.sh 0x01000000 initrd.img 1 533 0 > scc_bootinfo.asm scc_bootinfo.bin: scc_bootinfo.asm $(NASM) $(NASMFLAGS) -o $@ $< diff --git a/tools/load.map b/tools/load.map index 6263ab88..ef05bd83 100644 --- a/tools/load.map +++ b/tools/load.map @@ -1,5 +1,5 @@ 0x00080000 scc_bootinfo.bin 0x00090200 scc_setup.bin 0x00100000 metalsvm.bin -0x00400000 initrd.img +0x01000000 initrd.img 0xfffff000 reset_vector.bin