static void control (SB16State *s, int hold) { int dma = s->use_hdma ? s->hdma : s->dma; s->dma_running = hold; ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma); if (hold) { DMA_hold_DREQ (dma); AUD_set_active_out (s->voice, 1); } else { DMA_release_DREQ (dma); AUD_set_active_out (s->voice, 0); } }
static int dsound_run_in (HWVoiceIn *hw) { int err; HRESULT hr; DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; int live, len, dead; DWORD blen1, blen2; DWORD len1, len2; DWORD decr; DWORD cpos, rpos; LPVOID p1, p2; int hwshift; dsound *s = ds->s; if (!dscb) { dolog ("Attempt to run without capture buffer\n"); return 0; } hwshift = hw->info.shift; live = audio_pcm_hw_get_live_in (hw); dead = hw->samples - live; if (!dead) { return 0; } hr = IDirectSoundCaptureBuffer_GetCurrentPosition ( dscb, &cpos, ds->first_time ? &rpos : NULL ); if (FAILED (hr)) { dsound_logerr (hr, "Could not get capture buffer position\n"); return 0; } if (ds->first_time) { ds->first_time = 0; if (rpos & hw->info.align) { ldebug ("warning: Misaligned capture read position %ld(%d)\n", rpos, hw->info.align); } hw->wpos = rpos >> hwshift; }
int linux_creat(struct thread *td, struct linux_creat_args *args) { char *path; int error; LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(creat)) printf(ARGS(creat, "%s, %d"), path, args->mode); #endif error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, args->mode); LFREEPATH(path); return (error); }
int linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args) { struct l_statfs linux_statfs; struct statfs bsd_statfs; int error; #ifdef DEBUG if (ldebug(fstatfs)) printf(ARGS(fstatfs, "%d, *"), args->fd); #endif error = kern_fstatfs(td, args->fd, &bsd_statfs); if (error) return error; bsd_to_linux_statfs(&bsd_statfs, &linux_statfs); return copyout(&linux_statfs, args->buf, sizeof(linux_statfs)); }
int linux_getgroups16(struct proc *p, struct linux_getgroups16_args *args) { struct ucred *cred; l_gid16_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; #ifdef DEBUG if (ldebug(getgroups16)) printf(ARGS(getgroups16, "%d, *"), args->gidsetsize); #endif cred = p->p_ucred; bsd_gidset = cred->cr_groups; bsd_gidsetsz = cred->cr_ngroups - 1; /* * cr_groups[0] holds egid. Returning the whole set * here will cause a duplicate. Exclude cr_groups[0] * to prevent that. */ if ((ngrp = args->gidsetsize) == 0) { p->p_retval[0] = bsd_gidsetsz; return (0); } if (ngrp < bsd_gidsetsz) return (EINVAL); ngrp = 0; while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } error = copyout(linux_gidset, (caddr_t)args->gidset, ngrp * sizeof(l_gid16_t)); if (error) return (error); p->p_retval[0] = ngrp; return (0); }
int linux_vfork(struct thread *td, struct linux_vfork_args *args) { int error; struct proc *p2; struct thread *td2; #ifdef DEBUG if (ldebug(vfork)) printf(ARGS(vfork, "")); #endif /* Exclude RFPPWAIT */ if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2, NULL, 0)) != 0) return (error); td->td_retval[0] = p2->p_pid; error = linux_proc_init(td, td->td_retval[0], 0); if (error) return (error); PROC_LOCK(p2); p2->p_flag |= P_PPWAIT; PROC_UNLOCK(p2); td2 = FIRST_THREAD_IN_PROC(p2); /* * Make this runnable after we are finished with it. */ thread_lock(td2); TD_SET_CAN_RUN(td2); sched_add(td2, SRQ_BORING); thread_unlock(td2); /* wait for the children to exit, ie. emulate vfork */ PROC_LOCK(p2); while (p2->p_flag & P_PPWAIT) cv_wait(&p2->p_pwait, &p2->p_mtx); PROC_UNLOCK(p2); return (0); }
int linux_fstat64(struct thread *td, struct linux_fstat64_args *args) { struct stat buf; int error; #ifdef DEBUG if (ldebug(fstat64)) printf(ARGS(fstat64, "%d, *"), args->fd); #endif error = kern_fstat(td, args->fd, &buf); translate_fd_major_minor(td, args->fd, &buf); if (!error) error = stat64_copyout(&buf, args->statbuf); return (error); }
int linux_openat(struct thread *td, struct linux_openat_args *args) { char *path; int dfd; dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; if (args->flags & LINUX_O_CREAT) LCONVPATH_AT(td, args->filename, &path, 1, dfd); else LCONVPATH_AT(td, args->filename, &path, 0, dfd); #ifdef DEBUG if (ldebug(openat)) printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd, path, args->flags, args->mode); #endif return (linux_common_open(td, dfd, path, args->flags, args->mode)); }
int linux_open(struct thread *td, struct linux_open_args *args) { char *path; if (args->flags & LINUX_O_CREAT) LCONVPATHCREAT(td, args->path, &path); else LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(open)) printf(ARGS(open, "%s, 0x%x, 0x%x"), path, args->flags, args->mode); #endif return (linux_common_open(td, AT_FDCWD, path, args->flags, args->mode)); }
static void control (SB16State *s, int hold) { int dma = s->use_hdma ? s->hdma : s->dma; IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma; IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma); s->dma_running = hold; ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma); if (hold) { k->hold_DREQ(isa_dma, dma); AUD_set_active_out (s->voice, 1); } else { k->release_DREQ(isa_dma, dma); AUD_set_active_out (s->voice, 0); } }
static void command (SB16State *s, uint8_t cmd) { ldebug ("command %#x\n", cmd); if (cmd > 0xaf && cmd < 0xd0) { if (cmd & 8) { dolog ("ADC not yet supported (command %#x)\n", cmd); } switch (cmd >> 4) { case 11: case 12: break; default: dolog ("%#x wrong bits\n", cmd); } s->needed_bytes = 3; } else {
static int ipc_reap_events(void) { int len, events = 0; merlin_event *pkt; node_log_event_count(&ipc, 0); len = node_recv(&ipc); if (len < 0) return len; while ((pkt = node_get_event(&ipc))) { events++; handle_ipc_event(pkt); } ldebug("Read %d events in %s from %s", events, human_bytes(len), ipc.name); return 0; }
int linux_lchown16(struct proc *p, struct linux_lchown16_args *args) { struct lchown_args bsd; caddr_t sg; sg = stackgap_init(); CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG if (ldebug(lchown16)) printf(ARGS(lchown16, "%s, %d, %d"), args->path, args->uid, args->gid); #endif bsd.path = args->path; bsd.uid = CAST_NOCHG(args->uid); bsd.gid = CAST_NOCHG(args->gid); return (lchown(p, &bsd)); }
static void command (SB16State *s, uint8_t cmd) { ldebug ("command %#x\n", cmd); if (cmd > 0xaf && cmd < 0xd0) { if (cmd & 8) { qemu_log_mask(LOG_UNIMP, "ADC not yet supported (command %#x)\n", cmd); } switch (cmd >> 4) { case 11: case 12: break; default: qemu_log_mask(LOG_GUEST_ERROR, "%#x wrong bits\n", cmd); } s->needed_bytes = 3; } else {
int linux_lstat64(struct thread *td, struct linux_lstat64_args *args) { struct stat sb; char *filename; int error; LCONVPATHEXIST(td, args->filename, &filename); #ifdef DEBUG if (ldebug(lstat64)) printf(ARGS(lstat64, "%s, *"), args->filename); #endif error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb); LFREEPATH(filename); if (error) return (error); return (stat64_copyout(&sb, args->statbuf)); }
int linux_newlstat(struct thread *td, struct linux_newlstat_args *args) { struct stat sb; char *path; int error; LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(newlstat)) printf(ARGS(newlstat, "%s, *"), path); #endif error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb); LFREEPATH(path); if (error) return (error); return (newstat_copyout(&sb, args->buf)); }
int linux_lstat(struct thread *td, struct linux_lstat_args *args) { struct stat buf; char *path; int error; LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(lstat)) printf(ARGS(lstat, "%s, *"), path); #endif error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf); if (error) { LFREEPATH(path); return (error); } LFREEPATH(path); return(stat_copyout(&buf, args->up)); }
int linux_statfs(struct thread *td, struct linux_statfs_args *args) { struct l_statfs linux_statfs; struct statfs bsd_statfs; char *path; int error; LCONVPATHEXIST(td, args->path, &path); #ifdef DEBUG if (ldebug(statfs)) printf(ARGS(statfs, "%s, *"), path); #endif error = kern_statfs(td, path, UIO_SYSSPACE, &bsd_statfs); LFREEPATH(path); if (error) return (error); bsd_to_linux_statfs(&bsd_statfs, &linux_statfs); return copyout(&linux_statfs, args->buf, sizeof(linux_statfs)); }
int linux_execve(struct thread *td, struct linux_execve_args *args) { struct image_args eargs; char *newpath; int error; LCONVPATHEXIST(td, args->path, &newpath); #ifdef DEBUG if (ldebug(execve)) printf(ARGS(execve, "%s"), newpath); #endif error = exec_copyin_args(&eargs, newpath, UIO_SYSSPACE, args->argp, args->envp); free(newpath, M_TEMP); if (error == 0) error = linux_common_execve(td, &eargs); return (error); }
int linux_signal(struct thread *td, struct linux_signal_args *args) { l_sigaction_t nsa, osa; int error; #ifdef DEBUG if (ldebug(signal)) printf(ARGS(signal, "%d, %p"), args->sig, (void *)(uintptr_t)args->handler); #endif nsa.lsa_handler = args->handler; nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; LINUX_SIGEMPTYSET(nsa.lsa_mask); error = linux_do_sigaction(td, args->sig, &nsa, &osa); td->td_retval[0] = (int)(intptr_t)osa.lsa_handler; return (error); }
int linux_lseek(struct thread *td, struct linux_lseek_args *args) { struct lseek_args /* { int fd; int pad; off_t offset; int whence; } */ tmp_args; int error; #ifdef DEBUG if (ldebug(lseek)) printf(ARGS(lseek, "%d, %ld, %d"), args->fdes, (long)args->off, args->whence); #endif tmp_args.fd = args->fdes; tmp_args.offset = (off_t)args->off; tmp_args.whence = args->whence; error = sys_lseek(td, &tmp_args); return (error); }
/* * Reads input from a particular node and ships it off to * the "handle_network_event()" routine up above */ static int net_input(merlin_node *node) { merlin_event *pkt; int len, events = 0; errno = 0; len = node_recv(node); if (len < 0) { return 0; } node->stats.bytes.read += len; node->last_recv = time(NULL); while ((pkt = node_get_event(node))) { events++; handle_network_event(node, pkt); } ldebug("Read %d events in %s from %s node %s", events, human_bytes(len), node_type(node), node->name); return events; }
static void adlib_kill_timers (AdlibState *s) { size_t i; for (i = 0; i < 2; ++i) { if (s->ticking[i]) { uint64_t delta; delta = AUD_get_elapsed_usec_out (s->voice, &s->ats); ldebug ( "delta = %f dexp = %f expired => %d\n", delta / 1000000.0, s->dexp[i] / 1000000.0, delta >= s->dexp[i] ); if (ADLIB_KILL_TIMERS || delta >= s->dexp[i]) { adlib_stop_opl_timer (s, i); AUD_init_time_stamp_out (s->voice, &s->ats); } } } }
int linux_llseek(struct thread *td, struct linux_llseek_args *args) { int error; off_t off; #ifdef DEBUG if (ldebug(llseek)) printf(ARGS(llseek, "%d, %d:%d, %d"), args->fd, args->ohigh, args->olow, args->whence); #endif off = (args->olow) | (((off_t) args->ohigh) << 32); error = kern_lseek(td, args->fd, off, args->whence); if (error != 0) return (error); error = copyout(td->td_retval, args->res, sizeof(off_t)); if (error != 0) return (error); td->td_retval[0] = 0; return (0); }
static int linux_clone_thread(struct thread *td, struct linux_clone_args *args) { struct linux_emuldata *em; struct thread *newtd; struct proc *p; int error; #ifdef DEBUG if (ldebug(clone)) { printf(ARGS(clone, "thread: flags %x, stack %p, parent tid: %p, " "child tid: %p"), (unsigned)args->flags, args->stack, args->parent_tidptr, args->child_tidptr); } #endif LINUX_CTR4(clone_thread, "thread(%d) flags %x ptid %p ctid %p", td->td_tid, (unsigned)args->flags, args->parent_tidptr, args->child_tidptr); if (args->flags & LINUX_CLONE_PARENT_SETTID) if (args->parent_tidptr == NULL) return (EINVAL); /* Threads should be created with own stack */ if (args->stack == NULL) return (EINVAL); p = td->td_proc; #ifdef RACCT if (racct_enable) { PROC_LOCK(p); error = racct_add(p, RACCT_NTHR, 1); PROC_UNLOCK(p); if (error != 0) return (EPROCLIM); } #endif /* Initialize our td */ error = kern_thr_alloc(p, 0, &newtd); if (error) goto fail; cpu_copy_thread(newtd, td); bzero(&newtd->td_startzero, __rangeof(struct thread, td_startzero, td_endzero)); bcopy(&td->td_startcopy, &newtd->td_startcopy, __rangeof(struct thread, td_startcopy, td_endcopy)); newtd->td_proc = p; thread_cow_get(newtd, td); /* create the emuldata */ linux_proc_init(td, newtd, args->flags); em = em_find(newtd); KASSERT(em != NULL, ("clone_thread: emuldata not found.\n")); if (args->flags & LINUX_CLONE_SETTLS) linux_set_cloned_tls(newtd, args->tls); if (args->flags & LINUX_CLONE_CHILD_SETTID) em->child_set_tid = args->child_tidptr; else em->child_set_tid = NULL; if (args->flags & LINUX_CLONE_CHILD_CLEARTID) em->child_clear_tid = args->child_tidptr; else em->child_clear_tid = NULL; cpu_thread_clean(newtd); linux_set_upcall_kse(newtd, PTROUT(args->stack)); PROC_LOCK(p); p->p_flag |= P_HADTHREADS; bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name)); if (args->flags & LINUX_CLONE_PARENT) thread_link(newtd, p->p_pptr); else thread_link(newtd, p); thread_lock(td); /* let the scheduler know about these things. */ sched_fork_thread(td, newtd); thread_unlock(td); if (P_SHOULDSTOP(p)) newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; PROC_UNLOCK(p); tidhash_add(newtd); #ifdef DEBUG if (ldebug(clone)) printf(ARGS(clone, "successful clone to %d, stack %p"), (int)newtd->td_tid, args->stack); #endif LINUX_CTR2(clone_thread, "thread(%d) successful clone to %d", td->td_tid, newtd->td_tid); if (args->flags & LINUX_CLONE_PARENT_SETTID) { error = copyout(&newtd->td_tid, args->parent_tidptr, sizeof(newtd->td_tid)); if (error) printf(LMSG("clone_thread: copyout failed!")); } /* * Make this runnable after we are finished with it. */ thread_lock(newtd); TD_SET_CAN_RUN(newtd); sched_add(newtd, SRQ_BORING); thread_unlock(newtd); td->td_retval[0] = newtd->td_tid; return (0); fail: #ifdef RACCT if (racct_enable) { PROC_LOCK(p); racct_sub(p, RACCT_NTHR, 1); PROC_UNLOCK(p); } #endif return (error); }
static int linux_clone_proc(struct thread *td, struct linux_clone_args *args) { struct fork_req fr; int error, ff = RFPROC | RFSTOPPED; struct proc *p2; struct thread *td2; int exit_signal; struct linux_emuldata *em; #ifdef DEBUG if (ldebug(clone)) { printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, " "child tid: %p"), (unsigned)args->flags, args->stack, args->parent_tidptr, args->child_tidptr); } #endif exit_signal = args->flags & 0x000000ff; if (LINUX_SIG_VALID(exit_signal)) { exit_signal = linux_to_bsd_signal(exit_signal); } else if (exit_signal != 0) return (EINVAL); if (args->flags & LINUX_CLONE_VM) ff |= RFMEM; if (args->flags & LINUX_CLONE_SIGHAND) ff |= RFSIGSHARE; /* * XXX: In Linux, sharing of fs info (chroot/cwd/umask) * and open files is independent. In FreeBSD, its in one * structure but in reality it does not cause any problems * because both of these flags are usually set together. */ if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS))) ff |= RFFDG; if (args->flags & LINUX_CLONE_PARENT_SETTID) if (args->parent_tidptr == NULL) return (EINVAL); if (args->flags & LINUX_CLONE_VFORK) ff |= RFPPWAIT; bzero(&fr, sizeof(fr)); fr.fr_flags = ff; fr.fr_procp = &p2; error = fork1(td, &fr); if (error) return (error); td2 = FIRST_THREAD_IN_PROC(p2); /* create the emuldata */ linux_proc_init(td, td2, args->flags); em = em_find(td2); KASSERT(em != NULL, ("clone_proc: emuldata not found.\n")); if (args->flags & LINUX_CLONE_CHILD_SETTID) em->child_set_tid = args->child_tidptr; else em->child_set_tid = NULL; if (args->flags & LINUX_CLONE_CHILD_CLEARTID) em->child_clear_tid = args->child_tidptr; else em->child_clear_tid = NULL; if (args->flags & LINUX_CLONE_PARENT_SETTID) { error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid)); if (error) printf(LMSG("copyout failed!")); } PROC_LOCK(p2); p2->p_sigparent = exit_signal; PROC_UNLOCK(p2); /* * In a case of stack = NULL, we are supposed to COW calling process * stack. This is what normal fork() does, so we just keep tf_rsp arg * intact. */ linux_set_upcall_kse(td2, PTROUT(args->stack)); if (args->flags & LINUX_CLONE_SETTLS) linux_set_cloned_tls(td2, args->tls); /* * If CLONE_PARENT is set, then the parent of the new process will be * the same as that of the calling process. */ if (args->flags & LINUX_CLONE_PARENT) { sx_xlock(&proctree_lock); PROC_LOCK(p2); proc_reparent(p2, td->td_proc->p_pptr); PROC_UNLOCK(p2); sx_xunlock(&proctree_lock); } #ifdef DEBUG if (ldebug(clone)) printf(LMSG("clone: successful rfork to %d, " "stack %p sig = %d"), (int)p2->p_pid, args->stack, exit_signal); #endif /* * Make this runnable after we are finished with it. */ thread_lock(td2); TD_SET_CAN_RUN(td2); sched_add(td2, SRQ_BORING); thread_unlock(td2); td->td_retval[0] = p2->p_pid; return (0); }
/* * executed when a node comes online and reports itself as * being active. This is where we run the configuration sync * if any is configured * * Note that the 'push' and 'fetch' options in the configuration * are simply guidance names. One could configure them in reverse * if one wanted, or make them boil noodles for the IT staff or * paint a skateboard blue for all Merlin cares. It will just * assume that things work out just fine so long as the config * is (somewhat) in sync. */ void csync_node_active(merlin_node *node) { int val = 0; merlin_confsync *cs = NULL; merlin_child *child = NULL; ldebug("CSYNC: %s: Checking...", node->name); /* bail early if we have no push/fetch configuration */ cs = node->csync ? node->csync : &csync; if (!cs->push.cmd && !cs->fetch.cmd) { ldebug("CSYNC: %s: No config sync configured.", node->name); return; } val = csync_config_cmp(node); if (!val) return; /* * The most common setup is that configuration is done on a master * node and then pushed to the pollers, so if a master has older * config than we do, a node-specific "push" command is required * to make us push to that master. * This is to prevent normal setup behaviour from engaging in * pingpong action with config-files when config-files take more * than 1 second to generate */ if (val < 0 && node->type == MODE_MASTER && cs == &csync) { ldebug("CSYNC: Refusing to run global sync to a master node"); return; } if (val < 0) { if (cs->push.cmd) { child = &cs->push; ldebug("CSYNC: We'll try to push"); } else { ldebug("CSYNC: Should have pushed, but push not configured for %s", node->name); } } else if (val > 0) { if (cs->fetch.cmd) { child = &cs->fetch; ldebug("CSYNC: We'll try to fetch"); } else { ldebug("CSYNC: Should have fetched, but fetch not configured for %s", node->name); } } if (!child) { ldebug("CSYNC: No action required for %s", node->name); return; } if (child->pid) { ldebug("CSYNC: '%s' already running for %s, or globally", child->cmd, node->name); return; } ldebug("CSYNC: node %s; val: %d; sync-command: [%s]", node->name, val, child->cmd); run_program("csync", child->cmd, &child->pid); if (child->pid > 0) { ldebug("CSYNC: command has pid %d", child->pid); } else { child->pid = 0; } }
static int linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode) { cap_rights_t rights; struct proc *p = td->td_proc; struct file *fp; int fd; int bsd_flags, error; bsd_flags = 0; switch (l_flags & LINUX_O_ACCMODE) { case LINUX_O_WRONLY: bsd_flags |= O_WRONLY; break; case LINUX_O_RDWR: bsd_flags |= O_RDWR; break; default: bsd_flags |= O_RDONLY; } if (l_flags & LINUX_O_NDELAY) bsd_flags |= O_NONBLOCK; if (l_flags & LINUX_O_APPEND) bsd_flags |= O_APPEND; if (l_flags & LINUX_O_SYNC) bsd_flags |= O_FSYNC; if (l_flags & LINUX_O_NONBLOCK) bsd_flags |= O_NONBLOCK; if (l_flags & LINUX_FASYNC) bsd_flags |= O_ASYNC; if (l_flags & LINUX_O_CREAT) bsd_flags |= O_CREAT; if (l_flags & LINUX_O_TRUNC) bsd_flags |= O_TRUNC; if (l_flags & LINUX_O_EXCL) bsd_flags |= O_EXCL; if (l_flags & LINUX_O_NOCTTY) bsd_flags |= O_NOCTTY; if (l_flags & LINUX_O_DIRECT) bsd_flags |= O_DIRECT; if (l_flags & LINUX_O_NOFOLLOW) bsd_flags |= O_NOFOLLOW; if (l_flags & LINUX_O_DIRECTORY) bsd_flags |= O_DIRECTORY; /* XXX LINUX_O_NOATIME: unable to be easily implemented. */ error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode); if (error != 0) goto done; if (bsd_flags & O_NOCTTY) goto done; /* * XXX In between kern_open() and fget(), another process * having the same filedesc could use that fd without * checking below. */ fd = td->td_retval[0]; if (fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp) == 0) { if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); goto done; } sx_slock(&proctree_lock); PROC_LOCK(p); if (SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { PROC_UNLOCK(p); sx_sunlock(&proctree_lock); /* XXXPJD: Verify if TIOCSCTTY is allowed. */ (void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, td); } else { PROC_UNLOCK(p); sx_sunlock(&proctree_lock); } fdrop(fp, td); } done: #ifdef DEBUG if (ldebug(open)) printf(LMSG("open returns error %d"), error); #endif LFREEPATH(path); return (error); }
static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) { s->use_hdma = cmd < 0xc0; s->fifo = (cmd >> 1) & 1; s->dma_auto = (cmd >> 2) & 1; s->fmt_signed = (d0 >> 4) & 1; s->fmt_stereo = (d0 >> 5) & 1; switch (cmd >> 4) { case 11: s->fmt_bits = 16; break; case 12: s->fmt_bits = 8; break; } if (-1 != s->time_const) { #if 1 int tmp = 256 - s->time_const; s->freq = (1000000 + (tmp / 2)) / tmp; #else /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */ s->freq = 1000000 / ((255 - s->time_const)); #endif s->time_const = -1; } s->block_size = dma_len + 1; s->block_size <<= (s->fmt_bits == 16); if (!s->dma_auto) { /* It is clear that for DOOM and auto-init this value shouldn't take stereo into account, while Miles Sound Systems setsound.exe with single transfer mode wouldn't work without it wonders of SB16 yet again */ s->block_size <<= s->fmt_stereo; } ldebug ("freq %d, stereo %d, sign %d, bits %d, " "dma %d, auto %d, fifo %d, high %d\n", s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, s->block_size, s->dma_auto, s->fifo, s->highspeed); if (16 == s->fmt_bits) { if (s->fmt_signed) { s->fmt = AUD_FMT_S16; } else { s->fmt = AUD_FMT_U16; } } else { if (s->fmt_signed) { s->fmt = AUD_FMT_S8; } else { s->fmt = AUD_FMT_U8; } } s->left_till_irq = s->block_size; s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); s->highspeed = 0; s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; if (s->block_size & s->align) { dolog ("warning: misaligned block size %d, alignment %d\n", s->block_size, s->align + 1); } if (s->freq) { struct audsettings as; s->audio_free = 0; as.freq = s->freq; as.nchannels = 1 << s->fmt_stereo; as.fmt = s->fmt; as.endianness = 0; s->voice = AUD_open_out ( &s->card, s->voice, "sb16", s, SB_audio_callback, &as ); } control (s, 1); speaker (s, 1); }
// _FrameGenerator int32 VideoProducer::_FrameGenerator() { bool forceSendingBuffer = true; bigtime_t lastFrameSentAt = 0; bool running = true; while (running) { ldebug("VideoProducer: loop: %Ld\n", fFrame); // lock the node manager status_t err = fManager->LockWithTimeout(10000); bool ignoreEvent = false; // Data to be retrieved from the node manager. bigtime_t performanceTime = 0; bigtime_t nextPerformanceTime = 0; bigtime_t waitUntil = 0; bigtime_t nextWaitUntil = 0; bigtime_t maxRenderTime = 0; int32 playingDirection = 0; int64 playlistFrame = 0; switch (err) { case B_OK: { ldebug("VideoProducer: node manager successfully locked\n"); // get the times for the current and the next frame performanceTime = fManager->TimeForFrame(fFrame); nextPerformanceTime = fManager->TimeForFrame(fFrame + 1); maxRenderTime = min_c(bigtime_t(33334 * 0.9), max_c(fSupplier->ProcessingLatency(), maxRenderTime)); waitUntil = TimeSource()->RealTimeFor(fPerformanceTimeBase + performanceTime, 0) - maxRenderTime; nextWaitUntil = TimeSource()->RealTimeFor(fPerformanceTimeBase + nextPerformanceTime, 0) - maxRenderTime; // get playing direction and playlist frame for the current frame bool newPlayingState; playlistFrame = fManager->PlaylistFrameAtFrame(fFrame, playingDirection, newPlayingState); ldebug("VideoProducer: performance time: %Ld, playlist frame: %Ld\n", performanceTime, playlistFrame); forceSendingBuffer |= newPlayingState; fManager->SetCurrentVideoTime(nextPerformanceTime); fManager->Unlock(); break; } case B_TIMED_OUT: ldebug("VideoProducer: Couldn't lock the node manager.\n"); ignoreEvent = true; waitUntil = system_time() - 1; break; default: printf("Couldn't lock the node manager. Terminating video producer " "frame generator thread.\n"); ignoreEvent = true; waitUntil = system_time() - 1; running = false; break; } // Force sending a frame, if the last one has been sent more than // one second ago. if (lastFrameSentAt + 1000000 < performanceTime) forceSendingBuffer = true; ldebug("VideoProducer: waiting (%Ld)...\n", waitUntil); // wait until... err = acquire_sem_etc(fFrameSync, 1, B_ABSOLUTE_TIMEOUT, waitUntil); // The only acceptable responses are B_OK and B_TIMED_OUT. Everything // else means the thread should quit. Deleting the semaphore, as in // VideoProducer::_HandleStop(), will trigger this behavior. switch (err) { case B_OK: ldebug("VideoProducer::_FrameGenerator - going back to sleep.\n"); break; case B_TIMED_OUT: ldebug("VideoProducer: timed out => event\n"); // Catch the cases in which the node manager could not be // locked and we therefore have no valid data to work with, // or the producer is not running or enabled. if (ignoreEvent || !fRunning || !fEnabled) { ldebug("VideoProducer: ignore event\n"); // nothing to do // Drop frame if it's at least a frame late. } else if (nextWaitUntil < system_time()) { //printf("VideoProducer: dropped frame (%ld)\n", fFrame); if (fManager->LockWithTimeout(10000) == B_OK) { fManager->FrameDropped(); fManager->Unlock(); } // next frame fFrame++; // Send buffers only, if playing, the node is running and the // output has been enabled } else if (playingDirection != 0 || forceSendingBuffer) { ldebug("VideoProducer: produce frame\n"); BAutolock _(fLock); // Fetch a buffer from the buffer group BBuffer *buffer = fUsedBufferGroup->RequestBuffer( fConnectedFormat.display.bytes_per_row * fConnectedFormat.display.line_count, 0LL); if (buffer) { // Fill out the details about this buffer. media_header *h = buffer->Header(); h->type = B_MEDIA_RAW_VIDEO; h->time_source = TimeSource()->ID(); h->size_used = fConnectedFormat.display.bytes_per_row * fConnectedFormat.display.line_count; // For a buffer originating from a device, you might // want to calculate this based on the // PerformanceTimeFor the time your buffer arrived at // the hardware (plus any applicable adjustments). h->start_time = fPerformanceTimeBase + performanceTime; h->file_pos = 0; h->orig_size = 0; h->data_offset = 0; h->u.raw_video.field_gamma = 1.0; h->u.raw_video.field_sequence = fFrame; h->u.raw_video.field_number = 0; h->u.raw_video.pulldown_number = 0; h->u.raw_video.first_active_line = 1; h->u.raw_video.line_count = fConnectedFormat.display.line_count; // Fill in a frame media_format mf; mf.type = B_MEDIA_RAW_VIDEO; mf.u.raw_video = fConnectedFormat; ldebug("VideoProducer: frame: %Ld, playlistFrame: %Ld\n", fFrame, playlistFrame); bool forceOrWasCached = forceSendingBuffer; // if (fManager->LockWithTimeout(5000) == B_OK) { // we need to lock the manager, or our // fSupplier might work on bad data err = fSupplier->FillBuffer(playlistFrame, buffer->Data(), &mf, forceOrWasCached); // fManager->Unlock(); // } else { // err = B_ERROR; // } // clean the buffer if something went wrong if (err != B_OK) { memset(buffer->Data(), 0, h->size_used); err = B_OK; } // Send the buffer on down to the consumer if (!forceOrWasCached) { if (SendBuffer(buffer, fOutput.source, fOutput.destination) != B_OK) { printf("_FrameGenerator: Error sending buffer\n"); // If there is a problem sending the buffer, // or if we don't send the buffer because its // contents are the same as the last one, // return it to its buffer group. buffer->Recycle(); // we tell the supplier to delete // its caches if there was a problem sending // the buffer fSupplier->DeleteCaches(); } } else buffer->Recycle(); // Only if everything went fine we clear the flag // that forces us to send a buffer even if not // playing. if (err == B_OK) { forceSendingBuffer = false; lastFrameSentAt = performanceTime; } } else ldebug("no buffer!\n"); // next frame fFrame++; } else { ldebug("VideoProducer: not playing\n"); // next frame fFrame++; } break; default: ldebug("Couldn't acquire semaphore. Error: %s\n", strerror(err)); running = false; break; } } ldebug("VideoProducer: frame generator thread done.\n"); return B_OK; }