289 lines
7.4 KiB
C
289 lines
7.4 KiB
C
|
/* Stand-alone library for Sparclet 701 board
|
||
|
*
|
||
|
* Copyright (c) 1996 Cygnus Support
|
||
|
*
|
||
|
* The authors hereby grant permission to use, copy, modify, distribute,
|
||
|
* and license this software and its documentation for any purpose, provided
|
||
|
* that existing copyright notices are retained in all copies and that this
|
||
|
* notice is included verbatim in any distributions. No written agreement,
|
||
|
* license, or royalty fee is required for any of the authorized uses.
|
||
|
* Modifications to this software may be copyrighted by their authors
|
||
|
* and need not follow the licensing terms described here, provided that
|
||
|
* the new terms are clearly indicated on the first page of each file where
|
||
|
* they apply.
|
||
|
*/
|
||
|
|
||
|
#define RAM_BASE ((unsigned char *)0x12000000) /* Start of cacheable dram */
|
||
|
#define DCACHE_LINES 128 /* Number of lines in data cache */
|
||
|
#define DCACHE_LINE_SIZE 16 /* Bytes per data cache line */
|
||
|
#define DCACHE_BANKS 4 /* 4-way associative */
|
||
|
#define CACHE_INST_TAG_ADDR ((unsigned char *)0xc0020000) /* I-Cache tag base address */
|
||
|
#define ALL_BANKS 0x0000f000 /* Selects all 4 cache banks */
|
||
|
#define ICACHE_LINES 128 /* Number of lines in inst cache */
|
||
|
#define ICACHE_LINE_SIZE 32 /* Bytes per inst cache line */
|
||
|
|
||
|
/* I/O Base addresses */
|
||
|
#define CACHE_INST_BASE_ADD 0xc0000000
|
||
|
#define CACHE_DATA_BASE_ADD 0xc8000000
|
||
|
#define _InstrCacheCtlBase 0xc0000000
|
||
|
#define _DataCacheCtlBase 0xc8000000
|
||
|
|
||
|
#define USART_BASE_ADD 0x92000000
|
||
|
#define USART_BASE_ADRS(n) (USART_BASE_ADD + ((n)<<21)) /*0..3*/
|
||
|
|
||
|
/* Serial receiver definitions */
|
||
|
#define USART_RX_CHAR(n) (*(unsigned char *) (USART_BASE_ADRS(n) +(2<<19)))
|
||
|
#define USART_RX_CTRL_BASE_ADRS(n) (USART_BASE_ADRS(n)+(3<<19))
|
||
|
#define URSTR(n) (*(unsigned int *) (USART_RX_CTRL_BASE_ADRS(n)+(2<<15)))
|
||
|
#define URSTR_CHAR_NUM 0x1f00 /* Bits 8-12 */
|
||
|
|
||
|
/* Serial receiver definitions */
|
||
|
#define USART_TX_CHAR(n) (*(unsigned char *) (USART_BASE_ADRS(n)+3))
|
||
|
#define USART_TX_CTRL_BASE_ADRS(n) (USART_BASE_ADRS(n)+(1<<19))
|
||
|
#define UTSTR(n) (*(unsigned int *) (USART_TX_CTRL_BASE_ADRS(n)+(2<<15)))
|
||
|
#define UTSTR_CHAR_FREE 0x1f0 /* Bits 4-8 */
|
||
|
|
||
|
/* Cache definitions */
|
||
|
#define DCCA_NB_LINES 128 /* Nb of lines of the cache */
|
||
|
/* Bank number, used for Cache Memory and Cache Tag */
|
||
|
#define ICCA_B3 0x000008000 /* Bit 15 - 1:Bank3 selected */
|
||
|
#define ICCA_B2 0x000004000 /* Bit 14 - 1:Bank2 selected */
|
||
|
#define ICCA_B1 0x000002000 /* Bit 13 - 1:Bank1 selected */
|
||
|
#define ICCA_B0 0x000001000 /* Bit 12 - 1:Bank0 selected */
|
||
|
/* Register address, show which register is to be checked/updated */
|
||
|
#define ICCACR 0x00000000 /* Bits 17 - 16 - Control register */
|
||
|
#define ICCAMEM 0x00010000 /* Bits 17 - 16 - Cache memory */
|
||
|
#define DCCACR 0x00000000 /* Bits 16 - 15 - Control register */
|
||
|
/* Instruction Cache Controller Register */
|
||
|
#define ICCR_DISABLE 0xfffffffe /* Reset enable bit */
|
||
|
|
||
|
/* Serial I/O routines */
|
||
|
|
||
|
#define STUB_PORT 1 /* 0 = serial port A; 1 = serial port B */
|
||
|
|
||
|
static volatile unsigned char *rx_fifo = &USART_RX_CHAR(STUB_PORT);
|
||
|
static volatile unsigned int *rx_status = &URSTR(STUB_PORT);
|
||
|
|
||
|
static volatile unsigned char *tx_fifo = &USART_TX_CHAR(STUB_PORT);
|
||
|
static volatile unsigned int *tx_status = &UTSTR(STUB_PORT);
|
||
|
|
||
|
/* library-free debug reoutines */
|
||
|
#ifdef XDEBUG
|
||
|
#define XDBG_MSG(x) pmsg(x)
|
||
|
#define XDBG_HEX(x) phex(x)
|
||
|
#else
|
||
|
#define XDBG_MSG(x)
|
||
|
#define XDBG_HEX(x)
|
||
|
#endif
|
||
|
|
||
|
static int
|
||
|
rx_rdy()
|
||
|
{
|
||
|
return (*rx_status & URSTR_CHAR_NUM);
|
||
|
}
|
||
|
|
||
|
static unsigned char
|
||
|
rx_char()
|
||
|
{
|
||
|
return *rx_fifo;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
tx_char(char c)
|
||
|
{
|
||
|
*tx_fifo = c;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
tx_rdy()
|
||
|
{
|
||
|
return (*tx_status & UTSTR_CHAR_FREE);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getDebugChar()
|
||
|
{
|
||
|
while (!rx_rdy())
|
||
|
;
|
||
|
return rx_char();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
putDebugChar(int c)
|
||
|
{
|
||
|
while (!tx_rdy())
|
||
|
;
|
||
|
tx_char(c);
|
||
|
}
|
||
|
|
||
|
#ifdef XDEBUG
|
||
|
/* library-free debug reoutines */
|
||
|
/* print a string */
|
||
|
void pmsg(char *p)
|
||
|
{
|
||
|
while (*p)
|
||
|
{
|
||
|
if (*p == '\n')
|
||
|
putDebugChar('\r');
|
||
|
putDebugChar(*p++);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* print a hex number */
|
||
|
void phex(long x)
|
||
|
{
|
||
|
char buf[9];
|
||
|
int i;
|
||
|
|
||
|
buf[8] = '\0';
|
||
|
for (i = 7; i >= 0; i--)
|
||
|
{
|
||
|
char c = x & 0x0f;
|
||
|
buf[i] = c < 10 ? c + '0' : c - 10 + 'A';
|
||
|
x >>= 4;
|
||
|
}
|
||
|
pmsg(buf);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* rdtbr() - read the trap base register */
|
||
|
|
||
|
unsigned long rdtbr();
|
||
|
|
||
|
asm("
|
||
|
.text
|
||
|
.align 4
|
||
|
.globl _rdtbr
|
||
|
_rdtbr:
|
||
|
retl
|
||
|
mov %tbr, %o0
|
||
|
");
|
||
|
|
||
|
/* wrtbr() - write the trap base register */
|
||
|
|
||
|
void wrtbr(unsigned long);
|
||
|
|
||
|
asm("
|
||
|
.text
|
||
|
.align 4
|
||
|
.globl _wrtbr
|
||
|
_wrtbr:
|
||
|
retl
|
||
|
mov %o0, %tbr
|
||
|
");
|
||
|
|
||
|
/* Each entry in the trap vector occupies four words. */
|
||
|
|
||
|
struct trap_entry
|
||
|
{
|
||
|
unsigned sethi_filler:10;
|
||
|
unsigned sethi_imm22:22;
|
||
|
unsigned jmpl_filler:19;
|
||
|
unsigned jmpl_simm13:13;
|
||
|
unsigned long filler[2];
|
||
|
};
|
||
|
|
||
|
extern struct trap_entry fltr_proto;
|
||
|
asm ("
|
||
|
.data
|
||
|
.globl _fltr_proto
|
||
|
.align 4
|
||
|
_fltr_proto: ! First level trap routine prototype
|
||
|
sethi 0, %l0
|
||
|
jmpl 0+%l0, %g0
|
||
|
nop
|
||
|
nop
|
||
|
|
||
|
.text
|
||
|
.align 4
|
||
|
");
|
||
|
|
||
|
/* copy_vectors - Copy the trap vectors from ROM to RAM, set the TBR register
|
||
|
to point to the RAM vectors, and return the address of the RAM vectors. */
|
||
|
|
||
|
extern struct trap_entry __trap_vectors[256]; /* defined in matra.ld */
|
||
|
|
||
|
struct trap_entry *copy_vectors()
|
||
|
{
|
||
|
int i;
|
||
|
struct trap_entry *old = (struct trap_entry *) (rdtbr() & ~0xfff);
|
||
|
|
||
|
XDBG_MSG("Copying vectors...\n");
|
||
|
for (i = 0; i < 256; i++)
|
||
|
__trap_vectors[i] = old[i];
|
||
|
wrtbr ((unsigned long)__trap_vectors);
|
||
|
XDBG_MSG("Done\n");
|
||
|
return __trap_vectors;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
disable_cache()
|
||
|
{
|
||
|
unsigned long *ptr;
|
||
|
static unsigned long CACHE_shadow_iccr = 0; /* Because CR cannot be read */
|
||
|
static unsigned long CACHE_shadow_dccr = 0; /* Because CR cannot be read */
|
||
|
|
||
|
XDBG_MSG("Disabling cache...\n");
|
||
|
ptr = (unsigned long*)(CACHE_INST_BASE_ADD | ICCACR);
|
||
|
CACHE_shadow_iccr = CACHE_shadow_iccr & ICCR_DISABLE;
|
||
|
*ptr = CACHE_shadow_iccr;
|
||
|
|
||
|
ptr = (unsigned long*)(CACHE_DATA_BASE_ADD | DCCACR);
|
||
|
CACHE_shadow_dccr = CACHE_shadow_dccr & ICCR_DISABLE;
|
||
|
*ptr = CACHE_shadow_dccr;
|
||
|
XDBG_MSG("Done\n");
|
||
|
}
|
||
|
|
||
|
/* Flush the instruction cache. We need to do this for the debugger stub so
|
||
|
that breakpoints, et. al. become visible to the instruction stream after
|
||
|
storing them in memory. FIXME!!
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
flush_i_cache ()
|
||
|
{
|
||
|
volatile unsigned char *addr;
|
||
|
|
||
|
/* First, force all dirty items in the data cache to be moved out to real
|
||
|
memory. This is done by making read refs to alternate addresses that will
|
||
|
fill up all four banks for each line. Note that we actually have to
|
||
|
reference 8 locs per line just in case the region of memory we use is one
|
||
|
of the areas that needs to be flushed. */
|
||
|
|
||
|
for (addr = RAM_BASE;
|
||
|
addr < RAM_BASE + (DCACHE_LINES * DCACHE_LINE_SIZE * DCACHE_BANKS) * 2;
|
||
|
addr += DCACHE_LINE_SIZE)
|
||
|
*addr; /* Read the loc */
|
||
|
|
||
|
/* Now, flush the instruction cache. */
|
||
|
|
||
|
for (addr = CACHE_INST_TAG_ADDR + ALL_BANKS;
|
||
|
addr <= CACHE_INST_TAG_ADDR + ALL_BANKS + ICACHE_LINES * ICACHE_LINE_SIZE;
|
||
|
addr += ICACHE_LINE_SIZE)
|
||
|
*(unsigned long *)addr = 0; /* Clr tag entry for all banks on this line */
|
||
|
}
|
||
|
|
||
|
/* Setup trap TT to go to ROUTINE. */
|
||
|
|
||
|
void
|
||
|
exceptionHandler (int tt, unsigned long routine)
|
||
|
{
|
||
|
static struct trap_entry *tb; /* Trap vector base address */
|
||
|
|
||
|
if (!tb)
|
||
|
{
|
||
|
tb = copy_vectors(); /* Copy trap vectors to RAM */
|
||
|
disable_cache(); /* Disable cache FIXME!! */
|
||
|
}
|
||
|
|
||
|
XDBG_MSG("Setting exception handler for trap...\n");
|
||
|
|
||
|
tb[tt] = fltr_proto;
|
||
|
|
||
|
tb[tt].sethi_imm22 = routine >> 10;
|
||
|
tb[tt].jmpl_simm13 = routine & 0x3ff;
|
||
|
|
||
|
XDBG_MSG("Done\n");
|
||
|
}
|