Line 40... |
Line 40... |
static struct dev_16450 uarts[NR_UARTS];
|
static struct dev_16450 uarts[NR_UARTS];
|
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 void set_char_clks(int uartchip)
|
static unsigned long char_clks(int dll, int dlh, int lcr)
|
{
|
{
|
int bauds_per_char = 0;
|
float bauds_per_char = 0;
|
|
unsigned long char_clks = (dlh << 8) + dll;
|
|
|
uarts[uartchip].char_clks = (uarts[uartchip].regs.dlh << 8)
|
if (lcr & UART_LCR_PARITY)
|
+ uarts[uartchip].regs.dll;
|
bauds_per_char = bauds_per_char + 1.;
|
|
|
if (uarts[uartchip].regs.lcr & UART_LCR_PARITY)
|
/* stop bits 1 or two */
|
bauds_per_char++;
|
if (lcr & UART_LCR_STOP)
|
|
bauds_per_char = bauds_per_char + 2.;
|
if (uarts[uartchip].regs.lcr & UART_LCR_STOP)
|
else
|
bauds_per_char += 2;
|
if ((lcr & 0x3) != 0)
|
|
bauds_per_char = bauds_per_char + 1.;
|
else
|
else
|
bauds_per_char++;
|
bauds_per_char = bauds_per_char + 1.5;
|
|
|
bauds_per_char += (5 + (uarts[uartchip].regs.lcr & 0x2));
|
bauds_per_char = bauds_per_char + (5. + (lcr & 0x3));
|
|
|
uarts[uartchip].char_clks *= bauds_per_char;
|
return char_clks * bauds_per_char;
|
}
|
}
|
|
|
/* Set a specific UART register with value. */
|
/* Set a specific UART register with value. */
|
void uart_write_byte(unsigned long addr, unsigned long value)
|
void uart_write_byte(unsigned long addr, unsigned long value)
|
{
|
{
|
Line 76... |
Line 78... |
|
|
if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
|
if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
|
switch (addr % UART_ADDR_SPACE) {
|
switch (addr % UART_ADDR_SPACE) {
|
case UART_DLL:
|
case UART_DLL:
|
uarts[chipsel].regs.dll = value;
|
uarts[chipsel].regs.dll = value;
|
set_char_clks(chipsel);
|
uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
|
return;
|
return;
|
case UART_DLH:
|
case UART_DLH:
|
uarts[chipsel].regs.dlh = value;
|
uarts[chipsel].regs.dlh = value;
|
return;
|
return;
|
}
|
}
|
Line 284... |
Line 286... |
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
|
uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
|
uarts[i].istat.thre_int = 1;
|
uarts[i].istat.thre_int = 1;
|
} else
|
} else
|
uarts[i].regs.lsr |= UART_LSR_TXSERE;
|
uarts[i].regs.lsr |= UART_LSR_TXSERE;
|
} else if (uarts[i].char_clks >= uarts[i].istat.txser_clks++) {
|
} else if (uarts[i].char_clks >= uarts[i].istat.txser_clks++) {
|
debug(8, "TX \'%c\' via UART%d...\n", uarts[i].iregs.txser, i);
|
debug(4, "TX \'%c\' via UART%d...\n", uarts[i].iregs.txser, i);
|
if (uarts[i].regs.mcr & UART_MCR_LOOP)
|
if (uarts[i].regs.mcr & UART_MCR_LOOP)
|
uarts[i].iregs.loopback = uarts[i].iregs.txser;
|
uarts[i].iregs.loopback = uarts[i].iregs.txser;
|
else {
|
else {
|
/* Send to either VAPI or to file */
|
/* Send to either VAPI or to file */
|
if (config.uarts[i].vapi_id) {
|
if (config.uarts[i].vapi_id) {
|
vapi_send (config.uarts[i].vapi_id, uarts[i].iregs.txser);
|
int par, pe, fe, nbits = (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5;
|
|
int i, data;
|
|
unsigned long packet = 0;
|
|
|
|
/* Encode a packet */
|
|
packet = uarts[i].regs.lcr & ((1 << nbits) - 1);
|
|
|
|
/* Calculate parity */
|
|
for (i = 0; i < nbits; i++)
|
|
par ^= (packet >> i) & 1;
|
|
|
|
if (uarts[i].regs.lcr & UART_LCR_PARITY) {
|
|
if (uarts[i].regs.lcr & UART_LCR_SPAR) {
|
|
packet |= 1 << nbits;
|
|
} else {
|
|
if (uarts[i].regs.lcr & UART_LCR_EPAR)
|
|
packet |= par << nbits;
|
|
else
|
|
packet |= (par ^ 1) << nbits;
|
|
}
|
|
nbits++;
|
|
}
|
|
packet |= 1 << (nbits++);
|
|
if (uarts[i].regs.lcr & UART_LCR_STOP)
|
|
packet |= 1 << (nbits++);
|
|
|
|
/* Decode a packet */
|
|
nbits = (uarts[i].vapi.lcr & UART_LCR_WLEN8) + 5;
|
|
data = packet & ((1 << nbits) - 1);
|
|
|
|
/* Calculate parity, including parity bit */
|
|
for (i = 0; i < nbits + 1; i++)
|
|
par ^= (packet >> i) & 1;
|
|
|
|
if (uarts[i].vapi.lcr & UART_LCR_PARITY) {
|
|
if (uarts[i].vapi.lcr & UART_LCR_SPAR) {
|
|
pe = !((packet >> nbits) & 1);
|
|
} else {
|
|
if (uarts[i].vapi.lcr & UART_LCR_EPAR)
|
|
pe = par != 0;
|
|
else
|
|
pe = par != 1;
|
|
}
|
|
nbits++;
|
|
} else
|
|
pe = 0;
|
|
|
|
fe |= ((packet >> (nbits++)) & 1) ^ 1;
|
|
if (uarts[i].vapi.lcr & UART_LCR_STOP)
|
|
fe |= ((packet >> (nbits++)) & 1) ^ 1;
|
|
|
|
printf ("%08x %08x\n", config.uarts[i].vapi_id, data | (uarts[i].vapi.lcr << 8) | (pe << 16) | (fe << 17));
|
|
vapi_send (config.uarts[i].vapi_id, data | (uarts[i].vapi.lcr << 8) | (pe << 16) | (fe << 17));
|
} else {
|
} else {
|
fputc((int)(uarts[i].iregs.txser & 0xFF), uarts[i].txfs);
|
fputc((int)(uarts[i].iregs.txser & 0xFF), uarts[i].txfs);
|
fflush(uarts[i].txfs);
|
fflush(uarts[i].txfs);
|
}
|
}
|
}
|
}
|
uarts[i].istat.txser_full = 1;
|
uarts[i].istat.txser_full = 0;
|
uarts[i].istat.txser_clks = 0;
|
uarts[i].istat.txser_clks = 0;
|
}
|
}
|
|
|
/* Receive */
|
/* Receive */
|
if (uarts[i].istat.rxser_full) {
|
if (uarts[i].istat.rxser_full) {
|
if (uarts[i].char_clks >= uarts[i].istat.rxser_clks++) {
|
if (uarts[i].char_clks >= uarts[i].istat.rxser_clks++) {
|
debug(8, "Receiving via UART%d...\n", i);
|
debug(4, "Receiving via UART%d...\n", i);
|
uarts[i].istat.rxser_full = 0;
|
uarts[i].istat.rxser_full = 0;
|
uarts[i].istat.rxser_clks = 0;
|
uarts[i].istat.rxser_clks = 0;
|
|
|
if (++uarts[i].istat.rxbuf_full > uarts[i].fifo_len)
|
if (++uarts[i].istat.rxbuf_full > uarts[i].fifo_len)
|
uarts[i].regs.lsr |= UART_LSR_OVRRUN;
|
uarts[i].regs.lsr |= UART_LSR_OVRRUN;
|
Line 328... |
Line 382... |
if (!config.uarts[i].vapi_id) {
|
if (!config.uarts[i].vapi_id) {
|
if((retval = fgetc(uarts[i].rxfs)) != EOF)
|
if((retval = fgetc(uarts[i].rxfs)) != EOF)
|
uarts[i].iregs.rxser = (char)retval;
|
uarts[i].iregs.rxser = (char)retval;
|
uarts[i].istat.rxser_full = 1;
|
uarts[i].istat.rxser_full = 1;
|
} else { /* VAPI */
|
} else { /* VAPI */
|
|
int received = 0;
|
|
while (!received) {
|
if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
|
if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
|
uarts[i].iregs.rxser = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
|
unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
|
uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % uarts[i].fifo_len;
|
uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % uarts[i].fifo_len;
|
|
switch (data >> 24) {
|
|
case 0x00:
|
|
uarts[i].vapi.lcr = (data >> 8) & 0xff;
|
|
/* Put data into rx fifo */
|
|
uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
|
|
if (uarts[i].vapi.lcr != uarts[i].regs.lcr || uarts[i].vapi.char_clks != uarts[i].char_clks
|
|
|| uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
|
|
fprintf (stderr, "WARNING: unmatched VAPI and uart modes.\n");
|
|
/* Set error bits */
|
|
uarts[i].regs.lsr |= UART_LSR_PARITY | UART_LSR_FRAME;
|
|
break;
|
|
} else {
|
|
uarts[i].iregs.rxser = data & 0xff;
|
uarts[i].istat.rxser_full = 1;
|
uarts[i].istat.rxser_full = 1;
|
}
|
}
|
|
received = 1;
|
|
break;
|
|
case 0x01:
|
|
uarts[i].vapi.dll = (data >> 0) & 0xff;
|
|
uarts[i].vapi.dlh = (data >> 8) & 0xff;
|
|
break;
|
|
case 0x02:
|
|
uarts[i].vapi.lcr = data & 0xff;
|
|
break;
|
|
case 0x03:
|
|
uarts[i].vapi.skew = (signed short)(data & 0xffff);
|
|
break;
|
|
default:
|
|
fprintf (stderr, "WARNING: Invalid vapi command %02x\n", data >> 24);
|
|
break;
|
|
}
|
|
} else break;
|
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Loopback */
|
/* Loopback */
|
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
|
if (uarts[i].regs.mcr & UART_MCR_LOOP) {
|