📄 dv-tx3904sio.c
字号:
int space, unsigned_word base, unsigned nr_bytes){ struct tx3904sio *controller = hw_data (me); unsigned byte; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); /* tickle fifos */ tx3904sio_tickle(me); for (byte = 0; byte < nr_bytes; byte++) { address_word address = base + byte; int reg_number = (address - controller->base_address) / 4; int reg_offset = (address - controller->base_address) % 4; unsigned_4 register_value; /* in target byte order */ /* fill in entire register_value word */ switch (reg_number) { case SLCR_REG: register_value = controller->slcr; break; case SLSR_REG: register_value = controller->slsr; break; case SDICR_REG: register_value = controller->sdicr; break; case SDISR_REG: register_value = controller->sdisr; break; case SFCR_REG: register_value = controller->sfcr; break; case SBGR_REG: register_value = controller->sbgr; break; case TFIFO_REG: register_value = 0; break; case SFIFO_REG: /* consume rx fifo for MS byte */ if(reg_offset == 0 && tx3904sio_fifo_nonempty(me, & controller->rx_fifo)) register_value = (tx3904sio_fifo_pop(me, & controller->rx_fifo) << 24); else register_value = 0; break; default: register_value = 0; } /* write requested byte out */ register_value = H2T_4(register_value); /* HW_TRACE ((me, "byte %d %02x", reg_offset, ((char*)& register_value)[reg_offset])); */ memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); } return nr_bytes;} static unsignedtx3904sio_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word base, unsigned nr_bytes){ struct tx3904sio *controller = hw_data (me); unsigned byte; HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); for (byte = 0; byte < nr_bytes; byte++) { address_word address = base + byte; unsigned_1 write_byte = ((const unsigned char*) source)[byte]; int reg_number = (address - controller->base_address) / 4; int reg_offset = 3 - (address - controller->base_address) % 4; /* HW_TRACE ((me, "byte %d %02x", reg_offset, write_byte)); */ /* fill in entire register_value word */ switch (reg_number) { case SLCR_REG: SLCR_SET_BYTE(controller, reg_offset, write_byte); break; case SLSR_REG: /* unwriteable */ break; case SDICR_REG: { unsigned_4 last_int, next_int; /* deassert interrupt upon clear */ last_int = controller->sdisr & controller->sdicr; /* HW_TRACE ((me, "sdicr - sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ SDICR_SET_BYTE(controller, reg_offset, write_byte); /* HW_TRACE ((me, "sdicr + sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ next_int = controller->sdisr & controller->sdicr; if(SDICR_GET_SDMAE(controller)) hw_abort(me, "Cannot support DMA-driven sio."); 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); } break; case SDISR_REG: { unsigned_4 last_int, next_int; /* deassert interrupt upon clear */ last_int = controller->sdisr & controller->sdicr; /* HW_TRACE ((me, "sdisr - sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ SDISR_CLEAR_FLAG_BYTE(controller, reg_offset, write_byte); /* HW_TRACE ((me, "sdisr + sdisr %08x sdicr %08x", controller->sdisr, controller->sdicr)); */ next_int = 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); } break; case SFCR_REG: SFCR_SET_BYTE(controller, reg_offset, write_byte); if(SFCR_GET_FRSTE(controller)) { if(SFCR_GET_TFRST(controller)) tx3904sio_fifo_reset(me, & controller->tx_fifo); if(SFCR_GET_RFRST(controller)) tx3904sio_fifo_reset(me, & controller->rx_fifo); } break; case SBGR_REG: SBGR_SET_BYTE(controller, reg_offset, write_byte); break; case SFIFO_REG: /* unwriteable */ break; case TFIFO_REG: if(reg_offset == 3) /* first byte */ tx3904sio_fifo_push(me, & controller->tx_fifo, write_byte); break; default: HW_TRACE ((me, "write to illegal register %d", reg_number)); } } /* loop over bytes */ /* tickle fifos */ tx3904sio_tickle(me); return nr_bytes;} /* Send enqueued characters from tx_fifo and trigger TX interrupt.Receive characters into rx_fifo and trigger RX interrupt. */voidtx3904sio_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); }}inttx3904sio_fifo_nonempty(struct hw* me, struct tx3904sio_fifo* fifo){ /* HW_TRACE ((me, "fifo used: %d", fifo->used)); */ return(fifo->used > 0);}chartx3904sio_fifo_pop(struct hw* me, struct tx3904sio_fifo* fifo){ char it; ASSERT(fifo->used > 0); ASSERT(fifo->buffer != NULL); it = fifo->buffer[0]; memcpy(& fifo->buffer[0], & fifo->buffer[1], fifo->used - 1); fifo->used --; /* HW_TRACE ((me, "pop fifo -> %02x", it)); */ return it;}voidtx3904sio_fifo_push(struct hw* me, struct tx3904sio_fifo* fifo, char it){ /* HW_TRACE ((me, "push %02x -> fifo", it)); */ if(fifo->size == fifo->used) /* full */ { int next_size = fifo->size * 2 + 16; char* next_buf = zalloc(next_size); memcpy(next_buf, fifo->buffer, fifo->used); if(fifo->buffer != NULL) zfree(fifo->buffer); fifo->buffer = next_buf; fifo->size = next_size; } fifo->buffer[fifo->used] = it; fifo->used ++;}voidtx3904sio_fifo_reset(struct hw* me, struct tx3904sio_fifo* fifo){ /* HW_TRACE ((me, "reset fifo")); */ fifo->used = 0; fifo->size = 0; zfree(fifo->buffer); fifo->buffer = 0;}voidtx3904sio_poll(struct hw* me, void* ignored){ struct tx3904sio* controller = hw_data (me); tx3904sio_tickle (me); hw_event_queue_deschedule (me, controller->poll_event); controller->poll_event = hw_event_queue_schedule (me, 1000, tx3904sio_poll, NULL);}const struct hw_descriptor dv_tx3904sio_descriptor[] = { { "tx3904sio", tx3904sio_finish, }, { NULL },};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -