static pipeline_t va_pipe_pipeline(pipeline_t result_so_far, va_list args) { pipe_processor_t proc = va_arg(args, pipe_processor_t); if(proc == NULL) return result_so_far; void* aux = va_arg(args, void*); size_t pipe_size = va_arg(args, size_t); if(pipe_size == 0) { pipe_consumer_free(result_so_far.out); result_so_far.out = NULL; return result_so_far; } pipe_t* pipe = pipe_new(pipe_size, 0); pipe_connect(result_so_far.out , proc, aux, pipe_producer_new(pipe)); result_so_far.out = pipe_consumer_new(pipe); pipe_free(pipe); return va_pipe_pipeline(result_so_far, args); }
static int pipe_close(FAR struct file *filep) { struct inode *inode = filep->f_inode; struct pipe_dev_s *dev = inode->i_private; int ret; /* Some sanity checking */ #if CONFIG_DEBUG if (!dev) { return -EBADF; } #endif /* Perform common close operations */ ret = pipecommon_close(filep); if (ret == 0 && dev->d_refs == 0) { /* Release the pipe when there are no further open references to it. */ pipe_free(dev->d_pipeno); } return ret; }
/* * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a * pipe control structure and set *pipep to its address. * pipe is locked, when pipe_new returns with no error. */ static int pipe_new( pipe_control_t **pipep ) { pipe_control_t *pipe; int err = 0; err = pipe_lock(); if (err) return err; pipe = *pipep; if (pipe == NULL) { err = pipe_alloc(&pipe); if (err) goto out; } if (! PIPE_LOCK(pipe)) err = -EINTR; if (*pipep == NULL) { if (err) pipe_free(pipe); else *pipep = pipe; } out: pipe_unlock(); return err; }
/* * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a * pipe control structure and set *pipep to its address. * pipe is locked, when pipe_new returns with no error. */ static int pipe_new( pipe_control_t **pipep ) { pipe_control_t *pipe; int err = 0; if (rtems_semaphore_obtain(rtems_pipe_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) return -EINTR; pipe = *pipep; if (pipe == NULL) { err = pipe_alloc(&pipe); if (err) goto out; } if (! PIPE_LOCK(pipe)) err = -EINTR; if (*pipep == NULL) { if (err) pipe_free(pipe); else *pipep = pipe; } out: rtems_semaphore_release(rtems_pipe_semaphore); return err; }
// internal, get or create a pipe pipe_t tcp4_pipe(net_tcp4_t net, char *ip, int port) { pipe_t pipe; pipe_tcp4_t to; char id[23]; snprintf(id,23,"%s:%d",ip,port); pipe = xht_get(net->pipes,id); if(pipe) return pipe; LOG("new pipe to %s",id); // create new tcp4 pipe if(!(pipe = pipe_new("tcp4"))) return NULL; if(!(pipe->arg = to = malloc(sizeof (struct pipe_tcp4_struct)))) return pipe_free(pipe); memset(to,0,sizeof (struct pipe_tcp4_struct)); to->net = net; to->sa.sin_family = AF_INET; inet_aton(ip, &(to->sa.sin_addr)); to->sa.sin_port = htons(port); if(!(to->chunks = chunks_new(0))) return tcp4_free(pipe); // set up pipe pipe->id = strdup(id); xht_set(net->pipes,pipe->id,pipe); pipe->send = tcp4_send; return pipe; }
/* * Interface to file system close. * * *pipep points to pipe control structure. When the last user releases pipe, * it will be set to NULL. */ int pipe_release( pipe_control_t **pipep, rtems_libio_t *iop ) { pipe_control_t *pipe = *pipep; uint32_t mode; rtems_status_code sc; sc = rtems_semaphore_obtain(pipe->Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); /* WARN pipe not released! */ if(sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(sc); mode = LIBIO_ACCMODE(iop); if (mode & LIBIO_FLAGS_READ) pipe->Readers --; if (mode & LIBIO_FLAGS_WRITE) pipe->Writers --; sc = rtems_semaphore_obtain(rtems_pipe_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); /* WARN pipe not freed and pipep not set to NULL! */ if(sc != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred(sc); PIPE_UNLOCK(pipe); if (pipe->Readers == 0 && pipe->Writers == 0) { #if 0 /* To delete an anonymous pipe file when all users closed it */ if (pipe->Anonymous) delfile = TRUE; #endif pipe_free(pipe); *pipep = NULL; } else if (pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE) /* Notify waiting Writers that all their partners left */ PIPE_WAKEUPWRITERS(pipe); else if (pipe->Writers == 0 && mode != LIBIO_FLAGS_READ) PIPE_WAKEUPREADERS(pipe); rtems_semaphore_release(rtems_pipe_semaphore); #if 0 if (! delfile) return 0; if (iop->pathinfo.ops->unlink_h == NULL) return 0; /* This is safe for IMFS, but how about other FSes? */ iop->flags &= ~LIBIO_FLAGS_OPEN; if(iop->pathinfo.ops->unlink_h(&iop->pathinfo)) return -errno; #endif return 0; }
/* * Interface to file system close. * * *pipep points to pipe control structure. When the last user releases pipe, * it will be set to NULL. */ void pipe_release( pipe_control_t **pipep, rtems_libio_t *iop ) { pipe_control_t *pipe = *pipep; uint32_t mode; #if defined(RTEMS_DEBUG) /* WARN pipe not freed and pipep not set to NULL! */ if (pipe_lock()) rtems_fatal_error_occurred(0xdeadbeef); /* WARN pipe not released! */ if (!PIPE_LOCK(pipe)) rtems_fatal_error_occurred(0xdeadbeef); #endif mode = LIBIO_ACCMODE(iop); if (mode & LIBIO_FLAGS_READ) pipe->Readers --; if (mode & LIBIO_FLAGS_WRITE) pipe->Writers --; PIPE_UNLOCK(pipe); if (pipe->Readers == 0 && pipe->Writers == 0) { #if 0 /* To delete an anonymous pipe file when all users closed it */ if (pipe->Anonymous) delfile = TRUE; #endif pipe_free(pipe); *pipep = NULL; } else if (pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE) /* Notify waiting Writers that all their partners left */ PIPE_WAKEUPWRITERS(pipe); else if (pipe->Writers == 0 && mode != LIBIO_FLAGS_READ) PIPE_WAKEUPREADERS(pipe); pipe_unlock(); #if 0 if (! delfile) return; if (iop->pathinfo.ops->unlink_h == NULL) return; /* This is safe for IMFS, but how about other FSes? */ iop->flags &= ~LIBIO_FLAGS_OPEN; if(iop->pathinfo.ops->unlink_h(&iop->pathinfo)) return; #endif }
pipe_t tcp4_free(pipe_t pipe) { pipe_tcp4_t to; if(!pipe) return NULL; to = (pipe_tcp4_t)pipe->arg; if(!to) return LOG("internal error, invalid pipe, leaking it"); LOG("removing %d"); xht_set(to->net->pipes,pipe->id,NULL); pipe_free(pipe); if(to->client > 0) close(to->client); chunks_free(to->chunks); free(to); return NULL; }
pipeline_t pipe_parallel(size_t instances, size_t in_size, pipe_processor_t proc, void* aux, size_t out_size) { pipe_t* in = pipe_new(in_size, 0), * out = pipe_new(out_size, 0); while(instances--) pipe_connect(pipe_consumer_new(in), proc, aux, pipe_producer_new(out)); pipeline_t ret = { .in = pipe_producer_new(in), .out = pipe_consumer_new(out) }; pipe_free(in); pipe_free(out); return ret; }
pipe_t net_serial_add(net_serial_t net, const char *name, int (*read)(void), int (*write)(uint8_t *buf, size_t len), uint8_t buffer) { pipe_t pipe; pipe_serial_t to; // just sanity checks if(!net || !name || !read || !write) return NULL; pipe = xht_get(net->pipes, name); if(!pipe) { if(!(pipe = pipe_new("serial"))) return NULL; if(!(pipe->arg = to = malloc(sizeof (struct pipe_serial_struct)))) return pipe_free(pipe); memset(to,0,sizeof (struct pipe_serial_struct)); to->net = net; if(!(to->chunks = util_chunks_new(buffer))) { free(to); return pipe_free(pipe); } // set up pipe pipe->id = strdup(name); xht_set(net->pipes,pipe->id,pipe); pipe->send = serial_send; }else{ if(!(to = (pipe_serial_t)pipe->arg)) return NULL; } // these can be modified to->read = read; to->write = write; return pipe; }
pipeline_t pipe_pipeline(size_t first_size, ...) { va_list va; va_start(va, first_size); pipe_t* p = pipe_new(first_size, 0); pipeline_t ret = va_pipe_pipeline(pipe_trivial_pipeline(p), va); pipe_free(p); va_end(va); return ret; }
int pipe2(int pipefd[2], int flags) { struct idesc_table *it; struct pipe *pipe; int res = 0; it = task_resource_idesc_table(task_self()); assert(it); pipe = pipe_alloc(); if (!pipe) { res = ENOMEM; goto out_err; } idesc_pipe_init(&pipe->read_desc, pipe, FS_MAY_READ); idesc_pipe_init(&pipe->write_desc, pipe, FS_MAY_WRITE); pipefd[0] = idesc_table_add(it, &pipe->read_desc.idesc, flags); pipefd[1] = idesc_table_add(it, &pipe->write_desc.idesc, flags); if (pipefd[0] < 0 || pipefd[1] < 0) { res = ENOMEM; goto out_err; } return 0; out_err: if (pipefd[1] >= 0) { idesc_table_del(it, pipefd[1]); } if (pipefd[0] >= 0) { idesc_table_del(it, pipefd[0]); } if (pipe) { pipe_free(pipe); } SET_ERRNO(res); return -1; }
static int pipe_close(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct pipe_dev_s *dev = inode->i_private; int ret; DEBUGASSERT(dev); /* Perform common close operations */ ret = pipecommon_close(filep); if (ret == 0 && dev->d_refs == 0) { /* Release the pipe when there are no further open references to it. */ pipe_free(dev->d_pipeno); } return ret; }
void net_loopback_free(net_loopback_t pair) { pipe_free(pair->pipe); free(pair); return; }
int pipe(int fd[2]) { FAR struct pipe_dev_s *dev = NULL; char devname[16]; int pipeno; int err; int ret; /* Get exclusive access to the pipe allocation data */ ret = sem_wait(&g_pipesem); if (ret < 0) { /* sem_wait() will have already set errno */ return ERROR; } /* Allocate a minor number for the pipe device */ pipeno = pipe_allocate(); if (pipeno < 0) { (void)sem_post(&g_pipesem); err = -pipeno; goto errout; } /* Create a pathname to the pipe device */ sprintf(devname, "/dev/pipe%d", pipeno); /* Check if the pipe device has already been created */ if ((g_pipecreated & (1 << pipeno)) == 0) { /* No.. Allocate and initialize a new device structure instance */ dev = pipecommon_allocdev(); if (!dev) { (void)sem_post(&g_pipesem); err = ENOMEM; goto errout_with_pipe; } dev->d_pipeno = pipeno; /* Register the pipe device */ ret = register_driver(devname, &pipe_fops, 0666, (FAR void *)dev); if (ret != 0) { (void)sem_post(&g_pipesem); err = -ret; goto errout_with_dev; } /* Remember that we created this device */ g_pipecreated |= (1 << pipeno); } (void)sem_post(&g_pipesem); /* Get a write file descriptor */ fd[1] = open(devname, O_WRONLY); if (fd[1] < 0) { err = -fd[1]; goto errout_with_driver; } /* Get a read file descriptor */ fd[0] = open(devname, O_RDONLY); if (fd[0] < 0) { err = -fd[0]; goto errout_with_wrfd; } return OK; errout_with_wrfd: close(fd[1]); errout_with_driver: unregister_driver(devname); errout_with_dev: if (dev) { pipecommon_freedev(dev); } errout_with_pipe: pipe_free(pipeno); errout: set_errno(err); return ERROR; }
wtp_handle_t* wtp_alloc(const char* device, wtp_aslan_msg_cb msg_cb) { if ((!device) || (!msg_cb)) { errno = EINVAL; return NULL; } int ret = -1; wtp_handle_t *handle = calloc(1, sizeof(wtp_handle_t)); if (!handle) { errno = ENOMEM; return NULL; } handle->wtp_state = WTP_STATE_NONE; handle->msg_cb = msg_cb; //for testing purposes only char hds_ip[] = "192.168.1.10"; handle->hds_port = ASLAN_PROTOCOL_PORT; handle->hello_interval_seconds = 5; /* UDP socket */ int s = -1; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { free(handle); return NULL; } handle->udp_socket = s; if (pthread_mutex_init(&handle->hello_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->udp_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->ack_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->sta_mutex, NULL) != 0) { free(handle); return NULL; } if (pthread_mutex_init(&handle->monitor_mutex, NULL) != 0) { free(handle); return NULL; } handle->wtp_sta_hashmap = NULL; /* HDS parameters */ handle->hds_inet_addr.sin_family = AF_INET; if (!inet_aton(hds_ip, (struct in_addr*) &(handle->hds_inet_addr.sin_addr.s_addr))) { errno = EINVAL; close_wtp(handle); return NULL; } handle->hds_ip = ntohl(handle->hds_inet_addr.sin_addr.s_addr); /* interface name */ strncpy(handle->device, device, IFNAMSIZ - 1); /* interface IP */ struct ifreq ifr; ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); if (ioctl(handle->udp_socket, SIOCGIFADDR, &ifr) == -1) { close_wtp(handle); return NULL; } handle->local_ip = ntohl(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr); /* HDS sockaddr_in structure */ handle->hds_inet_addr.sin_addr.s_addr = htonl(handle->hds_ip); handle->hds_inet_addr.sin_family = AF_INET; handle->hds_inet_addr.sin_port = htons(handle->hds_port); /* UDP socket local port */ struct sockaddr_in address; memset((char*) &address, 0, sizeof(address)); address.sin_addr.s_addr = htonl(INADDR_ANY); address.sin_port = 0; address.sin_family = AF_INET; bind(handle->udp_socket, (struct sockaddr*) &address, sizeof(address)); struct sockaddr_in sin = {0}; socklen_t len = sizeof(sin); if (getsockname(handle->udp_socket, (struct sockaddr*)&sin, &len) == -1) { close_wtp(handle); return NULL; } handle->local_port = ntohs(sin.sin_port); wpa_printf(MSG_INFO, "INFO: UDP socket for ASLAN messages created, listening on port: %d\n", handle->local_port); /* create FIFO pipe producers and consumers */ pipe_t* recv_pipe = pipe_new(sizeof(aslan_msg_t *), 100); handle->msg_recv_producer = pipe_producer_new(recv_pipe); handle->msg_recv_consumer = pipe_consumer_new(recv_pipe); pipe_free(recv_pipe); pipe_t* send_pipe = pipe_new(sizeof(aslan_msg_t *), 100); handle->msg_send_producer = pipe_producer_new(send_pipe); handle->msg_send_consumer = pipe_consumer_new(send_pipe); pipe_free(send_pipe); /* start receiving thread for ASLAN messages */ if (pthread_create(&(handle->receive_thread), NULL, receive_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: receiving thread for ASLAN messages created\n"); /* start processing thread for ASLAN messages */ if (pthread_create(&(handle->process_thread), NULL, process_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: processing thread for ASLAN messages created\n"); /* start sending thread for ASLAN messages */ if (pthread_create(&(handle->send_thread), NULL, send_msg_thread, (void*)handle) != 0) { errno = ENOMEM; close_wtp(handle); return NULL; } wpa_printf(MSG_INFO, "DEBUG: sending thread for ASLAN messages created\n"); /* obtain HDS MAC address by a Hello message */ if (wtp_send_hello_msg(handle) == -1) { close_wtp(handle); return NULL; } /* Check ARP cache */ if (handle->local_ip != handle->hds_ip) { struct arpreq areq; memset(&areq, 0, sizeof(areq)); struct sockaddr_in* sockaddr = NULL; sockaddr = (struct sockaddr_in*) &(areq.arp_pa); sockaddr->sin_family = AF_INET; sockaddr->sin_addr.s_addr = htonl(handle->hds_ip); sockaddr = (struct sockaddr_in*) &(areq.arp_ha); sockaddr->sin_family = ARPHRD_ETHER; strncpy(areq.arp_dev, device, IFNAMSIZ - 1); int i = 0; unsigned char mac_loopback[] = {0, 0, 0, 0, 0, 0}; ioctl(s, SIOCGARP, (caddr_t) &areq); while ((i < 5) && (mac_cmp(areq.arp_ha.sa_data, mac_loopback))) { i++; sleep(1); ioctl(s, SIOCGARP, (caddr_t) &areq); } memcpy(handle->hds_mac, areq.arp_ha.sa_data, 6); if (mac_cmp(areq.arp_ha.sa_data, mac_loopback)) wpa_printf(MSG_WARNING, "WARNING: HDS MAC address obtaining failed\n"); else wpa_printf(MSG_INFO, "INFO: HDS MAC address found: "MACSTR"\n", MAC2STR(handle->hds_mac)); } else wpa_printf(MSG_INFO, "INFO: WTP started at loopback\n"); return handle; }
static void pipeDevice_doCommand( PipeDevice* dev, uint32_t command ) { Pipe** lookup = pipe_list_findp_channel(&dev->pipes, dev->channel); Pipe* pipe = *lookup; CPUOldState* env = cpu_single_env; /* Check that we're referring a known pipe channel */ if (command != PIPE_CMD_OPEN && pipe == NULL) { dev->status = PIPE_ERROR_INVAL; return; } /* If the pipe is closed by the host, return an error */ if (pipe != NULL && pipe->closed && command != PIPE_CMD_CLOSE) { dev->status = PIPE_ERROR_IO; return; } switch (command) { case PIPE_CMD_OPEN: DD("%s: CMD_OPEN channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel); if (pipe != NULL) { dev->status = PIPE_ERROR_INVAL; break; } pipe = pipe_new(dev->channel, dev); pipe->next = dev->pipes; dev->pipes = pipe; dev->status = 0; break; case PIPE_CMD_CLOSE: DD("%s: CMD_CLOSE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel); /* Remove from device's lists */ *lookup = pipe->next; pipe->next = NULL; pipe_list_remove_waked(&dev->signaled_pipes, pipe); pipe_free(pipe); break; case PIPE_CMD_POLL: dev->status = pipe->funcs->poll(pipe->opaque); DD("%s: CMD_POLL > status=%d", __FUNCTION__, dev->status); break; case PIPE_CMD_READ_BUFFER: { /* Translate virtual address into physical one, into emulator memory. */ GoldfishPipeBuffer buffer; target_ulong address = dev->address; target_ulong page = address & TARGET_PAGE_MASK; hwaddr phys; phys = safe_get_phys_page_debug(ENV_GET_CPU(env), page); #ifdef TARGET_X86_64 phys = phys & TARGET_PTE_MASK; #endif buffer.data = qemu_get_ram_ptr(phys) + (address - page); buffer.size = dev->size; dev->status = pipe->funcs->recvBuffers(pipe->opaque, &buffer, 1); extern int matchMeInPidTid(CPUArchState *); extern int getMeContextId(CPUArchState *); if(matchMeInPidTid(env)) { printf("%d %s: CMD_READ_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", getMeContextId(env), __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); } DD("%s: CMD_READ_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); break; } case PIPE_CMD_WRITE_BUFFER: { /* Translate virtual address into physical one, into emulator memory. */ GoldfishPipeBuffer buffer; target_ulong address = dev->address; target_ulong page = address & TARGET_PAGE_MASK; hwaddr phys; phys = safe_get_phys_page_debug(ENV_GET_CPU(env), page); #ifdef TARGET_X86_64 phys = phys & TARGET_PTE_MASK; #endif buffer.data = qemu_get_ram_ptr(phys) + (address - page); buffer.size = dev->size; dev->status = pipe->funcs->sendBuffers(pipe->opaque, &buffer, 1); extern int matchMeInPidTid(CPUArchState *); extern int getMeContextId(CPUArchState *); if(matchMeInPidTid(env)) { printf("%d %s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", getMeContextId(env), __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); } DD("%s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); break; } case PIPE_CMD_WAKE_ON_READ: DD("%s: CMD_WAKE_ON_READ channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel); if ((pipe->wanted & PIPE_WAKE_READ) == 0) { pipe->wanted |= PIPE_WAKE_READ; pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); } dev->status = 0; break; case PIPE_CMD_WAKE_ON_WRITE: DD("%s: CMD_WAKE_ON_WRITE channel=0x%llx", __FUNCTION__, (unsigned long long)dev->channel); if ((pipe->wanted & PIPE_WAKE_WRITE) == 0) { pipe->wanted |= PIPE_WAKE_WRITE; pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); } dev->status = 0; break; default: D("%s: command=%d (0x%x)\n", __FUNCTION__, command, command); } }
static void pipeDevice_doCommand( PipeDevice* dev, uint32_t command ) { Pipe** lookup = pipe_list_findp_channel(&dev->pipes, dev->channel); Pipe* pipe = *lookup; CPUState* env = cpu_single_env; if (command != PIPE_CMD_OPEN && pipe == NULL) { dev->status = PIPE_ERROR_INVAL; return; } if (pipe != NULL && pipe->closed && command != PIPE_CMD_CLOSE) { dev->status = PIPE_ERROR_IO; return; } switch (command) { case PIPE_CMD_OPEN: DD("%s: CMD_OPEN channel=0x%x", __FUNCTION__, dev->channel); if (pipe != NULL) { dev->status = PIPE_ERROR_INVAL; break; } pipe = pipe_new(dev->channel, dev); pipe->next = dev->pipes; dev->pipes = pipe; dev->status = 0; break; case PIPE_CMD_CLOSE: DD("%s: CMD_CLOSE channel=0x%x", __FUNCTION__, dev->channel); *lookup = pipe->next; pipe->next = NULL; pipe_list_remove_waked(&dev->signaled_pipes, pipe); pipe_free(pipe); break; case PIPE_CMD_POLL: dev->status = pipe->funcs->poll(pipe->opaque); DD("%s: CMD_POLL > status=%d", __FUNCTION__, dev->status); break; case PIPE_CMD_READ_BUFFER: { GoldfishPipeBuffer buffer; uint32_t address = dev->address; uint32_t page = address & TARGET_PAGE_MASK; target_phys_addr_t phys; phys = safe_get_phys_page_debug(env, page); buffer.data = qemu_get_ram_ptr(phys) + (address - page); buffer.size = dev->size; dev->status = pipe->funcs->recvBuffers(pipe->opaque, &buffer, 1); DD("%s: CMD_READ_BUFFER channel=0x%x address=0x%08x size=%d > status=%d", __FUNCTION__, dev->channel, dev->address, dev->size, dev->status); break; } case PIPE_CMD_WRITE_BUFFER: { GoldfishPipeBuffer buffer; uint32_t address = dev->address; uint32_t page = address & TARGET_PAGE_MASK; target_phys_addr_t phys; phys = safe_get_phys_page_debug(env, page); buffer.data = qemu_get_ram_ptr(phys) + (address - page); buffer.size = dev->size; dev->status = pipe->funcs->sendBuffers(pipe->opaque, &buffer, 1); DD("%s: CMD_WRITE_BUFFER channel=0x%x address=0x%08x size=%d > status=%d", __FUNCTION__, dev->channel, dev->address, dev->size, dev->status); break; } case PIPE_CMD_WAKE_ON_READ: DD("%s: CMD_WAKE_ON_READ channel=0x%x", __FUNCTION__, dev->channel); if ((pipe->wanted & PIPE_WAKE_READ) == 0) { pipe->wanted |= PIPE_WAKE_READ; pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); } dev->status = 0; break; case PIPE_CMD_WAKE_ON_WRITE: DD("%s: CMD_WAKE_ON_WRITE channel=0x%x", __FUNCTION__, dev->channel); if ((pipe->wanted & PIPE_WAKE_WRITE) == 0) { pipe->wanted |= PIPE_WAKE_WRITE; pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); } dev->status = 0; break; default: D("%s: command=%d (0x%x)\n", __FUNCTION__, command, command); } }