Line 35... |
Line 35... |
#include "16450.h"
|
#include "16450.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "pic.h"
|
#include "pic.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "sched.h"
|
#include "sched.h"
|
|
#include "channel.h"
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
static struct dev_16450 uarts[MAX_UARTS];
|
static struct dev_16450 uarts[MAX_UARTS]; /* simulation info */
|
|
static struct channel * channels[MAX_UARTS] = { NULL, }; /* emulation info */
|
static int thre_int;
|
static int thre_int;
|
|
|
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
|
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
|
before a single character is transmitted or received. */
|
before a single character is transmitted or received. */
|
static unsigned long char_clks(int dll, int dlh, int lcr)
|
static unsigned long char_clks(int dll, int dlh, int lcr)
|
Line 306... |
Line 308... |
data |= (uarts[uart].vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uarts[uart].vapi.lcr << 8);
|
data |= (uarts[uart].vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uarts[uart].vapi.lcr << 8);
|
PRINTF ("vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
|
PRINTF ("vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
|
debug (4, "vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
|
debug (4, "vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
|
vapi_send (config.uarts[uart].vapi_id, data);
|
vapi_send (config.uarts[uart].vapi_id, data);
|
} else {
|
} else {
|
fputc((int)(uarts[uart].iregs.txser & 0xFF), uarts[uart].txfs);
|
char buffer[1] = { uarts[uart].iregs.txser & 0xFF };
|
fflush(uarts[uart].txfs);
|
channel_write(channels[uart], buffer, 1);
|
}
|
}
|
}
|
}
|
uarts[uart].istat.txser_full = 0;
|
uarts[uart].istat.txser_full = 0;
|
uarts[uart].istat.txser_clks = 0;
|
uarts[uart].istat.txser_clks = 0;
|
}
|
}
|
Line 342... |
Line 344... |
SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
|
SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
|
|
|
/* If VAPI is not selected, UART communicates with two file streams;
|
/* If VAPI is not selected, UART communicates with two file streams;
|
if VAPI is selected, we use VAPI streams. */
|
if VAPI is selected, we use VAPI streams. */
|
/* if txfs is corrupted, skip this uart. */
|
/* if txfs is corrupted, skip this uart. */
|
if (!config.uarts[i].vapi_id && !uarts[i].txfs) return;
|
if (!config.uarts[i].vapi_id && !channel_ok(channels[i])) return;
|
|
|
if (uarts[i].vapi.next_break_cnt >= 0)
|
if (uarts[i].vapi.next_break_cnt >= 0)
|
if (--uarts[i].vapi.next_break_cnt < 0) {
|
if (--uarts[i].vapi.next_break_cnt < 0) {
|
if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
|
if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
|
uarts[i].istat.break_set = 0;
|
uarts[i].istat.break_set = 0;
|
Line 431... |
Line 433... |
} else {
|
} else {
|
if (!config.uarts[i].vapi_id) {
|
if (!config.uarts[i].vapi_id) {
|
if(uarts[i].istat.rxser_full == 0) {
|
if(uarts[i].istat.rxser_full == 0) {
|
if (uarts[i].slowdown)
|
if (uarts[i].slowdown)
|
uarts[i].slowdown--;
|
uarts[i].slowdown--;
|
else if((retval = fgetc(uarts[i].rxfs)) != EOF) {
|
else {
|
uarts[i].iregs.rxser = (char)retval;
|
char buffer[1];
|
|
retval = channel_read(channels[i], buffer, 1);
|
|
if(retval < 0)
|
|
perror(config.uarts[i].channel);
|
|
else if(retval > 0) {
|
|
uarts[i].iregs.rxser = buffer[0];
|
uarts[i].istat.rxser_full = 1;
|
uarts[i].istat.rxser_full = 1;
|
} else uarts[i].slowdown = UART_FGETC_SLOWDOWN;
|
} else
|
|
uarts[i].slowdown = UART_FGETC_SLOWDOWN;
|
|
}
|
}
|
}
|
} else { /* VAPI */
|
} else { /* VAPI */
|
int received = 0;
|
int received = 0;
|
/* do not handle commands while receiving */
|
/* do not handle commands while receiving */
|
if (uarts[i].istat.rxser_full) return;
|
if (uarts[i].istat.rxser_full) return;
|
Line 561... |
Line 570... |
for(i = 0; i < config.nuarts; i++) {
|
for(i = 0; i < config.nuarts; i++) {
|
if (config.uarts[i].vapi_id) {
|
if (config.uarts[i].vapi_id) {
|
if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
|
if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
|
fprintf (stderr, "ERROR: Wrong vapi_id (0x%x) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
|
fprintf (stderr, "ERROR: Wrong vapi_id (0x%x) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
|
config.uarts[i].vapi_id = 0;
|
config.uarts[i].vapi_id = 0;
|
uarts[i].txfs = 0;
|
|
} else {
|
} else {
|
vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
|
vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
|
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
|
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
|
}
|
}
|
} else if (config.uarts[i].txfile) { /* MM: Try to create stream. */
|
} else if (config.uarts[i].channel[0]) { /* MM: Try to create stream. */
|
if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
|
if(channels[i])
|
&& !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
|
channel_close(channels[i]);
|
debug (0, "WARNING: UART%d has problems with RX file stream.\n", i);
|
else
|
|
channels[i] = channel_init(config.uarts[i].channel);
|
|
if(channel_open(channels[i]) < 0) {
|
|
debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
|
continue;
|
continue;
|
}
|
}
|
uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
|
if (config.sim.verbose)
|
if (uarts[i].rxfs && uarts[i].txfs && config.sim.verbose) {
|
|
PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
|
PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
|
PRINTF("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
|
|
} else
|
|
debug (1, "WARNING: UART%d has problems with TX file stream.\n", i);
|
|
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
|
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
|
|
} else {
|
|
debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
|
|
continue;
|
}
|
}
|
|
|
if (config.uarts[i].uart16550)
|
if (config.uarts[i].uart16550)
|
uarts[i].fifo_len = 16;
|
uarts[i].fifo_len = 16;
|
else
|
else
|
Line 632... |
Line 642... |
PRINTF("rxser: %d txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
|
PRINTF("rxser: %d txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
|
PRINTF("rxbuf: %d txbuf: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
|
PRINTF("rxbuf: %d txbuf: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
|
PRINTF("Using IRQ%i\n", config.uarts[i].irq);
|
PRINTF("Using IRQ%i\n", config.uarts[i].irq);
|
if (config.uarts[i].vapi_id)
|
if (config.uarts[i].vapi_id)
|
PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
|
PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
|
else
|
/* TODO: replace by a channel_status
|
PRINTF("RX fs: %p TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
|
else
|
|
PRINTF("RX fs: %p TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
|
|
*/
|
}
|
}
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|