static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct serial_state *info = tty->driver_data; int c, ret = 0; unsigned long flags; if (!info->xmit.buf) return 0; local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) c = count; if (c <= 0) { break; } memcpy(info->xmit.buf + info->xmit.head, buf, c); info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); buf += c; count -= c; ret += c; } local_irq_restore(flags); /* * Hey, we transmit directly from here in our case */ if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) && !tty->stopped && !tty->hw_stopped) transmit_chars(tty, info, NULL); return ret; }
/********************************************************************************************************** * Description: This function is used to fill tx buffer. * * Arguments : port is the uart port * buf is the user buffer. * count is the user data length * * Returns : **********************************************************************************************************/ int tls_uart_write(struct tls_uart_port *port, char *buf, u32 count) { struct tls_uart_circ_buf *xmit; int c; int ret = 0; xmit = &port->xmit; if (!xmit->buf) return WM_FAILED; while (1) { c = CIRC_SPACE_TO_END(xmit->head, xmit->tail, TLS_UART_TX_BUF_SIZE); if (count < c) c = count; if (c <= 0) break; MEMCPY((char *)(xmit->buf + xmit->head), buf, c); xmit->head = (xmit->head + c) & (TLS_UART_TX_BUF_SIZE - 1); buf += c; count -= c; ret += c; } return ret; }
/* * rx_done_callback_packet_buffer() * We have completed a DMA xfer into the temp packet buffer. * Move to ring. * * flag values: * on init, -EAGAIN * on reset, -EINTR * on RPE, -EIO * on short packet -EPIPE */ static void rx_done_callback_packet_buffer( int flag, int size ) { charstats.cnt_rx_complete++; if ( flag == 0 || flag == -EPIPE ) { size_t n; charstats.bytes_rx += size; n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE ); n = MIN( n, size ); size -= n; memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n ); rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1); memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size ); rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1); wake_up_interruptible( &wq_read ); last_rx_result = 0; kick_start_rx(); } else if ( flag != -EAGAIN ) { charstats.cnt_rx_errors++; last_rx_result = flag; wake_up_interruptible( &wq_read ); } else /* init, start a read */ kick_start_rx(); }
static void ev3_uart_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct ev3_uart_port_data *port = tty->disc_data; struct circ_buf *cb = &port->circ_buf; int size; if (port->closing) return; if (count > CIRC_SPACE(cb->head, cb->tail, EV3_UART_BUFFER_SIZE)) return; size = CIRC_SPACE_TO_END(cb->head, cb->tail, EV3_UART_BUFFER_SIZE); if (count > size) { memcpy(cb->buf + cb->head, cp, size); memcpy(cb->buf, cp + size, count - size); cb->head = count - size; } else { memcpy(cb->buf + cb->head, cp, count); cb->head += count; } schedule_work(&port->rx_data_work); }
/******************************************************************************** * 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() ----- */
/* * This function is called when the tty layer has data for us send. We store * the data first in a circular buffer, and then dequeue as much of that data * as possible. * * We don't need to worry about whether there is enough room in the buffer for * all the data. The purpose of ehv_bc_tty_write_room() is to tell the tty * layer how much data it can safely send to us. We guarantee that * ehv_bc_tty_write_room() will never lie, so the tty layer will never send us * too much data. */ static int ehv_bc_tty_write(struct tty_struct *ttys, const unsigned char *s, int count) { struct ehv_bc_data *bc = ttys->driver_data; unsigned long flags; unsigned int len; unsigned int written = 0; while (1) { spin_lock_irqsave(&bc->lock, flags); len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE); if (count < len) len = count; if (len) { memcpy(bc->buf + bc->head, s, len); bc->head = (bc->head + len) & (BUF_SIZE - 1); } spin_unlock_irqrestore(&bc->lock, flags); if (!len) break; s += len; count -= len; written += len; } ehv_bc_tx_dequeue(bc); return written; }
size_t whitebox_user_source_space_available(struct whitebox_user_source *user_source, unsigned long *dest) { long tail, head, space; head = user_source->buf.head; tail = ACCESS_ONCE(user_source->buf.tail); space = CIRC_SPACE_TO_END(head, tail, user_source->buf_size) & ~3; *dest = (unsigned long)user_source->buf.buf + head; d_printk(7, "%ld\n", space); return space; }
static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) { int c, ret = 0; struct async_struct *info; unsigned long flags; info = tty->driver_data; if (serial_paranoia_check(info, tty->name, "rs_write")) return 0; if (!info->xmit.buf) return 0; local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) c = count; if (c <= 0) { break; } memcpy(info->xmit.buf + info->xmit.head, buf, c); info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); buf += c; count -= c; ret += c; } local_irq_restore(flags); if (info->xmit.head != info->xmit.tail && !tty->stopped && !tty->hw_stopped && !(info->IER & UART_IER_THRI)) { info->IER |= UART_IER_THRI; local_irq_disable(); custom.intena = IF_SETCLR | IF_TBE; mb(); /* set a pending Tx Interrupt, transmitter should restart now */ custom.intreq = IF_SETCLR | IF_TBE; mb(); local_irq_restore(flags); } return ret; }
/* * serial_buf_put * * Copy data data from a user buffer and put it into the circular buffer. * Restrict to the amount of space available. * * Return the number of bytes copied. */ static int serial_buf_put(struct circ_buf *cb, const char *buf, int count) { int c, ret = 0; while (1) { c = CIRC_SPACE_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(cb->buf + cb->head, buf, c); cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1); buf += c; count -= c; ret= c; } return ret; }
int mcuio_soft_hc_push_chars(struct mcuio_soft_hc *shc, const u8 *in, int len) { int s = sizeof(shc->rx_buf), available, actual; struct circ_buf *buf = &shc->rx_circ_buf; available = CIRC_SPACE_TO_END(buf->head, buf->tail, s); if (available < sizeof(u32)) { pr_debug("%s %d\n", __func__, __LINE__); return -EAGAIN; } actual = min(len, available); memcpy(&buf->buf[buf->head], in, actual); buf->head = (buf->head + actual) & (s - 1); /* set irq status register RX_RDY bit */ shc->irqstat |= RX_RDY; if (shc->irq_enabled) queue_kthread_work(&shc->irq_kworker, &shc->do_irq); return actual; }
static void send_tx_char (struct uart_btlinux_port *up) { struct circ_buf *xmit = &up->port.info->xmit; unsigned char *buf; int c, d, count; count = uart_circ_chars_pending(xmit); buf = &xmit->buf[xmit->tail]; /* write to tx buffer */ while (1) { c = CIRC_SPACE_TO_END(up->tx_data_head, up->tx_data_tail, TX_BUFFERS_SIZE); if (count < c) c = count; if (c <= 0) break; if (xmit->head > xmit->tail) { memcpy(up->tx_data + up->tx_data_head, buf, c); buf += c; xmit->tail = (xmit->tail + c) & (UART_XMIT_SIZE - 1); } else { d = (UART_XMIT_SIZE - xmit->tail); if (c < d) d = c; memcpy(up->tx_data + up->tx_data_head, buf, d); xmit->tail = (xmit->tail + d) & (UART_XMIT_SIZE - 1); buf = &xmit->buf[xmit->tail]; if (c > d) { memcpy(up->tx_data + up->tx_data_head + d, buf, (c-d)); xmit->tail = (xmit->tail + (c-d)) & (UART_XMIT_SIZE - 1); buf = &xmit->buf[xmit->tail]; } } up->tx_data_head = (up->tx_data_head + c) & (TX_BUFFERS_SIZE - 1); count -= c; } if (uart_circ_chars_pending(xmit) < 1024) uart_write_wakeup(&up->port); /* dbg("tx head %d - tx tail = %d", up->tx_data_head, up->tx_data_tail);*/ }
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 int uart_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct uart_state *state = tty->driver_data; struct uart_port *port; struct circ_buf *circ; unsigned long flags; int c, ret = 0; if (!state) { WARN_ON(1); return -EL3HLT; } port = state->uart_port; circ = &state->xmit; if (!circ->buf) return 0; spin_lock_irqsave(&port->lock, flags); while (1) { c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(circ->buf + circ->head, buf, c); circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); buf += c; count -= c; ret += c; } spin_unlock_irqrestore(&port->lock, flags); uart_start(tty); return ret; }
static unsigned _fifo_write(struct m_fifo *q, void *src, unsigned count, copyfunc copy) { unsigned n; unsigned head = *q->head; unsigned tail = *q->tail; unsigned size = q->size; if (CIRC_SPACE(head, tail, size) < count) return 0; n = CIRC_SPACE_TO_END(head, tail, size); if (likely(n >= count)) { copy(q->data + head, src, count); } else { copy(q->data + head, src, n); copy(q->data, src + n, count - n); } //*q->head = (head + count) & (size - 1); return count; }
int produce_item(struct circ_buf *ring, char *data, int count) { int len = 0; int left,i,size; int to_end_space=0; if ( (size=CIRC_SPACE(ring->head, ring->tail, CIRC_BUF_SIZE)) >= 1 ) { left = len = count<=size ? count : size; to_end_space = CIRC_SPACE_TO_END(ring->head, ring->tail, CIRC_BUF_SIZE); if(left > to_end_space) { memcpy(&(ring->buf[ring->head]), data, to_end_space); for(i=0; i<to_end_space; i++) { printf("produec_item %02d bytes: ring->buf[%02d]=%d\n", to_end_space, ring->head+i, ring->buf[ring->head+i]); } ring->head = (ring->head + to_end_space) & (CIRC_BUF_SIZE - 1); left -= to_end_space; } else { to_end_space = 0; } memcpy(&(ring->buf[ring->head]), &data[to_end_space], left); for(i=0; i<left; i++) { printf("produec_item %02d bytes: ring->buf[%02d]=%d\n", left, ring->head+i, ring->buf[ring->head+i]); } ring->head = (ring->head + left) & (CIRC_BUF_SIZE - 1); } printf("-----------------------------------------------------------------------------------------------\n"); return len; }
/* * Send a packet of bytes to the device */ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) { /* Copy data to buffer */ int n = LO(cmd); int c; int empty; int head, tail; unsigned long flags; /* * Update head and tail of xmit buffer */ spin_lock_irqsave(&iforce->xmit_lock, flags); head = iforce->xmit.head; tail = iforce->xmit.tail; if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) { warn("not enough space in xmit buffer to send new packet"); spin_unlock_irqrestore(&iforce->xmit_lock, flags); return -1; } empty = head == tail; XMIT_INC(iforce->xmit.head, n+2); /* * Store packet in xmit buffer */ iforce->xmit.buf[head] = HI(cmd); XMIT_INC(head, 1); iforce->xmit.buf[head] = LO(cmd); XMIT_INC(head, 1); c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); if (n < c) c=n; memcpy(&iforce->xmit.buf[head], data, c); if (n != c) { memcpy(&iforce->xmit.buf[0], data + c, n - c); } XMIT_INC(head, n); spin_unlock_irqrestore(&iforce->xmit_lock, flags); /* * If necessary, start the transmission */ switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_232 case IFORCE_232: if (empty) iforce_serial_xmit(iforce); break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: if (iforce->usbdev && empty && !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) { iforce_usb_xmit(iforce); } break; #endif } return 0; }
static int uart_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct uart_state *state = tty->driver_data; struct uart_port *port; struct circ_buf *circ; unsigned long flags; int c, ret = 0; #ifdef CONFIG_IMC_UART2DM_HANDSHAKE u8 retries=0; #endif if (!state) { WARN_ON(1); return -EL3HLT; } port = state->uart_port; circ = &state->xmit; #ifdef CONFIG_IMC_UART2DM_HANDSHAKE if (!strcmp(tty->name,"ttyHS1") && !modem_fatal) { if (!radio_state) { printk("[GSM_RADIO] %s %s radio is off \n",__func__, tty->name); return -EINVAL; } imc_msm_hs_request_clock_on(port); pr_uartdm_debug("%s %s PDA_INT_BB + \n",__func__, tty->name); gpio_set_value(JEL_DD_GPIO_GSM_AP_XMM_WAKE, 1); mdelay(1); while(!gpio_get_value(JEL_DD_GPIO_GSM_XMM_AP_STATUS)){ gpio_set_value(JEL_DD_GPIO_GSM_AP_XMM_STATUS, 0); msleep(5); gpio_set_value(JEL_DD_GPIO_GSM_AP_XMM_STATUS, 1); msleep(20); if (retries>40){ printk("[GSM_RADIO] %s %s wait for BB_STATUS + timeout \n",__func__, tty->name); return -EAGAIN; } retries++; } } #endif if (!circ->buf) return 0; spin_lock_irqsave(&port->lock, flags); while (1) { c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); if (count < c) c = count; if (c <= 0) break; memcpy(circ->buf + circ->head, buf, c); circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); buf += c; count -= c; ret += c; } spin_unlock_irqrestore(&port->lock, flags); uart_start(tty); return ret; }
static int rs_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { int c, ret = 0; struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; if (!tty || !info->xmit.buf || !tmp_buf) return 0; if (from_user) { down(&tmp_buf_sem); while (1) { int c1; c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) c = count; if (c <= 0) break; c -= copy_from_user(tmp_buf, buf, c); if (!c) { if (!ret) ret = -EFAULT; break; } local_irq_save(flags); { c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (c1 < c) c = c1; memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); } local_irq_restore(flags); buf += c; count -= c; ret += c; } up(&tmp_buf_sem); } else { local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) c = count; if (c <= 0) { break; } memcpy(info->xmit.buf + info->xmit.head, buf, c); info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); buf += c; count -= c; ret += c; } local_irq_restore(flags); } /* * Hey, we transmit directly from here in our case */ if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) && !tty->stopped && !tty->hw_stopped) { transmit_chars(info, NULL); } return ret; }