Line 59... |
Line 59... |
static void uart_sched_recv_check(struct dev_16450 *uart);
|
static void uart_sched_recv_check(struct dev_16450 *uart);
|
static void uart_vapi_cmd(void *dat);
|
static void uart_vapi_cmd(void *dat);
|
static void uart_clear_int(struct dev_16450 *uart, int intr);
|
static void uart_clear_int(struct dev_16450 *uart, int intr);
|
void uart_tx_send(void *dat);
|
void uart_tx_send(void *dat);
|
|
|
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
|
/* Number of clock cycles (one clock cycle is when UART_CLOCK_DIVIDER simulator
|
before a single character is transmitted or received. */
|
* cycles have elapsed) 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)
|
{
|
{
|
unsigned int bauds_per_char = 2;
|
unsigned int bauds_per_char = 2;
|
unsigned long char_clks = ((dlh << 8) + dll);
|
unsigned long char_clks = ((dlh << 8) + dll);
|
|
|
Line 266... |
Line 266... |
* code is probably still running with interrupts disabled and this function
|
* code is probably still running with interrupts disabled and this function
|
* is called from the uart_{read,write}_byte functions. */
|
* is called from the uart_{read,write}_byte functions. */
|
SCHED_ADD(uart_next_int, uart, 0);
|
SCHED_ADD(uart_next_int, uart, 0);
|
}
|
}
|
|
|
|
/*----------------------------------------------------[ Loopback handling ]---*/
|
|
static void uart_loopback(struct dev_16450 *uart)
|
|
{
|
|
if(!(uart->regs.mcr & UART_MCR_LOOP))
|
|
return;
|
|
|
|
if((uart->regs.mcr & UART_MCR_AUX2) != ((uart->regs.msr & UART_MSR_DCD) >> 4))
|
|
uart->regs.msr |= UART_MSR_DDCD;
|
|
|
|
if((uart->regs.mcr & UART_MCR_AUX1) < ((uart->regs.msr & UART_MSR_RI) >> 4))
|
|
uart->regs.msr |= UART_MSR_TERI;
|
|
|
|
if((uart->regs.mcr & UART_MCR_RTS) != ((uart->regs.msr & UART_MSR_CTS) >> 3))
|
|
uart->regs.msr |= UART_MSR_DCTS;
|
|
|
|
if((uart->regs.mcr & UART_MCR_DTR) != ((uart->regs.msr & UART_MSR_DSR) >> 5))
|
|
uart->regs.msr |= UART_MSR_DDSR;
|
|
|
|
uart->regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI | UART_MSR_DSR | UART_MSR_CTS);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
|
|
|
|
if(uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI |
|
|
UART_MSR_DDCD))
|
|
uart_int_msi(uart);
|
|
}
|
|
|
/*----------------------------------------------------[ Transmitter logic ]---*/
|
/*----------------------------------------------------[ Transmitter logic ]---*/
|
/* Sends the data in the shift register to the outside world */
|
/* Sends the data in the shift register to the outside world */
|
static void send_char (struct dev_16450 *uart, int bits_send)
|
static void send_char (struct dev_16450 *uart, int bits_send)
|
{
|
{
|
PRINTF ("%c", (char)uart->iregs.txser);
|
PRINTF ("%c", (char)uart->iregs.txser);
|
Line 610... |
Line 639... |
uart->regs.lcr = value & UART_VALID_LCR;
|
uart->regs.lcr = value & UART_VALID_LCR;
|
uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
|
uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
|
break;
|
break;
|
case UART_MCR:
|
case UART_MCR:
|
uart->regs.mcr = value & UART_VALID_MCR;
|
uart->regs.mcr = value & UART_VALID_MCR;
|
|
uart_loopback(uart);
|
break;
|
break;
|
case UART_SCR:
|
case UART_SCR:
|
uart->regs.scr = value;
|
uart->regs.scr = value;
|
break;
|
break;
|
default:
|
default:
|
Line 702... |
Line 732... |
break;
|
break;
|
case UART_MSR:
|
case UART_MSR:
|
value = uart->regs.msr & UART_VALID_MSR;
|
value = uart->regs.msr & UART_VALID_MSR;
|
uart->regs.msr = 0;
|
uart->regs.msr = 0;
|
uart_clear_int(uart, UART_IIR_MSI);
|
uart_clear_int(uart, UART_IIR_MSI);
|
|
uart_loopback(uart);
|
break;
|
break;
|
case UART_SCR:
|
case UART_SCR:
|
value = uart->regs.scr;
|
value = uart->regs.scr;
|
break;
|
break;
|
default:
|
default:
|
Line 813... |
Line 844... |
}
|
}
|
if(!uart->istat.receiveing)
|
if(!uart->istat.receiveing)
|
uart_vapi_cmd(uart);
|
uart_vapi_cmd(uart);
|
}
|
}
|
|
|
/* Simulation hook. Must be called every clock cycle to simulate all UART
|
|
devices. It does internal functional UART simulation. */
|
|
void uart_clock16 (void *dat)
|
|
{
|
|
struct dev_16450 *uart = dat;
|
|
|
|
/* Schedule for later */
|
|
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
|
|
|
|
TRACE("Running uart clock:\n");
|
|
|
|
/* If VAPI is not selected, UART communicates with two file streams;
|
|
if VAPI is selected, we use VAPI streams. */
|
|
/* if txfs is corrupted, skip this uart. */
|
|
if (!uart->vapi_id && !channel_ok(uart->channel)) return;
|
|
|
|
TRACE("\tChannel stream or VAPI checks out ok\n");
|
|
|
|
/***************** Loopback *****************/
|
|
if (uart->regs.mcr & UART_MCR_LOOP) {
|
|
TRACE("uart_clock: Loopback\n");
|
|
if ((uart->regs.mcr & UART_MCR_AUX2) !=
|
|
((uart->regs.msr & UART_MSR_DCD) >> 4))
|
|
uart->regs.msr |= UART_MSR_DDCD;
|
|
if ((uart->regs.mcr & UART_MCR_AUX1) <
|
|
((uart->regs.msr & UART_MSR_RI) >> 4))
|
|
uart->regs.msr |= UART_MSR_TERI;
|
|
if ((uart->regs.mcr & UART_MCR_RTS) !=
|
|
((uart->regs.msr & UART_MSR_CTS) >> 3))
|
|
uart->regs.msr |= UART_MSR_DCTS;
|
|
if ((uart->regs.mcr & UART_MCR_DTR) !=
|
|
((uart->regs.msr & UART_MSR_DSR) >> 5))
|
|
uart->regs.msr |= UART_MSR_DDSR;
|
|
uart->regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
|
|
| UART_MSR_DSR | UART_MSR_CTS);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
|
|
uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
|
|
}
|
|
}
|
|
|
|
/* Reset. It initializes all registers of all UART devices to zero values,
|
/* Reset. It initializes all registers of all UART devices to zero values,
|
(re)opens all RX/TX file streams and places devices in memory address
|
(re)opens all RX/TX file streams and places devices in memory address
|
space. */
|
space. */
|
void uart_reset(void *dat)
|
void uart_reset(void *dat)
|
{
|
{
|
Line 920... |
Line 909... |
|
|
uart->vapi_buf_head_ptr = 0;
|
uart->vapi_buf_head_ptr = 0;
|
uart->vapi_buf_tail_ptr = 0;
|
uart->vapi_buf_tail_ptr = 0;
|
memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf));
|
memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf));
|
|
|
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
|
|
uart_sched_recv_check(uart);
|
uart_sched_recv_check(uart);
|
}
|
}
|
|
|
/* Print register values on stdout. */
|
/* Print register values on stdout. */
|
void uart_status(void *dat)
|
void uart_status(void *dat)
|