int serial8250_tx_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; struct circ_buf *xmit = &p->port.state->xmit; struct dma_async_tx_descriptor *desc; if (dma->tx_running) { uart_write_wakeup(&p->port); return -EBUSY; } dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, dma->tx_size, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) return -EBUSY; dma->tx_running = 1; desc->callback = __dma_tx_complete; desc->callback_param = p; dma->tx_cookie = dmaengine_submit(desc); dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); dma_async_issue_pending(dma->txchan); return 0; }
static int copy_sleep_history(struct sleep_history *buf, int count) { int c, err; int head, tail; struct sleep_history *ring_buf; if (!buf) { err = -EINVAL; goto err_invalid; } memset(buf, 0, count * sizeof(struct sleep_history)); ring_buf = (struct sleep_history *)(sleep_history_data.sleep_history.buf); head = sleep_history_data.sleep_history.head; tail = sleep_history_data.sleep_history.tail; c = CIRC_CNT(head, tail, SLEEP_HISTORY_RINGBUFFER_SIZE); if (c == 0) { err = -EINVAL; goto err_read; } else if (c == SLEEP_HISTORY_RINGBUFFER_SIZE - 1) { c = CIRC_CNT_TO_END(head, tail, SLEEP_HISTORY_RINGBUFFER_SIZE); memcpy(buf, ring_buf + tail, c * sizeof(struct sleep_history)); memcpy(buf + c, ring_buf, (SLEEP_HISTORY_RINGBUFFER_SIZE-c) * sizeof(struct sleep_history)); c = SLEEP_HISTORY_RINGBUFFER_SIZE - 1; } else memcpy(buf, ring_buf + tail, c * sizeof(struct sleep_history)); return c; err_invalid: err_read: return err; }
/* Called with u->lock taken */ static void tegra_start_next_tx(struct tegra_uart_port *t) { unsigned long tail; unsigned long count; struct circ_buf *xmit; xmit = &t->uport.state->xmit; tail = (unsigned long)&xmit->buf[xmit->tail]; count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); dev_vdbg(t->uport.dev, "+%s %lu %d\n", __func__, count, t->tx_in_progress); if (count == 0) goto out; if (!t->use_tx_dma || count < TEGRA_UART_MIN_DMA) tegra_start_pio_tx(t, count); else if (BYTES_TO_ALIGN(tail) > 0) tegra_start_pio_tx(t, BYTES_TO_ALIGN(tail)); else tegra_start_dma_tx(t, count); out: dev_vdbg(t->uport.dev, "-%s", __func__); }
static void uart_task_action(unsigned long data) { struct uart_pxa_port *up = (struct uart_pxa_port *)data; struct circ_buf *xmit = &up->port.state->xmit; unsigned char *tmp = up->uart_dma.txdma_addr; unsigned long flags; int count = 0, c; /* if the tx is stop, just return.*/ if (up->uart_dma.tx_stop) return; spin_lock_irqsave(&up->port.lock, flags); if (up->uart_dma.dma_status & TX_DMA_RUNNING) { spin_unlock_irqrestore(&up->port.lock, flags); return; } up->uart_dma.dma_status |= TX_DMA_RUNNING; while (1) { c = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (c <= 0) break; memcpy(tmp, xmit->buf + xmit->tail, c); xmit->tail = (xmit->tail + c) & (UART_XMIT_SIZE - 1); tmp += c; count += c; up->port.icount.tx += c; } spin_unlock_irqrestore(&up->port.lock, flags); pr_debug("count =%d", count); pxa_uart_transmit_dma_start(up, count); }
static int stmp_appuart_copy_tx(struct uart_port *u, u8 *target, int tx_buffer_size) { int last = 0, portion; struct circ_buf *xmit = &u->info->xmit; while (last < tx_buffer_size) { /* let's fill the only descriptor */ if (u->x_char) { target[last++] = u->x_char; u->x_char = 0; } else if (!uart_circ_empty(xmit) && !uart_tx_stopped(u)) { portion = min((u32)tx_buffer_size, (u32)uart_circ_chars_pending(xmit)); portion = min((u32)portion, (u32)CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); memcpy(target + last, &xmit->buf[xmit->tail], portion); xmit->tail = (xmit->tail + portion) & (UART_XMIT_SIZE - 1); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(u); last += portion; } else { /* All tx data copied into buffer */ return last; } } return last; }
static int spi_read(struct bathos_pipe *pipe, char *buf, int len) { struct spi_data *data = &spi_data; int flags; int l; interrupt_disable(flags); l = min(len, CIRC_CNT_TO_END(data->cbufrx.head, data->cbufrx.tail, SPI_BUF_SIZE)); if (!l) { interrupt_restore(flags); return -EAGAIN; } memcpy(buf, &data->bufrx[data->cbufrx.tail], l); data->cbufrx.tail = (data->cbufrx.tail + l) & (SPI_BUF_SIZE - 1); data->overrun = 0; if (CIRC_CNT(data->cbufrx.head, data->cbufrx.tail, SPI_BUF_SIZE)) pipe_dev_trigger_event(&__spi_dev, &evt_pipe_input_ready, EVT_PRIO_MAX); interrupt_restore(flags); return l; }
/******************************************************************************** * Description: * Input Args: * Output Args: * Return Value: ********************************************************************************/ int main (int argc, char **argv) { int i, len; struct circ_buf tx_ring; char data[LEN]; char buf[LEN]; memset(&tx_ring, 0, sizeof(struct circ_buf)); tx_ring.buf = malloc(CIRC_BUF_SIZE); if( NULL == tx_ring.buf ) { printf("Allocate Ring buffer failure.\n"); return -1; } memset(data, 0, sizeof(data)); /* Prepare for the data */ for(i=0; i<sizeof(data); i++) { data[i] = 30+i; } printf("CIRC_SPACE: %d\n", CIRC_SPACE(tx_ring.head, tx_ring.tail, CIRC_BUF_SIZE)); printf("CIRC_SPACE_TO_END: %d\n", CIRC_SPACE_TO_END(tx_ring.head, tx_ring.tail, CIRC_BUF_SIZE)); printf("CIRC_CNT: %d\n", CIRC_CNT(tx_ring.head, tx_ring.tail, CIRC_BUF_SIZE)); printf("CIRC_CNT_TO_END: %d\n", CIRC_CNT_TO_END(tx_ring.head, tx_ring.tail, CIRC_BUF_SIZE)); while(1) { produce_item(&tx_ring, data, sizeof(data)); len = consume_item(&tx_ring, buf, sizeof(buf) ); sleep(1); } return 0; } /* ----- End of main() ----- */
static ssize_t userio_char_read(struct file *file, char __user *user_buffer, size_t count, loff_t *ppos) { struct userio_device *userio = file->private_data; int error; size_t nonwrap_len, copylen; unsigned char buf[USERIO_BUFSIZE]; unsigned long flags; /* * By the time we get here, the data that was waiting might have * been taken by another thread. Grab the buffer lock and check if * there's still any data waiting, otherwise repeat this process * until we have data (unless the file descriptor is non-blocking * of course). */ for (;;) { spin_lock_irqsave(&userio->buf_lock, flags); nonwrap_len = CIRC_CNT_TO_END(userio->head, userio->tail, USERIO_BUFSIZE); copylen = min(nonwrap_len, count); if (copylen) { memcpy(buf, &userio->buf[userio->tail], copylen); userio->tail = (userio->tail + copylen) % USERIO_BUFSIZE; } spin_unlock_irqrestore(&userio->buf_lock, flags); if (nonwrap_len) break; /* buffer was/is empty */ if (file->f_flags & O_NONBLOCK) return -EAGAIN; /* * count == 0 is special - no IO is done but we check * for error conditions (see above). */ if (count == 0) return 0; error = wait_event_interruptible(userio->waitq, userio->head != userio->tail); if (error) return error; } if (copylen) if (copy_to_user(user_buffer, buf, copylen)) return -EFAULT; return copylen; }
size_t whitebox_user_source_data_available(struct whitebox_user_source *user_source, unsigned long *src) { long head, tail, data; head = ACCESS_ONCE(user_source->buf.head); tail = user_source->buf.tail; data = CIRC_CNT_TO_END(head, tail, user_source->buf_size); d_printk(7, "%ld\n", data); *src = (long)user_source->buf.buf + tail; return data; }
int serial8250_tx_dma(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; struct circ_buf *xmit = &p->port.state->xmit; struct dma_async_tx_descriptor *desc; int ret; if (dma->tx_running) return 0; if (uart_tx_stopped(&p->port) || uart_circ_empty(xmit)) { /* We have been called from __dma_tx_complete() */ serial8250_rpm_put_tx(p); return 0; } dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); desc = dmaengine_prep_slave_single(dma->txchan, dma->tx_addr + xmit->tail, dma->tx_size, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { ret = -EBUSY; goto err; } dma->tx_running = 1; desc->callback = __dma_tx_complete; desc->callback_param = p; dma->tx_cookie = dmaengine_submit(desc); dma_sync_single_for_device(dma->txchan->device->dev, dma->tx_addr, UART_XMIT_SIZE, DMA_TO_DEVICE); dma_async_issue_pending(dma->txchan); if (dma->tx_err) { dma->tx_err = 0; if (p->ier & UART_IER_THRI) { p->ier &= ~UART_IER_THRI; serial_out(p, UART_IER, p->ier); } } return 0; err: dma->tx_err = 1; return ret; }
static int sprd_tx_buf_remap(struct uart_port *port) { struct sprd_uart_port *sp = container_of(port, struct sprd_uart_port, port); struct circ_buf *xmit = &port->state->xmit; sp->tx_dma.trans_len = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); sp->tx_dma.phys_addr = dma_map_single(port->dev, (void *)&(xmit->buf[xmit->tail]), sp->tx_dma.trans_len, DMA_TO_DEVICE); return dma_mapping_error(port->dev, sp->tx_dma.phys_addr); }
static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit) { while (!uart_circ_empty(xmit)) { unsigned long ra = __pa(xmit->buf + xmit->tail); unsigned long len, status, sent; len = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); status = sun4v_con_write(ra, len, &sent); if (status != HV_EOK) break; xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1); port->icount.tx += sent; } }
static void tegra_tcu_uart_start_tx(struct uart_port *port) { struct tegra_tcu *tcu = port->private_data; struct circ_buf *xmit = &port->state->xmit; unsigned long count; for (;;) { count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (!count) break; tegra_tcu_write(tcu, &xmit->buf[xmit->tail], count); xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); } uart_write_wakeup(port); }
static void l4ser_shm_tx_chars(struct uart_port *port) { struct l4ser_shm_uart_port *l4port = (struct l4ser_shm_uart_port *)port; struct circ_buf *xmit = &port->state->xmit; int c, do_trigger = 0; struct tty_struct *tty = port->state->port.tty; tty->hw_stopped = 0; tty->stopped = 0; if (port->x_char) { if (tx_buf(port, &port->x_char, 1)) { L4XV_V(f); port->icount.tx++; port->x_char = 0; L4XV_L(f); l4shmc_trigger(&l4port->tx_sig); L4XV_U(f); } return; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { return; } while (!uart_circ_empty(xmit)) { unsigned long r; c = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (!(r = tx_buf(port, &xmit->buf[xmit->tail], c))) break; xmit->tail = (xmit->tail + r) & (UART_XMIT_SIZE - 1); port->icount.tx += r; do_trigger = 1; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (do_trigger) { L4XV_V(f); L4XV_L(f); l4shmc_trigger(&l4port->tx_sig); L4XV_U(f); } }
/* * serial_buf_get * * Get data from the circular buffer and copy to the given buffer. * Restrict to the amount of data available. * * Return the number of bytes copied. */ static int serial_buf_get(struct circ_buf *cb, char *buf, int count) { int c, ret = 0; while (1) { c = CIRC_CNT_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(buf, cb->buf + cb->tail, c); cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1); buf += c; count -= c; ret= c; } return ret; }
static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj,struct device,kobj); struct Scsi_Host *host = class_to_shost(dev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; uint8_t *ptmpQbuffer; int32_t allxfer_len = 0; unsigned long flags; if (!capable(CAP_SYS_ADMIN)) return -EACCES; /* do message unit read. */ ptmpQbuffer = (uint8_t *)buf; spin_lock_irqsave(&acb->rqbuffer_lock, flags); if (acb->rqbuf_getIndex != acb->rqbuf_putIndex) { unsigned int tail = acb->rqbuf_getIndex; unsigned int head = acb->rqbuf_putIndex; unsigned int cnt_to_end = CIRC_CNT_TO_END(head, tail, ARCMSR_MAX_QBUFFER); allxfer_len = CIRC_CNT(head, tail, ARCMSR_MAX_QBUFFER); if (allxfer_len > ARCMSR_API_DATA_BUFLEN) allxfer_len = ARCMSR_API_DATA_BUFLEN; if (allxfer_len <= cnt_to_end) memcpy(ptmpQbuffer, acb->rqbuffer + tail, allxfer_len); else { memcpy(ptmpQbuffer, acb->rqbuffer + tail, cnt_to_end); memcpy(ptmpQbuffer + cnt_to_end, acb->rqbuffer, allxfer_len - cnt_to_end); } acb->rqbuf_getIndex = (acb->rqbuf_getIndex + allxfer_len) % ARCMSR_MAX_QBUFFER; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { struct QBUFFER __iomem *prbuffer; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; prbuffer = arcmsr_get_iop_rqbuffer(acb); if (arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; } spin_unlock_irqrestore(&acb->rqbuffer_lock, flags); return allxfer_len; }
void iforce_usb_xmit(struct iforce *iforce) { int n, c; unsigned long flags; spin_lock_irqsave(&iforce->xmit_lock, flags); if (iforce->xmit.head == iforce->xmit.tail) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); spin_unlock_irqrestore(&iforce->xmit_lock, flags); return; } ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); n = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); iforce->out->transfer_buffer_length = n + 1; iforce->out->dev = iforce->usbdev; /* Copy rest of data then */ c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE); if (n < c) c=n; memcpy(iforce->out->transfer_buffer + 1, &iforce->xmit.buf[iforce->xmit.tail], c); if (n != c) { memcpy(iforce->out->transfer_buffer + 1 + c, &iforce->xmit.buf[0], n-c); } XMIT_INC(iforce->xmit.tail, n); if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); dev_warn(&iforce->intf->dev, "usb_submit_urb failed %d\n", n); } /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended. * As long as the urb completion handler is not called, the transmiting * is considered to be running */ spin_unlock_irqrestore(&iforce->xmit_lock, flags); }
void hsu_dma_tx(struct uart_hsu_port *up) { struct circ_buf *xmit = &up->port.state->xmit; struct hsu_dma_buffer *dbuf = &up->txbuf; int count; /* test_and_set_bit may be better, but anyway it's in lock protected mode */ if (up->dma_tx_on) return; /* Update the circ buf info */ xmit->tail += dbuf->ofs; xmit->tail &= UART_XMIT_SIZE - 1; up->port.icount.tx += dbuf->ofs; dbuf->ofs = 0; /* Disable the channel */ chan_writel(up->txc, HSU_CH_CR, 0x0); if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) { dma_sync_single_for_device(up->port.dev, dbuf->dma_addr, dbuf->dma_size, DMA_TO_DEVICE); count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); dbuf->ofs = count; /* Reprogram the channel */ chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail); chan_writel(up->txc, HSU_CH_D0TSR, count); /* Reenable the channel */ chan_writel(up->txc, HSU_CH_DCR, 0x1 | (0x1 << 8) | (0x1 << 16) | (0x1 << 24)); up->dma_tx_on = 1; chan_writel(up->txc, HSU_CH_CR, 0x1); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); }
static void tegra_uart_start_next_tx(struct tegra_uart_port *tup) { unsigned long tail; unsigned long count; struct circ_buf *xmit = &tup->uport.state->xmit; tail = (unsigned long)&xmit->buf[xmit->tail]; count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (!count) return; if (count < TEGRA_UART_MIN_DMA) tegra_uart_start_pio_tx(tup, count); else if (BYTES_TO_ALIGN(tail) > 0) tegra_uart_start_pio_tx(tup, BYTES_TO_ALIGN(tail)); else tegra_uart_start_tx_dma(tup, count); }
/* Called with u->lock taken */ static void tegra_start_next_tx(struct tegra_uart_port *t) { unsigned long tail; unsigned long count; unsigned long lsr; struct uart_port *u = &t->uport; struct circ_buf *xmit; xmit = &t->uport.state->xmit; tail = (unsigned long)&xmit->buf[xmit->tail]; count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); dev_vdbg(t->uport.dev, "+%s %lu %d\n", __func__, count, t->tx_in_progress); if (count == 0) { if (t->is_irda && !irda_loop) { do { lsr = uart_readb(t, UART_LSR); if (lsr & UART_LSR_TEMT) break; } while (1); tegra_start_rx(u); } goto out; } if (t->is_irda && !irda_loop) { if (t->rx_in_progress) tegra_stop_rx(u); } if (!t->use_tx_dma || count < TEGRA_UART_MIN_DMA) tegra_start_pio_tx(t, count); else if (BYTES_TO_ALIGN(tail) > 0) tegra_start_pio_tx(t, BYTES_TO_ALIGN(tail)); else tegra_start_dma_tx(t, count); out: dev_vdbg(t->uport.dev, "-%s", __func__); }
void iforce_usb_xmit(struct iforce *iforce) { int n, c; unsigned long flags; spin_lock_irqsave(&iforce->xmit_lock, flags); if (iforce->xmit.head == iforce->xmit.tail) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); spin_unlock_irqrestore(&iforce->xmit_lock, flags); return; } ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); n = iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); iforce->out->transfer_buffer_length = n + 1; iforce->out->dev = iforce->usbdev; c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE); if (n < c) c=n; memcpy(iforce->out->transfer_buffer + 1, &iforce->xmit.buf[iforce->xmit.tail], c); if (n != c) { memcpy(iforce->out->transfer_buffer + 1 + c, &iforce->xmit.buf[0], n-c); } XMIT_INC(iforce->xmit.tail, n); if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) { clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); dev_warn(&iforce->dev->dev, "usb_submit_urb failed %d\n", n); } spin_unlock_irqrestore(&iforce->xmit_lock, flags); }
static int uart_read(struct bathos_pipe *pipe, char *buf, int len) { struct uart_data *data = &uart_data; int l; l = min(len, CIRC_CNT_TO_END(data->cbuf.head, data->cbuf.tail, UART_BUF_SIZE)); if (!l) return -EAGAIN; memcpy(buf, &data->buf[data->cbuf.tail], l); data->cbuf.tail = (data->cbuf.tail + l) & (UART_BUF_SIZE - 1); data->overrun = 0; if (CIRC_CNT(data->cbuf.head, data->cbuf.tail, UART_BUF_SIZE)) pipe_dev_trigger_event(&__uart_dev, &evt_pipe_input_ready, EVT_PRIO_MAX); return l; }
int consume_item(struct circ_buf *ring, char *buf, int count) { int len = 0; int i, left, size; int to_end_space=0; if ( (size=CIRC_CNT(ring->head, ring->tail, CIRC_BUF_SIZE)) >= 1 ) { left = len = count<=size ? count : size; to_end_space = CIRC_CNT_TO_END(ring->head, ring->tail, CIRC_BUF_SIZE); if(left > to_end_space) { memcpy(buf, &(ring->buf[ring->tail]), to_end_space); for(i=0; i<to_end_space; i++) { printf("consume_item %02d bytes: ring->buf[%02d]=%d\n", to_end_space, ring->tail+i, ring->buf[ring->tail+i]); } ring->tail = (ring->tail + to_end_space) & (CIRC_BUF_SIZE - 1); left -= to_end_space; } else { to_end_space = 0; } memcpy(&buf[to_end_space], &(ring->buf[ring->tail]), left); for(i=0; i<left; i++) { printf("consume_item %02d bytes: ring->buf[%02d]=%d\n", left, ring->tail+i, ring->buf[ring->tail+i]); } ring->tail = (ring->tail + left) & (CIRC_BUF_SIZE - 1); } for(i=0; i<len; i++) printf("output_data %02d bytes: buf[%02d]=%d\n", len, i, buf[i]); printf("-----------------------------------------------------------------------------------------------\n"); return len; }
static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport) { struct uart_port *port = &ourport->port; struct circ_buf *xmit = &port->state->xmit; unsigned long count; /* Get data size up to the end of buffer */ count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (!count) { s3c24xx_serial_stop_tx(port); return; } if (!ourport->dma || !ourport->dma->tx_chan || count < ourport->min_dma_size || xmit->tail & (dma_get_cache_alignment() - 1)) s3c24xx_serial_start_tx_pio(ourport); else s3c24xx_serial_start_tx_dma(ourport, count); }
void d_printk_loop(int level) { unsigned long src; struct circ_buf *mock_buf = &whitebox_device->mock_buf; struct whitebox_user_sink *user_sink = &whitebox_device->user_sink; struct whitebox_user_source *user_source = &whitebox_device->user_source; struct whitebox_rf_sink *rf_sink = &whitebox_device->rf_sink; struct whitebox_rf_source *rf_source = &whitebox_device->rf_source; u32 exciter_state = rf_sink->exciter->ops->get_state(rf_sink->exciter); u32 receiver_state = rf_source->receiver->ops->get_state(rf_source->receiver); d_printk(level, "stats %c%c user_source_data/space=%d/%d rf_sink_space=%d mock_data/space=%d/%d rf_source_data=%d user_sink_data/space=%d/%d\n", exciter_state & WES_TXEN ? 'T' : ' ', receiver_state & WRS_RXEN ? 'R' : ' ', whitebox_user_source_data_available(user_source, &src), whitebox_user_source_space_available(user_source, &src), whitebox_rf_sink_space_available(rf_sink, &src), CIRC_CNT_TO_END(mock_buf->head, mock_buf->tail, PAGE_SIZE << whitebox_mock_order), CIRC_SPACE_TO_END(mock_buf->head, mock_buf->tail, PAGE_SIZE << whitebox_mock_order), whitebox_rf_source_data_available(rf_source, &src), whitebox_user_sink_data_available(user_sink, &src), whitebox_user_sink_space_available(user_sink, &src)); }
static unsigned _fifo_read(struct m_fifo *q, void *dst, unsigned count, copyfunc copy) { unsigned n; unsigned head = *q->head; unsigned tail = *q->tail; unsigned size = q->size; if (CIRC_CNT(head, tail, size) < count) return 0; n = CIRC_CNT_TO_END(head, tail, size); if (likely(n >= count)) { copy(dst, q->data + tail, count); } else { copy(dst, q->data + tail, n); copy(dst + n, q->data, count - n); } //*q->tail = (tail + count) & (size - 1); return count; }
static void genode_serial_tx_chars(struct uart_port *port) { struct genode_uart_port *l4port = (struct genode_uart_port *)port; struct circ_buf *xmit = &port->state->xmit; unsigned long flags; unsigned c; if (port->x_char) { local_irq_save(flags); genode_terminal_writechar(l4port->idx, &port->x_char, sizeof(char)); local_irq_restore(flags); port->icount.tx++; port->x_char = 0; return; } while (!uart_circ_empty(xmit)) { c = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); local_irq_save(flags); genode_terminal_writechar(l4port->idx, &xmit->buf[xmit->tail], c); local_irq_restore(flags); xmit->tail = (xmit->tail + c) & (UART_XMIT_SIZE - 1); port->icount.tx += c; } }
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) { struct s3c24xx_uart_port *ourport = id; struct uart_port *port = &ourport->port; struct circ_buf *xmit = &port->state->xmit; unsigned long flags; int count, dma_count = 0; spin_lock_irqsave(&port->lock, flags); count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (ourport->dma && ourport->dma->tx_chan && count >= ourport->min_dma_size) { int align = dma_get_cache_alignment() - (xmit->tail & (dma_get_cache_alignment() - 1)); if (count-align >= ourport->min_dma_size) { dma_count = count-align; count = align; } } if (port->x_char) { wr_regb(port, S3C2410_UTXH, port->x_char); port->icount.tx++; port->x_char = 0; goto out; } /* if there isn't anything more to transmit, or the uart is now * stopped, disable the uart and exit */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { s3c24xx_serial_stop_tx(port); goto out; } /* try and drain the buffer... */ if (count > port->fifosize) { count = port->fifosize; dma_count = 0; } while (!uart_circ_empty(xmit) && count > 0) { if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull) break; wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; count--; } if (!count && dma_count) { s3c24xx_serial_start_tx_dma(ourport, dma_count); goto out; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { spin_unlock(&port->lock); uart_write_wakeup(port); spin_lock(&port->lock); } if (uart_circ_empty(xmit)) s3c24xx_serial_stop_tx(port); out: spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; }
static void sirfsoc_uart_tx_with_dma(struct sirfsoc_uart_port *sirfport) { struct uart_port *port = &sirfport->port; struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg; struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en; struct circ_buf *xmit = &port->state->xmit; unsigned long tran_size; unsigned long tran_start; unsigned long pio_tx_size; tran_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); tran_start = (unsigned long)(xmit->buf + xmit->tail); if (uart_circ_empty(xmit) || uart_tx_stopped(port) || !tran_size) return; if (sirfport->tx_dma_state == TX_DMA_PAUSE) { dmaengine_resume(sirfport->tx_dma_chan); return; } if (sirfport->tx_dma_state == TX_DMA_RUNNING) return; if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg)& ~(uint_en->sirfsoc_txfifo_empty_en)); else wr_regl(port, SIRFUART_INT_EN_CLR, uint_en->sirfsoc_txfifo_empty_en); /* * DMA requires buffer address and buffer length are both aligned with * 4 bytes, so we use PIO for * 1. if address is not aligned with 4bytes, use PIO for the first 1~3 * bytes, and move to DMA for the left part aligned with 4bytes * 2. if buffer length is not aligned with 4bytes, use DMA for aligned * part first, move to PIO for the left 1~3 bytes */ if (tran_size < 4 || BYTES_TO_ALIGN(tran_start)) { wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP); wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl)| SIRFUART_IO_MODE); if (BYTES_TO_ALIGN(tran_start)) { pio_tx_size = sirfsoc_uart_pio_tx_chars(sirfport, BYTES_TO_ALIGN(tran_start)); tran_size -= pio_tx_size; } if (tran_size < 4) sirfsoc_uart_pio_tx_chars(sirfport, tran_size); if (!sirfport->is_atlas7) wr_regl(port, ureg->sirfsoc_int_en_reg, rd_regl(port, ureg->sirfsoc_int_en_reg)| uint_en->sirfsoc_txfifo_empty_en); else wr_regl(port, ureg->sirfsoc_int_en_reg, uint_en->sirfsoc_txfifo_empty_en); wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START); } else { /* tx transfer mode switch into dma mode */ wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_STOP); wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, rd_regl(port, ureg->sirfsoc_tx_dma_io_ctrl)& ~SIRFUART_IO_MODE); wr_regl(port, ureg->sirfsoc_tx_fifo_op, SIRFUART_FIFO_START); tran_size &= ~(0x3); sirfport->tx_dma_addr = dma_map_single(port->dev, xmit->buf + xmit->tail, tran_size, DMA_TO_DEVICE); sirfport->tx_dma_desc = dmaengine_prep_slave_single( sirfport->tx_dma_chan, sirfport->tx_dma_addr, tran_size, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); if (!sirfport->tx_dma_desc) { dev_err(port->dev, "DMA prep slave single fail\n"); return; } sirfport->tx_dma_desc->callback = sirfsoc_uart_tx_dma_complete_callback; sirfport->tx_dma_desc->callback_param = (void *)sirfport; sirfport->transfer_size = tran_size; dmaengine_submit(sirfport->tx_dma_desc); dma_async_issue_pending(sirfport->tx_dma_chan); sirfport->tx_dma_state = TX_DMA_RUNNING; } }
static void ev3_uart_handle_rx_data(struct work_struct *work) { struct ev3_uart_port_data *port = container_of(work, struct ev3_uart_port_data, rx_data_work); struct circ_buf *cb = &port->circ_buf; u8 message[EV3_UART_MAX_MESSAGE_SIZE + 2]; int count = CIRC_CNT(cb->head, cb->tail, EV3_UART_BUFFER_SIZE); int i, speed, size_to_end; u8 cmd, cmd2, type, mode, msg_type, msg_size, chksum; #ifdef DEBUG printk("received: "); for (i = 0; i < count; i++) { cmd = cb->buf[(cb->tail + i) % EV3_UART_BUFFER_SIZE]; if (cmd >= 32 && cmd < 127) printk("%c ", cmd); else printk("0x%02x ", cmd); } printk("(%d)\n", count); #endif /* * To get in sync with the data stream from the sensor, we look * for a valid TYPE command. */ while (!port->synced) { if (count < 3) return; cmd = cb->buf[cb->tail]; cb->tail++; if (cb->tail >= EV3_UART_BUFFER_SIZE) cb->tail = 0; count--; if (cmd != (EV3_UART_MSG_TYPE_CMD | EV3_UART_CMD_TYPE)) continue; type = cb->buf[cb->tail]; if (!type || type > EV3_UART_TYPE_MAX) continue; chksum = 0xFF ^ cmd ^ type; if ((u8)cb->buf[(cb->tail + 1) % EV3_UART_BUFFER_SIZE] != chksum) continue; port->sensor.num_modes = 1; port->sensor.num_view_modes = 1; for (i = 0; i <= EV3_UART_MODE_MAX; i++) port->mode_info[i] = ev3_uart_default_mode_info; port->type_id = type; /* look up well-known driver names */ port->device_name[0] = 0; for (i = 0; i < NUM_LEGO_EV3_SENSOR_TYPES; i++) { if (type == ev3_uart_sensor_defs[i].type_id) { snprintf(port->device_name, LEGO_SENSOR_NAME_SIZE, "%s", ev3_uart_sensor_defs[i].name); break; } } /* or use generic name if well-known name is not found */ if (!port->device_name[0]) snprintf(port->device_name, LEGO_SENSOR_NAME_SIZE, EV3_UART_SENSOR_NAME("%u"), type); port->info_flags = EV3_UART_INFO_FLAG_CMD_TYPE; port->synced = 1; port->info_done = 0; port->data_rec = 0; port->num_data_err = 0; cb->tail = (cb->tail + 2) % EV3_UART_BUFFER_SIZE; count -= 2; } if (!port->synced) return; while (count > 0) { /* * Sometimes we get 0xFF after switching baud rates, so just * ignore it. */ if ((u8)cb->buf[cb->tail] == 0xFF) { cb->tail++; if (cb->tail >= EV3_UART_BUFFER_SIZE) cb->tail = 0; count--; continue; } msg_size = ev3_uart_msg_size((u8)cb->buf[cb->tail]); if (msg_size > count) break; size_to_end = CIRC_CNT_TO_END(cb->head, cb->tail, EV3_UART_BUFFER_SIZE); if (msg_size > size_to_end) { memcpy(message, cb->buf + cb->tail, size_to_end); memcpy(message + size_to_end, cb->buf, msg_size - size_to_end); cb->tail = msg_size - size_to_end; } else { memcpy(message, cb->buf + cb->tail, msg_size); cb->tail += msg_size; if (cb->tail >= EV3_UART_BUFFER_SIZE) cb->tail = 0; } count -= msg_size; #ifdef DEBUG printk("processing: "); for (i = 0; i < msg_size; i++) printk("0x%02x ", message[i]); printk(" (%d)\n", msg_size); #endif if (msg_size > EV3_UART_MAX_MESSAGE_SIZE) { port->last_err = "Bad message size."; goto err_invalid_state; } msg_type = message[0] & EV3_UART_MSG_TYPE_MASK; cmd = message[0] & EV3_UART_MSG_CMD_MASK; mode = cmd; cmd2 = message[1]; if (msg_size > 1) { chksum = 0xFF; for (i = 0; i < msg_size - 1; i++) chksum ^= message[i]; debug_pr("chksum:%d, actual:%d\n", chksum, message[msg_size - 1]); /* * The LEGO EV3 color sensor sends bad checksums * for RGB-RAW data (mode 4). The check here could be * improved if someone can find a pattern. */ if (chksum != message[msg_size - 1] && port->type_id != EV3_UART_TYPE_ID_COLOR && message[0] != 0xDC) { port->last_err = "Bad checksum."; if (port->info_done) { port->num_data_err++; goto err_bad_data_msg_checksum; } else goto err_invalid_state; } } switch (msg_type) { case EV3_UART_MSG_TYPE_SYS: debug_pr("SYS:%d\n", message[0] & EV3_UART_MSG_CMD_MASK); switch(cmd) { case EV3_UART_SYS_SYNC: /* IR sensor (type 33) sends checksum after SYNC */ if (msg_size > 1 && (cmd ^ cmd2) == 0xFF) msg_size++; break; case EV3_UART_SYS_ACK: if (!port->sensor.num_modes) { port->last_err = "Received ACK before all mode INFO."; goto err_invalid_state; } if ((port->info_flags & EV3_UART_INFO_FLAG_REQUIRED) != EV3_UART_INFO_FLAG_REQUIRED) { port->last_err = "Did not receive all required INFO."; goto err_invalid_state; } schedule_delayed_work(&port->send_ack_work, msecs_to_jiffies(EV3_UART_SEND_ACK_DELAY)); port->info_done = 1; return; } break; case EV3_UART_MSG_TYPE_CMD: debug_pr("CMD:%d\n", cmd); switch (cmd) { case EV3_UART_CMD_MODES: if (test_and_set_bit(EV3_UART_INFO_BIT_CMD_MODES, &port->info_flags)) { port->last_err = "Received duplicate modes INFO."; goto err_invalid_state; } if (!cmd2 || cmd2 > EV3_UART_MODE_MAX) { port->last_err = "Number of modes is out of range."; goto err_invalid_state; } port->sensor.num_modes = cmd2 + 1; if (msg_size > 3) port->sensor.num_view_modes = message[2] + 1; else port->sensor.num_view_modes = port->sensor.num_modes; debug_pr("num_modes:%d, num_view_modes:%d\n", port->sensor.num_modes, port->sensor.num_view_modes); break; case EV3_UART_CMD_SPEED: if (test_and_set_bit(EV3_UART_INFO_BIT_CMD_SPEED, &port->info_flags)) { port->last_err = "Received duplicate speed INFO."; goto err_invalid_state; } speed = *(int*)(message + 1); if (speed < EV3_UART_SPEED_MIN || speed > EV3_UART_SPEED_MAX) { port->last_err = "Speed is out of range."; goto err_invalid_state; } port->new_baud_rate = speed; debug_pr("speed:%d\n", speed); break; default: port->last_err = "Unknown command."; goto err_invalid_state; } break; case EV3_UART_MSG_TYPE_INFO: debug_pr("INFO:%d, mode:%d\n", cmd2, mode); switch (cmd2) { case EV3_UART_INFO_NAME: port->info_flags &= ~EV3_UART_INFO_FLAG_ALL_INFO; if (message[2] < 'A' || message[2] > 'z') { port->last_err = "Invalid name INFO."; goto err_invalid_state; } /* * Name may not have null terminator and we * are done with the checksum at this point * so we are writing 0 over the checksum to * ensure a null terminator for the string * functions. */ message[msg_size - 1] = 0; if (strlen(message + 2) > EV3_UART_MODE_NAME_SIZE) { port->last_err = "Name is too long."; goto err_invalid_state; } snprintf(port->mode_info[mode].name, EV3_UART_MODE_NAME_SIZE + 1, "%s", message + 2); if (port->sensor.mode != mode) { port->sensor.mode = mode; kobject_uevent(&port->sensor.dev.kobj, KOBJ_CHANGE); } port->info_flags |= EV3_UART_INFO_FLAG_INFO_NAME; debug_pr("mode %d name:%s\n", mode, port->sensor.address); break; case EV3_UART_INFO_RAW: if (port->sensor.mode != mode) { port->last_err = "Received INFO for incorrect mode."; goto err_invalid_state; } if (test_and_set_bit(EV3_UART_INFO_BIT_INFO_RAW, &port->info_flags)) { port->last_err = "Received duplicate raw scaling INFO."; goto err_invalid_state; } port->raw_min = *(u32 *)(message + 2); port->raw_max = *(u32 *)(message + 6); debug_pr("mode %d raw_min:%08x, raw_max:%08x\n", mode, port->mode_info[mode].raw_min, port->mode_info[mode].raw_max); break; case EV3_UART_INFO_PCT: if (port->sensor.mode != mode) { port->last_err = "Received INFO for incorrect mode."; goto err_invalid_state; } if (test_and_set_bit(EV3_UART_INFO_BIT_INFO_PCT, &port->info_flags)) { port->last_err = "Received duplicate percent scaling INFO."; goto err_invalid_state; } port->pct_min = *(u32 *)(message + 2); port->pct_max = *(u32 *)(message + 6); debug_pr("mode %d pct_min:%08x, pct_max:%08x\n", mode, port->mode_info[mode].pct_min, port->mode_info[mode].pct_max); break; case EV3_UART_INFO_SI: if (port->sensor.mode != mode) { port->last_err = "Received INFO for incorrect mode."; goto err_invalid_state; } if (test_and_set_bit(EV3_UART_INFO_BIT_INFO_SI, &port->info_flags)) { port->last_err = "Received duplicate SI scaling INFO."; goto err_invalid_state; } port->si_min = *(u32 *)(message + 2); port->si_max = *(u32 *)(message + 6); debug_pr("mode %d si_min:%08x, si_max:%08x\n", mode, port->mode_info[mode].si_min, port->mode_info[mode].si_max); break; case EV3_UART_INFO_UNITS: if (port->sensor.mode != mode) { port->last_err = "Received INFO for incorrect mode."; goto err_invalid_state; } if (test_and_set_bit(EV3_UART_INFO_BIT_INFO_UNITS, &port->info_flags)) { port->last_err = "Received duplicate SI units INFO."; goto err_invalid_state; } /* * Units may not have null terminator and we * are done with the checksum at this point * so we are writing 0 over the checksum to * ensure a null terminator for the string * functions. */ message[msg_size - 1] = 0; snprintf(port->mode_info[mode].units, EV3_UART_UNITS_SIZE + 1, "%s", message + 2); debug_pr("mode %d units:%s\n", mode, port->mode_info[mode].units); break; case EV3_UART_INFO_FORMAT: if (port->sensor.mode != mode) { port->last_err = "Received INFO for incorrect mode."; goto err_invalid_state; } if (test_and_set_bit(EV3_UART_INFO_BIT_INFO_FORMAT, &port->info_flags)) { port->last_err = "Received duplicate format INFO."; goto err_invalid_state; } port->mode_info[mode].data_sets = message[2]; if (!port->mode_info[mode].data_sets) { port->last_err = "Invalid number of data sets."; goto err_invalid_state; } if (msg_size < 7) { port->last_err = "Invalid format message size."; goto err_invalid_state; } if ((port->info_flags & EV3_UART_INFO_FLAG_REQUIRED) != EV3_UART_INFO_FLAG_REQUIRED) { port->last_err = "Did not receive all required INFO."; goto err_invalid_state; } switch (message[3]) { case EV3_UART_DATA_8: port->mode_info[mode].data_type = LEGO_SENSOR_DATA_S8; break; case EV3_UART_DATA_16: port->mode_info[mode].data_type = LEGO_SENSOR_DATA_S16; break; case EV3_UART_DATA_32: port->mode_info[mode].data_type = LEGO_SENSOR_DATA_S32; break; case EV3_UART_DATA_FLOAT: port->mode_info[mode].data_type = LEGO_SENSOR_DATA_FLOAT; break; default: port->last_err = "Invalid data type."; goto err_invalid_state; } port->mode_info[mode].figures = message[4]; port->mode_info[mode].decimals = message[5]; if (port->info_flags & EV3_UART_INFO_FLAG_INFO_RAW) { port->mode_info[mode].raw_min = lego_sensor_ftoi(port->raw_min, 0); port->mode_info[mode].raw_max = lego_sensor_ftoi(port->raw_max, 0); } if (port->info_flags & EV3_UART_INFO_FLAG_INFO_PCT) { port->mode_info[mode].pct_min = lego_sensor_ftoi(port->pct_min, 0); port->mode_info[mode].pct_max = lego_sensor_ftoi(port->pct_max, 0); } if (port->info_flags & EV3_UART_INFO_FLAG_INFO_SI) { port->mode_info[mode].si_min = lego_sensor_ftoi(port->si_min, port->mode_info[mode].decimals); port->mode_info[mode].si_max = lego_sensor_ftoi(port->si_max, port->mode_info[mode].decimals); } if (port->sensor.mode) port->sensor.mode--; debug_pr("mode %d - data_sets:%d, data_type:%d, figures:%d, decimals:%d\n", mode, port->mode_info[mode].data_sets, port->mode_info[mode].data_type, port->mode_info[mode].figures, port->mode_info[mode].decimals); debug_pr("raw_min: %d, raw_max: %d\n", port->mode_info[mode].raw_min, port->mode_info[mode].raw_max); debug_pr("pct_min: %d, pct_max: %d\n", port->mode_info[mode].pct_min, port->mode_info[mode].pct_max); debug_pr("si_min: %d, si_max: %d\n", port->mode_info[mode].si_min, port->mode_info[mode].si_max); break; } break; case EV3_UART_MSG_TYPE_DATA: debug_pr("DATA:%d\n", message[0] & EV3_UART_MSG_CMD_MASK); if (!port->info_done) { port->last_err = "Received DATA before INFO was complete."; goto err_invalid_state; } if (mode > EV3_UART_MODE_MAX) { port->last_err = "Invalid mode received."; goto err_invalid_state; } if (mode != port->sensor.mode) { if (mode == port->new_mode) { port->sensor.mode = mode; kobject_uevent(&port->sensor.dev.kobj, KOBJ_CHANGE); } else { port->last_err = "Unexpected mode."; goto err_invalid_state; } } if (!completion_done(&port->set_mode_completion) && mode == port->new_mode) complete(&port->set_mode_completion); memcpy(port->mode_info[mode].raw_data, message + 1, msg_size - 2); port->data_rec = 1; if (port->num_data_err) port->num_data_err--; break; } err_bad_data_msg_checksum: count = CIRC_CNT(cb->head, cb->tail, EV3_UART_BUFFER_SIZE); } return; err_invalid_state: port->synced = 0; port->new_baud_rate = EV3_UART_SPEED_MIN; schedule_work(&port->change_bitrate_work); }