unsigned bfin_uart_read_buffer (struct hw *me, unsigned char *buffer, unsigned nr_bytes) { SIM_DESC sd = hw_system (me); struct bfin_uart *uart = hw_data (me); int status = dv_sockser_status (sd); unsigned i = 0; if (status & DV_SOCKSER_DISCONNECTED) { int ret; while (uart->saved_count > 0 && i < nr_bytes) { buffer[i++] = uart->saved_byte; --uart->saved_count; } ret = sim_io_poll_read (sd, 0/*STDIN*/, (char *) buffer, nr_bytes - i); if (ret > 0) i += ret; } else buffer[i++] = dv_sockser_read (sd); return i; }
static void do_polling_event (struct hw *me, void *data) { SIM_DESC sd = hw_system (me); struct mn103ser *serial = hw_data(me); long serial_reg = (long) data; char c; int count, status; status = dv_sockser_status (sd); if (!(status & DV_SOCKSER_DISCONNECTED)) { int rd; rd = dv_sockser_read (sd); if(rd != -1) { c = (char) rd; count = 1; } else { count = HW_IO_NOT_READY; } } else { count = do_hw_poll_read (me, serial->reader, 0/*STDIN*/, &c, sizeof(c)); } switch (count) { case HW_IO_NOT_READY: case HW_IO_EOF: serial->device[serial_reg].rxb = 0; serial->device[serial_reg].status &= ~SIO_STAT_RRDY; break; default: serial->device[serial_reg].rxb = c; serial->device[serial_reg].status |= SIO_STAT_RRDY; hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1); } /* Schedule next polling event */ serial->device[serial_reg].event = hw_event_queue_schedule (me, 1000, do_polling_event, (void *)serial_reg); }
/* Switch between socket and stdin on the fly. */ bu16 bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh) { SIM_DESC sd = hw_system (me); struct bfin_uart *uart = hw_data (me); int status = dv_sockser_status (sd); bool _fresh; /* NB: The "uart" here may only use interal state. */ if (!fresh) fresh = &_fresh; *fresh = false; if (uart->saved_count > 0) { *fresh = true; rbr = uart->saved_byte; --uart->saved_count; } else if (mcr & LOOP_ENA) { /* RX is disconnected, so only return local data. */ } else if (status & DV_SOCKSER_DISCONNECTED) { char byte; int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1); if (ret > 0) { *fresh = true; rbr = byte; } } else rbr = dv_sockser_read (sd); return rbr; }
/* Send enqueued characters from tx_fifo and trigger TX interrupt. Receive characters into rx_fifo and trigger RX interrupt. */ void tx3904sio_tickle(struct hw *me) { struct tx3904sio* controller = hw_data(me); int c; char cc; unsigned_4 last_int, next_int; /* HW_TRACE ((me, "tickle backend: %02x", controller->backend)); */ switch(controller->backend) { case sio_tcp: while(tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) { cc = tx3904sio_fifo_pop(me, & controller->tx_fifo); dv_sockser_write(hw_system(me), cc); HW_TRACE ((me, "tcp output: %02x", cc)); } c = dv_sockser_read(hw_system(me)); while(c != -1) { cc = (char) c; HW_TRACE ((me, "tcp input: %02x", cc)); tx3904sio_fifo_push(me, & controller->rx_fifo, cc); c = dv_sockser_read(hw_system(me)); } break; case sio_stdio: while(tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) { cc = tx3904sio_fifo_pop(me, & controller->tx_fifo); sim_io_write_stdout(hw_system(me), & cc, 1); sim_io_flush_stdout(hw_system(me)); HW_TRACE ((me, "stdio output: %02x", cc)); } c = sim_io_poll_read(hw_system(me), 0 /* stdin */, & cc, 1); while(c == 1) { HW_TRACE ((me, "stdio input: %02x", cc)); tx3904sio_fifo_push(me, & controller->rx_fifo, cc); c = sim_io_poll_read(hw_system(me), 0 /* stdin */, & cc, 1); } break; default: hw_abort(me, "Illegal backend mode: %d", controller->backend); } /* Update RDIS / TDIS flags */ last_int = controller->sdisr & controller->sdicr; /* HW_TRACE ((me, "tickle - sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ if(tx3904sio_fifo_nonempty(me, & controller->rx_fifo)) SDISR_SET_RDIS(controller); if(! tx3904sio_fifo_nonempty(me, & controller->tx_fifo)) SDISR_SET_TDIS(controller); next_int = controller->sdisr & controller->sdicr; /* HW_TRACE ((me, "tickle + sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ if(~last_int & next_int) /* any bits set? */ hw_port_event(me, INT_PORT, 1); if(last_int & ~next_int) /* any bits cleared? */ hw_port_event(me, INT_PORT, 0); /* Add periodic polling for this port, if it's not already going. */ if(controller->poll_event == NULL) { controller->poll_event = hw_event_queue_schedule (me, 1000, tx3904sio_poll, NULL); } }
static void read_status_reg (struct hw *me, struct mn103ser *serial, unsigned_word serial_reg, void *dest, unsigned nr_bytes) { char c; int count; if ( (serial->device[serial_reg].status & SIO_STAT_RRDY) == 0 ) { SIM_DESC sd = hw_system (me); int status; /* FIFO is empty */ /* Kill current poll event */ if ( NULL != serial->device[serial_reg].event ) { hw_event_queue_deschedule (me, serial->device[serial_reg].event); serial->device[serial_reg].event = NULL; } status = dv_sockser_status (sd); if (!(status & DV_SOCKSER_DISCONNECTED)) { int rd; rd = dv_sockser_read (sd); if(rd != -1) { c = (char) rd; count = 1; } else { count = HW_IO_NOT_READY; } } else { count = do_hw_poll_read (me, serial->reader, 0/*STDIN*/, &c, sizeof(c)); } switch (count) { case HW_IO_NOT_READY: case HW_IO_EOF: serial->device[serial_reg].rxb = 0; serial->device[serial_reg].status &= ~SIO_STAT_RRDY; break; default: serial->device[serial_reg].rxb = c; serial->device[serial_reg].status |= SIO_STAT_RRDY; hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1); } /* schedule polling event */ serial->device[serial_reg].event = hw_event_queue_schedule (me, 1000, do_polling_event, (void *) (long) serial_reg); } if ( nr_bytes == 1 ) { *(unsigned8 *)dest = (unsigned8)serial->device[serial_reg].status; } else if ( nr_bytes == 2 && serial_reg != SC2STR ) { *(unsigned16 *)dest = H2LE_2 (serial->device[serial_reg].status); } else { hw_abort (me, "bad read size of %d bytes from SC%dSTR.", nr_bytes, serial_reg); } }
void m68hc11sio_rx_poll (struct hw *me, void *data) { SIM_DESC sd; struct m68hc11sio *controller; sim_cpu *cpu; char cc; int cnt; int check_interrupt = 0; controller = hw_data (me); sd = hw_system (me); cpu = STATE_CPU (sd, 0); switch (controller->backend) { case sio_tcp: cnt = dv_sockser_read (sd); if (cnt != -1) { cc = (char) cnt; cnt = 1; } break; case sio_stdio: cnt = sim_io_poll_read (sd, 0 /* stdin */, &cc, 1); break; default: cnt = 0; break; } if (cnt == 1) { /* Raise the overrun flag if the previous character was not read. */ if (cpu->ios[M6811_SCSR] & M6811_RDRF) cpu->ios[M6811_SCSR] |= M6811_OR; cpu->ios[M6811_SCSR] |= M6811_RDRF; controller->rx_char = cc; controller->rx_clear_scsr = 0; check_interrupt = 1; } else { /* handle idle line detect here. */ ; } if (controller->rx_poll_event) { hw_event_queue_deschedule (me, controller->rx_poll_event); controller->rx_poll_event = 0; } if (cpu->ios[M6811_SCCR2] & M6811_RE) { unsigned long clock_cycle; /* Compute CPU clock cycles to wait for the next character. */ clock_cycle = controller->data_length * controller->baud_cycle; controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle, m68hc11sio_rx_poll, NULL); } if (check_interrupt) interrupts_update_pending (&cpu->cpu_interrupts); }