Line 29... |
Line 29... |
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <string.h>
|
#include <string.h>
|
|
|
|
#include "abstract.h"
|
#include "16450.h"
|
#include "16450.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "pic.h"
|
#include "pic.h"
|
|
|
static struct dev_16450 uarts[NR_UARTS];
|
static struct dev_16450 uarts[NR_UARTS];
|
Line 59... |
Line 60... |
|
|
uarts[uartchip].char_clks *= bauds_per_char;
|
uarts[uartchip].char_clks *= bauds_per_char;
|
}
|
}
|
|
|
/* Set a specific UART register with value. */
|
/* Set a specific UART register with value. */
|
void uart_write(unsigned long addr, unsigned long value)
|
void uart_write8(unsigned long addr, unsigned char value)
|
{
|
{
|
int chipsel;
|
int chipsel;
|
|
|
debug("uart_write(%x,%x)\n", addr, (value >> 24));
|
debug("uart_write8(%x,%02x)\n", addr, (unsigned)value);
|
|
|
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
|
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
|
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
|
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
|
break;
|
break;
|
else if (chipsel == NR_UARTS)
|
else if (chipsel == NR_UARTS)
|
return;
|
return;
|
|
|
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 >> 24);
|
uarts[chipsel].regs.dll = value;
|
break;
|
break;
|
case UART_DLH:
|
case UART_DLH:
|
uarts[chipsel].regs.dlh = (value >> 24);
|
uarts[chipsel].regs.dlh = value;
|
break;
|
break;
|
case UART_LCR:
|
case UART_LCR:
|
uarts[chipsel].regs.lcr = (value >> 24) & UART_VALID_LCR;
|
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
|
break;
|
break;
|
default:
|
default:
|
debug("write out of range (addr %x, DLAB=1)\n", addr);
|
debug("write out of range (addr %x, DLAB=1)\n", addr);
|
}
|
}
|
set_char_clks(chipsel);
|
set_char_clks(chipsel);
|
return;
|
return;
|
}
|
}
|
|
|
switch (addr % UART_ADDR_SPACE) {
|
switch (addr % UART_ADDR_SPACE) {
|
case UART_TXBUF:
|
case UART_TXBUF:
|
uarts[chipsel].regs.txbuf = (value >> 24);
|
uarts[chipsel].regs.txbuf = value;
|
uarts[chipsel].istat.txbuf = FULL;
|
uarts[chipsel].istat.txbuf = FULL;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXSERE;
|
uarts[chipsel].regs.lsr &= ~UART_LSR_TXSERE;
|
uarts[chipsel].istat.thre_int = 0;
|
uarts[chipsel].istat.thre_int = 0;
|
break;
|
break;
|
case UART_IER:
|
case UART_IER:
|
uarts[chipsel].regs.ier = (value >> 24) & UART_VALID_IER;
|
uarts[chipsel].regs.ier = value & UART_VALID_IER;
|
break;
|
break;
|
case UART_LCR:
|
case UART_LCR:
|
uarts[chipsel].regs.lcr = (value >> 24) & UART_VALID_LCR;
|
uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
|
break;
|
break;
|
case UART_MCR:
|
case UART_MCR:
|
uarts[chipsel].regs.mcr = (value >> 24) & UART_VALID_MCR;
|
uarts[chipsel].regs.mcr = value & UART_VALID_MCR;
|
break;
|
break;
|
case UART_SCR:
|
case UART_SCR:
|
uarts[chipsel].regs.scr = (value >> 24);
|
uarts[chipsel].regs.scr = value;
|
break;
|
break;
|
default:
|
default:
|
debug("write out of range (addr %x)\n", addr);
|
debug("write out of range (addr %x)\n", addr);
|
}
|
}
|
set_char_clks(chipsel);
|
set_char_clks(chipsel);
|
return;
|
return;
|
}
|
}
|
|
|
/* Read a specific UART register. */
|
/* Read a specific UART register. */
|
unsigned long uart_read(unsigned long addr)
|
unsigned char uart_read8(unsigned long addr)
|
{
|
{
|
unsigned char value = 0;
|
unsigned char value = 0;
|
int chipsel;
|
int chipsel;
|
|
|
debug("uart_read(%x)\n", addr);
|
debug("uart_read8(%x)\n", addr);
|
|
|
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
|
for(chipsel = 0; chipsel < NR_UARTS; chipsel++)
|
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
|
if ((addr & ~(UART_ADDR_SPACE-1)) == uarts[chipsel].baseaddr)
|
break;
|
break;
|
else if (chipsel == NR_UARTS)
|
else if (chipsel == NR_UARTS)
|
Line 141... |
Line 142... |
value = uarts[chipsel].regs.dlh;
|
value = uarts[chipsel].regs.dlh;
|
break;
|
break;
|
default:
|
default:
|
debug("read out of range (addr %x, DLAB=1)\n", addr);
|
debug("read out of range (addr %x, DLAB=1)\n", addr);
|
}
|
}
|
return (value << 24);
|
return value;
|
}
|
}
|
|
|
switch (addr % UART_ADDR_SPACE) {
|
switch (addr % UART_ADDR_SPACE) {
|
case UART_RXBUF:
|
case UART_RXBUF:
|
value = uarts[chipsel].regs.rxbuf;
|
value = uarts[chipsel].regs.rxbuf;
|
Line 179... |
Line 180... |
value = uarts[chipsel].regs.scr;
|
value = uarts[chipsel].regs.scr;
|
break;
|
break;
|
default:
|
default:
|
debug("read out of range (addr %x)\n", addr);
|
debug("read out of range (addr %x)\n", addr);
|
}
|
}
|
return (value << 24);
|
return value;
|
}
|
}
|
|
|
/* 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. */
|
Line 206... |
Line 207... |
if (uarts[i].txfs && uarts[i].txfs) {
|
if (uarts[i].txfs && uarts[i].txfs) {
|
printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
|
printf("UART%d at 0x%.8x uses ", i, uarts[i].baseaddr);
|
printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
|
printf("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
|
} else
|
} else
|
printf("UART%d has problems with TX file stream.\n", i);
|
printf("UART%d has problems with TX file stream.\n", i);
|
register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE, uart_read, uart_write);
|
register_memoryarea(uarts[i].baseaddr, UART_ADDR_SPACE, 1, uart_read8, uart_write8, 0);
|
}
|
}
|
}
|
}
|
|
|
/* Simulation hook. Must be called every clock cycle to simulate all UART
|
/* Simulation hook. Must be called every clock cycle to simulate all UART
|
devices. It does internal functional UART simulation. */
|
devices. It does internal functional UART simulation. */
|
Line 318... |
Line 319... |
void uart_status()
|
void uart_status()
|
{
|
{
|
int i;
|
int i;
|
|
|
for(i = 0; i < NR_UARTS; i++) {
|
for(i = 0; i < NR_UARTS; i++) {
|
/* if (!uarts[i].txfs)
|
if ( !uarts[i].baseaddr )
|
continue;
|
continue;
|
*/
|
|
printf("\nUART%d visible registers at 0x%.8x:\n", i, uarts[i].baseaddr);
|
printf("\nUART%d visible registers at 0x%.8x:\n", i, uarts[i].baseaddr);
|
printf("RXBUF: %.2x TXBUF: %.2x\n", uarts[i].regs.rxbuf, uarts[i].regs.txbuf);
|
printf("RXBUF: %.2x TXBUF: %.2x\n", uarts[i].regs.rxbuf, uarts[i].regs.txbuf);
|
printf("DLL : %.2x DLH : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
|
printf("DLL : %.2x DLH : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
|
printf("IER : %.2x IIR : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
|
printf("IER : %.2x IIR : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
|
printf("LCR : %.2x MCR : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
|
printf("LCR : %.2x MCR : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
|