/* Stand-alone library for SPARClite * * Copyright (c) 1995 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. */ #include "sparclite.h" #include "asm.h" /* LED blinking pattern can be changed by modifying __led_algorithm. */ enum ledtype { led_marching, /* marching pattern, only one led on at a time */ led_random, /* pseudo-random pattern */ led_blinking, /* all leds blink on and off */ led_none /* leds off all the time */ }; enum ledtype __led_algorithm = led_marching; /* Pointer to hook for outbyte, set by stub's exception handler. */ void (*__outbyte_hook) (int c); #ifdef SL931 #define SDTR_BASE 0x200 #define SDTR_ASI 1 #define SDTR_SHIFT 0 #else #define SDTR_BASE 0x10000000 #define SDTR_ASI 4 #define SDTR_SHIFT 16 #endif #define get_uart_status(PORT) \ (read_asi (SDTR_ASI, SDTR_BASE + 0x24 + (PORT) * 0x10) >> SDTR_SHIFT) #define xmt_char(PORT, C) \ write_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10, (C) << SDTR_SHIFT) #define rcv_char(PORT) \ (read_asi (SDTR_ASI, SDTR_BASE + 0x20 + (PORT) * 0x10) >> SDTR_SHIFT) void putDebugChar(); #if 0 void set_uart (cmd) int cmd; { write_asi (SDTR_ASI, SDTR_BASE + 0x24, cmd << SDTR_SHIFT); } void set_timer_3 (val) int val; { write_asi (SDTR_ASI, SDTR_BASE + 0x78, val << SDTR_SHIFT); } #endif asm(" .text .align 4 ! Register window overflow handler. Come here when save would move us ! into the invalid window. This routine runs with traps disabled, and ! must be careful not to touch the condition codes, as PSR is never ! restored. ! ! We are called with %l0 = wim, %l1 = pc, %l2 = npc .globl " STRINGSYM(win_ovf) " " STRINGSYM(win_ovf) ": mov %g1, %l3 ! Save g1, we use it to hold the wim srl %l0, 1, %g1 ! Rotate wim right sll %l0, __WINSIZE-1, %l0 or %l0, %g1, %g1 save %g0, %g0, %g0 ! Slip into next window mov %g1, %wim ! Install the new wim std %l0, [%sp + 0 * 4] ! save L & I registers std %l2, [%sp + 2 * 4] std %l4, [%sp + 4 * 4] std %l6, [%sp + 6 * 4] std %i0, [%sp + 8 * 4] std %i2, [%sp + 10 * 4] std %i4, [%sp + 12 * 4] std %i6, [%sp + 14 * 4] restore ! Go back to trap window. mov %l3, %g1 ! Restore %g1 jmpl %l1, %g0 rett %l2 ! Register window underflow handler. Come here when restore would move us ! into the invalid window. This routine runs with traps disabled, and ! must be careful not to touch the condition codes, as PSR is never ! restored. ! ! We are called with %l0 = wim, %l1 = pc, %l2 = npc .globl " STRINGSYM(win_unf) " " STRINGSYM(win_unf) ": sll %l0, 1, %l3 ! Rotate wim left srl %l0, __WINSIZE-1, %l0 or %l0, %l3, %l0 mov %l0, %wim ! Install the new wim restore ! User's window restore ! His caller's window ldd [%sp + 0 * 4], %l0 ! restore L & I registers ldd [%sp + 2 * 4], %l2 ldd [%sp + 4 * 4], %l4 ldd [%sp + 6 * 4], %l6 ldd [%sp + 8 * 4], %i0 ldd [%sp + 10 * 4], %i2 ldd [%sp + 12 * 4], %i4 ldd [%sp + 14 * 4], %i6 save %g0, %g0, %g0 ! Back to trap window save %g0, %g0, %g0 jmpl %l1, %g0 rett %l2 ! Read the TBR. .globl " STRINGSYM(rdtbr) " " STRINGSYM(rdtbr) ": retl mov %tbr, %o0 "); extern unsigned long rdtbr(); void die(val) int val; { static unsigned char *leds = (unsigned char *)0x02000003; *leds = val; while (1) ; } /* 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 " STRINGSYM(fltr_proto) " .align 4 " STRINGSYM(fltr_proto) ": ! First level trap routine prototype sethi 0, %l0 jmpl 0+%l0, %g0 nop nop .text .align 4 "); /* Setup trap TT to go to ROUTINE. If TT is between 0 and 255 inclusive, the normal trap vector will be used. If TT is 256, then it's for the SPARClite DSU, and that always vectors off to 255 unrelocated. */ void exceptionHandler (tt, routine) int tt; unsigned long routine; { struct trap_entry *tb; /* Trap vector base address */ if (tt != 256) tb = (struct trap_entry *) (rdtbr() & ~0xfff); else { tt = 255; tb = (struct trap_entry *) 0; } tb[tt] = fltr_proto; tb[tt].sethi_imm22 = routine >> 10; tb[tt].jmpl_simm13 = routine & 0x3ff; } void update_leds() { static unsigned char *leds = (unsigned char *)0x02000003; static enum ledtype prev_algorithm = led_none; if (prev_algorithm != __led_algorithm) { *leds = 0xff; /* turn the LEDs off */ prev_algorithm = __led_algorithm; } switch (__led_algorithm) { case led_marching: { static unsigned char curled = 1; static unsigned char dir = 0; *leds = ~curled; if (dir) curled <<= 1; else curled >>= 1; if (curled == 0) { if (dir) curled = 0x80; else curled = 1; dir = ~dir; } break; } case led_random: { static unsigned int next = 0; *leds = next & 0xff; next = (next * 1103515245 + 12345) & 0x7fff; break; } case led_blinking: { static unsigned char next = 0; *leds = next; next = ~next; break; } default: break; } } /* 1/5th of a second? */ #define LEDTIME (20000000 / 500) unsigned long ledtime = LEDTIME; int inbyte() { return (getDebugChar()); } int getDebugChar() { unsigned long countdown = ledtime; update_leds(); while (1) { if ((get_uart_status(0) & 2) != 0) break; if (countdown-- == 0) { countdown = ledtime; update_leds(); } } return rcv_char(0); } /* Output one character to the serial port */ void outbyte(c) int c; { if (__outbyte_hook) __outbyte_hook (c); else putDebugChar(c); } void putDebugChar(c) int c; { update_leds(); while ((get_uart_status(0) & 1) == 0) ; xmt_char(0, c); } #if 0 int write(fd, data, length) int fd; unsigned char *data; int length; { int olength = length; while (length--) putDebugChar(*data++); return olength; } int read(fd, data, length) int fd; unsigned char *data; int length; { int olength = length; int c; while (length--) *data++ = getDebugChar(); return olength; } #endif /* Set the baud rate for the serial port, returns 0 for success, -1 otherwise */ #if 0 int set_baud_rate(baudrate) int baudrate; { /* Convert baud rate to uart clock divider */ switch (baudrate) { case 38400: baudrate = 16; break; case 19200: baudrate = 33; break; case 9600: baudrate = 65; break; default: return -1; } set_timer_3(baudrate); /* Set it */ } #endif