|  | #include <ros/resource.h> | 
|  | #include <ros/procdata.h> | 
|  | #include <ros/event.h> | 
|  | #include <ros/bcq.h> | 
|  | #include <parlib.h> | 
|  | #include <vcore.h> | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  | #include <fcntl.h> | 
|  | #include <arch/arch.h> | 
|  | #include <unistd.h> | 
|  | #include <errno.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <sys/mman.h> | 
|  | #include <timing.h> | 
|  | #include <assert.h> | 
|  | #include <event.h> | 
|  | #include <uthread.h> | 
|  |  | 
|  | void *core0_tls = 0; | 
|  | void *in_buf, *out_buf; | 
|  |  | 
|  | /* Test program for the audio device.  mmap()s the stuff, sets up a notif | 
|  | * handler, and switches to multi_mode. | 
|  | * | 
|  | * Note: this has a lot of mhello-like MCP infrastructure.  When Lithe is | 
|  | * working, you won't need any of this.  Just the mmap stuff and the notif | 
|  | * handler.  Stuff specific to the ethernet audio device is marked ETH_AUD. */ | 
|  | int main() | 
|  | { | 
|  | int retval; | 
|  | int in_fd, out_fd; | 
|  | /* ETHAUD mmap the input and output buffers */ | 
|  | in_fd = open("/dev/eth_audio_in", O_RDONLY); | 
|  | out_fd = open("/dev/eth_audio_out", O_RDWR); | 
|  | assert(in_fd != -1); | 
|  | assert(out_fd != -1); | 
|  | in_buf = mmap(0, PGSIZE, PROT_READ, 0, in_fd, 0); | 
|  | if (in_buf == MAP_FAILED) { | 
|  | int err = errno; | 
|  | perror("Can't mmap the input buf:"); | 
|  | } | 
|  | out_buf = mmap(0, PGSIZE, PROT_READ | PROT_WRITE, MAP_POPULATE, out_fd, 0); | 
|  | if (out_buf == MAP_FAILED) { | 
|  | int err = errno; | 
|  | perror("Can't mmap the output buf:"); | 
|  | } | 
|  | //strncpy(out_buf, "Nanwan loves you!\n", 19); | 
|  |  | 
|  | /* begin: stuff userspace needs to do before switching to multi-mode */ | 
|  | vcore_init(); | 
|  |  | 
|  | /* ETHAUD Turn on Free apple pie (which is the network packet) */ | 
|  | enable_kevent(EV_FREE_APPLE_PIE, 0, EVENT_IPI); | 
|  |  | 
|  | /* Need to save this somewhere that you can find it again when restarting | 
|  | * core0 */ | 
|  | core0_tls = get_tls_desc(0); | 
|  | /* Need to save our floating point state somewhere (like in the | 
|  | * user_thread_tcb so it can be restarted too */ | 
|  |  | 
|  | /* end: stuff userspace needs to do before switching to multi-mode */ | 
|  | /* ETHAUD */ | 
|  | /* Switch into _M mode */ | 
|  | retval = vcore_request(1); | 
|  |  | 
|  | /* Stay alive for a minute (will take interrupts) */ | 
|  | udelay(60000000); | 
|  |  | 
|  | printf("Eth aud, finishing up!\n"); | 
|  | /* Need to do unmap it, due to some limitations in the kernel */ | 
|  | munmap(in_buf, PGSIZE); | 
|  | munmap(out_buf, PGSIZE); | 
|  | close(in_fd); | 
|  | close(out_fd); | 
|  | } | 
|  |  | 
|  | /* ETHAUD, with some debugging commands... */ | 
|  | void process_packet(void) | 
|  | { | 
|  | //printf("Received a packet!\n"); | 
|  | //memset(out_buf, 0, PGSIZE); | 
|  | memcpy(out_buf, in_buf, 1280);	/* size of the payload. */ | 
|  | memset(out_buf + 1280, 0, 4);	/* 4 bytes of control info. */ | 
|  | //printf("contents of out_buf %s\n", out_buf); | 
|  | } | 
|  |  | 
|  | void vcore_entry(void) | 
|  | { | 
|  | uint32_t vcoreid = vcore_id(); | 
|  | static bool first_time = TRUE; | 
|  |  | 
|  | printf("GIANT WARNING: this is ancient shit\n"); | 
|  | /* begin: stuff userspace needs to do to handle events/notifications */ | 
|  |  | 
|  | struct vcore *vc = &__procinfo.vcoremap[vcoreid]; | 
|  | struct preempt_data *vcpd; | 
|  | vcpd = &__procdata.vcore_preempt_data[vcoreid]; | 
|  |  | 
|  | /* Ghetto way to get just an event number */ | 
|  | unsigned int ev_type = get_event_type(&vcpd->ev_mbox_public); | 
|  |  | 
|  | /* ETHAUD app: process the packet if we got a notif */ | 
|  | if (ev_type == EV_FREE_APPLE_PIE) | 
|  | process_packet(); | 
|  |  | 
|  | if (vc->preempt_pending) { | 
|  | printf("Oh crap, vcore %d is being preempted!  Yielding\n", vcoreid); | 
|  | sys_yield(TRUE); | 
|  | printf("After yield on vcore %d. I wasn't being preempted.\n", vcoreid); | 
|  | } | 
|  |  | 
|  | /* Lets try to restart vcore0's context.  Note this doesn't do anything to | 
|  | * set the appropriate TLS.  On x86, this will involve changing the LDT | 
|  | * entry for this vcore to point to the TCB of the new user-thread. */ | 
|  | if (vcoreid == 0) { | 
|  | handle_events(vcoreid); | 
|  | set_tls_desc(core0_tls, 0); | 
|  | assert(__vcoreid == 0); /* in case anyone uses this */ | 
|  | /* Load silly state (Floating point) too */ | 
|  | pop_user_ctx(&vcpd->uthread_ctx, vcoreid); | 
|  | printf("should never see me!"); | 
|  | } | 
|  | /* unmask notifications once you can let go of the uthread_ctx and it is | 
|  | * okay to clobber the transition stack. | 
|  | * Check Documentation/processes.txt: 4.2.4.  In real code, you should be | 
|  | * popping the tf of whatever user process you want (get off the x-stack) */ | 
|  | vcpd->notif_disabled = FALSE; | 
|  |  | 
|  | /* end: stuff userspace needs to do to handle notifications */ | 
|  | /* The other vcores will hit here. */ | 
|  | while (1) | 
|  | cpu_relax(); | 
|  | } |