Added banking for the apple2enh target.

The machines targeted by apple2enh mostly do have 128kB of RAM. But it's not that easy to make use of banking in an event driver system like Contiki. Anyway I discovered one scenario feasable: The machines in question allow to bank in just 8kB of the second 64kB into the address space (at a fixed location).

The Contiki Kernel consists of three major parts: The Event Kernel (EK) which is the base system for everything else, the Contiki Tool Kit (CTK) which manages the GUI and the network stack (UIP) which does the TCP/IP handling. Both CTK and UIP make use of EK, but CTK never calls into UIP and vice versa.

The CTK code is a little larger than 8kB while the UIP code (without DNS) is a little smaller than 8kB, resulting in this setup: The UIP code is moved into the additional 8kB while making sure that the CTK code "covers" the whole memory area used for banking.

This setup allows most calls out of UIP to go without any banking simply because all callees are always visible. The only exception to this is ek_post_synch() because UIP uses it for the "Application Upcall" mechanism and I didn't want to make assumptions on the application code called.

Ordinary calls into UIP are routed through banking functions by conditional name mapping via macros. Calls into UIP via function pointers only occur for the event and poll handler. And there are fortunately already macros in place which could be (ob)used.

This is a (working) prototype with these TODOs:
- Make sure /RAM is empty on startup
- Cleanup /RAM on exit
- Support command line parameters
- ...
diff --git a/contiki-apple2/Makefile.apple2 b/contiki-apple2/Makefile.apple2
index 9910674..f246225 100644
--- a/contiki-apple2/Makefile.apple2
+++ b/contiki-apple2/Makefile.apple2
@@ -30,7 +30,7 @@
 #
 # This file is part of the Contiki desktop environment
 #
-# $Id: Makefile.apple2,v 1.18 2006/04/09 16:32:44 oliverschmidt Exp $
+# $Id: Makefile.apple2,v 1.19 2006/05/17 15:55:29 oliverschmidt Exp $
 #
 
 all: contiki
@@ -45,14 +45,21 @@
 CFLAGS:=$(CFLAGSCC65) --code-name CONTIKI \
         -DWITH_ASCII -DWITH_UIP -DWITH_LOADER_ARCH -DWITH_ETHERNET
 
-ifeq ($(SYS),apple2enh)
-CTK=ctk.o ctk-mousetext.o ctk-mouse.o
-else
+ifeq ($(SYS),apple2)
+
 CTK=ctk.o ctk-conio.o
-endif
+
+else # apple2
+
+CTK=ctk.o ctk-mousetext.o ctk-mouse.o
+
+uip.s uip_arch.s uiplib.s tcpip.s: %.s: %.c
+	$(CC) $(CFLAGS) $(OPT) -DUIP_CODE -o $(notdir $@) $<
+
+endif # apple2
 
 contiki:crt0.o main.o ek.o ek-service.o timer.o program-handler.o arg.o \
-	$(CTK) $(UIP) loader-arch.o clock-arch.o bank.o kfs.o import.o \
+	loader-arch.o clock-arch.o bank.o kfs.o import.o $(CTK) $(UIP) \
 	www-dsc.o \
 	email-dsc.o \
 	ftp-dsc.o \
diff --git a/contiki-apple2/apple2.cfg b/contiki-apple2/apple2.cfg
index 405797c..1c386ed 100644
--- a/contiki-apple2/apple2.cfg
+++ b/contiki-apple2/apple2.cfg
@@ -32,4 +32,5 @@
 }
 SYMBOLS {
     __STACKSIZE__ = $200;
+    __UIP_SIZE__  = $0000;
 }
diff --git a/contiki-apple2/apple2enh.cfg b/contiki-apple2/apple2enh.cfg
index 0286a5a..24274c5 100644
--- a/contiki-apple2/apple2enh.cfg
+++ b/contiki-apple2/apple2enh.cfg
@@ -6,6 +6,7 @@
     PIC:    start = $0000, size = $FFFF, file = "contiki";
     TMP:    start = $0000, size = $FFFF, file = "contiki";
     LC:     start = $D000, size = $1000, file = "contiki";
