Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 12 additions & 24 deletions drivers/serial/arm/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,18 @@ static void set_baud(long bps)

static void tx_provide(void)
{
bool reprocess = true;
bool transferred = false;
while (reprocess) {
char c;
while (!(uart_regs->fr & PL011_FR_TXFF) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->dr = (uint32_t)c;
transferred = true;
}

serial_request_producer_signal(&tx_queue_handle);
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->fr & PL011_FR_TXFF && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->imsc |= PL011_IMSC_TX_INT;
} else {
uart_regs->imsc &= ~PL011_IMSC_TX_INT;
}
reprocess = false;
char c;
while (!(uart_regs->fr & PL011_FR_TXFF) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->dr = (uint32_t)c;
transferred = true;
}

if (!(uart_regs->fr & PL011_FR_TXFF) && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&tx_queue_handle);
uart_regs->imsc &= ~PL011_IMSC_TX_INT;
reprocess = true;
}
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->fr & PL011_FR_TXFF && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->imsc |= PL011_IMSC_TX_INT;
} else {
uart_regs->imsc &= ~PL011_IMSC_TX_INT;
}

if (transferred && serial_require_consumer_signal(&tx_queue_handle)) {
Expand All @@ -84,7 +73,7 @@ static void rx_return(void)
}

if (!(uart_regs->fr & PL011_FR_RXFE) && serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) {
/* Disable rx interrupts until virtualisers queue is no longer empty. */
/* Disable rx interrupts until virtualisers queue is no longer full. */
uart_regs->imsc &= ~(PL011_IMSC_RX_TIMEOUT | PL011_IMSC_RX_INT);
serial_request_consumer_signal(&rx_queue_handle);
}
Expand All @@ -97,8 +86,7 @@ static void rx_return(void)
}
}

if (enqueued && serial_require_producer_signal(&rx_queue_handle)) {
serial_cancel_producer_signal(&rx_queue_handle);
if (enqueued) {
microkit_notify(config.rx.id);
}
}
Expand Down
36 changes: 12 additions & 24 deletions drivers/serial/imx/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,18 @@ static void set_baud(long bps)

static void tx_provide(void)
{
bool reprocess = true;
bool transferred = false;
while (reprocess) {
char c;
while (!(uart_regs->ts & UART_TST_TX_FIFO_FULL) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->txd = (uint32_t)c;
transferred = true;
}

serial_request_producer_signal(&tx_queue_handle);
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->ts & UART_TST_TX_FIFO_FULL && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->cr1 |= UART_CR1_TX_READY_INT;
} else {
uart_regs->cr1 &= ~UART_CR1_TX_READY_INT;
}
reprocess = false;
char c;
while (!(uart_regs->ts & UART_TST_TX_FIFO_FULL) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->txd = (uint32_t)c;
transferred = true;
}

if (!(uart_regs->ts & UART_TST_TX_FIFO_FULL) && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&tx_queue_handle);
uart_regs->cr1 &= ~UART_CR1_TX_READY_INT;
reprocess = true;
}
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->ts & UART_TST_TX_FIFO_FULL && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->cr1 |= UART_CR1_TX_READY_INT;
} else {
uart_regs->cr1 &= ~UART_CR1_TX_READY_INT;
}

if (transferred && serial_require_consumer_signal(&tx_queue_handle)) {
Expand All @@ -85,7 +74,7 @@ static void rx_return(void)
}

if (!(uart_regs->ts & UART_TST_RX_FIFO_EMPTY) && serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) {
/* Disable rx interrupts until virtualisers queue is no longer empty. */
/* Disable rx interrupts until virtualisers queue is no longer full. */
uart_regs->cr1 &= ~UART_CR1_RX_READY_INT;
serial_request_consumer_signal(&rx_queue_handle);
}
Expand All @@ -98,8 +87,7 @@ static void rx_return(void)
}
}

if (enqueued && serial_require_producer_signal(&rx_queue_handle)) {
serial_cancel_producer_signal(&rx_queue_handle);
if (enqueued) {
microkit_notify(config.rx.id);
}
}
Expand Down
36 changes: 12 additions & 24 deletions drivers/serial/meson/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,29 +73,18 @@ static void set_baud(unsigned long baud)

