Line 41... |
Line 41... |
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
static struct dev_16450 uarts[MAX_UARTS]; /* simulation info */
|
static struct dev_16450 uarts[MAX_UARTS]; /* simulation info */
|
static struct channel * channels[MAX_UARTS] = { NULL, }; /* emulation info */
|
static struct channel * channels[MAX_UARTS] = { NULL, }; /* emulation info */
|
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 113... |
Line 112... |
uarts[chipsel].fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
|
uarts[chipsel].fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
|
if (value & UART_FCR_RTXFI) {
|
if (value & UART_FCR_RTXFI) {
|
uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0;
|
uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0;
|
uarts[chipsel].istat.txbuf_full = 0;
|
uarts[chipsel].istat.txbuf_full = 0;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
|
|
uarts[chipsel].istat.thre_int = 0;
|
}
|
}
|
if (value & UART_FCR_RRXFI) {
|
if (value & UART_FCR_RRXFI) {
|
uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
|
uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
|
uarts[chipsel].istat.rxbuf_full = 0;
|
uarts[chipsel].istat.rxbuf_full = 0;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
|
}
|
}
|
break;
|
break;
|
case UART_IER:
|
case UART_IER:
|
uarts[chipsel].regs.ier = value & UART_VALID_IER;
|
uarts[chipsel].regs.ier = value & UART_VALID_IER;
|
#if 0
|
|
if (uarts[chipsel].regs.ier & UART_IER_THRI)
|
|
uarts[chipsel].istat.thre_int = 1;
|
|
#endif
|
|
break;
|
break;
|
case UART_LCR:
|
case UART_LCR:
|
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
|
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
|
uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
|
uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
|
break;
|
break;
|
Line 361... |
Line 357... |
uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
|
uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
|
uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
|
uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
|
uarts[i].istat.txser_full = 1;
|
uarts[i].istat.txser_full = 1;
|
uarts[i].istat.txbuf_full--;
|
uarts[i].istat.txbuf_full--;
|
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
|
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
|
|
|
|
// When UART is in either character mode, i.e. 16450 emulation mode, or FIFO mode,
|
|
// the THRE interrupt is raised when THR transitions from full to empty.
|
|
if (!uarts[i].istat.txbuf_full) {
|
uarts[i].istat.thre_int = 1;
|
uarts[i].istat.thre_int = 1;
|
|
uarts[i].regs.lsr |= UART_LSR_TXBUFE;
|
|
}
|
} else {
|
} else {
|
uarts[i].regs.lsr |= UART_LSR_TXSERE;
|
uarts[i].regs.lsr |= UART_LSR_TXSERE;
|
uarts[i].regs.lsr |= UART_LSR_TXBUFE;
|
|
}
|
}
|
} else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
|
} else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
|
send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
|
send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
|
} else {
|
} else {
|
/* We are still sending char here*/
|
/* We are still sending char here*/
|
Line 388... |
Line 389... |
/* mark as character was sent */
|
/* mark as character was sent */
|
uarts[i].istat.txser_full = 0;
|
uarts[i].istat.txser_full = 0;
|
uarts[i].istat.txser_clks = 0;
|
uarts[i].istat.txser_clks = 0;
|
} else
|
} else
|
uarts[i].vapi.break_sent = 0;
|
uarts[i].vapi.break_sent = 0;
|
|
|
|
}
|
|
|
|
// For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
|
|
if (!uarts[i].istat.txbuf_full && (uarts[i].fifo_len == 16)) {
|
|
uarts[i].regs.lsr |= UART_LSR_TXBUFE;
|
|
uarts[i].istat.thre_int = 1;
|
}
|
}
|
|
|
/***************** Receive *****************/
|
/***************** Receive *****************/
|
|
|
/* Is there a break? */
|
/* Is there a break? */
|
Line 542... |
Line 550... |
uarts[i].regs.iir = UART_IIR_RDI;
|
uarts[i].regs.iir = UART_IIR_RDI;
|
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* timeout */
|
} else if ((uarts[i].regs.ier & UART_IER_RDI) /* timeout */
|
&& (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
|
&& (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)) {
|
uarts[i].regs.iir = UART_IIR_CTI;
|
uarts[i].regs.iir = UART_IIR_CTI;
|
} else if (uarts[i].regs.ier & UART_IER_THRI && /* Transm. empty */
|
} else if (uarts[i].regs.ier & UART_IER_THRI && /* Transm. empty */
|
uarts[i].regs.lsr & UART_LSR_TXBUFE &&
|
|
uarts[i].istat.thre_int == 1) {
|
uarts[i].istat.thre_int == 1) {
|
uarts[i].regs.iir = UART_IIR_THRI;
|
uarts[i].regs.iir = UART_IIR_THRI;
|
} else if (uarts[i].regs.ier & UART_IER_MSI && /* Modem status */
|
} else if (uarts[i].regs.ier & UART_IER_MSI && /* Modem status */
|
uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
|
uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
|
| UART_MSR_TERI | UART_MSR_DDCD)) {
|
| UART_MSR_TERI | UART_MSR_DDCD)) {
|