+    AUX:    start = $2000, size = $2000, file = "contiki";
 }
 SEGMENTS {
     ZEROPAGE: load = ZP,             type = zp;
@@ -19,6 +20,7 @@
     BOOT:     load = PIC,            type = ro,  define = yes;
     INIT:     load = TMP, run = RAM, type = ro,  define = yes;
     CODE:     load = LC,             type = ro,  define = yes;
+    UIP:      load = AUX,            type = ro,  define = yes;
 }
 FEATURES {
     CONDES: segment = INIT,
diff --git a/contiki-apple2/conf/uip-conf.h b/contiki-apple2/conf/uip-conf.h
index 971e684..b4e379b 100644
--- a/contiki-apple2/conf/uip-conf.h
+++ b/contiki-apple2/conf/uip-conf.h
@@ -32,7 +32,7 @@
  *
  * This file is part of the Contiki Destop OS
  *
- * $Id: uip-conf.h,v 1.3 2005/03/16 22:37:01 oliverschmidt Exp $
+ * $Id: uip-conf.h,v 1.4 2006/05/17 15:55:29 oliverschmidt Exp $
  *
  */
 #ifndef __UIP_CONF_H__
@@ -41,8 +41,49 @@
 #define UIP_CONF_MAX_LISTENPORTS 10
 #define UIP_CONF_BUFFER_SIZE     1024 - 2
 #define UIP_CONF_RECEIVE_WINDOW  UIP_TCP_MSS
+#define UIP_CONF_BYTE_ORDER      LITTLE_ENDIAN
 #define UIP_CONF_EXTERNAL_BUFFER
 
-#define UIP_CONF_BYTE_ORDER      LITTLE_ENDIAN
+#ifdef UIP_CODE
+
+#pragma codeseg("UIP");
+
+#include "ek-conf.h"
+
+#undef  EK_PROCESS_INIT
+#define EK_PROCESS_INIT(name, arg)					\
+  void _tcpip_init(void *arg)
+
+#undef  EK_EVENTHANDLER
+#define EK_EVENTHANDLER(name, ev, data)					\
+  void _tcpip_eventhandler(ek_event_t ev, ek_data_t data)
+
+#undef  EK_POLLHANDLER
+#define EK_POLLHANDLER(name)						\
+  void _tcpip_pollhandler(void)
+
+#undef  EK_PROCESS
+#define EK_PROCESS(name, strname, prio, eventh, pollh, stateptr)	\
+  void tcpip_eventhandler(ek_event_t ev, ek_data_t data);		\
+  void tcpip_pollhandler(void);						\
+  static struct ek_proc name = {NULL, EK_ID_NONE, strname, prio, tcpip_eventhandler, tcpip_pollhandler, stateptr}
+
+#define htons                _htons
+#define uiplib_ipaddrconv    _uiplib_ipaddrconv
+#define tcp_markconn         _tcp_markconn
+#define tcp_listen           _tcp_listen
+#define tcp_unlisten         _tcp_unlisten
+#define tcp_connect          _tcp_connect
+#define udp_new              _udp_new
+#define tcpip_set_forwarding _tcpip_set_forwarding
+#define tcpip_input          _tcpip_input
+#define tcpip_output         _tcpip_output
+#define tcpip_poll_tcp       _tcpip_poll_tcp
+#define tcpip_poll_udp       _tcpip_poll_udp
+
+#define ek_post_synch        _ek_post_synch
+void _ek_post_synch(ek_id_t id, ek_event_t ev, ek_data_t data);
+
+#endif /* UIP_CODE */
 
 #endif /* __UIP_CONF_H__ */
diff --git a/contiki-apple2/lib/bank.S b/contiki-apple2/lib/bank.S
index 1d7e504..9d3d866 100644
--- a/contiki-apple2/lib/bank.S
+++ b/contiki-apple2/lib/bank.S
@@ -2,10 +2,10 @@
 ; Bank switching code for Contiki (Apple2 version)
 ;
 
-	.export		VTABZ
-
 	.segment	"CONTIKI"
 
+	.export		VTABZ
+
 VTABZ:
 	; Switch in ROM and call VTABZ
 	bit	$C082
@@ -14,3 +14,125 @@
 	; Switch in LC bank 2 for R/O and return
 	bit	$C080
 	rts
+
+.ifdef  __APPLE2ENH__
+
+	.code
+
+main2aux:
+	; Switch in $2000-$3FFF from aux memory
+	bit	$C055		; Page2
+	bit	$C057		; HiRes
+	rts
+	
+aux2main:
+	; Switch in $2000-$3FFF from main memory
+	bit	$C056		; LoRes
+	bit	$C054		; Page1
+	rts
+
+	.export		_tcpip_init
+	.import		__tcpip_init
+
+_tcpip_init:
+	jsr	main2aux
+	jsr	__tcpip_init
+	jmp	aux2main
+	
+	.export		_tcpip_eventhandler
+	.import		__tcpip_eventhandler
+
+_tcpip_eventhandler:
+	jsr	main2aux
+	jsr	__tcpip_eventhandler
+	jmp	aux2main
+	
+	.export		_tcpip_pollhandler
+	.import		__tcpip_pollhandler
+
+_tcpip_pollhandler:
+	jsr	main2aux
+	jsr	__tcpip_pollhandler
+	jmp	aux2main
+	
+	.export		_htons
+	.import		__htons
+
+_htons:
+	jsr	main2aux
+	jsr	__htons
+	jmp	aux2main
+	
+	.export		_uiplib_ipaddrconv
+	.import		__uiplib_ipaddrconv
+
+_uiplib_ipaddrconv:
+	jsr	main2aux
+	jsr	__uiplib_ipaddrconv
+	jmp	aux2main
+	
+	.export		_tcp_markconn
+	.import		__tcp_markconn
+
+_tcp_markconn:
+	jsr	main2aux
+	jsr	__tcp_markconn
+	jmp	aux2main
+
+	.export		_tcp_listen
+	.import		__tcp_listen
+
+_tcp_listen:
+	jsr	main2aux
+	jsr	__tcp_listen
+	jmp	aux2main
+
+	.export		_tcp_unlisten
+	.import		__tcp_unlisten
+
+_tcp_unlisten:
+	jsr	main2aux
+	jsr	__tcp_unlisten
+	jmp	aux2main
+
+	.export		_tcp_connect
+	.import		__tcp_connect
+
+_tcp_connect:
+	jsr	main2aux
+	jsr	__tcp_connect
+	jmp	aux2main
+
+	.export		_udp_new
+	.import		__udp_new
+
+_udp_new:
+	jsr	main2aux
+	jsr	__udp_new
+	jmp	aux2main
+
+	.export		_tcpip_input
+	.import		__tcpip_input
+
+_tcpip_input:
+	jsr	main2aux
+	jsr	__tcpip_input
+	jmp	aux2main
+
+	.export		_tcpip_poll_udp
+	.import		__tcpip_poll_udp
+
+_tcpip_poll_udp:
+	jsr	main2aux
+	jsr	__tcpip_poll_udp
+	jmp	aux2main
+	
+	.export		__ek_post_synch
+	.import		_ek_post_synch
+
+__ek_post_synch:
+	jsr	aux2main
+	jsr	_ek_post_synch
+	jmp	main2aux
+
+.endif
diff --git a/contiki-apple2/lib/crt0.S b/contiki-apple2/lib/crt0.S
index 786541d..03cdcf9 100644
--- a/contiki-apple2/lib/crt0.S
+++ b/contiki-apple2/lib/crt0.S
@@ -7,12 +7,13 @@
 	.export		_exit
 	.import	   	zerobss, initlib, callmain, donelib
 .ifdef  __APPLE2ENH__
-	.import		callirq
+	.import		_uip_buf, callirq
 .endif
-	.import	       	__STARTUP_RUN__, __BOOT_SIZE__	; Linker generated
+	.import	       	__STARTUP_RUN__			; Linker generated
 	.import	       	__BSS_RUN__, __BSS_SIZE__	; Linker generated
 	.import	       	__INIT_RUN__, __INIT_SIZE__	; Linker generated
 	.import	       	__CODE_RUN__, __CODE_SIZE__	; Linker generated
+	.import	       	__BOOT_SIZE__, __UIP_SIZE__	; Linker generated
 	.importzp	sp
 	.linecont	+
 
@@ -23,8 +24,8 @@
 
 	.word  	__STARTUP_RUN__				; Start address
 	.word  	__BSS_RUN__   + __BOOT_SIZE__ +		\
-		__INIT_SIZE__ + __CODE_SIZE__ -		\
-		__STARTUP_RUN__				; Size
+		__INIT_SIZE__ + __CODE_SIZE__ +		\
+		__UIP_SIZE__ - __STARTUP_RUN__		; Size
 
 ; ------------------------------------------------------------------------
 ; Place the startup code in a special segment.
@@ -40,7 +41,7 @@
 ; ProDOS TechRefMan, chapter 6.2:
 ; "Each installed routine must begin with a CLD instruction."
 
-intrpt: cld
+irq:	cld
 
 ; Switch in LC bank 2 for R/O
 
@@ -95,10 +96,10 @@
 
 ; Deallocate interrupt vector table entry
 
-	dec     params		; Adjust parameter count
+	dec     intrpt		; Adjust parameter count
 	jsr     $BF00
 	.byte   $41		; Dealloc interrupt
-	.addr   params
+	.addr   intrpt
 
 .endif
 
@@ -111,25 +112,13 @@
 	jmp	$03D0
 
 ; ------------------------------------------------------------------------
-; The linker doesn't calculate where this code runs so it has to be PIC
+; The linker doesn't understand that the "BOOT" segment overlays the "BSS"
+; segment so the automatic fixup of references to the "BOOT" segment does
+; not work. Therefore references to this segment have to be expressed as
+; offsets to __BSS_RUN__.
 
 .segment	"BOOT"
 
-.ifdef  __APPLE2ENH__
-
-; Allocate interrupt vector table entry
-
-	jsr     $BF00
-	.byte   $40		; Alloc interrupt
-	.addr   params
-
-; Switch to 80 column mode
-
-	lda	#$0D
-	jsr	$C300
-
-.endif
-
 ; Setup the stack at HIMEM
 
 	lda    	$73
@@ -156,6 +145,48 @@
 	eor	#$A5
 	sta	$03F4
 		
+.ifdef  __APPLE2ENH__
+
+; Allocate interrupt vector table entry
+
+	jsr     $BF00
+	.byte   $40		; Alloc interrupt
+	.addr   intrpt
+
+; Switch to 80 column mode here to show some progress
+
+	lda	#$0D
+	jsr	$C300
+	
+; ProDOS TechRefMan, chapter 5.2.2.1:
+; "... you may protect those areas of auxiliary memory. If you save a
+;  dummy 8K file as the first entry in /RAM, it will always be saved
+;  at $2000 to $3FFF."
+;
+; Relocate the "UIP" segment by writing it to /RAM as the first file.
+
+	jsr     $BF00
+	.byte   $C0		; Create file
+	.addr   create
+
+	jsr     $BF00
+	.byte   $C8		; Open file
+	.addr   open
+	
+	lda	o_ref
+	sta	w_ref
+	sta	c_ref
+
+	jsr     $BF00
+	.byte   $CB		; Write file
+	.addr   write
+
+	jsr     $BF00
+	.byte   $CC		; Close file
+	.addr   close
+
+.endif
+
 ; Switch in LC bank 2 for W/O
 
 	bit	$C081
@@ -220,6 +251,47 @@
 ; Forward control to code in the "INIT" segment
 
 	jmp	init
+	
+.ifdef  __APPLE2ENH__
+
+create	= __BSS_RUN__ + *
+	.byte	$07		; Parameter count
+	.addr	name		; Pathname
+	.byte	%11000011	; Access:	Standard full access
+	.byte	$00		; File type:	Typeless file
+	.word	$0000		; Aux type:	N/A
+	.byte	$01		; Storage type:	Standard seedling file
+	.word	$0000		; Create date:	Current date
+	.word	$0000		; Create time:	Current time
+
+open	= __BSS_RUN__ + *
+	.byte	$03		; Parameter count
+	.addr	name		; Pathname
+	.addr	_uip_buf	; IO buffer
+o_ref	= __BSS_RUN__ + *
+	.byte	$00		; Reference number
+
+write	= __BSS_RUN__ + *
+	.byte	$04		; Parameter count
+w_ref	= __BSS_RUN__ + *
+	.byte	$00		; Reference number
+	.addr	__BSS_RUN__ + \
+		__BOOT_SIZE__ + \
+		__INIT_SIZE__ + \
+		__CODE_SIZE__	; Data buffer
+	.word	__UIP_SIZE__	; Requested count
+	.word	$0000		; Transfered count
+
+close	= __BSS_RUN__ + *
+	.byte	$01		; Parameter count
+c_ref	= __BSS_RUN__ + *
+	.byte	$00		; Reference number
+
+name	= __BSS_RUN__ + *
+	.byte	14
+	.byte	"/RAM/CONTIKI.1"
+
+.endif
 
 ; ------------------------------------------------------------------------
 ; The "INIT" segment will be overwritten by the heap
@@ -247,8 +319,8 @@
 
 .ifdef  __APPLE2ENH__
 
-params: .byte   $02		; Parameter count
+intrpt: .byte   $02		; Parameter count
 	.byte   $00		; Interrupt number
-	.addr   intrpt		; Interrupt handler
+	.addr   irq		; Interrupt handler
 
 .endif
\ No newline at end of file