#include <stdio.h>
#include <ds400rom.h>
+// ROM globals, taken from startup400.a51
+__data unsigned char __at (0x68) DSS_wos_crit_count;
+__data unsigned int __at (0x6b) DSS_timerReload;
+__data unsigned char __at (0x6d) DSS_curr_pc[3];
+__data unsigned char __at (0x72) DSS_sched[3];
+__data unsigned char __at (0x74) DSS_ms_count[5];
+__data unsigned char __at (0x7b) DSS_hb_chandle[5];
+
// Register bank 3 equates.
#define R0_B3 0x18
#define R1_B3 0x19
#define R7_B3 0x1F
+// The top of the redirect function table in RAM.
+#define CALL_TABLE_TOP 256
+
// The bank the ROM is stored in. Should be 0FFh for production
// 400's. Change this value when running with a debug ROM.
#define ROMXT_AUTOBAUD (99 * ROMXT_ENTRYSIZE)
#define ROMXT_TFTP_CLOSE (100 * ROMXT_ENTRYSIZE)
+
+#define ROMRT_ENTRYSIZE 3
+
+//
+// ROM REDIRECT TABLE FUNCTIONS (denoted with ROMRT)
+//
+#define ROMRT_KERNELMALLOC ( 1 * ROMRT_ENTRYSIZE)
+#define ROMRT_KERNELFREE ( 2 * ROMRT_ENTRYSIZE)
+#define ROMRT_MALLOC ( 3 * ROMRT_ENTRYSIZE)
+#define ROMRT_FREE ( 4 * ROMRT_ENTRYSIZE)
+#define ROMRT_MALLOCDIRTY ( 5 * ROMRT_ENTRYSIZE)
+#define ROMRT_DEREF ( 6 * ROMRT_ENTRYSIZE)
+#define ROMRT_GETFREERAM ( 7 * ROMRT_ENTRYSIZE)
+#define ROMRT_GETTIMEMILLIS ( 8 * ROMRT_ENTRYSIZE)
+#define ROMRT_GETTHREADID ( 9 * ROMRT_ENTRYSIZE)
+#define ROMRT_THREADRESUME (10 * ROMRT_ENTRYSIZE)
+#define ROMRT_THREADIOSLEEP (11 * ROMRT_ENTRYSIZE)
+#define ROMRT_THREADIOSLEEPNC (12 * ROMRT_ENTRYSIZE)
+#define ROMRT_THREADSAVE (13 * ROMRT_ENTRYSIZE)
+#define ROMRT_THREADRESTORE (14 * ROMRT_ENTRYSIZE)
+#define ROMRT_SLEEP (15 * ROMRT_ENTRYSIZE)
+#define ROMRT_GETTASKID (16 * ROMRT_ENTRYSIZE)
+#define ROMRT_INFOSENDCHAR (17 * ROMRT_ENTRYSIZE)
+#define ROMRT_IP_COMPUTECHECKSUM_SOFTWARE (18 * ROMRT_ENTRYSIZE)
+#define ROMRT_0 (19 * ROMRT_ENTRYSIZE) // undefined
+#define ROMRT_DHCPNOTIFY (20 * ROMRT_ENTRYSIZE)
+#define ROMRT_ROM_TASK_CREATE (21 * ROMRT_ENTRYSIZE)
+#define ROMRT_ROM_TASK_DUPLICATE (22 * ROMRT_ENTRYSIZE)
+#define ROMRT_ROM_TASK_DESTROY (23 * ROMRT_ENTRYSIZE)
+#define ROMRT_ROM_TASK_SWITCH_IN (24 * ROMRT_ENTRYSIZE)
+#define ROMRT_ROM_TASK_SWITCH_OUT (25 * ROMRT_ENTRYSIZE)
+#define ROMRT_OWIP_READCONFIG (26 * ROMRT_ENTRYSIZE)
+#define ROMRT_SETMACID (27 * ROMRT_ENTRYSIZE)
+#define ROMRT_UNDEREF (28 * ROMRT_ENTRYSIZE)
+
+
#define GETC \
clr a \
movc a, @a+dptr
// expects function number in R6_B3 (low byte) & R7_B3 (high byte)
-void _romcall(void) _naked
+void _romcall(void) __naked
{
-_asm
+__asm
push dpx ; dptr0 preserved here
push dph
push dpl
ret ; this is not a ret, it is a call!
; the called function ends with a ret which will return to our original caller.
-_endasm ;
+__endasm ;
}
+// expects function number in R6_B3 (low byte) & R7_B3 (high byte)
+void _romredirect(void) __naked
+{
+__asm
+ push dpx
+ push dph
+ push dpl
+ push acc
+ ; dptr = CALL_TABLE_TOP + function offset.
+ mov a, #(CALL_TABLE_TOP & 0xff)
+ add a, R6_B3 ; add function offset to the table
+ mov dpl, a
+ mov a, #((CALL_TABLE_TOP >> 8) & 0xff)
+ addc a, R7_B3
+ mov dph, a
+ mov dpx, #((CALL_TABLE_TOP >> 16) & 0xff)
+ movx a, @dptr ; read high byte
+ mov R5_B3, a
+ inc dptr
+ movx a, @dptr ; read mid byte
+ mov R4_B3, a
+ inc dptr
+ movx a, @dptr ; read low byte
+ mov R3_B3, a
+ pop acc ; restore acc and dptr
+ pop dpl
+ pop dph
+ pop dpx
+ push R3_B3 ; push low byte of target address
+ push R4_B3
+ push R5_B3 ; push high byte of target address
+ ret ; this is not a ret, it is a call!
+
+ ; the called function ends with a ret which will return to our original caller.
+__endasm;
+}
+
+
// This macro is invalid for the standard C preprocessor, since it
// includes a hash character in the expansion, hence the SDCC specific
// pragma.
mov R7_B3, #((x >> 8) & 0xff) \
lcall __romcall
+#define ROMREDIRECT(x) \
+ mov R6_B3, #(x & 0xff) \
+ mov R7_B3, #((x >> 8) & 0xff) \
+ lcall __romredirect
+
-// rom_init: the ds400 ROM_INIT ROM function.
-unsigned char rom_init(void xdata *loMem,
- void xdata *hiMem) _naked
+// init_rom: the ds400 ROM_INIT ROM function.
+unsigned char init_rom(void __xdata *loMem,
+ void __xdata *hiMem) __naked
{
// shut compiler up about unused parameters.
loMem;
hiMem;
-_asm
+__asm
; load params.
; loMem is already in DPTR.
mov r2, dpx
mov r1, dph
mov r0, dpl
- ; hiMem is in _rom_init_PARM_2
- mov dptr, #_rom_init_PARM_2
+ ; hiMem is in _init_rom_PARM_2
+ mov dptr, #_init_rom_PARM_2
mov r5, dpx
mov r4, dph
mov r3, dpl
; result is in acc, move to dpl for C convention.
mov dpl, a
ret
-_endasm ;
+__endasm ;
}
-// all other ROM functions should go here, using rom_init as a template...
-
-// Various utility functions.
-
-// Return the start of the XI_SEG. Really just a workaround for the
-// fact that the linker defined symbol (s_XISEG) isn't directly accessible
-// from C due to the lack of a leading underscore, and I'm too lazy to hack
-// the linker.
-static void xdata *_xisegStart(void) _naked
+// DSS_gettimemillis: note that the ROM actually returns 5 bytes of time,
+// we're discarding the high byte here.
+unsigned long task_gettimemillis_long(void) __naked
{
-_asm
- mov dptr, #(s_XISEG)
- ret
-_endasm;
+__asm
+ ; no parameters to load.
+ ROMREDIRECT(ROMRT_GETTIMEMILLIS)
+ ; results in r4 - r0, return in DPTR/B
+ mov dpl, r0
+ mov dph, r1
+ mov dpx, r2
+ mov b, r3
+ ret
+__endasm;
}
-// Return the length of the XI_SEG. Really just a workaround for the
-// fact that the linker defined symbol (l_XISEG) isn't directly accessible
-// from C due to the lack of a leading underscore, and I'm too lazy to hack
-// the linker.
-static unsigned _xisegLen(void) _naked
+unsigned char task_getthreadID(void) __naked
{
-_asm
- mov dptr, #(l_XISEG)
- ret
-_endasm;
+__asm
+ ; no parameters to load.
+ ROMREDIRECT(ROMRT_GETTHREADID)
+ ; results in acc, return in dpl
+ mov dpl, a
+ ret
+__endasm;
}
-// Returns the address of the first byte available for heap memory,
-// i.e. the first byte following the XI_SEG.
-static void xdata *_firstHeapByte(void)
+unsigned int task_gettickreload(void)
{
- unsigned char xdata *start;
-
- start = (unsigned char xdata *) _xisegStart();
- start += _xisegLen();
-
- return (void xdata *)start;
+ return DSS_timerReload;
}
-// A simple wrapper for ROM_INIT which allocates all available RAM in the CE0 area
-// to the heap.
-
-// The last addressible byte of the CE0 area.
-#define CE0_END 0xfffff
-
-unsigned char romInit(unsigned char noisy)
+void task_settickreload(unsigned int rl)
{
- void xdata *heapStart;
- void xdata *heapEnd;
- unsigned long heapLen;
- unsigned char rc;
-
- heapStart = _firstHeapByte();
- heapEnd = (void xdata *)CE0_END;
-
- rc = rom_init(heapStart, heapEnd);
-
- if (noisy)
- {
- if (rc)
- {
- printf("error: rom_init returns %d\n", (int)rc);
- }
- else
- {
- heapLen = CE0_END - (unsigned long)heapStart;
- printf("Heap starts at %p, length %luK\n", heapStart, heapLen / 1024);
- }
- }
- return rc;
+ DSS_timerReload = rl;
}
-// Install an interrupt handler.
-void installInterrupt(void (*isrPtr)(void), unsigned char offset)
-{
- unsigned char xdata * vectPtr = (unsigned char xdata *) offset;
- unsigned long isr = (unsigned long)isrPtr;
-
- *vectPtr++ = 0x02;
- *vectPtr++ = (unsigned char)(isr >> 16);
- *vectPtr++ = (unsigned char)(isr >> 8);
- *vectPtr = (unsigned char)isr;
-}