static errno_t threads_test() { hal_cond_init(&c, "threadTest"); hal_mutex_init(&m, "threadTest"); hal_sem_init(&s, "threadTest"); int i = 40; n_t_empty = i; while(i-- > 0) phantom_create_thread( t_empty, "Empty", 0 ); pressEnter("will create thread"); phantom_create_thread( thread1, "__T1__", 0 ); phantom_create_thread( thread1, "__T2__", 0 ); //phantom_create_thread( thread1, "__T3__" ); //phantom_create_thread( t_wait, "__TW__" ); int tid = hal_start_kernel_thread_arg( t_wait, "__TW__" ); i = 40; while(i-- > 0) { if(TEST_CHATTY) pressEnter("will yield"); YIELD(); if(TEST_CHATTY) printf("!! back in main\n"); } t_kill_thread( tid ); hal_sleep_msec( 30 ); thread_stop_request = 1; hal_sleep_msec( 10 ); thread_activity_counter = 0; hal_sleep_msec( 1000 ); if( thread_activity_counter ) { SHOW_ERROR0( 0, "Can't stop thread" ); return -1; } while(n_t_empty > 0) { SHOW_FLOW( 0, "wait for %d threads", n_t_empty ); hal_sleep_msec(500); } if(p._ah.refCount != 1) { SHOW_ERROR( 0, "p._ah.refCount = %d", p._ah.refCount ); test_fail_msg( -1, "refcount" ); } else SHOW_ERROR( 0, "p._ah.refCount = %d, SUCCESS", p._ah.refCount ); return 0; }
int do_test_sem(const char *test_parm) { (void) test_parm; printf("Testing semaphores\n"); hal_sem_init(&test_sem_0, "semTest"); softirq = hal_alloc_softirq(); if( softirq < 0 ) test_fail_msg( 1, "Unable to get softirq" ); hal_set_softirq_handler( softirq, sem_softirq, 0 ); //int tid = hal_start_kernel_thread_arg( sem_rel, 0 ); printf("sema wait 1\n"); // Direct sem_released = 0; hal_sem_acquire( &test_sem_0 ); test_check_eq(sem_released,1); hal_sleep_msec( 100 ); printf("sema wait 2\n"); #if TEST_SOFTIRQ // Softirq sem_released = 0; hal_sem_acquire( &test_sem_0 ); test_check_eq(sem_released,1); #endif hal_sleep_msec( 100 ); printf("sema timeout\n"); sem_released = 0; hal_start_kernel_thread_arg( sem_etc, 0 ); hal_sleep_msec( 100 ); test_check_eq(sem_released,0); hal_sleep_msec( 120 ); test_check_eq(sem_released,1); test_check_eq( rc, ETIMEDOUT); stop_sem_test = 1; printf("Done testing semaphores\n"); return 0; }
static void trfs_recv_thread(void *arg) { (void) arg; u_int8_t buf[TRFS_MAX_PKT]; t_current_set_name("TRFS Recv"); while(connect_trfs()) { SHOW_ERROR0( 1, "Unable to connect" ); hal_sleep_msec(20000); //return; } while(1) { int rc; if( ( rc = trfs_recv( &buf, TRFS_MAX_PKT)) <= 0 ) { SHOW_ERROR( 1, "recv err %d", rc ); again: hal_sleep_msec( 100 ); // Against tight loop continue; } if( rc < (int)sizeof(trfs_pkt_t) ) { SHOW_ERROR( 1, "recv pkt size %d < required %d", rc, sizeof(trfs_pkt_t) ); goto again; } trfs_pkt_t *rq = (trfs_pkt_t *)buf; SHOW_FLOW( 6, "got pkt type %d", rq->type ); if(rq->sessionId != sessionId) { trfs_reset_session(rq->sessionId); if(rq->type != PKT_T_Error) continue; } switch(rq->type) { case PKT_T_Error: recvError(rq); break; case PKT_T_ReadReply: recvReadReply(rq); break; case PKT_T_FindReply: recvFindReply(rq); break; default: SHOW_ERROR( 0, "TRFS: unknown packet type %d", rq->type); } } }
static void trfs_resend_thread(void *arg) { (void) arg; t_current_set_name("TRFS Resend"); while(1) { hal_sleep_msec( 1000 ); // between bursts hal_mutex_lock(&lock); trfs_queue_t *first = 0; again: if(queue_empty(&requests)) { hal_mutex_unlock(&lock); continue; } trfs_queue_t *elt; // Move to end queue_remove_first( &requests, elt, trfs_queue_t *, chain ); queue_enter(&requests, elt, trfs_queue_t *, chain); if( elt == first ) { hal_mutex_unlock(&lock); continue; } first = elt; if( TRFS_NEED_RESEND(elt) ) { if( elt->resend_count++ > MAX_RETRY ) { queue_remove( &requests, elt, trfs_queue_t *, chain ); //elt->orig_request->flag_ioerror = 1; elt->orig_request->rc = ETIMEDOUT; trfs_signal_done(elt); } else { SHOW_FLOW0( 1, "rerequest" ); sendRequest(elt); hal_sleep_msec( 100 ); // between packets } goto again; }
int phantom_dev_keyboard_get_key(void) { //#warning completely wrong!!! // return debug_console_getc(); while(1) hal_sleep_msec(10000); }
void disk_page_io_wait(disk_page_io *me) { #if 0 // BUG! RACES! while( req.flag_pagein || req.flag_pageout ) hal_sleep( &req ); #else // BUG! polling! hal_sleep_msec( 1 ); //phantom_scheduler_yield(); while( me->req.flag_pagein || me->req.flag_pageout ) hal_sleep_msec( 10 ); #endif }
void dpc_init() { SHOW_FLOW0( 1, "Starting DPC"); hal_cond_init( &dpc_thread_sleep_stone, "DPC" ); spinlock_init( &dpc_request_lock ); hal_mutex_init(&unused_dpc_mutex, "DPC"); SHOW_FLOW0( 1, "Starting DPC thread..."); //dpc_thread_object = hal_start_kernel_thread(dpc_thread); #if !DPC_WAKE_TIMER SHOW_FLOW0( 1, " starting DPC waker thread..."); //dpc_timed_waker_thread_object = hal_start_kernel_thread(dpc_timed_waker_thread); #else dpc_timer_wake(0); #endif while(!dpc_init_ok) { SHOW_FLOW0( 2, " wait for DPC threads..."); hal_sleep_msec(1); // wait for thread to start } SHOW_FLOW0( 0, "DPC start done"); }
static void dpc_serve1( void *arg ) { if( strcmp( arg, DPC_ARG1 ) ) { SHOW_ERROR0( 0, "DPC 1 arg is wrong" ); test_fail( -1 ); } dpc1_triggered = 1; hal_sleep_msec(2000); }
static void dpc_timed_waker_thread(void) { hal_set_thread_name("DPC Waker"); while(1) { hal_sleep_msec(1000); if(dpc_stop_request) hal_exit_kernel_thread(); dpc_timed(); } }
static void sem_rel(void *a) { (void) a; hal_sleep_msec( 300 ); printf("sema release 1 (direct)\n"); sem_released = 1; hal_sem_release( &test_sem_0 ); #if TEST_SOFTIRQ hal_sleep_msec( 300 ); printf("sema release 2 (softirq %d)\n", softirq ); sem_released = 1; hal_request_softirq( softirq ); #endif /* while(!stop_sem_test) { hal_sleep_msec( 500 ); } */ }
void phantom_finish_all_threads(void) { phantom_virtual_machine_stop_request = 1; phantom_virtual_machine_snap_request = 1; SHOW_FLOW( 2, "Finishing %d threads", n_vm_threads); while(n_vm_threads > 0) { SHOW_FLOW( 6, "Waiting for threads to finish, %d left", n_vm_threads); hal_sleep_msec(1); // For snapper may, possibly, decrement it till then phantom_virtual_machine_snap_request = 1; } }
static void stray_catch_thread(void) { hal_set_thread_name("StrayCheck"); printf("Stray checker running, %d windows\n", ncr); while(1) { // 1 sec //hal_sleep_msec(1000); hal_sleep_msec(50); stray(); } }
static void start_new_vm_thread(struct pvm_object new_thread) { args_used++; //int tid = hal_start_thread(thread_run_func, &new_thread, THREAD_FLAG_VM|THREAD_FLAG_USER); int tid = hal_start_thread(thread_run_func, &new_thread, THREAD_FLAG_VM); struct data_area_4_thread *tda = pvm_object_da( new_thread, thread ); tda->tid = tid; t_set_owner( tid, new_thread.data ); //phantom_thread_t *t = get_thread(tid); //t->owner = new_thread.data; while(args_used > 0) hal_sleep_msec(1); if(tda->sleep_flag) { //timedcall_t *e = &(tda->timer); net_timer_event *e = &(tda->timer); int didit = 0; if( e->pending ) { bigtime_t msecMore = e->sched_time - hal_system_time(); msecMore /= 1000; if( msecMore > 0 ) { // Thread is sleeping on timer, reactivate wakeup phantom_wakeup_after_msec( msecMore, tda ); } else { // Sleep time is passed, just wake SYSCALL_WAKE_THREAD_UP(tda); } didit = 1; } if(!didit) { SHOW_ERROR( 0, "Sleeping VM thread has no means to wakeup (%p)", new_thread.data ); } } }
static void thread_ones(void *a) { (void) a; register int a01 = 1; register int a02 = 1; register int a03 = 1; register int a04 = 1; register int a05 = 1; register int a06 = 1; register int a07 = 1; register int a08 = 1; register int a09 = 1; register int a10 = 1; int c = 2000; while( c-- > 0 ) { hal_sleep_msec(1); zo_check_eq(a01,1); zo_check_eq(a02,1); zo_check_eq(a03,1); zo_check_eq(a04,1); zo_check_eq(a05,1); zo_check_eq(a06,1); zo_check_eq(a07,1); zo_check_eq(a08,1); zo_check_eq(a09,1); zo_check_eq(a10,1); } zo_run--; hal_sleep_msec(10000); }
static void thread_zeroes(void *a) { (void) a; register int a01 = 0; register int a02 = 0; register int a03 = 0; register int a04 = 0; register int a05 = 0; register int a06 = 0; register int a07 = 0; register int a08 = 0; register int a09 = 0; register int a10 = 0; int c = 2000; while( c-- > 0 ) { hal_sleep_msec(1); zo_check_eq(a01,0); zo_check_eq(a02,0); zo_check_eq(a03,0); zo_check_eq(a04,0); zo_check_eq(a05,0); zo_check_eq(a06,0); zo_check_eq(a07,0); zo_check_eq(a08,0); zo_check_eq(a09,0); zo_check_eq(a10,0); } zo_run--; hal_sleep_msec(10000); }
static int phantom_window_getc(void) { //SHOW_FLOW0( 11, "window getc" ); //wtty_t *tty = &(GET_CURRENT_THREAD()->ctty); #if CONF_NEW_CTTY wtty_t *tty = GET_CURRENT_THREAD()->ctty_w; #else wtty_t *tty = GET_CURRENT_THREAD()->ctty; #endif if(tty == 0) { SHOW_ERROR0( 0, "No wtty, phantom_window_getc loops forever" ); while(1) hal_sleep_msec(10000); } return wtty_getc( tty ); }
int do_test_01_threads(const char *test_parm) { (void) test_parm; printf("Testing thread state integrity\n"); hal_start_kernel_thread_arg( thread_ones, 0 ); hal_start_kernel_thread_arg( thread_zeroes, 0 ); printf("Wait for 01 threads to finish\n"); while(zo_run) hal_sleep_msec(100); if(zo_fail) test_fail_msg( -1, "data corruption" ); return 0; }
static void t_empty(void *a) { (void) a; ref_inc_p(&p); hal_sleep_msec( random() % 6000 ); // TODO do some random things, such as sleep, set timer, etc ref_inc_p(&p); ref_inc_p(&p); ref_inc_p(&p); ref_dec_p(&p); ref_dec_p(&p); ref_dec_p(&p); ref_dec_p(&p); n_t_empty--; }
//! This thread delivers events from main Q to windows static void ev_push_thread() { t_current_set_name("UIEventQ"); // +1 so that it is a bit higher than regular sys threads t_current_set_priority(PHANTOM_SYS_THREAD_PRIO+1); #if EVENTS_ENABLED && 1 while(1) { ev_remove_extra_unused(); struct ui_event *e; hal_mutex_lock( &ev_main_q_mutex ); while(queue_empty(&ev_main_event_q)) hal_cond_wait( &ev_have_event, &ev_main_q_mutex ); if(queue_empty(&ev_main_event_q)) panic("out of events"); queue_remove_first(&ev_main_event_q, e, struct ui_event *, echain); ev_events_in_q--; hal_mutex_unlock( &ev_main_q_mutex ); SHOW_FLOW(8, "%p", e); // Deliver to 'em ev_push_event(e); // window code will return when done //return_unused_event(e); } #else while(1) { hal_sleep_msec(20000); } #endif }
errno_t disk_fence( struct phantom_disk_partition *p ) { assert(p); if( 0 == p->fence ) { SHOW_ERROR( 0, "no fence on part %s", p->name ); return ENODEV; } errno_t rc = p->fence( p ); if( rc ) { SHOW_ERROR( 0, "fence failed on part %s, rc %d", p->name, rc ); hal_sleep_msec( 10000 ); // At least - some chance... } return rc; }
static void net_timer_runner(void *arg) { (void) arg; net_timer_event *e; bigtime_t now; t_current_set_name("Net Timer"); for(;;) { //sem_acquire_etc(net_q.wait_sem, 1, SEM_FLAG_TIMEOUT, NET_TIMER_INTERVAL, NULL); hal_sleep_msec(NET_TIMER_INTERVAL); now = system_time(); //printf("(^)"); retry: mutex_lock(&net_q.lock); // pull off the head of the list and run it, if it timed out if((e = peek_queue_head()) != NULL && e->sched_time <= now) { remove_from_queue(e); e->pending = false; mutex_unlock(&net_q.lock); e->func(e->args); // Since we ran an event, loop back and check the head of // the list again, because the list may have changed while // inside the callback. goto retry; } else { mutex_unlock(&net_q.lock); } } }
phantom_device_t * driver_rtl_8169_probe( pci_cfg_t *pci, int stage ) { (void) stage; rtl8169 * nic = NULL; static int seq_number = 0; return 0; // on real hw beheaves strangely SHOW_FLOW0( 1, "probe" ); //nic = rtl8169_new(); nic = calloc(1, sizeof(rtl8169)); if (nic == NULL) { SHOW_ERROR0( 0, "out of mem"); return 0; } nic->irq = pci->interrupt; int i; for (i = 0; i < 6; i++) { if (pci->base[i] > 0xffff) { nic->phys_base = pci->base[i]; nic->phys_size = pci->size[i]; SHOW_INFO( 0, "base 0x%lx, size 0x%lx", nic->phys_base, nic->phys_size ); } else if( pci->base[i] > 0) { nic->io_port = pci->base[i]; SHOW_INFO( 0, "io_port 0x%x", nic->io_port ); } } #if 0 SHOW_FLOW0( 1, "stop" ); rtl8169_stop(nic); hal_sleep_msec(10); #endif SHOW_FLOW0( 1, "init"); if (rtl8169_init(nic) < 0) { SHOW_ERROR0( 0, "init failed"); return 0; } phantom_device_t * dev = malloc(sizeof(phantom_device_t)); dev->name = "rtl8169"; dev->seq_number = seq_number++; dev->drv_private = nic; dev->dops.read = rtl8169_read; dev->dops.write = rtl8169_write; dev->dops.get_address = rtl8169_get_address; ifnet *interface; if( if_register_interface( IF_TYPE_ETHERNET, &interface, dev) ) { SHOW_ERROR( 0, "Failed to register interface for %s", dev->name ); } else { if_simple_setup( interface, WIRED_ADDRESS, WIRED_NETMASK, WIRED_BROADCAST, WIRED_NET, WIRED_ROUTER, DEF_ROUTE_ROUTER ); } return dev; }
static int rtl8169_init(rtl8169 *r) { //bigtime_t time; int err = -1; //addr_t temp; //int i; hal_mutex_init(&r->lock,DEBUG_MSG_PREFIX); SHOW_FLOW(2, "rtl8169_init: r %p\n", r); /* r->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rtl8169_region", (void **)&r->virt_base, REGION_ADDR_ANY_ADDRESS, r->phys_size, LOCK_KERNEL|LOCK_RW, r->phys_base); if(r->region < 0) { SHOW_ERROR0(1, "rtl8169_init: error creating memory mapped region\n"); err = -1; goto err; }*/ size_t n_pages = BYTES_TO_PAGES(r->phys_size); hal_alloc_vaddress( (void **)&r->virt_base, n_pages); // alloc address of a page, but not memory hal_pages_control_etc( r->phys_base, (void *)r->virt_base, n_pages, page_map_io, page_rw, 0 ); SHOW_INFO(2, "rtl8169 mapped at address 0x%lx\n", r->virt_base); #if 0 /* create regions for tx and rx descriptors */ r->rxdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxdesc", (void **)&r->rxdesc, REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); r->rxdesc_phys = vtophys(r->rxdesc); SHOW_INFO(2, "rtl8169: rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys); r->txdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txdesc", (void **)&r->txdesc, REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * DESCRIPTOR_LEN, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); r->txdesc_phys = vtophys(r->txdesc); SHOW_INFO(2, "rtl8169: tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys); r->reg_spinlock = 0; /* create a large tx and rx buffer for the descriptors to point to */ r->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_rxbuf", (void **)&r->rxbuf, REGION_ADDR_ANY_ADDRESS, NUM_RX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW); r->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8169_txbuf", (void **)&r->txbuf, REGION_ADDR_ANY_ADDRESS, NUM_TX_DESCRIPTORS * BUFSIZE_PER_FRAME, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW); #endif hal_pv_alloc( &r->rxdesc_phys, (void**)&r->rxdesc, NUM_RX_DESCRIPTORS * DESCRIPTOR_LEN ); hal_pv_alloc( &r->txdesc_phys, (void**)&r->txdesc, NUM_TX_DESCRIPTORS * DESCRIPTOR_LEN ); SHOW_INFO(2, "rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys); SHOW_INFO(2, "tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys); hal_pv_alloc( &r->rxbuf_phys, (void**)&r->rxbuf, NUM_RX_DESCRIPTORS * BUFSIZE_PER_FRAME ); hal_pv_alloc( &r->txbuf_phys, (void**)&r->txbuf, NUM_TX_DESCRIPTORS * BUFSIZE_PER_FRAME ); /* create a receive sem */ hal_sem_init( &r->rx_sem, "rtl8169 rx_sem"); /* transmit sem */ hal_sem_init( &r->tx_sem, "rtl8169 tx_sem"); /* reset the chip */ int repeats = 100; RTL_WRITE_8(r, REG_CR, (1<<4)); // reset the chip, disable tx/rx do { hal_sleep_msec(10); // 10ms if(repeats -- <= 0 ) break; } while(RTL_READ_8(r, REG_CR) & (1<<4)); /* read in the mac address */ r->mac_addr[0] = RTL_READ_8(r, REG_IDR0); r->mac_addr[1] = RTL_READ_8(r, REG_IDR1); r->mac_addr[2] = RTL_READ_8(r, REG_IDR2); r->mac_addr[3] = RTL_READ_8(r, REG_IDR3); r->mac_addr[4] = RTL_READ_8(r, REG_IDR4); r->mac_addr[5] = RTL_READ_8(r, REG_IDR5); SHOW_INFO(2, "rtl8169: mac addr %x:%x:%x:%x:%x:%x\n", r->mac_addr[0], r->mac_addr[1], r->mac_addr[2], r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]); /* some voodoo from BSD driver */ RTL_WRITE_16(r, REG_CCR, RTL_READ_16(r, REG_CCR)); RTL_SETBITS_16(r, REG_CCR, 0x3); /* mask all interrupts */ RTL_WRITE_16(r, REG_IMR, 0); /* set up the tx/rx descriptors */ rtl8169_setup_descriptors(r); /* enable tx/rx */ RTL_SETBITS_8(r, REG_CR, (1<<3)|(1<<2)); /* set up the rx state */ /* 1024 byte dma threshold, 1024 dma max burst, CRC calc 8 byte+, accept all packets */ RTL_WRITE_32(r, REG_RCR, (1<<16) | (6<<13) | (6<<8) | (0xf << 0)); RTL_SETBITS_16(r, REG_CCR, (1<<5)); // rx checksum enable RTL_WRITE_16(r, REG_RMS, 1518); // rx mtu /* set up the tx state */ RTL_WRITE_32(r, REG_TCR, (RTL_READ_32(r, REG_TCR) & ~0x1ff) | (6<<8)); // 1024 max burst dma RTL_WRITE_8(r, REG_MTPS, 0x3f); // max tx packet size (must be careful to not actually transmit more than mtu) /* set up the interrupt handler */ //int_set_io_interrupt_handler(r->irq, &rtl8169_int, r, "rtl8169"); if(hal_irq_alloc( r->irq, &rtl8169_int, r, HAL_IRQ_SHAREABLE )) { SHOW_ERROR( 0, "unable to allocate irq %d", r->irq ); goto err1; } /* clear all pending interrupts */ RTL_WRITE_16(r, REG_ISR, 0xffff); /* unmask interesting interrupts */ RTL_WRITE_16(r, REG_IMR, IMR_SYSERR | IMR_LINKCHG | IMR_TER | IMR_TOK | IMR_RER | IMR_ROK | IMR_RXOVL); return 0; err1: // TODO free what? //vm_delete_region(vm_get_kernel_aspace_id(), r->region); //err: return err; }
void run_test( const char *test_name, const char *test_parm ) { int all = 0 == strcmp(test_name, "all" ); //int i; #ifndef ARCH_ia32 printf("sleeping 20 sec"); hal_sleep_msec(200000); #endif printf("Phantom ver %s svn %s test suite\n-----\n", PHANTOM_VERSION_STR, svn_version() ); TEST(misc); TEST(crypt); // moved here to test first - rewritten TEST(ports); // TODO mem leak! out of mem for 200! //for( i = 200; i; i-- ) { TEST(sem); } TEST(wtty); TEST(pool); // check if starting many threads eats memory //for( i = 200; i; i-- ) { TEST(many_threads); } #ifdef ARCH_mips // TEST(sem); TEST(01_threads); #endif TEST(physmem); TEST(physalloc_gen); TEST(malloc); TEST(amap); TEST(cbuf); TEST(udp_send); TEST(udp_syslog); TEST(resolver); TEST(tftp); TEST(tcp_connect); // These are long TEST(dpc); TEST(timed_call); // must test after timed calls for it depends on them TEST(ports); // These are very long, do 'em last TEST(threads); TEST(absname); #ifndef ARCH_ia32 // TEST(sem); TEST(01_threads); #endif TEST(rectangles); TEST(video); //TEST(video); //TEST(userland); printf("\n-----\n" ); if(nFailed) printf("some tests FAILED\n" ); else printf("all tests PASSED\n" ); // CI: this message is being watched by CI scripts (ci-runtest.sh) printf( "-----\nPhantom test suite FINISHED\n-----\n" ); }
static void phantom_debug_window_loop() { static char buf[DEBBS+1]; int step = 0; int show = 's'; t_current_set_name("Debug Win"); // Which thread will receive typein for this window phantom_debug_window->owner = get_current_tid(); int wx = 600; #if CONF_NEW_CTTY if( t_new_ctty( get_current_tid() ) ) panic("console t_new_ctty"); #else // Need separate ctty t_set_ctty( get_current_tid(), wtty_init( WTTY_SMALL_BUF ) ); #endif // TODO HACK! Need ioctl to check num of bytes? wtty_t *tty; t_get_ctty( get_current_tid(), &tty ); while(1) { if(tty && !wtty_is_empty(tty)) { char c = wtty_getc( tty ); switch(c) { case '?': case'h': printf( "Commands:\n" "---------\n" "w\t- show windows list\n" "t\t- show threads list\n" "s\t- show stats\n" "p\t- show profiler\n" "d\t- dump threads to JSON\n" ); break; case 'p': // profiler case 't': //w_set_title( phantom_debug_window, "Threads" ); //show = c; //break; case 'w': //w_set_title( phantom_debug_window, "Windows" ); //show = c; //break; case 's': //w_set_title( phantom_debug_window, "Stats" ); show = c; break; case 'd': { json_output jo = { 0 }; json_start( &jo ); json_dump_threads( &jo ); json_stop( &jo ); } break; } } { static char old_show = 0; if( old_show != show ) { old_show = show; switch(show) { case 't': w_set_title( phantom_debug_window, "Threads" ); break; case 'w': w_set_title( phantom_debug_window, "Windows" ); break; case 's': w_set_title( phantom_debug_window, "Stats" ); break; case 'p': w_set_title( phantom_debug_window, "Profiler" ); break; } } } //hal_sleep_msec(1000); hal_sleep_msec(100); #if 1 #if 1 w_clear( phantom_debug_window ); ttyd = DEBWIN_YS-20; ttxd = 0; #endif //put_progress(); void *bp = buf; int len = DEBBS; int rc; time_t sec = uptime(); int min = sec/60; sec %= 60; int hr = min/60; min %= 60; int days = hr/24; hr %= 24; struct tm mt = *current_time; rc = snprintf(bp, len, " View: \x1b[32mt\x1b[37mhreads \x1b[32ms\x1b[37mtats \x1b[32mw\x1b[37mindows \x1b[32mp\x1b[37mrofile \x1b[32m?\x1b[37m - help\n \x1b[32mStep %d, uptime %dd, %02d:%02d:%02d\x1b[37m, %d events\n Time %04d/%02d/%02d %02d:%02d:%02d GMT, CPU 0 %2d%% idle\n", step++, days, hr, min, (int)sec, ev_get_n_events_in_q(), mt.tm_year + 1900, mt.tm_mon, mt.tm_mday, mt.tm_hour, mt.tm_min, mt.tm_sec, 100-percpu_cpu_load[0] ); bp += rc; len -= rc; switch(show) { case 't': default: phantom_dump_threads_buf(bp,len); break; case 'w': phantom_dump_windows_buf(bp,len); break; case 's': phantom_dump_stats_buf(bp,len); break; case 'p': phantom_dump_profiler_buf(bp,len); break; } phantom_debug_window_puts(buf); if(wx == 600) wx = 620; else wx = 600; //w_move( phantom_debug_window, wx, 50 ); #endif put_progress(); w_update( phantom_debug_window ); } }
static void do_syscall_sw( uuprocess_t *u, struct trap_state *st) { #if HAVE_UNIX int callno = st->eax; /* unsigned int mina = 0, maxa = 0; { extern struct real_descriptor ldt[]; struct real_descriptor dsd = ldt[ st->ds/8 ]; mina = dsd.base_low | (dsd.base_med << 16) | (dsd.base_high << 24); maxa = (dsd.limit_low | dsd.limit_high << 16); if( dsd.granularity & SZ_G) maxa *= PAGE_SIZE; maxa += mina; } */ //phantom_thread_t *t = GET_CURRENT_THREAD(); //uuprocess_t *u = t->u; /* tid_t tid = get_current_tid(); pid_t pid; assert( !t_get_pid( tid, &pid )); uuprocess_t *u = proc_by_pid(pid); */ assert( u != 0 ); unsigned int mina = (int)u->mem_start, maxa = (int)u->mem_end; // trap state is good for interrupt. // call gate does not push eflags int user_esp = st->eflags; #ifndef ARCH_ia32 # warning machdep ia32 arg pass convention #endif // list of user syscsall arguments int *uarg = adjustin( user_esp, st ); uarg++; // syscall func return addr //SHOW_FLOW( 10, "Syscall pid %2d tid %2d, our esp %p, user esp %p, t kstack %p", u->pid, t->tid, &st, user_esp, t->kstack_top ); SHOW_FLOW( 8, "Syscall %d args %x, %x, %x", callno, uarg[0], uarg[1],uarg[2] ); int ret = 0; int err = 0; switch(callno) { case SYS__exit: // TODO housekeeping? SHOW_FLOW( 2, "exit %d", uarg[0] ); hal_exit_kernel_thread(); err = ENOSYS; break; case SYS_ssyslog: syslog( uarg[0], "%s", (const char *)adjustin( uarg[1], st ) ); SHOW_FLOW( 2, "syslog %d %s", uarg[0], (const char *)adjustin( uarg[1], st ) ); //SHOW_ERROR0( 0, "syslog not impl" ); break; case SYS_sleepmsec: //SHOW_FLOW( 2, "sleepmsec %d", uarg[0] ); hal_sleep_msec(uarg[0]); break; case SYS_getpagesize: ret = PAGE_SIZE; break; case SYS_personality: if( ((unsigned) uarg[0]) == 0xffffffff) { ret = 0; // Say we're Linux... well...to some extent. break; } err = EINVAL; break; case SYS_uname: err = copyout(uarg[0], mina, maxa, &phantom_uname, sizeof(phantom_uname) ); if( err ) ret = -1; break; case SYS_getuid: ret = u->uid; break; case SYS_getuid32: ret = u->uid;; break; case SYS_getegid: ret = u->egid; break; case SYS_getegid32: ret = u->egid; break; case SYS_geteuid: ret = u->euid; break; case SYS_geteuid32: ret = u->euid; break; case SYS_getgid: ret = u->gid; break; case SYS_getgid32: ret = u->gid; break; case SYS_gettid: ret = get_current_tid(); break; case SYS_getpid: ret = u->pid; break; case SYS_getpgrp: ret = u->pgrp_pid; break; case SYS_getppid: ret = u->ppid; break; case SYS_getpgid: goto unimpl; case SYS_time: { time_t t = time(0); AARG(time_t *, tp, 0, sizeof(time_t)); *tp = t; ret = t; break; } case SYS_nanosleep: // todo check for POSIX compliance, make it interruptible by signals //int nanosleep(const struct timespec *, struct timespec *); { goto unimpl; //AARG(struct timespec *, req_time, 0, sizeof(struct timespec)); //AARG(struct timespec *, rest_time, 1, sizeof(struct timespec)); //ret = usys_nanosleep( &err, u, req_time, rest_time ); //break; } case SYS_sync: case SYS_sysinfo: case SYS_sysfs: case SYS_klogctl: case SYS_shutdown: case SYS_reboot: case SYS_getitimer: case SYS_setitimer: case SYS_gettimeofday: case SYS_setuid: case SYS_setuid32: CHECK_CAP(CAP_SETUID); u->euid = uarg[0]; break; case SYS_setgid: case SYS_setgid32: CHECK_CAP(CAP_SETGID); u->egid = uarg[0]; break; case SYS_setgroups: case SYS_setgroups32: goto unimpl; case SYS_setpgid: case SYS_setregid: case SYS_setregid32: case SYS_setresgid: case SYS_setresgid32: case SYS_setresuid: case SYS_setresuid32: case SYS_setreuid: case SYS_setreuid32: goto unimpl; case SYS_open: ret = usys_open(&err, u, adjustin( uarg[0], st ), uarg[1], uarg[2] ); break; case SYS_close: ret = usys_close(&err, u, uarg[0] ); break; case SYS_read: { int count = uarg[2]; void *addr = adjustin( uarg[1], st ); CHECKA(addr,count); ret = usys_read(&err, u, uarg[0], addr, count ); break; } case SYS_write: { int count = uarg[2]; void *addr = adjustin( uarg[1], st ); CHECKA(addr,count); ret = usys_write(&err, u, uarg[0], addr, count ); break; } case SYS_lseek: ret = usys_lseek(&err, u, uarg[0], uarg[1], uarg[2] ); break; case SYS_creat: ret = usys_creat(&err, u, adjustin( uarg[0], st ), uarg[1] ); break; case SYS_chdir: { AARG(const char *, path, 0, 0); ret = usys_chdir(&err, u, path ); break; } case SYS_pipe: { AARG(int *, fds, 0, sizeof(int) * 2); ret = usys_pipe( &err, u, fds ); break; } case SYS_rmdir: case SYS_unlink: { AARG(const char *, name, 0, 1); ret = usys_rm( &err, u, name ); break; } case SYS_dup: ret = usys_dup( &err, u, uarg[0] ); break; case SYS_dup2: ret = usys_dup2( &err, u, uarg[0], uarg[1] ); break; case SYS_symlink: { AARG(const char *, n1, 0, 1); AARG(const char *, n2, 1, 1); ret = usys_symlink( &err, u, n1, n2 ); break; } case SYS_getcwd: { AARG(char *, buf, 0, uarg[1]); ret = usys_getcwd( &err, u, buf, uarg[1] ); break; } case SYS_mkdir: { AARG(const char *, path, 0, 2); ret = usys_mkdir( &err, u, path ); break; } case SYS_link: case SYS__llseek: case SYS_chroot: case SYS_lstat64: case SYS_mknod: goto unimpl; case SYS_mount: { const char *source = adjustin( uarg[0], st ); CHECKA(source,0); const char *target = adjustin( uarg[1], st ); CHECKA(target,0); const char *fstype = adjustin( uarg[2], st ); CHECKA(target,0); const void *data = adjustin( uarg[4], st ); CHECKA(data,0); ret = usys_mount(&err, u, source, target, fstype, uarg[3], data ); break; } case SYS_umount: { const char *target = adjustin( uarg[0], st ); CHECKA(target,0); ret = usys_umount(&err, u, target, 0 ); break; } /* case SYS_umount2: { const char *target = adjustin( uarg[0], st ); CHECKA(target); ret = usys_umount(&err, u, target, uarg[1] ); break; } */ case SYS_truncate: { AARG(const char *, path, 0, 0); ret = usys_truncate(&err, u, path, uarg[1] ); break; } case SYS_ftruncate: { ret = usys_ftruncate(&err, u, uarg[0], uarg[1] ); break; } case SYS_truncate64: case SYS_ftruncate64: goto unimpl; case SYS_fchdir: ret = usys_fchdir( &err, u, uarg[0] ); break; case SYS_readdir: { AARG(struct dirent *, ent, 1, sizeof(struct dirent)); ret = usys_readdir( &err, u, uarg[0], ent ); break; } case SYS_fchmod: ret = usys_fchmod( &err, u, uarg[0], uarg[1] ); break; case SYS_fchown: case SYS_fchown32: ret = usys_fchown( &err, u, uarg[0], uarg[1], uarg[2] ); break; case SYS_fcntl: { //AARG(void *, str, 2, sizeof(int)); // FIXME size of arg? ret = usys_fcntl( &err, u, uarg[0], uarg[1], uarg[0] ); } break; case SYS_fcntl64: case SYS_fdatasync: case SYS_flock: case SYS_fstat64: case SYS_fstatfs: case SYS_fsync: case SYS_utime: case SYS_chmod: case SYS_chown: case SYS_chown32: case SYS_access: case SYS_lchown: case SYS_lchown32: case SYS_pread: case SYS_pwrite: goto unimpl; case SYS_readv: { int fd = uarg[0]; int iovcnt = uarg[2]; AARG(struct iovec *, list, 1, sizeof(struct iovec) * iovcnt); unsigned int onerc; int lp; for( lp = 0; lp < iovcnt; lp++ ) { void *addr = adjustin( list[lp].iov_base, st ); CHECKA(addr,list[lp].iov_len); onerc = usys_read(&err, u, fd, addr, list[lp].iov_len ); /* if( onerc < 0 ) { ret = -1; goto err_ret; } */ ret += onerc; if( onerc < list[lp].iov_len ) break; } break; } case SYS_writev: { int fd = uarg[0]; int iovcnt = uarg[2]; AARG(struct iovec *, list, 1, sizeof(struct iovec) * iovcnt); unsigned int onerc; int lp; for( lp = 0; lp < iovcnt; lp++ ) { void *addr = adjustin( list[lp].iov_base, st ); CHECKA(addr,list[lp].iov_len); onerc = usys_write(&err, u, fd, addr, list[lp].iov_len ); /* if( onerc < 0 ) { ret = -1; goto err_ret; } */ ret += onerc; if( onerc < list[lp].iov_len ) break; } break; } case SYS_readlink: goto unimpl; case SYS_gethostname: { int len = uarg[1]; char *target = adjustin( uarg[0], st ); CHECKA(target,len); ret = usys_gethostname(&err, u, target, len ); break; } case SYS_sethostname: { int len = uarg[1]; const char *target = adjustin( uarg[0], st ); CHECKA(target,len); ret = usys_sethostname(&err, u, target, len ); break; } case SYS_socket: ret = usys_socket( &err, u, uarg[0], uarg[1], uarg[2] ); break; case SYS_setsockopt: { socklen_t optlen = uarg[4]; AARG(const void *, optval, 3, optlen); ret = usys_setsockopt( &err, u, uarg[0], uarg[1], uarg[2], optval, optlen); break; } case SYS_getsockopt: { AARG(socklen_t *, optlen, 4, sizeof(socklen_t)); AARG(void *, optval, 3, *optlen); ret = usys_getsockopt( &err, u, uarg[0], uarg[1], uarg[2], optval, optlen); break; } case SYS_getpeername: { AARG(socklen_t *, namelen, 2, sizeof(socklen_t)); AARG(struct sockaddr *, name, 1, *namelen); ret = usys_getpeername( &err, u, uarg[0], name, namelen); break; } case SYS_getsockname: { AARG(socklen_t *, namelen, 2, sizeof(socklen_t)); AARG(struct sockaddr *, name, 1, *namelen); ret = usys_getsockname( &err, u, uarg[0], name, namelen); break; } case SYS_bind: { AARG(const struct sockaddr *, addr, 1, sizeof(struct sockaddr)); ret = usys_bind( &err, u, uarg[0], addr, uarg[2] ); break; } case SYS_listen: ret = usys_listen( &err, u, uarg[0], uarg[1] ); break; case SYS_accept: { AARG( socklen_t *, len, 2, sizeof(socklen_t)); AARG( struct sockaddr *, acc_addr, 1, *len ); ret = usys_accept( &err, u, uarg[0], acc_addr, len ); break; } case SYS_recv: { int len = uarg[2]; AARG( void *, buf, 0, len ); ret = usys_recv( &err, u, uarg[0], buf, len, uarg[3] ); break; } case SYS_recvmsg: { AARG( struct msghdr *, msg, 0, sizeof(struct msghdr) ); ret = usys_recvmsg( &err, u, uarg[0], msg, uarg[2] ); break; } case SYS_send: { int len = uarg[2]; AARG( const void *, buf, 0, len ); ret = usys_send( &err, u, uarg[0], buf, len, uarg[3] ); break; } case SYS_sendmsg: { AARG( const struct msghdr *, msg, 0, sizeof(struct msghdr) ); ret = usys_sendmsg( &err, u, uarg[0], msg, uarg[2] ); break; } case SYS_sendto: { socklen_t tolen = uarg[5]; AARG( const struct sockaddr *, to, 4, tolen ); int len = uarg[2]; AARG( const void *, buf, 0, len ); ret = usys_sendto( &err, u, uarg[0], buf, len, uarg[3], to, tolen ); break; } case SYS_recvfrom: { AARG( socklen_t *, fromlen, 5, sizeof(socklen_t) ); AARG( struct sockaddr *, from, 4, *fromlen ); int len = uarg[2]; AARG( void *, buf, 0, len ); ret = usys_recvfrom( &err, u, uarg[0], buf, len, uarg[3], from, fromlen ); break; } case SYS_connect: // int connect(int socket, const struct sockaddr *address, socklen_t address_len); { int len = uarg[2]; AARG( struct sockaddr *, acc_addr, 1, len ); ret = usys_connect( &err, u, uarg[0], acc_addr, len ); break; } case SYS_socketpair: { AARG( int *, sv, 3, sizeof(int) * 2 ); ret = usys_socketpair( &err, u, uarg[0], uarg[1], uarg[2], sv ); break; } case SYS_sendfile: case SYS_socketcall: goto unimpl; case SYS_nice: { // int nice = uarg[0]; // set thr prio // break; goto unimpl; } case SYS_brk: goto unimpl; /*{ ret = usys_sbrk( &err, u, uarg[0] ); break; }*/ case SYS_fork: case SYS_vfork: goto unimpl; case SYS_ioctl: { void *data = adjustin( uarg[2], st ); CHECKA(data,0); ret = usys_ioctl( &err, u, uarg[0], uarg[1], data, uarg[3] ); break; } int statlink; case SYS_lstat: statlink = 1; goto dostat; case SYS_stat: statlink = 0; goto dostat; dostat: { const char *path = adjustin( uarg[0], st ); CHECKA(path,0); struct stat *data = adjustin( uarg[1], st ); CHECKA(data,sizeof(struct stat)); ret = usys_stat( &err, u, path, data, statlink ); break; } case SYS_fstat: { struct stat *data = adjustin( uarg[1], st ); CHECKA(data,sizeof(struct stat)); ret = usys_fstat( &err, u, uarg[0], data, 0 ); break; } case SYS_umask: { ret = u->umask; u->umask = uarg[0]; break; } case SYS_kill: { ret = usys_kill( &err, u, uarg[0], uarg[1] ); break; } case SYS_waitpid: { AARG(int *, addr, 1, sizeof(int)); ret = usys_waitpid( &err, u, uarg[0], addr, uarg[2] ); break; } case SYS_wait: { AARG(int *, addr, 0, sizeof(int)); ret = usys_waitpid( &err, u, -1, addr, 0 ); break; } case SYS_clone: goto unimpl; case SYS_madvise: case SYS_mincore: case SYS_mlock: case SYS_mlockall: case SYS_mmap: case SYS_mprotect: case SYS_mremap: case SYS_msync: case SYS_munlock: case SYS_munlockall: case SYS_munmap: goto unimpl; // NewOS/BeOS/Haiku case SYS_create_port: { // TODO check string length and final addr to be valid AARG(const char *, name, 1, 0); ret = port_create( uarg[0], name ); break; } case SYS_close_port: ret = port_close( uarg[0] ); break; case SYS_delete_port: ret = port_delete( uarg[0] ); break; case SYS_find_port: { // TODO check string length and final addr to be valid AARG(const char *, name, 0, 0); ret = port_find(name); break; } case SYS_get_port_info: { AARG(struct port_info *, info, 1, sizeof(struct port_info)); ret = port_get_info( uarg[0], info); } case SYS_get_port_bufsize: ret = port_buffer_size( uarg[0] ); break; case SYS_get_port_bufsize_etc: ret = port_buffer_size_etc( uarg[0], uarg[1], uarg[2] ); break; case SYS_get_port_count: ret = port_count( uarg[0] ); break; case SYS_read_port: { AARG(int32_t *, msg_code, 1, sizeof(int32_t)); AARG(void *, msg_buffer, 2, uarg[3]); ret = port_read( uarg[0], msg_code, msg_buffer, uarg[3]); break; } case SYS_write_port: { //AARG(int32_t *, msg_code, 1, sizeof(int32_t)); //AARG(int32_t, msg_code, 1, sizeof(int32_t)); AARG(void *, msg_buffer, 2, uarg[3]); ret = port_write( uarg[0], uarg[1], msg_buffer, uarg[3]); break; } case SYS_read_port_etc: case SYS_write_port_etc: case SYS_set_port_owner: case SYS_get_next_port_info: goto unimpl; case SYS_phantom_run: { // extern int phantom_run(const char *fname, const char **argv, const char **envp, int flags); AARG(const char *, fname, 0, 1); AARG(const char **, uav, 1, 4); AARG(const char **, uep, 2, 4); if( 0 == uarg[1] ) uav = 0; if( 0 == uarg[2] ) uep = 0; SHOW_FLOW( 2, "run %s flags 0x%b", fname, uarg[3], "\020\1<WAIT>\2<NEWWIN>\3<NEWPGRP>" ); char *a[1024]; char *e[1024]; SHOW_FLOW( 2, "run %s load args", fname ); if( user_args_load( mina, maxa, a, 1024, uav ) || user_args_load( mina, maxa, e, 1024, uep ) ) { ret = -1; err = EFAULT; SHOW_ERROR( 0, "fault reading args for %s", fname ); goto err_ret; } ret = usys_run( &err, u, fname, (const char**)a, (const char**)e, uarg[3] ); break; } case SYS_phantom_method: // AARG(const char *, m_name, 0, 1); // int nfd = aarg[1]; // AARG(int *, fds, 0, sizeof(int)*nfd); // ret = usys_pmethod( &err, u, m_name, int nfd, int fds[] ); case SYS_phantom_toobject: case SYS_phantom_fromobject: case SYS_phantom_intmethod: case SYS_phantom_strmethod: goto unimpl; // extern int phantom_runclass(const char *cname, int nmethod, int flags); case SYS_phantom_runclass: { AARG(const char *, cname, 0, 1); unsigned flags = uarg[2]; if(flags) SHOW_ERROR( 0, "SYS_phantom_runclass: unknown flags %x" , flags ); usys_phantom_runclass( &err, u, cname, uarg[1] ); ret = err; } break; case SYS_setproperty: { AARG(const char *, pName, 1, 1); // TODO check zero term string! AARG(const char *, pValue, 2, 1); usys_setproperty( &err, u, uarg[0], pName, pValue ); ret = err; } break; case SYS_getproperty: { AARG(const char *, pName, 1, 1); // TODO check zero term string! AARG(char *, pValue, 2, uarg[3]); usys_getproperty( &err, u, uarg[0], pName, pValue, uarg[3] ); ret = err; } break; case SYS_listproperties: { AARG(char *, buf, 2, uarg[3]); usys_listproperties( &err, u, uarg[0], uarg[1], buf, uarg[3] ); ret = err; } break; case SYS_name2ip: { AARG(in_addr_t *, out, 0, sizeof(in_addr_t)); AARG(const char *, name, 1, 1); ret = name2ip( out, name, uarg[2] ); if( ret != 0 ) err = ret; } break; case SYS_sigpending: { AARG(sigset_t *, set, 0, sizeof(sigset_t *)); ret = usys_sigpending( &err, u, set); break; } case SYS_signal: { #if 0 AARG(sighandler_t, hand, 1, sizeof(sighandler_t)); hand = usys_signal( &err, u, uarg[0], hand); // FIXME 64 bit error ret = ((int)hand) - mina; // Convert pointer back #else // We do not use pointer (ret and uarg 1), so we don't have to convert it ret = (int)usys_signal( &err, u, uarg[0], (void *)uarg[1]); #endif break; } case SYS_sigprocmask: //case raise: case SYS_sigaction: case SYS_siginterrupt: case SYS_sigsuspend: goto unimpl; unimpl: SHOW_ERROR( 0, "Unimplemented syscall %d called", callno ); err = ENOSYS; break; default: SHOW_ERROR( 0, "Unknown syscall %d called", callno ); err = ENOSYS; break; } #else // HAVE_UNIX int err = ENOSYS; int ret = -1; goto err_ret; // to clear warning #endif // HAVE_UNIX err_ret: #ifdef ARCH_ia32 #define _RET_OK st->eax = ret; st->edx = err; #endif #ifdef ARCH_mips #define _RET_OK st->r2 = ret; // v0 (normal ret register, low) st->r3 = err; // v1 (normal ret register, hi) #endif #ifdef ARCH_arm #define _RET_OK st->r0 = ret; // normal ret register st->r1 = err; // arg1 reg, we can safely use for return of errno #endif #ifndef _RET_OK #error arch ret #endif }
/*! * \brief Fetch the next packet out of the receive ring buffer. * * Nic interrupts must be disabled when calling this funtion. * */ static int NicGetPacket( struct phantom_device *dev, void *buf, int len ) { //NETBUF *nb = 0; //uint8_t *buf; u_int16_t f_status_word; u_int16_t fbytecount; /* Check the fifo empty bit. If it is set, then there is nothing in the receiver fifo. */ nic_bs(2); //if (nic_inw(NIC_FIFO) & 0x8000) // return 0; // TODO cond/sem timed wait while(nic_inw(NIC_FIFO) & 0x8000) hal_sleep_msec(100); /* Inialize pointer register. */ nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR); _NOP(); _NOP(); _NOP(); _NOP(); /* Read status word and byte count. */ f_status_word = nic_inw(NIC_DATA); fbytecount = nic_inw(NIC_DATA); //printf("[SW=%04X,BC=%04X]", f_status_word, fbytecount); int ret = ERR_IO_ERROR; /* Check for frame errors. */ if (f_status_word & 0xAC00) { //nb = (NETBUF *) 0xFFFF; ret = ERR_IO_ERROR; } /* Check the byte count. */ else if (fbytecount < 66 || fbytecount > 1524) { //nb = (NETBUF *) 0xFFFF; ret = ERR_IO_ERROR; } else { /* * Allocate a NETBUF. * Hack alert: Rev A chips never set the odd frame indicator. */ fbytecount -= 3; if( len < fbytecount ) ret = ERR_VFS_INSUFFICIENT_BUF; else { NicRead( dev, buf, fbytecount); ret = fbytecount; } } /* Release the packet. */ nic_outlb(NIC_MMUCR, MMU_TOP); return ret; }
phantom_device_t * driver_lanc111_probe( int port, int irq, int stage ) { (void) stage; lanc111_nic_t *nic = NULL; SHOW_INFO0( 0, "probe"); nic = calloc( 1, sizeof(lanc111_nic_t) ); assert(nic != NULL); hal_sleep_msec(10); if(LancInit(nic) < 0) { SHOW_ERROR0( 0, "init failed"); goto free1; } // Disable NIC interrupt. //cbi(EIMSK, LANC111_SIGNAL_IRQ); phantom_device_t * dev = calloc(1, sizeof(phantom_device_t)); dev->name = "lanc111"; dev->seq_number = seq_number++; dev->drv_private = nic; //NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */ //LancOutput, /*!< \brief Driver output routine, if_send(). */ //NutEtherOutput /*!< \brief Media output routine, if_output(). */ //dev->dops.read = pcnet32_read; //dev->dops.write = pcnet32_write; //dev->dops.get_address = pcnet32_get_address; dev->iobase = port; dev->irq = irq; //dev->iomem = ; //dev->iomemsize = ; if( hal_irq_alloc( irq, &NicInterrupt, dev, HAL_IRQ_SHAREABLE ) ) { SHOW_ERROR( 0, "IRQ %d is busy", irq ); goto free2; } static CONST uint8_t mac[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x86 }; // QEMU's range if( NicStart(dev, mac) ) goto free2; /* * Start the receiver thread. * */ //NutThreadCreate("rxi5", NicRxLanc, dev, (NUT_THREAD_LANCRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD); ifnet *interface; if( if_register_interface( IF_TYPE_ETHERNET, &interface, dev) ) { SHOW_ERROR( 0, "Failed to register interface for %s", dev->name ); } else { if_simple_setup(interface, WIRED_ADDRESS, WIRED_NETMASK, WIRED_BROADCAST, WIRED_NET, WIRED_ROUTER, DEF_ROUTE_ROUTER ); } return dev; free2: free( dev ); free1: free( nic ); return 0; }
int do_test_dpc(const char *test_parm) { (void) test_parm; int rc = 0; dpc_request_init( &dpc1, dpc_serve1 ); dpc_request_init( &dpc2, dpc_serve2 ); // DPC engine runs next thread only after a second hal_sleep_msec(2000); dpc_request_trigger( &dpc1, DPC_ARG1 ); hal_sleep_msec(200); dpc_request_trigger( &dpc2, DPC_ARG2 ); hal_sleep_msec(200); if( !dpc1_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 1 lost" ); } if( !dpc2_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 2 lost" ); } dpc1_triggered = 0; dpc2_triggered = 0; hal_sleep_msec(200); if( dpc1_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 1 sporadic" ); } if( dpc2_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 2 sporadic" ); } dpc_request_trigger( &dpc2, DPC_ARG2 ); hal_sleep_msec(200); if( dpc1_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 1 sporadic after DPC 2 trigger" ); } if( !dpc2_triggered ) { rc = -1; SHOW_ERROR0( 0, "DPC 2 lost 2" ); } return rc; }
int do_test_timed_call(const char *test_parm) { (void) test_parm; printf("Testing timed call undo, must be no echoes:\n"); called = 0; phantom_request_timed_call( &t2, 0 ); phantom_undo_timed_call(&t2); hal_sleep_msec(200); // Twice the time test_check_eq(called, 0); #if DUMPQ //dump_timed_call_queue(); #endif called = 0; printf("Testing timed calls, wait for echoes:\n"); phantom_request_timed_call( &t1, 0 ); //test_check_false(called); // it is still possible for this test to fail with correct code! phantom_request_timed_call( &t2, 0 ); #if DUMPQ //dump_timed_call_queue(); #endif phantom_request_timed_call( &t3, 0 ); phantom_request_timed_call( &t4, 0 ); //TIMEDCALL_FLAG_AUTOFREE requires call to free from interrupt :( //phantom_request_timed_func( echo, msg, 5000, 0 ); phantom_request_timed_call( &t5, 0 ); #if DUMPQ dump_timed_call_queue(); #endif // We check for >= (ge) because hal_sleep... can cleep for more than asked, and timed // calls are usually quite on time hal_sleep_msec(6); test_check_ge(called, 1); hal_sleep_msec(200); // Have lag of 106 msec, OK? test_check_ge(called, 2); hal_sleep_msec(2000-100); // Still have lag of 106 msec test_check_ge(called, 3); hal_sleep_msec(5000-2000); // Have lag of 206 msec test_check_ge(called, 4); hal_sleep_msec(2500+10000-5000-2000); // Strange - need quite big lag here... test_check_ge(called, 5); printf("Done testing timed calls\n"); return 0; }