void omap_clock_enable(DEV_OMAP* dev, clk_enable_t clk_cfg) { int enable_rc = 0; int functional_rc = 0; /* Our idle state can be changed by the ISR so we must use a spinlock */ InterruptLock(&dev->idle_spinlock); /* Only enable clocks if they aren't enabled already */ if (dev->idle == 0) { goto done; } if (dev->clkctrl_base) { /* Enable the clock */ out32(dev->clkctrl_base, OMAP_CLKCTRL_MODMODE_ENABLE); /* Wait for the module mode to have been written */ enable_rc = poll_for_condition(dev->clkctrl_base, OMAP_CLKCTRL_MODMODE_MASK, OMAP_CLKCTRL_MODMODE_ENABLE); /* Wait for the module idle status to report "fully functional" */ functional_rc = poll_for_condition(dev->clkctrl_base, OMAP_CLKCTRL_IDLEST_MASK, OMAP_CLKCTRL_IDLEST_FUNCTIONAL); /* Re-configure clock if specified otherwise simply skip it */ if (clk_cfg != clk_enable_skip) { /* Set the idle mode to smart idle with wake up */ set_port(dev->port[OMAP_UART_SYSC], OMAP_UART_SYSC_IDLEMODE_MASK, clk_cfg); } /* Enable the CTS wakeup */ write_omap(dev->port[OMAP_UART_WER], OMAP_UART_WER_CTS_ENABLE); /* Indicate clocks are enabled */ dev->idle = 0; } done: #ifdef WINBT /* clear CTS debounce timer and OHW_PAGED flag */ if (dev->tty.un.s.spare_tmr > 0) { dev->tty.un.s.spare_tmr = 0; if (dev->tty.flags & OHW_PAGED) atomic_clr (&dev->tty.flags, OHW_PAGED); } #endif omap_uart_ctx_restore(dev); InterruptUnlock(&dev->idle_spinlock); /* Don't slog while interrupts are disabled - otherwise slogf() will re-enable interrupts */ if (enable_rc) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Failed to set module mode to 'enabled'", __FUNCTION__); } if (functional_rc) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Module failed to report 'fully functional'", __FUNCTION__); } }
void setVolume(int level) { int volume; snd_mixer_t *mixer_handle; if (snd_mixer_open (&mixer_handle, card, device) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to open mixer\n"); return; } snd_mixer_group_read(mixer_handle, &group); volume = (float)(group.max - group.min) * ( level / 100.0) + group.min; if (group.channels & SND_MIXER_CHN_MASK_FRONT_LEFT) group.volume.names.front_left = volume; if (group.channels & SND_MIXER_CHN_MASK_REAR_LEFT) group.volume.names.rear_left = volume; if (group.channels & SND_MIXER_CHN_MASK_FRONT_CENTER) group.volume.names.front_center = volume; if (group.channels & SND_MIXER_CHN_MASK_FRONT_RIGHT) group.volume.names.front_right = volume; if (group.channels & SND_MIXER_CHN_MASK_REAR_RIGHT) group.volume.names.rear_right = volume; if (group.channels & SND_MIXER_CHN_MASK_WOOFER) group.volume.names.woofer = volume; snd_mixer_group_write(mixer_handle, &group); snd_mixer_close (mixer_handle); }
void slog_tid( procfs_status *status, const char *path ) { switch (status->why) { case _DEBUG_WHY_SIGNALLED: case _DEBUG_WHY_FAULTED: slogf( _SLOG_SETCODE( _SLOGC_DUMPER, 0 ), _SLOG_INFO, "run fault pid %d tid %d signal %d code %d ip %#llx %s", (int)status->pid, (int)status->tid, (int)status->info.si_signo, (int)status->info.si_code, (uint64_t)status->ip, path ?:"" ); break; default: slogf( _SLOG_SETCODE( _SLOGC_DUMPER, 0 ), _SLOG_INFO, "run fault pid %d tid %d why %d what %d ip %#llx %s", (int)status->pid, (int)status->tid, (int)status->why, (int)status->what, (uint64_t)status->ip, path ?:"" ); break; } }
static void termination_hndlr(int sig_num) { char * pMsgTxt = "Hit with signal: %d, shutting down\n"; if(verbosity) fprintf(stderr, pMsgTxt, sig_num); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt, sig_num); input_shutdown(); }
int omap_clock_toggle_init(DEV_OMAP* dev) { if (OMAP_UART1_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART1_CLKCTRL; } else if (OMAP_UART2_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART2_CLKCTRL; } else if (OMAP_UART3_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART3_CLKCTRL; } else if (OMAP_UART4_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART4_CLKCTRL; } else if (OMAP5_UART5_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART5_CLKCTRL; } else if (OMAP5_UART6_PHYSBASE == dev->physbase) { dev->clkctrl_phys = CM_L4PER_UART6_CLKCTRL; } else { dev->clkctrl_phys = 0; dev->clkctrl_base = 0; slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Unrecognized physical address, clock toggling not enabled", __FUNCTION__); return -1; } if (dev->clkctrl_phys) { dev->clkctrl_base = mmap_device_io(4, dev->clkctrl_phys); if (dev->clkctrl_base == (uintptr_t)MAP_FAILED) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: mmap_device_io clkctrl_base: %s", __FUNCTION__, strerror(errno)); return -1; } } /* Indicate clocks are disabled by default */ dev->idle = 1; /* oband notification set to off */ dev->signal_oband_notification = 0; /* initialize UART context */ omap_uart_ctx_init(dev); return 0; }
/* Comment : Must be called before any other devi_usb... function */ void devi_usb_init() { LIST_INIT(&modList); pGlbConnection = NULL; if(EOK != pthread_mutex_init(&mod_mutex, NULL)) { char * pMsgTxt = "Error: USB stack initialization error. Driver is terminating\n"; fprintf(stderr, pMsgTxt); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt); exit(-1); } }
void omap_clock_disable(DEV_OMAP* dev) { int rc = 0; /* Our idle state can be changed by the ISR so we must use a spinlock */ InterruptLock(&dev->idle_spinlock); /* Only disable clocks if needed */ if (dev->idle == 1) { goto done; } if (dev->clkctrl_base) { /* Indicate clocks are disabled */ dev->idle = 1; /* Save UART context */ omap_uart_ctx_save(dev); /* Set the idle mode to smart idle with wake up */ write_omap(dev->port[OMAP_UART_SYSC], OMAP_UART_SYSC_IDLEMODE_SMARTWAKEUP | OMAP_UART_SYSC_ENAWAKEUP_ENABLE | OMAP_UART_SYSC_AUTOIDLE_ENABLE); /* Enable the wakeup event */ set_port(dev->port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN, OMAP_SCR_WAKEUPEN); /* Disable the clock */ out32(dev->clkctrl_base, OMAP_CLKCTRL_MODMODE_DISABLE); /* Wait for the module mode to have been written */ rc = poll_for_condition(dev->clkctrl_base, OMAP_CLKCTRL_MODMODE_MASK, OMAP_CLKCTRL_MODMODE_DISABLE); } done: InterruptUnlock(&dev->idle_spinlock); /* Don't slog while interrupts are disabled - otherwise slogf() will re-enable interrupts */ if (rc) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Failed to set module mode to 'disabled'", __FUNCTION__); } }
/* devices ( see devi_register_hid_client) */ int devi_usb_server_connect(char * serv_path_name) { int rc = EOK; usbd_funcs_t funcs = { _USBDI_NFUNCS, insertion, removal, NULL }; usbd_device_ident_t interest = { USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD, USBD_CONNECT_WILDCARD }; usbd_connect_parm_t parm = { NULL, USB_VERSION, USBD_VERSION, 0, 0, NULL, 0, &interest, &funcs, USBD_CONNECT_WAIT }; parm.path = serv_path_name; if(EOK != ( rc = usbd_connect( &parm, &pGlbConnection ) ) ) { char * pMsgTxt = "Error: cannot connect to USB server (error code = %d).\nDriver is terminating\n"; fprintf(stderr, pMsgTxt, rc); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt, rc); exit(-2); } return EOK; }
static int remove_ocb(devi_attr_t *attr, RESMGR_OCB_T *ocb) { struct _ocb_list *op; for (op = attr->ocb_list; op; op = op->next) { if (op->ocb == ocb) break; } if (op == NULL) { char * pMsgTxt = "Error: nable to remove ocb from list, not found\n"; fprintf(stderr, pMsgTxt); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt); return (-1); } /* If removing first one */ if (op->prev == NULL) { if (op->next) { attr->ocb_list = op->next; op->next->prev = NULL; } else { attr->ocb_list = NULL; } } else { if (op->next) { op->prev->next = op->next; op->next->prev = op->prev; } else op->prev->next = NULL; } return (0); }
int begin(int argc, char *argv[]) { int i, j; uint32_t ph_flags = 0; thread_pool_attr_t tp_attr; static void *tpp; dispatch_t *dpp; dpp = dispatch_create(); if (dpp == NULL) { char * pMsgTxt = "Error: cannot create dispatch interface\n"; fprintf(stderr, pMsgTxt); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt); return (EXIT_FAILURE); } devi_set_dispatch_handle(dpp); /* set up the module table */ if (modules != NULL) { for (i = 0; i < MODULE_TABLE_SIZE && ModuleTable[i] != NULL; i++) ; /* add extra modules to end of ModuleTable */ for (j = 0; j < (MODULE_TABLE_SIZE - i) && modules[j] != NULL; j++, i++) ModuleTable[i] = modules[j]; } if(ThreadCtl(_NTO_TCTL_IO, 0) == -1) { errno_print("ThreadCtl"); return (EXIT_FAILURE); } // Call global callback if it was specified if(commonCallbacks.pre_init && commonCallbacks.pre_init()) return (EXIT_FAILURE); if (options(argc, argv, &ph_flags, &OptFlags) < 0) return (EXIT_FAILURE); // Call global callback if it was specified if(commonCallbacks.post_init && commonCallbacks.post_init()) return (EXIT_FAILURE); sig_install(signal_table, termination_hndlr); if (procmgr_daemon(0, PROCMGR_DAEMON_NODEVNULL | PROCMGR_DAEMON_NOCLOSE) < 0) { errno_print("procmgr_daemon"); return (EXIT_FAILURE); } if (!(OptFlags & OPT_NO_PHOTON)) { if (start_photon_interface(ph_flags) < 0) { errno_print("unable to start photon interface"); return (EXIT_FAILURE); } } memset(&tp_attr, 0, sizeof(tp_attr)); tp_attr.handle = devi_get_dispatch_handle(); tp_attr.context_alloc = dispatch_context_alloc; tp_attr.block_func = dispatch_block; tp_attr.handler_func = dispatch_handler; tp_attr.context_free = dispatch_context_free; /* We'd rather not to use thread pool for device driver - it could cause desynchronizing and data losing */ tp_attr.lo_water = 1; /* min amount threads waiting blocked */ tp_attr.hi_water = 1; /* max amount threads waiting blocked */ tp_attr.increment = 1; tp_attr.maximum = 1; tpp = thread_pool_create(&tp_attr, POOL_FLAG_USE_SELF); if (tpp == NULL) { errno_print("thread_pool_create"); return (EXIT_FAILURE); } thread_pool_start(tpp); return (EOK); }
/* * Return -1 * This prp can never match the criteria * Return 0 * This prp does not currently match the criteria * Return WNOHANG * An error with wap, reply was done (i.e. a thread unblocked) * Return non-zero W????? * This prp matched and a reply was done (i.e. a thread unblocked) */ int procmgr_wait_check(PROCESS *prp, PROCESS *parent, struct wait_entry *wap, int match) { struct _msg_info info; /* * Check if this prp matched the requested group */ switch(wap->idtype) { case P_ALL: break; case P_PID: if(prp->pid != wap->id) { return -1; } break; case P_PGID: if(prp->pgrp != wap->id) { return -1; } break; default: MsgError(wap->rcvid, EINVAL); return WNOHANG; } if(match) { /* * Check for match, if parent is ignoring SIGCHLD, are we the last child? */ match &= wap->options; if(wap->idtype == P_ALL && (prp->sibling || parent->child != prp) && sigismember(&parent->sig_ignore, SIGCHLD)) { match &= ~WEXITED; } /* * Have we already responded with exit code? */ if(!(prp->flags & _NTO_PF_WAITINFO)) { match &= ~WEXITED; } } else { /* * Check if the requested prp currently matches any options */ if((wap->options & WTRAPPED) && (prp->flags & (_NTO_PF_DEBUG_STOPPED | _NTO_PF_PTRACED)) == (_NTO_PF_DEBUG_STOPPED | _NTO_PF_PTRACED)) { match = WTRAPPED; } else if((wap->options & WEXITED) && (prp->flags & _NTO_PF_WAITINFO)) { match = WEXITED; } else if((wap->options & WCONTINUED) && (prp->flags & _NTO_PF_CONTINUED)) { match = WCONTINUED; } else if((wap->options & WUNTRACED) && (prp->flags & _NTO_PF_STOPPED) && prp->siginfo.si_signo != 0) { match = WUNTRACED; } } /* * If no options matched, check if it could ever match options */ if(match == 0) { int options = wap->options; if(prp->flags & (_NTO_PF_ZOMBIE | _NTO_PF_TERMING)) { options &= ~(WUNTRACED|WTRAPPED|WCONTINUED); } if((prp->flags & (_NTO_PF_ZOMBIE | _NTO_PF_WAITINFO)) == _NTO_PF_ZOMBIE) { options &= ~WEXITED; } if((prp->flags & _NTO_PF_NOZOMBIE) || sigismember(&parent->sig_ignore, SIGCHLD)) { options &= ~WEXITED; } if(prp->flags & _NTO_PF_WAITDONE) { options &= ~WEXITED; } if(!(prp->flags & _NTO_PF_PTRACED)) { options &= ~WTRAPPED; } if((options & (WEXITED|WUNTRACED|WTRAPPED|WCONTINUED)) == 0) { return -1; } return 0; } /* * Unblock the waiting thread... */ if(MsgInfo(wap->rcvid, &info) != -1) { siginfo_t siginfo; // unbind and unblock if rcvid is still around if((!parent->wap) || ((parent->wap == wap) && (parent->wap->next == NULL))) { (void)_resmgr_unbind(&info); } siginfo = prp->siginfo; if(siginfo.si_signo != SIGCHLD) { if(prp->flags & _NTO_PF_COREDUMP) { siginfo.si_code = CLD_DUMPED; } else { siginfo.si_code = CLD_KILLED; } siginfo.si_status = siginfo.si_signo; siginfo.si_pid = prp->pid; siginfo.si_signo = SIGCHLD; } if(info.flags & _NTO_MI_ENDIAN_DIFF) { ENDIAN_SWAP32(&siginfo.si_signo); ENDIAN_SWAP32(&siginfo.si_code); ENDIAN_SWAP32(&siginfo.si_errno); ENDIAN_SWAP32(&siginfo.si_pid); ENDIAN_SWAP32(&siginfo.si_status); ENDIAN_SWAP32(&siginfo.si_utime); ENDIAN_SWAP32(&siginfo.si_stime); } MsgReply(wap->rcvid, 0, &siginfo, sizeof siginfo); } else { KerextSlogf( _SLOG_SETCODE( _SLOGC_PROC, 0 ), _SLOG_INFO, "proc_wait_check: MsgInfo() failed, errno=%d", errno); } /* * Clean up prp status if requested so it is not reported again */ if(wap->options & WNOWAIT) { return WNOWAIT; } switch(match) { case WEXITED: if(prp->flags & _NTO_PF_WAITINFO) { parent->kids_running_time += prp->running_time + prp->kids_running_time; parent->kids_system_time += prp->system_time + prp->kids_system_time; prp->flags &= ~_NTO_PF_WAITINFO; prp->flags |= _NTO_PF_WAITDONE; } if(prp->flags & _NTO_PF_ZOMBIE) { MsgSendPulse(PROCMGR_COID, prp->terming_priority, PROC_CODE_TERM, prp->pid); } else { match = WNOWAIT; } break; case WUNTRACED: // also WSTOPPED prp->siginfo.si_signo = 0; break; case WTRAPPED: break; case WCONTINUED: prp->flags &= ~_NTO_PF_CONTINUED; break; default: break; } return match; }
int tto(TTYDEV *ttydev, int action, int arg1) { TTYBUF *bup = &ttydev->obuf; DEV_OMAP *dev = (DEV_OMAP *)ttydev; const uintptr_t *port = dev->port; unsigned char c; #ifdef PWR_MAN if (dev->idle) { /* Check the client lists for notify conditions */ return(tto_checkclients(&dev->tty)); } #endif switch(action) { case TTO_STTY: // if (dev->driver_pmd.cur_mode == PM_MODE_ACTIVE) ser_stty(dev); return (0); case TTO_CTRL: if(arg1 & _SERCTL_BRK_CHG) set_port(port[OMAP_UART_LCR], OMAP_LCR_BREAK, arg1 &_SERCTL_BRK ? OMAP_LCR_BREAK : 0); if(arg1 & _SERCTL_DTR_CHG) set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR, arg1 & _SERCTL_DTR ? OMAP_MCR_DTR : 0); if(arg1 & _SERCTL_RTS_CHG) { if (dev->auto_rts_enable) { /* For auto-rts enable/disable RX & LS interrupts to assert/clear * input flow control (the FIFO will automatically handle the RTS line) */ if (arg1 & _SERCTL_RTS) write_omap(port[OMAP_UART_IER], read_omap(port[OMAP_UART_IER] ) | OMAP_IER_RHR | OMAP_IER_LS ); else write_omap(port[OMAP_UART_IER], read_omap(port[OMAP_UART_IER] ) & ~(OMAP_IER_RHR | OMAP_IER_LS ) ); } else set_port(port[OMAP_UART_MCR], OMAP_MCR_RTS, arg1 & _SERCTL_RTS ? OMAP_MCR_RTS : 0); } #ifdef WINBT if (arg1 & _CTL_TIMED_CHG) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Turning clocks OFF due to CTS glitch\n", __FUNCTION__); dev->signal_oband_notification = 0; omap_clock_disable(dev); } #endif return (0); case TTO_LINESTATUS: return (((read_omap(port[OMAP_UART_MSR]) << 8) | read_omap(port[OMAP_UART_MCR])) & 0xf003); case TTO_DATA: case TTO_EVENT: break; default: return (0); } while (bup->cnt > 0 && (!(read_omap(port[OMAP_UART_SSR]) & OMAP_SSR_TXFULL)) ) { /* * If the OSW_PAGED_OVERRIDE flag is set then allow * transmit of character even if output is suspended via * the OSW_PAGED flag. This flag implies that the next * character in the obuf is a software flow control * charater (STOP/START). * Note: tx_inject sets it up so that the contol * character is at the start (tail) of the buffer. * */ if (dev->tty.flags & (OHW_PAGED | OSW_PAGED) && !(dev->tty.xflags & OSW_PAGED_OVERRIDE)) break; /* Get character from obuf and do any output processing */ dev_lock(&dev->tty); c = tto_getchar(&dev->tty); dev_unlock(&dev->tty); /* Print the character */ dev->tty.un.s.tx_tmr = 3; /* Timeout 3 */ write_omap(port[OMAP_UART_THR], c); /* Clear the OSW_PAGED_OVERRIDE flag as we only want * one character to be transmitted in this case. */ if (dev->tty.xflags & OSW_PAGED_OVERRIDE){ atomic_clr(&dev->tty.xflags, OSW_PAGED_OVERRIDE); break; } } /* If there is still data in the obuf and we are not in a flow * controlled state then turn TX interrupts back on to notify us * when the hardware is ready for more characters. */ if (bup->cnt > 0 && !(dev->tty.flags & (OHW_PAGED|OSW_PAGED)) ) { // enable all interrupts set_port(dev->port[OMAP_UART_IER], OMAP_IER_THR, OMAP_IER_THR); } /* Check the client lists for notify conditions */ return(tto_checkclients(&dev->tty)); }
/* Return : None */ void insertion( struct usbd_connection *pConnection, usbd_device_instance_t *pInstance ) { int rc; struct usbd_device * pDevice; pModule_data_t pModule, * ppModule; if(verbosity) printf("Try to inser device\n"); if( EOK != (rc = usbd_attach( pConnection, pInstance, sizeof(module_data_t **), &pDevice ) )) { char * pMsgTxt = "Error: cannot attach USB device #%i (error code is %i)\n"; fprintf(stderr, pMsgTxt, (int)(pInstance -> devno), rc); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt, (int)(pInstance -> devno), rc); return; } ppModule = (pModule_data_t *)usbd_device_extra(pDevice); // Try to find if somebody cares about keyboard reports for(pModule = LIST_FIRST_ITEM(&modList); NULL != pModule; pModule = LIST_NEXT_ITEM(pModule, lst_conn)) { // Check device number if specified if( (USBD_CONNECT_WILDCARD != pModule -> nDev) && (pModule -> nDev != pInstance -> devno)) continue; if( (USBD_CONNECT_WILDCARD != pModule -> nVendor) && (pModule -> nVendor != pInstance -> ident.vendor)) continue; // Wrong vendor - ignore if((USBD_CONNECT_WILDCARD != pModule -> nClass) && (pModule -> nClass != pInstance -> ident.dclass)) continue; if((USBD_CONNECT_WILDCARD != pModule -> nSubClass) && (pModule -> nSubClass != pInstance -> ident.subclass)) continue; pModule -> pInstance = pInstance; pModule -> pDevice = pDevice; if( EOK == parse_descriptors( pModule) ) { if( pModule -> ep_int_buf = usbd_alloc( pModule -> ep_int_size ) ) { if( pModule -> urb = usbd_alloc_urb( NULL ) ) { // Initialize request block usbd_setup_interrupt( pModule -> urb, URB_DIR_IN, pModule -> ep_int_buf, pModule->ep_int_size ); // Initialize Interrupt callback function if( EOK == usbd_io( pModule -> urb, pModule -> ep_int, usb_dev_int, pModule, USBD_TIME_INFINITY ) ) { pModule -> flags |= USB_DEVICE_ON | USB_DEVICE_PRESENT; *ppModule = pModule; if(verbosity) printf("Attach device\n"); return; } else { if(verbosity) printf("Cannot attach device\n"); } } usbd_free( pModule -> ep_int_buf ); } usbd_detach( pDevice ); } } }
// Initialize audio and report back a few parameters of the channel int setupAudio( ) { int error; snd_pcm_channel_info_t pi; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t ps; //if ((error = snd_pcm_open_name (&playback_handle, "pcmPreferred", SND_PCM_OPEN_PLAYBACK)) < 0) { if ((error = snd_pcm_open_name (&playback_handle, "tones", SND_PCM_OPEN_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to open preferred audio driver\n"); return -error; } sample_handle = snd_pcm_file_descriptor( playback_handle, SND_PCM_CHANNEL_PLAYBACK ); if ((error = snd_pcm_plugin_set_disable (playback_handle, PLUGIN_DISABLE_MMAP)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to disable mmap\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_set_enable (playback_handle, PLUGIN_ROUTING)) < 0) { slogf ( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "snd_pcm_plugin_set_enable failed: %s\n", snd_strerror (error)); snd_pcm_close(playback_handle); return -error; } // Find what sample rate and format to use memset( &pi, 0, sizeof(pi) ); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((error = snd_pcm_channel_info (playback_handle, &pi)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to get plugin info\n"); snd_pcm_close(playback_handle); return -error; } // Initialize the playback channel memset(&pp, 0, sizeof(pp) ); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; pp.buf.block.frags_max = 3; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.format = SND_PCM_SFMT_S16_LE; pp.format.rate = 48000; pp.format.voices = 2; memset( &ps, 0, sizeof( ps ) ); memset( &group, 0, sizeof( group ) ); ps.channel = SND_PCM_CHANNEL_PLAYBACK; ps.mixer_gid = &group.gid; //strcpy(pp.sw_mixer_subchn_name, "Wave playback channel"); strcpy(pp.sw_mixer_subchn_name, "voice_ringtone"); if ((error = snd_pcm_plugin_params( playback_handle, &pp)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set plugin params\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set prepare plugin\n"); snd_pcm_close(playback_handle); return -error; } if ((error = snd_pcm_plugin_setup (playback_handle, &ps)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to setup plugin\n"); snd_pcm_close(playback_handle); return -error; } card = ps.mixer_card; device = ps.mixer_device; if( audioman_handle ) { if ((error = snd_pcm_set_audioman_handle (playback_handle, audioman_handle)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to set audioman handle \n"); snd_pcm_close(playback_handle); return -error; } } sample_frequency = ps.format.rate; frag_samples = ps.buf.block.frag_size / 4; frame_size = ps.buf.block.frag_size; format = pp.format.format; /* // Only support 16-bit samples for now frag_buffer = malloc( ps.buf.block.frag_size * 2 ); if( frag_buffer == NULL ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to alloc frag buffer\n"); snd_pcm_close(playback_handle); return ENOMEM; } */ fprintf (stderr,"Playback Format %s card = %d\n", snd_pcm_get_format_name (ps.format.format),card); fprintf (stderr,"Playback preferred frame_size %d \n", pi.max_fragment_size); fprintf (stderr,"Playback frame_size %d \n", ps.buf.block.frag_size); fprintf (stderr,"Playback frame_samples %d \n", frag_samples); fprintf (stderr,"Playback Rate %d \n", ps.format.rate); if (group.gid.name[0] == 0) { fprintf (stderr,"Playback Mixer Pcm Group [%s] Not Set \n", group.gid.name); return -1; } fprintf (stderr, "Playback Mixer Pcm Group [%s]\n", group.gid.name); return EOK; }
static void *processTones(void *dummy) { bool done; int error; int length; int index; Tone *tone, *nextTone; snd_pcm_channel_status_t status; //pthread_setname_np(pthread_self(), "tonegen"); // Main loop. Wait for audio driver to need more data while( live ) { pthread_mutex_lock( &toneMutex ); if( tone_count == 0 ) { // Wait for a tone command to come in snd_pcm_playback_flush( playback_handle ); snd_pcm_plugin_prepare( playback_handle, SND_PCM_CHANNEL_PLAYBACK ); pthread_cond_wait( &condvar_newtone, &toneMutex ); } if( tone_count == 0 ) { pthread_mutex_unlock( &toneMutex ); continue; } pthread_mutex_unlock( &toneMutex ); // Send tone data FD_ZERO( &write_handles ); FD_SET( sample_handle, &write_handles ); error = select(sample_handle + 1, NULL, &write_handles, NULL, NULL); if( error < 0 ) { // Select failed. slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "processTones select failed %d (%d)\n", error, errno); pthread_mutex_unlock( &toneMutex ); live = DEAD; break; } length = 0; // This should always be true if( FD_ISSET( sample_handle, &write_handles ) ) { int active_count = 0; for(tone = tones; tone != NULL; tone = tone->next) { done = tone->killed || (tonepos > tone->end); //fprintf (stderr,"processTone::writeTone (before active check) tone %ld tone->end %ld active %d done %d tonepos %ld \n", tone, tone->end, tone->active, done, tonepos); if( !done ) { // Write the tone error = writeTone(tone, (tone != tones)); //error = tone->generator(tone->position, length, sample_frequency, frag_buffer, &tone->data, terminating); if( error != EOK ) { done = true; } active_count++; } tone->active &= !done; //fprintf (stderr,"processTone::writeTone tone %ld tone->end %ld active %d tonepos %ld \n", tone, tone->end, tone->active, tonepos); } for(index = 0; index < frag_samples; index++) { record_buffer[index*2 ] = stage_buffer[index] / stage_samples[index]; record_buffer[index*2+1] = stage_buffer[index] / stage_samples[index]; } pthread_mutex_lock(&fillMutex); if (render_buffer != NULL) { memcpy(render_buffer, record_buffer, frame_size); } pthread_mutex_unlock(&fillMutex); tonepos += frag_samples; if (active_count > 0) { fprintf (stderr,"processTone tonepos %ld \n", tonepos); error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size); if( error != frame_size ) { memset (&status, 0, sizeof (status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if ((error = snd_pcm_plugin_status (playback_handle, &status)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "retrieving audio interface status failed (%s)\n", snd_strerror (error)); } else if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN || status.status == SND_PCM_STATUS_CHANGE) { if ((error = snd_pcm_plugin_prepare (playback_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "cannot prepare audio interface for use (%s)\n", snd_strerror (error)); } } else { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "non-underrun write failure (%s)\n", snd_strerror (error)); } // Retry now that we're prepared error = snd_pcm_plugin_write (playback_handle, record_buffer, frame_size); } if( error != frame_size ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "write to audio interface failed (%s) %d\n", snd_strerror (error), error); } } } else { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unknown file handle activated" ); } pthread_mutex_lock( &toneMutex ); //fprintf (stderr,"processTone::delete tones %lx count %d \n", tones, tone_count); int delete_count; do { delete_count = 0; for(tone = tones; tone != NULL; tone = tone->next) { done = tone->killed || (tonepos > tone->end); if( done || !tone->active ) { // Remove the tone from the list if (tone->prev != NULL) { tone->prev->next = tone->next; } else { tones = tone->next; } if (tone->next != NULL) { tone->next->prev = tone->prev; } tone_count--; free(tone); delete_count++; fprintf (stderr,"processTone::delete tone %lx tones %lx count %d \n", tone, tones, tone_count); break; } } } while (delete_count > 0); pthread_mutex_unlock( &toneMutex ); if (tone_count == 0) { memset(record_buffer, 0, frame_size); } } return NULL; }
int initToneGenerator(void) { _int32 staticMemSize, scratchMemSize; int policy; struct sched_param param; int error; pthread_attr_t attr; if( live == RUNNING) { return 0; } else if( live == DEAD ) { return -EINVAL; } if( (error = pthread_mutex_init (&fillMutex, NULL) ) != 0 ) { return error; } tone_count = 0; if( (error = pthread_mutex_init( &toneMutex, NULL ) ) != 0 ) { return error; } if( (error = pthread_cond_init( &condvar_newtone, NULL ) ) != 0 ) { pthread_mutex_destroy( &toneMutex ); return error; } audio_manager_get_handle( AUDIO_TYPE_VOICE_TONES, getpid(), true, &audioman_handle ); if( (error = setupAudio( )) != 0 ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to initialize audio %s\n", snd_strerror(error)); pthread_mutex_destroy( &toneMutex ); pthread_cond_destroy( &condvar_newtone ); if( audioman_handle ) { audio_manager_free_handle( audioman_handle ); } return error; } // Re-usable buffer for generation stage_buffer = malloc (frame_size); memset(stage_buffer, 0, frame_size); stage_samples = malloc (frame_size); memset(stage_samples, 0, frame_size); record_buffer = malloc (frame_size); memset(record_buffer, 0, frame_size); render_buffer = malloc (frame_size); memset(render_buffer, 0, frame_size); // Default tonegen volume is 75% to achieve a 16dB loss ( SW mixer uses 10%=6dB. ) setVolume(85); live = RUNNING; pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED); pthread_getschedparam (pthread_self (), &policy, ¶m); param.sched_priority=12; pthread_attr_setschedparam (&attr, ¶m); pthread_attr_setschedpolicy (&attr, SCHED_RR); if( (error = pthread_create( &toneGeneratorThread, &attr, processTones, NULL ) ) != 0 ) { slogf( _SLOG_SETCODE(_SLOGC_AUDIO, 0), _SLOG_CRITICAL, "Unable to create tone thread %s\n", strerror(error)); snd_pcm_close (playback_handle); //free( frag_buffer ); pthread_mutex_destroy( &toneMutex ); pthread_cond_destroy( &condvar_newtone ); live = STOPPED; if( audioman_handle ) { audio_manager_free_handle( audioman_handle ); } pthread_attr_destroy(&attr); return error; } pthread_attr_destroy(&attr); return 0; }
/******************************************************************************* ** ** gckCOMMAND_Stall ** ** The calling thread will be suspended until the command queue has been ** completed. ** ** INPUT: ** ** gckCOMMAND Command ** Pointer to an gckCOMMAND object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckCOMMAND_Stall( IN gckCOMMAND Command ) { gckOS os; gckHARDWARE hardware; gckEVENT event; gceSTATUS status; gctSIGNAL signal = gcvNULL; gcmkHEADER_ARG("Command=0x%x", Command); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND); #if gcdNULL_DRIVER == 2 /* Do nothing with infinite hardware. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; #endif /* Extract the gckOS object pointer. */ os = Command->os; gcmkVERIFY_OBJECT(os, gcvOBJ_OS); /* Extract the gckHARDWARE object pointer. */ hardware = Command->kernel->hardware; gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE); /* Extract the gckEVENT object pointer. */ event = Command->kernel->event; gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT); /* Allocate the signal. */ gcmkONERROR( gckOS_CreateSignal(os, gcvTRUE, &signal)); /* Append the EVENT command to trigger the signal. */ gcmkONERROR(gckEVENT_Signal(event, signal, gcvKERNEL_PIXEL, gcvFALSE)); /* Submit the event queue. */ gcmkONERROR(gckEVENT_Submit(event, gcvTRUE, gcvFALSE)); #if gcdDUMP_COMMAND gcmkPRINT("@[kernel.stall]"); #endif if (status == gcvSTATUS_CHIP_NOT_READY) { /* Error. */ goto OnError; } do { /* Wait for the signal. */ status = gckOS_WaitSignal(os, signal, gcvINFINITE); if (status == gcvSTATUS_TIMEOUT) { #if gcdDEBUG gctUINT32 idle; /* IDLE */ gckOS_ReadRegister(Command->os, 0x0004, &idle); gcmkTRACE(gcvLEVEL_ERROR, "%s(%d): idle=%08x", __FUNCTION__, __LINE__, idle); gckOS_Log(_GFX_LOG_WARNING_, "%s : %d : idle register = 0x%08x \n", __FUNCTION__, __LINE__, idle); #endif #if MRVL_PRINT_CMD_BUFFER { gctUINT i; gctUINT32 idle; gctUINT32 intAck; gctUINT32 prevAddr = 0; gctUINT32 currAddr; gctBOOL changeDetected; changeDetected = gcvFALSE; /* IDLE */ gckOS_ReadRegister(Command->os, 0x0004, &idle); /* INT ACK */ gckOS_ReadRegister(Command->os, 0x0010, &intAck); /* DMA POS */ for (i = 0; i < 300; i += 1) { gckOS_ReadRegister(Command->os, 0x0664, &currAddr); if ((i > 0) && (prevAddr != currAddr)) { changeDetected = gcvTRUE; } prevAddr = currAddr; } gcmTRACE(0, "\n%s(%d):\n" " idle = 0x%08X\n" " int = 0x%08X\n" " dma = 0x%08X (change=%d)\n", __FUNCTION__, __LINE__, idle, intAck, currAddr, changeDetected ); _PrintCmdBuffer(Command, currAddr); _PrintLinkChain(); } #endif #if MRVL_LOW_POWER_MODE_DEBUG { int i = 0; printk(">>>>>>>>>>>>galDevice->kernel->kernelMSG\n"); printk("galDevice->kernel->msgLen=%d\n",Command->kernel->msgLen); for(i=0;i<Command->kernel->msgLen;i+=1024) { Command->kernel->kernelMSG[i+1023] = '\0'; printk("%s\n",(char*)Command->kernel->kernelMSG + i); } } #endif #ifdef __QNXNTO__ gctUINT32 reg_cmdbuf_fetch; gctUINT32 reg_intr; gcmkVERIFY_OK( gckOS_ReadRegister(Command->kernel->hardware->os, 0x0664, ®_cmdbuf_fetch)); if (idle == 0x7FFFFFFE) { /* * GPU is idle so there should not be pending interrupts. * Just double check. * * Note that reading interrupt register clears it. * That's why we don't read it in all cases. */ gcmkVERIFY_OK( gckOS_ReadRegister(Command->kernel->hardware->os, 0x10, ®_intr)); slogf( _SLOG_SETCODE(1, 0), _SLOG_CRITICAL, "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)", idle, reg_cmdbuf_fetch, reg_intr); } else { slogf( _SLOG_SETCODE(1, 0), _SLOG_CRITICAL, "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)", idle, reg_cmdbuf_fetch); } #endif gcmkVERIFY_OK( gckOS_MemoryBarrier(os, gcvNULL)); } } while (gcmIS_ERROR(status)); /* Delete the signal. */ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Free the signal. */ if (signal != gcvNULL) { gcmkVERIFY_OK(gckOS_DestroySignal(os, signal)); } /* Return the status. */ gcmkFOOTER(); return status; }
void ser_stty(DEV_OMAP *dev) { unsigned char lcr = 0; unsigned char efr = 0; const uintptr_t *port = dev->port; unsigned brd = 0; int multiple; int i; #ifdef PWR_MAN if (dev->idle) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "%s: Called while idle, ignoring\n", __FUNCTION__); return; } #endif /* determine data bits */ switch (dev->tty.c_cflag & CSIZE) { case CS8: ++lcr; case CS7: ++lcr; case CS6: ++lcr; } /* determine stop bits */ if (dev->tty.c_cflag & CSTOPB) lcr |= OMAP_LCR_STB2; /* determine parity bits */ if (dev->tty.c_cflag & PARENB) lcr |= OMAP_LCR_PEN; if ((dev->tty.c_cflag & PARODD) == 0) lcr |= OMAP_LCR_EPS; if (dev->tty.c_cflag & OHFLOW) efr = OMAP_EFR_AUTO_CTS; if (dev->tty.c_cflag & IHFLOW && dev->auto_rts_enable) efr |= OMAP_EFR_AUTO_RTS; /* Apply EFR value if changed */ if (dev->efr != efr) { /* Switch to Config mode B to access the Enhanced Feature Register (EFR) */ write_omap(port[OMAP_UART_LCR],0xbf); /* turn off S/W flow control, Config AUTO hw flow control, enable writes to MCR[7:5], FCR[5:4], and IER[7:4] */ set_port(port[OMAP_UART_EFR], efr, efr); /* Switch back to operational mode */ write_omap(port[OMAP_UART_LCR],0); /* Restore LCR config values */ write_omap(port[OMAP_UART_LCR], lcr); dev->lcr = lcr; dev->efr = efr; } if (dev->tty.baud != dev->baud) { /* Get acces to Divisor Latch registers */ write_omap(port[OMAP_UART_LCR], OMAP_LCR_DLAB); #ifdef OMAP5910 /* * Oscillator frequency is fixed at 12MHz. This normally wouldn't allow a * 115200 baud rate, since divisor = Fin / (16 * baud), which, for 115200, = 6.5, * which is out of tolerance. There is a special register with a bit which, when * set, automatically enables a 6.5 divisor value in hardware, and the DLH / DLL * registers can just be programmed with a 1. */ if (dev->tty.baud == 115200) { brd = 1; write_omap(port[OMAP_UART_DLL], brd); write_omap(port[OMAP_UART_DLH], (brd >> 8) & 0xff); write_omap(port[OMAP_UART_OSC_12M_SEL], 0x01); }
int resmgr_create_device(event_bus_line_t *line) { devi_attr_t *attr; resmgr_attr_t res_attr; static resmgr_connect_funcs_t connect_funcs; static resmgr_io_funcs_t io_funcs; static int once = 0; int i; char name[48]; char path[_POSIX_PATH_MAX]; int id; dev_t d; if ((attr = malloc(sizeof(devi_attr_t))) == NULL) { errno_print("malloc"); return (-1); } if (!once) { iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs, _RESMGR_IO_NFUNCS, &io_funcs); connect_funcs.open = devi_open; io_funcs.devctl = devi_devctl; io_funcs.read = devi_read; io_funcs.close_ocb = devi_close; io_funcs.unblock = devi_unblock; io_funcs.notify = devi_notify; once = 1; } iofunc_attr_init(&attr->attr, 0666 | S_IFCHR, NULL, NULL); attr->flags = line->type; attr->ocb_list = NULL; line->attr = attr; switch (attr->flags) { case DEVI_CLASS_KBD: strcpy(name, "keyboard"); break; case DEVI_CLASS_REL: strcpy(name, "mouse"); break; case DEVI_CLASS_ABS: strcpy(name, "touch"); break; } attr->line = line; memset(&res_attr, 0, sizeof(res_attr)); res_attr.msg_max_size = 2048; res_attr.nparts_max = 3; for (i = 0; i < 10; i++) { sprintf(path, DEVICE_NAME, name, i); if (access(path, F_OK) != 0) break; } if (i == 10) { char * pMsgTxt = "Error: unable to create device %s\n"; fprintf(stderr, pMsgTxt, path); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt, path); free(attr); return (-1); } id = resmgr_attach(devi_get_dispatch_handle(), &res_attr, path, _FTYPE_ANY, 0, &connect_funcs, &io_funcs, (void *) &attr->attr); if (id < 0) { char * pMsgTxt = "Error: could not attach resource manager\n"; fprintf(stderr, pMsgTxt); slogf(_SLOG_SETCODE(_SLOGC_INPUT, 0), _SLOG_ERROR, pMsgTxt); free(attr); return (-1); } attr->attr.rdev = rsrcdbmgr_devno_attach(name, -1, 0); resmgr_devino(id, &d, &attr->attr.inode); return (0); }
DEV_OMAP * create_device(TTYINIT_OMAP *dip, unsigned unit, unsigned maxim_xcvr_kick) { DEV_OMAP *dev; unsigned i; uintptr_t port; unsigned char msr; unsigned char tlr = 0, tcr = 0; #ifdef PWR_MAN clk_enable_t clk_cfg = clk_enable_none; #endif // Get a device entry and the input/output buffers for it. if ((dev = malloc(sizeof(*dev))) == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of device entry failed (%d)", errno); return (dev); } memset(dev, 0, sizeof(*dev)); // Get buffers. dev->tty.ibuf.head = dev->tty.ibuf.tail = dev->tty.ibuf.buff = malloc(dev->tty.ibuf.size = dip->tty.isize); if (dev->tty.ibuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of input buffer failed (%d)", errno); free(dev); return (NULL); } dev->tty.obuf.head = dev->tty.obuf.tail = dev->tty.obuf.buff = malloc(dev->tty.obuf.size = dip->tty.osize); if (dev->tty.obuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of output buffer failed (%d)", errno); free(dev->tty.ibuf.buff); free(dev); return (NULL); } dev->tty.cbuf.head = dev->tty.cbuf.tail = dev->tty.cbuf.buff = malloc(dev->tty.cbuf.size = dip->tty.csize); if (dev->tty.cbuf.buff == NULL) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Allocation of canonical buffer failed (%d)", errno); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } if (dip->tty.highwater) dev->tty.highwater = dip->tty.highwater; else dev->tty.highwater = dev->tty.ibuf.size - (FIFO_SIZE * 2); strcpy(dev->tty.name, dip->tty.name); dev->tty.baud = dip->tty.baud; dev->tty.fifo = dip->tty.fifo; dev->tty.verbose = dip->tty.verbose; port = mmap_device_io(OMAP_UART_SIZE, dip->tty.port); for (i = 0; i < OMAP_UART_SIZE; i += 4) dev->port[i] = port + i; dev->intr = dip->tty.intr; dev->clk = dip->tty.clk; dev->div = dip->tty.div; dev->tty.flags = EDIT_INSERT | LOSES_TX_INTR; dev->tty.c_cflag = dip->tty.c_cflag; dev->tty.c_iflag = dip->tty.c_iflag; dev->tty.c_lflag = dip->tty.c_lflag; dev->tty.c_oflag = dip->tty.c_oflag; dev->tty.lflags = dip->tty.lflags; if (dip->tty.logging_path[0] != NULL) dev->tty.logging_path = strdup(dip->tty.logging_path); #ifdef PWR_MAN dev->physbase = dip->tty.port; if (omap_clock_toggle_init(dev) != EOK) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize clocks for PM!"); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } #ifdef WINBT clk_cfg = clk_enable_smart_wkup; if (omap_force_rts_init(dev) != EOK) { slogf(_SLOG_SETCODE(_SLOGC_CHAR, 0), _SLOG_ERROR, "io-char: Fail to initialize force_rts for PM!"); free(dev->tty.ibuf.buff); free(dev->tty.obuf.buff); free(dev); return (NULL); } #endif omap_clock_enable(dev, clk_cfg); #ifdef WINBT bt_ctrl_init(); #endif #endif /* Set auto_rts mode */ dev->auto_rts_enable = dip->auto_rts_enable; // Do not enable MSR interrupt dev->no_msr_int = dip->no_msr_int; // Initialize termios cc codes to an ANSI terminal. ttc(TTC_INIT_CC, &dev->tty, 0); // Initialize the device's name. // Assume that the basename is set in device name. This will attach // to the path assigned by the unit number/minor number combination unit = SET_NAME_NUMBER(unit) | NUMBER_DEV_FROM_USER; ttc(TTC_INIT_TTYNAME, &dev->tty, unit); // see if we have a maxim rs-232 transceiver that needs to be // kicked after it goes to sleep dev->kick_maxim = maxim_xcvr_kick; // Only setup IRQ handler for non-pcmcia devices. // Pcmcia devices will have this done later when card is inserted. if (dip->tty.port != 0 && dip->tty.intr != _NTO_INTR_SPARE) { #ifdef OMAP5910 /* * Don't change default mode set in the very distant past. Even though * MODE_SELECT should be DISABLE before changing DLH, DLL. */ // enable the UART write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_16X); #else /* * TRM states: Before initializing or modifying clock parameter controls * (DLH, DLL), MODE_SELECT must be set to 0x7 (DISABLE). Failure to observe * this rule can result in unpredictable module behavior. */ write_omap(dev->port[OMAP_UART_MDR1], OMAP_MDR1_MODE_DISABLE); #endif /* Work around for silicon errata i202 states: */ /* Need a delay = 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) */ nanospin_ns(200); /* Clear FIFOs */ set_port(dev->port[OMAP_UART_FCR], OMAP_FCR_RXCLR | OMAP_FCR_TXCLR, OMAP_FCR_RXCLR | OMAP_FCR_TXCLR); /* Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and TX_FIFO_E bit is 1 */ i = 5; while ((read_omap(dev->port[OMAP_UART_LSR]) & (OMAP_UART_LSR_THRE | OMAP_UART_LSR_DR)) != OMAP_UART_LSR_THRE) { nanospin_ns(200); if (--i == 0) { break; /* No need to do anything drastic if FIFO is still not empty */ } } // enable access to divisor registers write_omap(dev->port[OMAP_UART_LCR], OMAP_LCR_DLAB); write_omap(dev->port[OMAP_UART_DLL], 0); write_omap(dev->port[OMAP_UART_DLH], 0); /* Switch to config mode B to get access to EFR Register */ write_omap(dev->port[OMAP_UART_LCR], 0xBF); /* Enable access to TLR register */ set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, OMAP_EFR_ENHANCED); /* Switch to operational mode to get acces to MCR register */ write_omap(dev->port[OMAP_UART_LCR], 0x00); /* set MCR bit 6 to enable access to TCR and TLR registers */ set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, OMAP_MCR_TCRTLR); write_omap(dev->port[OMAP_UART_FCR], OMAP_FCR_ENABLE|OMAP_FCR_RXCLR|OMAP_FCR_TXCLR); tcr = 0x0e; /* set auto-rts assert at 56 bytes, restore at 0 bytes */ if (dev->tty.fifo) { /* Set RX fifo trigger level */ switch (dev->tty.fifo >> 4) { case FIFO_TRIG_8: default: tlr = 0x20; break; case FIFO_TRIG_16: tlr = 0x40; break; case FIFO_TRIG_32: tlr = 0x80; break; case FIFO_TRIG_56: tlr = 0xe0; break; case FIFO_TRIG_60: tlr = 0xf0; tcr = 0x0f; /* Ensure auto-rts trigger is not less the RX trigger */ break; } /* Set TX fifo trigger level */ switch (dev->tty.fifo & 0x0f) { case FIFO_TRIG_8: default: tlr |= 0x02; break; case FIFO_TRIG_16: tlr |= 0x04; break; case FIFO_TRIG_32: tlr |= 0x08; break; case FIFO_TRIG_56: tlr |= 0x0e; break; case FIFO_TRIG_60: tlr |= 0x0f; break; } } write_omap(dev->port[OMAP_UART_TCR], tcr); write_omap(dev->port[OMAP_UART_TLR], tlr); #ifdef PWR_MAN write_omap(dev->port[OMAP_UART_SCR], OMAP_SCR_WAKEUPEN); #else write_omap(dev->port[OMAP_UART_SCR], 0x00); #endif /* Switch back to Config mode B to gain access to EFR again */ write_omap(dev->port[OMAP_UART_LCR], 0xBF); /* remove access to TLR register */ set_port(dev->port[OMAP_UART_EFR], OMAP_EFR_ENHANCED, 0); /* Switch to operational mode to get acces to MCR register */ write_omap(dev->port[OMAP_UART_LCR], 0x00); /* clr MCR bit 6 to remove access to TCR and TLR registers */ set_port(dev->port[OMAP_UART_MCR], OMAP_MCR_TCRTLR, 0); ser_stty(dev); ser_attach_intr(dev); }
int kdecl ker_msg_error(THREAD *act, struct kerargs_msg_error *kap) { CONNECT *cop; THREAD *thp; if((cop = lookup_rcvid((KERARGS *)(void *)kap, kap->rcvid, &thp)) == NULL) { return ENOERROR; } // Make sure thread is replied blocked on a channel owned by this process. if(thp->state != STATE_REPLY && thp->state != STATE_NET_REPLY) { return ESRCH; } // Verify that the message has been fully received, and that the receiving // thread has completed any specialret() processing that needs to be done. if ( thp->internal_flags & _NTO_ITF_SPECRET_PENDING ) { return ESRCH; } if(thp->blocked_on != cop) { CONNECT *cop1 = cop; cop = thp->blocked_on; if((cop->flags & COF_VCONNECT) == 0 || cop->un.lcl.cop != cop1) { return ESRCH; } } if(thp->internal_flags & _NTO_ITF_UNBLOCK_QUEUED) { remove_unblock(thp, cop, kap->rcvid); } lock_kernel(); if(thp->args.ms.server != 0) { thp->args.ms.server->client = 0; thp->args.ms.server = 0; } thp->flags &= ~(_NTO_TF_BUFF_MSG | _NTO_TF_UNBLOCK_REQ); if(kap->err == ERESTART) { CRASHCHECK(TYPE_MASK(thp->type) != TYPE_THREAD); SETKIP(thp, KIP(thp) - KER_ENTRY_SIZE); } else { if ( _TRACE_GETSYSCALL(thp->syscall) == __KER_CHANNEL_DESTROY ) { /* you may think we're crazy... but... ok, we ARE, but it's for the best, really. * * The only way we could be doing a MsgError on a thread that is really calling ChannelDestroy is * if we were handling the destruction of channel which has off-node connections, and net_send2 * had to deal with the qnet manager. It's now doing a MsgError to let us know the status of * that message. Unfortunately, the status field will overwrite the syscall type field of the * thread, which will mean that he will restart his kernel call with the wrong kernel call number! * * Aiieeeeee! */ if ( kap->err != EOK ) { KerextSlogf( _SLOG_SETCODE( _SLOGC_QNET, 0 ), _SLOG_INFO, "Qnet ChannelDestroy failed %d", kap->err); } } else { kererr(thp, kap->err); } } _TRACE_COMM_EMIT_ERROR(thp, cop, thp->tid+1); LINKPRIL_REM(thp); if(--cop->links == 0) { connect_detach(cop, thp->priority); } ready(thp); act->restart = NULL; return EOK; }