static void tx_provide(void)
{
bool reprocess = true;
bool transferred = false;
while (reprocess) {
char c;
while (!(uart_regs->sr & AML_UART_TX_FULL) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->wfifo = (uint32_t)c;
transferred = true;
}

serial_request_producer_signal(&tx_queue_handle);
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->sr & AML_UART_TX_FULL && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->cr |= AML_UART_TX_INT_EN;
} else {
uart_regs->cr &= ~AML_UART_TX_INT_EN;
}
reprocess = false;
char c;
while (!(uart_regs->sr & AML_UART_TX_FULL) && !serial_dequeue(&tx_queue_handle, &c)) {
uart_regs->wfifo = (uint32_t)c;
transferred = true;
}

if (!(uart_regs->sr & AML_UART_TX_FULL) && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&tx_queue_handle);
uart_regs->cr &= ~AML_UART_TX_INT_EN;
reprocess = true;
}
/* If transmit fifo is full and there is data remaining to be sent, enable interrupt when fifo is no longer full */
if (uart_regs->sr & AML_UART_TX_FULL && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
uart_regs->cr |= AML_UART_TX_INT_EN;
} else {
uart_regs->cr &= ~AML_UART_TX_INT_EN;
}

if (transferred && serial_require_consumer_signal(&tx_queue_handle)) {
Expand All @@ -116,7 +105,7 @@ static void rx_return(void)
}

if (!(uart_regs->sr & AML_UART_RX_EMPTY) && serial_queue_full(&rx_queue_handle, rx_queue_handle.queue->tail)) {
/* Disable rx interrupts until virtualisers queue is no longer empty. */
/* Disable rx interrupts until virtualisers queue is no longer full. */
uart_regs->cr &= ~AML_UART_RX_INT_EN;
serial_request_consumer_signal(&rx_queue_handle);
}
Expand All @@ -129,8 +118,7 @@ static void rx_return(void)
}
}

if (enqueued && serial_require_producer_signal(&rx_queue_handle)) {
serial_cancel_producer_signal(&rx_queue_handle);
if (enqueued) {
microkit_notify(config.rx.id);
}
}
Expand Down
38 changes: 12 additions & 26 deletions drivers/serial/snps/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,19 @@ static void set_baud(unsigned long baud)

static void tx_provide(void)
{
bool reprocess = true;
bool transferred = false;
while (reprocess) {
char c;

while ((*REG_PTR(UART_LSR) & UART_LSR_THRE) && !serial_dequeue(&tx_queue_handle, &c)) {
*REG_PTR(UART_THR) = c;
transferred = true;
}

serial_request_producer_signal(&tx_queue_handle);
/* If transmit FIFO is full and we still have data to be sent, enable TX IRQ */
if ((*REG_PTR(UART_LSR) & UART_LSR_THRE) == 0
&& !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
*REG_PTR(UART_IER) |= UART_IER_ETBEI;
} else {
*REG_PTR(UART_IER) &= ~UART_IER_ETBEI;
}
reprocess = false;
char c;
while ((*REG_PTR(UART_LSR) & UART_LSR_THRE) && !serial_dequeue(&tx_queue_handle, &c)) {
*REG_PTR(UART_THR) = c;
transferred = true;
}

if ((*REG_PTR(UART_LSR) & UART_LSR_THRE)
&& !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&tx_queue_handle);
*REG_PTR(UART_IER) &= ~UART_IER_ETBEI;
reprocess = true;
}
/* If transmit FIFO is full and we still have data to be sent, enable TX IRQ */
if ((*REG_PTR(UART_LSR) & UART_LSR_THRE) == 0
&& !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
*REG_PTR(UART_IER) |= UART_IER_ETBEI;
} else {
*REG_PTR(UART_IER) &= ~UART_IER_ETBEI;
}

if (transferred && serial_require_consumer_signal(&tx_queue_handle)) {
Expand Down Expand Up @@ -110,8 +97,7 @@ static void rx_return(void)
}
}

if (enqueued && serial_require_producer_signal(&rx_queue_handle)) {
serial_cancel_producer_signal(&rx_queue_handle);
if (enqueued) {
microkit_notify(config.rx.id);
}
}
Expand Down
64 changes: 26 additions & 38 deletions drivers/serial/virtio/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,49 +107,38 @@ volatile virtio_mmio_regs_t *uart_regs;

