static void seromap_enable(DEV_OMAP *dev, int enable) { uintptr_t *port = dev->port; write_omap(port[OMAP_UART_LCR], 0x80); if (!enable) { atomic_set(&dev->pwm_flag, SEROMAP_PWM_PAGED); // If HW flow control is ON, assert the RTS line if (dev->tty.c_cflag & IHFLOW) set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, 0); while (!(read_omap(port[OMAP_UART_LSR]) & OMAP_LSR_TSRE)) ; nanospin_ns(1000000); // pause for 1ms write_omap(port[OMAP_UART_MDR1], 0x07); write_omap(port[OMAP_UART_DLL], 0xFF); write_omap(port[OMAP_UART_DLH], 0xFF); } else { write_omap(port[OMAP_UART_DLL], dev->brd); write_omap(port[OMAP_UART_DLH], (dev->brd >> 8) & 0xff); write_omap(port[OMAP_UART_MDR1], 0x00); // If HW flow control is ON, de-assert the RTS line if(dev->tty.c_cflag & IHFLOW) set_port(port[OMAP_UART_MCR], OMAP_MCR_DTR|OMAP_MCR_RTS, OMAP_MCR_DTR|OMAP_MCR_RTS); // Allow data transmission to resume atomic_clr(&dev->pwm_flag, SEROMAP_PWM_PAGED); } write_omap(port[OMAP_UART_LCR], dev->lcr); }
static int _aio_wakeup(struct aiocb *aiocbp) { struct sigevent *ev = &aiocbp->aio_sigevent; int flag, ret = EOK; /* let's see if there is an suspend waiting us */ flag = atomic_set_value(&aiocbp->_aio_flag, _AIO_FLAG_DONE); if (flag & _AIO_FLAG_SUSPEND) { struct _aio_waiter *w; _mutex_lock(&_aio_cb->cb_mutex); if ((w = aiocbp->_aio_suspend) != NULL) { atomic_clr(&aiocbp->_aio_flag, _AIO_FLAG_SUSPEND); if ((ret = pthread_cond_signal(&w->w_cond)) != EOK) { aiocbp->_aio_result = (unsigned)-1; aiocbp->_aio_error = ret; } w->w_count--; aiocbp->_aio_suspend = NULL; } _mutex_unlock(&_aio_cb->cb_mutex); /* shall it be a wakeup even if there is an suspend ? */ return ret; } switch (SIGEV_GET_TYPE(ev)) { case SIGEV_SIGNAL: case SIGEV_SIGNAL_CODE: case SIGEV_SIGNAL_THREAD: ret = SignalKill_r(0, getpid(), 0, ev->sigev_signo, SI_ASYNCIO, ev->sigev_value.sival_int); break; case SIGEV_PULSE: ret = MsgSendPulse_r(ev->sigev_coid, ev->sigev_priority, ev->sigev_code, ev->sigev_value.sival_int); break; case SIGEV_THREAD: ret = pthread_create(NULL, ev->sigev_notify_attributes, (void *)ev->sigev_notify_function, ev->sigev_value.sival_ptr); break; case SIGEV_NONE: ret = EOK; break; case SIGEV_UNBLOCK: case SIGEV_INTR: default: /* don't know how to deliever these 2 */ ret = EOPNOTSUPP; break; } if (ret != EOK) { /* what if the io operation itself failed ? */ aiocbp->_aio_result = (unsigned)-1; aiocbp->_aio_error = ret; } return ret; }
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 pthread_exit(void *value_ptr) { struct __cleanup_handler *handler; int loop, again; volatile struct _thread_local_storage *tls = LIBC_TLS(); // Disable pthread_cancel and set cancel type to deferred atomic_set(&tls->__flags, PTHREAD_CANCEL_DISABLE); atomic_clr(&tls->__flags, PTHREAD_CANCEL_ASYNCHRONOUS); /* make defered */ // call the cleanup handlers while((handler = tls->__cleanup)) { tls->__cleanup = handler->__next; handler->__routine(handler->__save); } // Call the thread_specific_data destructor functions for(loop = 0, again = 1; again && loop < PTHREAD_DESTRUCTOR_ITERATIONS; loop++) { int i; int num; again = 0; num = min(tls->__numkeys, _key_count); for(i = 0; i < num; i++) { void *data; void (*destructor)(void *); if((destructor = _key_destructor[i]) && (destructor != _KEY_NONE) && (data = tls->__keydata[i])) { // Setting the data to NULL was the intention of the POSIX // committe, but did not make it into the POSIX spec. Doing // this still keeps our implementation POSIX complient, but // allow non-POSIX complient applications to be more efficient. tls->__keydata[i] = 0; destructor(data); again = 1; } } } // Unlock hanging file mutexes before exiting _Unlockfilemtx(); // Unlock hanging system mutexes before exiting _Unlocksysmtx(); (void)ThreadDestroy_r(0, -1, value_ptr); #ifdef __GNUC__ for( ;; ) ; /* Get gcc to shut up about a noreturn function returning */ #endif }
static void mmc_unit_ready(SIM_HBA *hba) { SIM_MMC_EXT *ext = (SIM_MMC_EXT *)hba->ext; CCB_SCSIIO *ccb = ext->nexus; if (ext->eflags & MMC_EFLAG_MEDIA_CHANGED) { mmc_sense(hba, SK_UNIT_ATN, ASC_MEDIUM_CHANGED, ASCQ_UNKNOWN_CHANGED); atomic_clr(&ext->eflags, MMC_EFLAG_MEDIA_CHANGED); } else if (ext->eflags & MMC_EFLAG_READY) { if (ext->detect(hba) != MMC_SUCCESS) { mmc_media_check(hba); mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0); } else ccb->cam_ch.cam_status = CAM_REQ_CMP; } else mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0); }
void dio_clear(uint8_t mask){ atomic_clr((unsigned*)&value, mask); out8(portHandle, value); }
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)); }