static void serial_data_rcv_done(serial_channel *chan, int chars_rcvd) { cbuf_t *cbuf = &chan->in_cbuf; cbuf->put += chars_rcvd; cbuf->nb += chars_rcvd; if (cbuf->put == cbuf->len) cbuf->put = 0; CYG_ASSERT(cbuf->nb <= cbuf->len, "Buffer overflow"); CYG_ASSERT(cbuf->put < cbuf->len, "Invalid put ptr"); CYG_ASSERT(cbuf->get < cbuf->len, "Invalid get ptr"); if (cbuf->waiting) { cbuf->waiting = false; cyg_drv_cond_signal(&cbuf->wait); } #ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL // If we've hit the high water mark, tell the other side to stop if ( cbuf->nb >= cbuf->high_water ) { throttle_rx( chan, false ); } #endif #ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT // Wake up any pending selectors if we have // put some data into a previously empty buffer. if (chars_rcvd == cbuf->nb) cyg_selwakeup( &cbuf->selinfo ); #endif #ifdef CYGDBG_USE_ASSERTS cbuf->block_mode_xfer_running = false; #endif }
// DSPI DSR static void dspi_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { cyg_spi_freescale_dspi_bus_t* dspi_bus = (cyg_spi_freescale_dspi_bus_t*) data; cyg_drv_dsr_lock(); cyg_drv_cond_signal(&dspi_bus->transfer_done); cyg_drv_dsr_unlock(); }
static void disk_transfer_done(struct disk_channel *chan, Cyg_ErrNo res) { disk_controller *ctlr = chan->controller; ctlr->result = res; cyg_drv_cond_signal( &ctlr->async ); }
static void usbs_devtab_callback(void* arg, int result) { usbs_callback_data* callback_data = (usbs_callback_data*) arg; callback_data->result = result; callback_data->completed = true; cyg_drv_cond_signal(&(callback_data->signal)); }
/** * * QSPI bus DSR handler * * @param vector - Number of ISR * @param data - Pointer to data structure (with driver handle) * * @return none * *****************************************************************************/ static void qspi_xc7z_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { cyg_qspi_xc7z_bus_t * qspi_bus = (cyg_qspi_xc7z_bus_t *)data; // Transfer ended qspi_bus->transfer_end = true; cyg_drv_cond_signal(&qspi_bus->transfer_cond); }
//========================================================================== // DSR signals data //========================================================================== static void lpc2xxx_i2c_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) { cyg_lpc2xxx_i2c_extra* extra = (cyg_lpc2xxx_i2c_extra*)data; if(extra->i2c_flag) { cyg_drv_cond_signal(&extra->i2c_wait); } }
static Cyg_ErrNo disk_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle; disk_channel *chan = (disk_channel *) t->priv; disk_controller *ctlr = chan->controller; cyg_disk_info_t *info = chan->info; disk_funs *funs = chan->funs; Cyg_ErrNo res = ENOERR; cyg_drv_mutex_lock( &ctlr->lock ); while( ctlr->busy ) cyg_drv_cond_wait( &ctlr->queue ); if (info->connected && chan->valid) { ctlr->busy = true; D(("disk set config key=%d\n", key)); switch ( key ) { case CYG_IO_SET_CONFIG_DISK_MOUNT: chan->mounts++; info->mounts++; D(("disk mount: chan %d disk %d\n",chan->mounts, info->mounts)); break; case CYG_IO_SET_CONFIG_DISK_UMOUNT: chan->mounts--; info->mounts--; D(("disk umount: chan %d disk %d\n",chan->mounts, info->mounts)); break; default: break; } // pass down to lower layers res = (funs->set_config)(chan, key, xbuf, len); ctlr->busy = false; cyg_drv_cond_signal( &ctlr->queue ); } else res = -EINVAL; cyg_drv_mutex_unlock( &ctlr->lock ); return res; }
static Cyg_ErrNo disk_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len) { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle; disk_channel *chan = (disk_channel *) t->priv; disk_controller *ctlr = chan->controller; cyg_disk_info_t *info = chan->info; cyg_disk_info_t *buf = (cyg_disk_info_t *) xbuf; disk_funs *funs = chan->funs; Cyg_ErrNo res = ENOERR; cyg_drv_mutex_lock( &ctlr->lock ); while( ctlr->busy ) cyg_drv_cond_wait( &ctlr->queue ); if (info->connected && chan->valid) { ctlr->busy = true; D(("disk get config key=%d\n", key)); switch (key) { case CYG_IO_GET_CONFIG_DISK_INFO: if (*len < sizeof(cyg_disk_info_t)) { res = -EINVAL; break; } D(("chan->info->block_size %u\n", chan->info->block_size )); D(("chan->info->blocks_num %u\n", chan->info->blocks_num )); D(("chan->info->phys_block_size %u\n", chan->info->phys_block_size )); *buf = *chan->info; *len = sizeof(cyg_disk_info_t); break; default: // pass down to lower layers res = (funs->get_config)(chan, key, xbuf, len); } ctlr->busy = false; cyg_drv_cond_signal( &ctlr->queue ); } else res = -EINVAL; cyg_drv_mutex_unlock( &ctlr->lock ); return res; }
// DSR signals data static void zynq_i2c_dsr(cyg_vector_t vec, cyg_ucount32 count, cyg_addrword_t data) { #ifdef ZYNQ_I2C_DEBUG DPRINTF("DSR executed\n"); #endif cyg_zynq_i2c_extra* extra = (cyg_zynq_i2c_extra*)data; if(extra->i2c_flag) { cyg_drv_cond_signal(&extra->i2c_wait); } cyg_drv_interrupt_unmask(vec); }
static void spi_at91_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { cyg_spi_at91_bus_t *spi_bus = (cyg_spi_at91_bus_t *) data; cyg_uint32 stat; // Read the status register and // check for transfer completition HAL_READ_UINT32(AT91_SPI+AT91_SPI_SR, stat); if((stat & AT91_SPI_SR_ENDRX) && (stat & AT91_SPI_SR_ENDTX)) { // Transfer ended spi_bus->transfer_end = true; cyg_drv_cond_signal(&spi_bus->transfer_cond); } else { // Transfer still in progress - unmask the SPI // int so we can get more SPI int events cyg_drv_interrupt_unmask(vector); } }
static void serial_rcv_char(serial_channel *chan, unsigned char c) { cbuf_t *cbuf = &chan->in_cbuf; #ifdef CYGPKG_NET_BLUEZ_STACK if(chan->receive)//clyu { extern unsigned char bluetooth_buf[]; int len = 0; struct tty_ldisc *ldisc = chan->tty_ldisc; if(ldisc && ldisc->receive_buf && cbuf->nb) { diag_printf("bluetooth\n"); if(cbuf->put < cbuf->get) { memcpy(bluetooth_buf, cbuf->data + cbuf->get, cbuf->len - cbuf->get); len = cbuf->len - cbuf->get; //ldisc->receive_buf(serial_driver, cbuf->data + cbuf->get, (char*)cbuf, cbuf->len - cbuf->get); cbuf->nb -= len; cbuf->get = 0; } memcpy(bluetooth_buf + len, cbuf->data + cbuf->get, cbuf->put); len += cbuf->put; cbuf->get = cbuf->put; cbuf->nb -= len; //ldisc->receive_buf(serial_driver, cbuf->data + cbuf->get, (char*)cbuf, cbuf->nb); ldisc->receive_buf(serial_driver, bluetooth_buf, (char*)cbuf, len); } chan->receive = 0; return; } #endif #if CYGINT_IO_SERIAL_BLOCK_TRANSFER CYG_ASSERT(false == cbuf->block_mode_xfer_running, "Attempting char rcv while block transfer is running"); #endif #ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE // for software flow control, if the driver returns one of the characters // we act on it and then drop it (the app must not see it) if ( chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_TX ) { if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR ) { throttle_tx( chan ); return; // it wasn't a "real" character } else if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR ) { restart_tx( chan ); return; // it wasn't a "real" character } } #endif #ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL // If we've hit the high water mark, tell the other side to stop if ( cbuf->nb >= cbuf->high_water ) { throttle_rx( chan, false ); } #endif #ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT // Wake up any pending selectors if we are about to // put some data into a previously empty buffer. if( cbuf->nb == 0 ) cyg_selwakeup( &cbuf->selinfo ); #endif // If the flow control is not enabled/sufficient and the buffer is // already full, just throw new characters away. if ( cbuf->nb < cbuf->len ) { cbuf->data[cbuf->put++] = c; if (cbuf->put == cbuf->len) cbuf->put = 0; cbuf->nb++; } // note trailing else #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS else { // Overrun. Report the error. cyg_serial_line_status_t stat; stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR; serial_indicate_status(chan, &stat); } #endif if (cbuf->waiting) { #ifdef XX_CYGDBG_DIAG_BUF extern int enable_diag_uart; int _enable = enable_diag_uart; int _time, _stime; externC cyg_tick_count_t cyg_current_time(void); enable_diag_uart = 0; HAL_CLOCK_READ(&_time); _stime = (int)cyg_current_time(); diag_printf("Signal reader - time: %x.%x\n", _stime, _time); enable_diag_uart = _enable; #endif // CYGDBG_DIAG_BUF cbuf->waiting = false; cyg_drv_cond_signal(&cbuf->wait); } }
static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len) { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; serial_channel *chan = (serial_channel *)t->priv; cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf; Cyg_ErrNo res = ENOERR; cbuf_t *out_cbuf = &chan->out_cbuf; cbuf_t *in_cbuf = &chan->in_cbuf; serial_funs *funs = chan->funs; switch (key) { case CYG_IO_GET_CONFIG_SERIAL_INFO: if (*len < sizeof(cyg_serial_info_t)) { return -EINVAL; } *buf = chan->config; *len = sizeof(chan->config); break; case CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO: // return rx/tx buffer sizes and counts { cyg_serial_buf_info_t *p; if (*len < sizeof(cyg_serial_buf_info_t)) return -EINVAL; *len = sizeof(cyg_serial_buf_info_t); p = (cyg_serial_buf_info_t *)xbuf; p->rx_bufsize = in_cbuf->len; if (p->rx_bufsize) p->rx_count = in_cbuf->nb; else p->rx_count = 0; p->tx_bufsize = out_cbuf->len; if (p->tx_bufsize) p->tx_count = out_cbuf->nb; else p->tx_count = 0; } break; case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN: // Wait for any pending output to complete if (out_cbuf->len == 0) break; // Nothing to do if not buffered cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing cyg_drv_dsr_lock();//dsr lock, it will lead to dsr interrupt can't be called; and serial_xmt_char can't be called forever while (out_cbuf->pending || (out_cbuf->nb > 0)) { //clyu //these codes will race with serial_xmt_char(cyg_drv_cond_broadcast) //if modify w90n740_serial_putc(...) return true always, these code will not run out_cbuf->waiting = true; if(!cyg_drv_cond_wait(&out_cbuf->wait) ) res = -EINTR; } cyg_drv_dsr_unlock(); cyg_drv_mutex_unlock(&out_cbuf->lock); break; case CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH: // Flush any buffered input if (in_cbuf->len == 0) break; // Nothing to do if not buffered cyg_drv_mutex_lock(&in_cbuf->lock); // Stop any further input processing cyg_drv_dsr_lock(); if (in_cbuf->waiting) { in_cbuf->abort = true; cyg_drv_cond_signal(&in_cbuf->wait); in_cbuf->waiting = false; } in_cbuf->get = in_cbuf->put = in_cbuf->nb = 0; // Flush buffered input cyg_drv_dsr_unlock(); cyg_drv_mutex_unlock(&in_cbuf->lock); break; case CYG_IO_GET_CONFIG_SERIAL_ABORT: // Abort any outstanding I/O, including blocked reads // Caution - assumed to be called from 'timeout' (i.e. DSR) code if (in_cbuf->len != 0) { in_cbuf->abort = true; cyg_drv_cond_signal(&in_cbuf->wait); } if (out_cbuf->len != 0) { out_cbuf->abort = true; cyg_drv_cond_signal(&out_cbuf->wait); } break; case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH: // Throw away any pending output if (out_cbuf->len == 0) break; // Nothing to do if not buffered cyg_drv_mutex_lock(&out_cbuf->lock); // Stop any further output processing cyg_drv_dsr_lock(); if (out_cbuf->nb > 0) { out_cbuf->get = out_cbuf->put = out_cbuf->nb = 0; // Empties queue! (funs->stop_xmit)(chan); // Done with transmit } if (out_cbuf->waiting) { out_cbuf->abort = true; cyg_drv_cond_signal(&out_cbuf->wait); out_cbuf->waiting = false; } cyg_drv_dsr_unlock(); cyg_drv_mutex_unlock(&out_cbuf->lock); break; #ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING case CYG_IO_GET_CONFIG_READ_BLOCKING: if (*len < sizeof(cyg_uint32)) { return -EINVAL; } *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0; break; case CYG_IO_GET_CONFIG_WRITE_BLOCKING: if (*len < sizeof(cyg_uint32)) { return -EINVAL; } *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0; break; #endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING default: res = -EINVAL; } return res; }
static Cyg_ErrNo disk_bwrite(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len, // In blocks cyg_uint32 pos) // In blocks { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *) handle; disk_channel *chan = (disk_channel *) t->priv; disk_controller *ctlr = chan->controller; disk_funs *funs = chan->funs; cyg_disk_info_t *info = chan->info; cyg_uint32 size = *len; cyg_uint8 *bbuf = (cyg_uint8 * const) buf; Cyg_ErrNo res = ENOERR; cyg_uint32 last; cyg_drv_mutex_lock( &ctlr->lock ); while( ctlr->busy ) cyg_drv_cond_wait( &ctlr->queue ); if (info->connected && chan->valid) { ctlr->busy = true; if (NULL != chan->partition) { pos += chan->partition->start; last = chan->partition->end; } else { last = info->blocks_num-1; } D(("disk write block=%d len=%d buf=%p\n", pos, *len, buf)); while( size > 0 ) { cyg_uint32 tfr = size; if (pos > last) { res = -EIO; goto done; } if( tfr > info->ident.max_transfer ) tfr = info->ident.max_transfer; ctlr->result = -EWOULDBLOCK; cyg_drv_dsr_lock(); res = (funs->write)(chan, (void*)bbuf, tfr, pos); if( res == -EWOULDBLOCK ) { // If the driver replys EWOULDBLOCK, then the transfer is // being handled asynchronously and when it is finished it // will call disk_transfer_done(). This will wake us up here // to continue. while( ctlr->result == -EWOULDBLOCK ) cyg_drv_cond_wait( &ctlr->async ); res = ctlr->result; } cyg_drv_dsr_unlock(); if (ENOERR != res) goto done; if (!info->connected) { res = -EINVAL; goto done; } bbuf += tfr * info->block_size; pos += tfr; size -= tfr; } ctlr->busy = false; cyg_drv_cond_signal( &ctlr->queue ); } else res = -EINVAL; done: cyg_drv_mutex_unlock( &ctlr->lock ); #ifdef CYGPKG_KERNEL cyg_thread_yield(); #endif *len -= size; return res; }