static void tx_provide(void)
{
bool reprocess = true;
bool transferred = false;
while (reprocess) {
char c;
while (!virtio_avail_full_tx(&tx_virtq) && !serial_dequeue(&tx_queue_handle, &c)) {

/* First, allocate somewhere to put the character */
uint32_t char_idx = -1;
int err = ialloc_alloc(&tx_char_ialloc_desc, &char_idx);
assert(!err && char_idx != -1);

/* Now we need to a descriptor to put into the virtIO ring */
uint32_t pkt_desc_idx = -1;
err = ialloc_alloc(&tx_ialloc_desc, &pkt_desc_idx);
assert(!err && pkt_desc_idx != -1);
char c;
while (!virtio_avail_full_tx(&tx_virtq) && !serial_dequeue(&tx_queue_handle, &c)) {

/* We should not run out of descriptors assuming that the avail ring is not full. */
assert(pkt_desc_idx < tx_virtq.num);
/* First, allocate somewhere to put the character */
uint32_t char_idx = -1;
int err = ialloc_alloc(&tx_char_ialloc_desc, &char_idx);
assert(!err && char_idx != -1);

/* Put the character into the data region */
virtio_tx_char[char_idx] = c;
/* Now we need to a descriptor to put into the virtIO ring */
uint32_t pkt_desc_idx = -1;
err = ialloc_alloc(&tx_ialloc_desc, &pkt_desc_idx);
assert(!err && pkt_desc_idx != -1);

/* Set up the packet */
tx_virtq.desc[pkt_desc_idx].addr = virtio_tx_char_paddr + char_idx;
tx_virtq.desc[pkt_desc_idx].len = 1;
tx_virtq.desc[pkt_desc_idx].flags = 0;
/* We should not run out of descriptors assuming that the avail ring is not full. */
assert(pkt_desc_idx < tx_virtq.num);

/* Enqueue the packet */
tx_virtq.avail->ring[tx_virtq.avail->idx % tx_virtq.num] = pkt_desc_idx;
/* Put the character into the data region */
virtio_tx_char[char_idx] = c;

tx_virtq.avail->idx++;
tx_last_desc_idx += 1;
/* Set up the packet */
tx_virtq.desc[pkt_desc_idx].addr = virtio_tx_char_paddr + char_idx;
tx_virtq.desc[pkt_desc_idx].len = 1;
tx_virtq.desc[pkt_desc_idx].flags = 0;

transferred = true;
}
/* Enqueue the packet */
tx_virtq.avail->ring[tx_virtq.avail->idx % tx_virtq.num] = pkt_desc_idx;

serial_request_producer_signal(&tx_queue_handle);
reprocess = false;
tx_virtq.avail->idx++;
tx_last_desc_idx += 1;

if (!virtio_avail_full_tx(&tx_virtq) && !serial_queue_empty(&tx_queue_handle, tx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&tx_queue_handle);
reprocess = true;
}
transferred = true;
}

if (transferred) {
Expand All @@ -165,7 +154,7 @@ static void tx_provide(void)

static void tx_return(void)
{
/* After the tx has been processed, we need to free the packet/character allocation */
/* After the tx has been processed, we need to free the packet/character allocation */
uint16_t enqueued = 0;
uint16_t i = tx_last_seen_used;
uint16_t curr_idx = tx_virtq.used->idx;
Expand Down Expand Up @@ -197,7 +186,7 @@ static void tx_return(void)

static void rx_provide(void)
{
/* Fill up the virtio available ring buffer */
/* Fill up the virtio available ring buffer */
bool transferred = false;
while (!virtio_avail_full_rx(&rx_virtq)) {
// Allocate a desc entry for the packet and the character
Expand Down Expand Up @@ -278,8 +267,7 @@ static void rx_return(void)

rx_last_seen_used += transferred;

if (transferred > 0 && serial_require_producer_signal(&rx_queue_handle)) {
serial_cancel_producer_signal(&rx_queue_handle);
if (transferred > 0) {
microkit_notify(RX_CH);
}
}
Expand Down
29 changes: 9 additions & 20 deletions examples/serial/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,17 @@ void init(void)
uint16_t char_count;
void notified(microkit_channel ch)
{
bool reprocess = true;
char c;
while (reprocess) {
while (!serial_dequeue(&rx_queue_handle, &c)) {
if (c == '\r') {
sddf_putchar_unbuffered('\\');
sddf_putchar_unbuffered('r');
} else {
sddf_putchar_unbuffered(c);
}
char_count++;
if (char_count % 10 == 0) {
sddf_printf("\n%s has received %u characters so far!\n", microkit_name, char_count);
}
while (!serial_dequeue(&rx_queue_handle, &c)) {
if (c == '\r') {
sddf_putchar_unbuffered('\\');
sddf_putchar_unbuffered('r');
} else {
sddf_putchar_unbuffered(c);
}

serial_request_producer_signal(&rx_queue_handle);
reprocess = false;

if (!serial_queue_empty(&rx_queue_handle, rx_queue_handle.queue->head)) {
serial_cancel_producer_signal(&rx_queue_handle);
reprocess = true;
char_count++;
if (char_count % 10 == 0) {
sddf_printf("\n%s has received %u characters so far!\n", microkit_name, char_count);
}
}
}
Loading