changeset 2615:530759e9f289

Added ccbkrn from Brett Gordon (level 2 only for now)
author Boisy Pitre <boisy.pitre@nuance.com>
date Mon, 06 Feb 2012 15:51:13 -0600
parents d9e5c4629696
children b9e8bb5a3796
files level2/coco3/makefile_common level2/coco3/modules/kernel/makefile level2/coco3/modules/makefile level2/modules/kernel/ccbfsrqmem.asm level2/modules/kernel/ccbkrn.asm level2/modules/kernel/ccbkrn.txt level2/modules/kernel/fnproc.asm
diffstat 7 files changed, 1647 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/level2/coco3/makefile_common	Sun Feb 05 13:30:35 2012 -0600
+++ b/level2/coco3/makefile_common	Mon Feb 06 15:51:13 2012 -0600
@@ -37,6 +37,7 @@
 STARTUP		= startup
 STARTUP_DW	= startup.dw
 SYSGO		= sysgo_dd
+CCBKRN		= ccbkrn
 
 PACKAGENAME	= $(DISTROVER).zip
 DSKDW3		= $(DISTROVER)_dw3.dsk
@@ -95,6 +96,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS_DW) ../$@,CMDS
@@ -148,6 +150,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS_DW) ../$@,CMDS
@@ -201,6 +204,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS_DW) ../$@,CMDS
@@ -254,6 +258,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS) ../$@,CMDS
@@ -276,6 +281,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS) ../$@,CMDS
@@ -338,6 +344,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS) ../$@,CMDS
@@ -393,6 +400,7 @@
 	$(MAKDIR) $@,CMDS
 	$(MAKDIR) $@,SYS
 	$(MAKDIR) $@,DEFS
+	$(CP) modules/$(CCBKRN) $@,$(CCBKRN)
 	$(CP) modules/$(SYSGO) $@,sysgo
 	$(OS9ATTR_EXEC) $@,sysgo
 	$(CD) cmds; $(CP) $(CMDS) ../$@,CMDS
--- a/level2/coco3/modules/kernel/makefile	Sun Feb 05 13:30:35 2012 -0600
+++ b/level2/coco3/modules/kernel/makefile	Mon Feb 06 15:51:13 2012 -0600
@@ -7,22 +7,25 @@
 AFLAGS		+= -I$(LEVEL2)/modules/kernel -I$(LEVEL1)/modules/kernel
 
 KERNEL		= krn
+KERNEL_CCB	= ccbkrn
 KERNELP2	= krnp2
 SYSCALLS	= fallimg.asm fallram.asm falltsk.asm faproc.asm fcmpnam.asm \
 		fcpymem.asm fdatlog.asm fdelram.asm ffmodul.asm ffreehb.asm \
 		fld.asm fldabx.asm flink.asm fmove.asm fnproc.asm fprsnam.asm \
-		freboot.asm fsrqmem.asm fssvc.asm fvmodul.asm \
+		freboot.asm fssvc.asm fvmodul.asm \
 		fallbit.asm fallprc.asm fchain.asm fclrblk.asm fcrcmod.asm \
 		fdelimg.asm fexit.asm ffind64.asm ffork.asm fgblkmp.asm \
 		fgcmdir.asm fgmoddr.asm fgprdsc.asm fgprocp.asm ficpt.asm \
 		fid.asm fmapblk.asm fmem.asm fsend.asm fsleep.asm fsprior.asm \
 		fsswi.asm fstime.asm fsuser.asm funlink.asm funload.asm
 
-ALLOBJS		= $(KERNEL) $(KERNELP2)
+ALLOBJS		= $(KERNEL) $(KERNEL_CCB) $(KERNELP2)
 
 all:	$(ALLOBJS)
 
-$(KERNEL):	krn.asm $(SYSCALLS)
+$(KERNEL):	krn.asm $(SYSCALLS) fsrqmem.asm
+
+$(KERNEL_CCB):	ccbkrn.asm $(SYSCALLS) ccbfsrqmem.asm
 
 $(KERNELP2):	krnp2.asm $(SYSCALLS)
 
--- a/level2/coco3/modules/makefile	Sun Feb 05 13:30:35 2012 -0600
+++ b/level2/coco3/modules/makefile	Mon Feb 06 15:51:13 2012 -0600
@@ -87,7 +87,7 @@
 all:	$(ALLOBJS)
 
 # Kernel
-krn krnp2:
+ccbkrn krn krnp2:
 	$(CD) kernel; make $@
 	$(CP) kernel/$@ .
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level2/modules/kernel/ccbfsrqmem.asm	Mon Feb 06 15:51:13 2012 -0600
@@ -0,0 +1,368 @@
+**************************************************
+* System Call: F$SRqMem
+*
+* Function: Request memory
+*
+* F$SRqMem allocates memory from the system's 64K address space in 256 byte 'pages.'
+* There are 256 of these '256 byte pages' in the system's RAM area (256*256=64K).
+* The allocation map, pointed to by D.SysMem holds one byte per page, making the
+* allocation map itself 256 bytes in size.
+*
+* Memory is allocated from the top of the system RAM map downwards.  Rel/Boot/Krn
+* also reside in this area, and are loaded from $ED00-$FFFF.  Since this area is
+* always allocated, we start searching for free pages from page $EC downward.
+*
+* F$SRqMem also updates the system memory map according to 8K DAT blocks. If an
+* empty block is found, this routine re-does the 32 entries in the SMAP table to
+* indicate that they are free.
+*
+* Input:  D = Byte count
+*
+* Output: U = Address of allocated memory area
+*
+* Error:  CC = C bit set; B = error code
+*
+FSRqMem  ldd   R$D,u        get memory allocation size requested
+         addd  #$00FF       round it up to nearest 256 byte page (e.g. $1FF = $2FE)
+         clrb               just keep # of pages (and start 8K block #, e.g. $2FE = $200)
+         std   R$D,u        save rounded version back to user
+*         leay  Bt.Start/256,y      
+*         leay  $20,y        skip Block 0 (always reserved for system)
+* Change to pshs a,b:use 1,s for block # to check, and ,s for TFM spot
+*         incb               skip block 0 (always reserved for system)
+         pshs  d            reserve a byte & put 0 byte on stack
+
+
+* IMPORTANT!!!
+* The following code was put in some time back to fix a problem.  That problem was not documented
+* so I cannot recall why this code was in place.  What it appears to do is reset the system page
+* memory map based upon the state of the system DAT image.
+* This code really slows down F$SRqMem and since that system call is used quite often in the system,
+* I am commenting it out in the hopes that I can remember what the hell I put it in for. -- Boisy
+         IFEQ  1
+         ldy   <D.SysMem    get ptr to SMAP table
+* This loop updates the SMAP table if anything can be marked as unused
+L082F    ldx   <D.SysDAT    get pointer to system DAT block list
+         lslb               adjust block offset for 2 bytes/entry
+         ldd   b,x          get block type/# from system DAT
+         cmpd  #DAT.Free    Unused block?
+         beq   L0847        yes, mark it free in SMAP table
+         ldx   <D.BlkMap    No, get ptr to MMAP table
+         lda   d,x          Get block marker for 2 meg mem map
+         cmpa  #RAMinUse    Is it in use (not free, ROM or used by module)?
+         bne   L0848        No, mark it as type it is in SMAP table
+         leay  32,y         Yes, move to next block in pages
+         bra   L084F        move to next block & try again
+* Free RAM:
+L0847    clra               Byte to fill system page map with (0=Not in use)
+* NOT! RAMinUse:
+         IFNE   H6309
+L0848    sta   ,s           Put it on stack
+         ldw   #$0020       Get size of 8K block in pages
+         tfm   s,y+         Mark entire block's worth of pages with A
+         ELSE
+L0848    ldb   #32		count = 32 pages
+L084A    sta   ,y+		mark the RAM
+         decb
+         bne    L084A
+         ENDC
+L084F    inc   1,s          Bump up to next block to check
+         ldb   1,s          Get it
+         cmpb  #DAT.BlCt    Done whole 64k system space?
+         blo   L082F        no, keep checking
+         ENDC
+
+
+* Now we can actually attempt to allocate the system RAM requested
+* NOTE: Opt for CoCo/TC9 OS9 ONLY: skip last 256 - Bt.Start pages since
+* they are: Kernel (REL/BOOT/KRN - 17 pages), vector RAM & I/O (2 pages)
+* (Already permanently marked @ L01D2)
+* At the start, Y is pointing to the end of the SMAP table+1
+         ldx   <D.SysMem    Get start of table ptr
+	 * CCB change - start scanning from f000 down, rather than ec00
+ *        leay  Bt.Start>>8,x
+*	 leay  Where>>8,x
+	 leay	$ff00>>8,x
+	 * end of CCB change
+         ldb   #32          skip block 0: it's always full
+         abx                same size, but faster than leax $20,x
+*         leay  -(256-(Bt.Start>>8)),y  skip Kernel, Vector RAM & I/O (Can't be free)
+L0857    ldb   R$A,u        Get # 256 byte pages requested
+* Loop (from end of system mem map) to look for # continuous pages requested
+L0859    equ   *
+         IFNE  H6309
+         cmpr  x,y          We still have any system RAM left to try?
+         ELSE
+         pshs  x
+         cmpy  ,s++
+         ENDC
+         bhi   L0863        Yes, continue
+         comb               Exit with No System RAM Error
+         ldb   #E$NoRAM
+         bra   L0894        Eat stack & exit
+
+L0863    lda   ,-y          Get page marker (starting @ end of SMAP)
+         bne   L0857        Used, try next lower page
+         decb               Found 1 page, dec # pages we need to allocate
+         bne   L0859        Still more pages needed, check if we can get more
+         sty   ,s           Found free contiguous pages, save SMAP entry ptr
+         lda   1,s          Get LSB of ptr
+         lsra               Divide by 32 (Calculate start 8K block #)
+         lsra  
+         lsra  
+         lsra  
+         lsra  
+         ldb   1,s          Get LSB of ptr again
+         andb  #%00011111   Keep only within 8K block offset
+         addb  R$A,u        Add # pages requested
+         addb  #$1F         Round up to nearest 8K block
+         lsrb               Divide by 32 (Calculate end 8K block #)
+         lsrb  
+         lsrb  
+         lsrb  
+         lsrb
+         ldx   <D.SysPrc    Get ptr to system proc. dsc.
+         lbsr  L09BE        Allocate an image with our start/end block #'s
+         bcs   L0894        Couldn't, exit with error
+         ldb   R$A,u        Get # pages requested
+*         lda   #RAMinUse    Get SMAP in use flag
+*L088A    sta   ,y+          Mark all the pages requested as In Use
+L088A    inc   ,y+          Since RAMinUse is 1, we can save space by INC'ing from 0->1
+         decb
+         bne   L088A
+         lda   1,s          Get MSB of ptr to start of newly allocated Sys RAM
+         std   R$U,u        Save for caller
+         clrb               No error
+L0894    puls  u,pc         Eat stack (U is changed after it exits) & return
+
+
+**************************************************
+* System Call: F$SRtMem
+*
+* Function: Return memory
+*
+* Input:  U = Address of memory to return
+*         D = Number of bytes to return
+*
+* Output: None
+*
+* Error:  CC = C bit set; B = error code
+*
+FSRtMem  ldd   R$D,u        get # pages to free up
+         beq   L08F2        nothing to free, return without error
+         addd  #$00FF       round it up to nearest page
+         ldb   R$U+1,u      get LSB of address
+         beq   L08A6        it's a even page, skip ahead
+         comb               set carry
+         ldb   #E$BPAddr    get error code
+         rts                return
+
+L08A6    ldb   R$U,u        get MSB of page address
+         beq   L08F2        not a legal page, return without error
+         ldx   <D.SysMem    get pointer to system memory map
+         abx                set pointer into map
+L08AD    equ   *
+         IFNE  H6309
+         aim   #^RAMinUse,,x+
+         ELSE
+         ldb   ,x
+         andb  #^RAMinUse
+         stb   ,x+
+         ENDC
+         deca  
+         bne   L08AD
+* Scan DAT image to find memory blocks to free up
+         ldx   <D.SysDAT    get pointer to system DAT image
+         IFNE  H6309
+         lde   #DAT.BlCt    get # blocks to check
+         ELSE
+         ldy   #DAT.BlCt
+         ENDC
+L08BC    ldd   ,x           get block image
+         cmpd  #DAT.Free    is it already free?
+         beq   L08EC        yes, skip to next one
+         ldu   <D.BlkMap    get pointer to MMU block map
+         lda   d,u          get allocation flag for this block: 16-bit offset
+         cmpa  #RAMinUse    being used?
+         bne   L08EC        no, move to next block
+         tfr   x,d
+         subd  <D.SysDAT
+         lslb  
+         lslb  
+         lslb  
+         lslb  
+         ldu   <D.SysMem    get pointer to system map
+         IFNE   H6309
+         addr   d,u
+* Check if we can remove the entire memory block from system map
+         ldf   #16          get # pages per block/2
+L08DA    ldd   ,u++         Either of these 2 pages allocated?
+         ELSE
+         leau  d,u
+         ldb   #32
+L08DA    lda   ,u+          Either of these 2 pages allocated?
+         ENDC
+         bne   L08EC        yes, can't free block, skip to next one
+         IFNE  H6309
+         decf               checked all pages?
+         ELSE
+         decb
+         ENDC
+         bne   L08DA        no, keep looking
+         ldd   ,x           get block # into B: could be >$80
+         ldu   <D.BlkMap    point to allocation table
+         IFNE  H6309
+         sta   d,u          clear the block using 16-bit offset
+         ELSE
+         clr   d,u
+         ENDC
+         ldd   #DAT.Free    get free block marker
+         std   ,x           save it into DAT image
+L08EC    leax  2,x          move to next DAT block
+         IFNE  H6309
+         dece               done?
+         ELSE
+         leay  -1,y
+         ENDC
+         bne   L08BC        no, keep checking
+L08F2    clrb               clear errors
+L08F3    rts                return
+
+
+**************************************************
+* System Call: F$Boot
+*
+* Function: Bootstrap the system
+*
+* Optimized for size, as it's only called once...
+*
+* Input:  None
+*
+* Output: None
+*
+* Error:  CC = C bit set; B = error code
+*
+FBoot
+	** CCB change: just panic
+         lda   #'t        tried to boot
+         jsr   <D.BtBug
+	 jmp   <D.Crash
+	**
+         coma               Set boot flag
+         lda   <D.Boot      we booted once before?
+         bne   L08F3        Yes, return
+         inc   <D.Boot      Set boot flag
+         ldx   <D.Init      Get ptr to init module if it exists
+         beq   L0908        it doesn't, point to boot name
+         ldd   <BootStr,x   Get offset to text
+         beq   L0908        Doesn't exist, get hard coded text
+         leax   d,x         Adjust X to point to boot module
+         bra   L090C        Try & link to module
+
+boot     fcs   /Boot/
+
+L0908    leax  <boot,pcr
+* Link to module and execute
+L090C    lda   #Systm+Objct
+         os9   F$Link   
+         bcs   L08F3
+         lda   #'b        calling boot
+         jsr   <D.BtBug
+         jsr   ,y           load boot file
+         bcs   L08F3
+         std   <D.BtSz      save boot file size
+         stx   <D.BtPtr     save start pointer of bootfile
+         lda   #'b        boot returns OK
+         jsr   <D.BtBug
+
+* added for IOMan system memory extentions
+         IFNE  H6309
+         ldd   M$Name,x   grab the name offset
+         ldd   d,x        find the first 2 bytes of the first module
+         cmpd  #$4E69     'Ni' ? (NitrOS9 module?)
+         bne   not.ext    no, not system memory extensions
+         ldd   M$Exec,x   grab the execution ptr
+         jmp   d,x        and go execute the system memory extension module
+         ENDC
+
+not.ext  ldd   <D.BtSz
+         bsr   I.VBlock   internal verify block routine
+         ldx   <D.SysDAT    get system DAT pointer
+         ldb   $0D,x      get highest allocated block number
+         incb             allocate block 0, too
+         ldx   <D.BlkMap  point to the memory block map
+         lbra  L01DF      and go mark the blocks as used.
+
+
+**************************************************
+* System Call: F$VBlock
+*
+* Function: ???
+*
+* Input:  D = Size of block to verify
+*         X = Start address to verify
+*
+* Output: None
+*
+* Error:  CC = C bit set; B = error code       
+*
+FVBlock  ldd   R$D,u      size of block to verify
+         ldx   R$X,u      start address to verify
+
+I.VBlock leau  d,x        point to end of bootfile
+         tfr   x,d	  transfer start of block to D
+         anda  #$E0         
+         clrb		  D is now block number
+         pshs  d,u	  save starting block and end of block
+         lsra  
+         lsra  
+         lsra  
+         lsra		  A is now logical block * 2  
+         ldy   <D.SysDAT  get pointer to system DAT
+         leay  a,y        y is pointer of sys block map of start of block
+L092D    ldd   M$ID,x     get module ID
+         cmpd  #M$ID12    legal ID?
+         bne   L0954      no, keep looking
+
+         ldd   M$Name,x   find name offset pointer
+         pshs  x
+         leax  d,x
+name.prt lda   ,x+        get first character of the name
+         jsr   <D.BtBug   print it out
+         bpl   name.prt
+         lda   #C$SPAC    a space
+         jsr   <D.BtBug
+         puls  x
+
+         IFNE  H6309
+         ldd   ,s         offset into block
+         subr  d,x        make X=offset into block
+         ELSE
+         tfr   x,d
+         subd  ,s
+         tfr   d,x
+         ENDC
+         tfr   y,d
+         os9   F$VModul
+         IFNE  H6309
+         ldw   ,s
+         leax  w,x
+         ELSE
+         pshs  b
+         ldd   1,s
+         leax  d,x
+         puls  b
+         ENDC
+         bcc   L094E
+         cmpb  #E$KwnMod
+         bne   L0954
+L094E    ldd   M$Size,x
+         leax  d,x
+         fcb   $8C        skip 2 bytes
+
+L0954    leax  1,x          move to next byte
+L0956    cmpx  2,s          gone thru whole bootfile?
+         bcs   L092D        no, keep looking
+         leas  4,s          purge stack
+         clrb
+         rts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level2/modules/kernel/ccbkrn.asm	Mon Feb 06 15:51:13 2012 -0600
@@ -0,0 +1,1121 @@
+********************************************************************
+* krn - NitrOS-9 Level 2 Kernel
+*
+* $Id: krn.asm,v 1.29 2010/05/20 16:35:47 boisy Exp $
+*
+* Edt/Rev  YYYY/MM/DD  Modified by
+* Comment
+* ------------------------------------------------------------------
+*  19r6    2002/08/21  Boisy G. Pitre
+* Assembles to the os9p1 module that works on my NitrOS-9 system.
+*
+*  19r7    2002/09/26  Boisy G. Pitre
+* Added check for CRC feature bit in init module
+*
+*  19r8    2003/09/22  Boisy G. Pitre
+* Back-ported to OS-9 Level Two.
+*
+*  19r8    2004/05/22  Boisy G. Pitre
+* Renamed to 'krn'
+*
+*  19r9    2004/07/12  Boisy G. Pitre
+* F$SRqMem now properly scans the DAT images of the system to update
+* the D.SysMem map.
+		
+	nam	krn
+	ttl	NitrOS-9 Level 2 Kernel
+		
+	IFP1	
+	use	defsfile
+	ENDC	
+		
+* defines for customizations
+Revision	set	9	module revision
+Edition	set	19	module Edition
+Where	equ	$F000	absolute address of where Kernel starts in memory
+				
+	mod	eom,MName,Systm,ReEnt+Revision,entry,0
+
+	* CCB Change: module name changes to CCBKrn		
+MName	fcs	/CCBKrn/
+	fcb	Edition
+	
+	* CCB Change: added a automagic "fill" directive
+	* between the end of the kernel module, proper, and the fe page code
+	* see way down. Manually refilling the empty space after each 
+	* code change was a pain and error prone.  BG
+			
+* FILL - all unused bytes are now here
+*	fcc	/www.nitros9.org /
+*	fcc	/www.nitros9.org /
+*	fcc	/www.ni/
+*	fcc	/w/
+*	fcc	/w/
+*	fcc	/w/
+*	IFNE	H6309
+*	fcc	/www.nitros9.org /
+*	fcc	/www.nitros9.org /
+*	fcc	/www/
+*	ELSE	
+*	fcc	/www.nit/
+*	ENDC	
+		
+* Might as well have this here as just past the end of Kernel...
+DisTable
+	fdb	L0CD2+Where	D.Clock absolute address at the start
+	fdb	XSWI3+Where	D.XSWI3
+	fdb	XSWI2+Where	D.XSWI2
+	fdb	D.Crash		D.XFIRQ crash on an FIRQ
+	fdb	XIRQ+Where	D.XIRQ
+	fdb	XSWI+Where	D.XSWI
+	fdb	D.Crash		D.XNMI crash on an NMI
+	fdb	$0055		D.ErrRst ??? Not used as far as I can tell
+	fdb	Sys.Vec+Where	Initial Kernel system call vector
+DisSize	equ	*-DisTable
+* DO NOT ADD ANYTHING BETWEEN THESE 2 TABLES: see code using 'SubSiz', below
+LowSub	equ	$0160		start of low memory subroutines
+SubStrt	equ	*
+* D.Flip0 - switch to system task 0
+R.Flip0	equ	*
+	IFNE	H6309
+	aim	#$FE,<D.TINIT	map type 0
+	lde	<D.TINIT	another 2 bytes saved if GRFDRV does: tfr cc,e
+	ste	>DAT.Task	and we can use A here, instead of E
+	ELSE	
+	pshs	a
+	lda	<D.TINIT
+	anda	#$FE
+	sta	<D.TINIT
+	sta	>DAT.Task
+	puls	a
+	ENDC	
+	clr	<D.SSTskN
+	tfr	x,s
+	tfr	a,cc
+	rts	
+SubSiz	equ	*-SubStrt
+* Don't add any code here: See L0065, below.
+* Interrupt service routine
+Vectors	jmp	[<-(D.SWI3-D.XSWI3),x]	(-$10) (Jmp to 2ndary vector)
+		
+* Let's start by initializing system page
+entry	equ	*
+	* CCB Addition - save stacked OS9Boot size and make a dummy kernel printer
+	pulu	d		pull boot file size from CoCoBoot and
+	std	<D.BtSz		save to direct page for later use
+	inc	<D.Boot		mark boot attempted flag
+	inc	<D.Speed	mark high speed
+	lds	#$1fff		reset system stack (s/b 0x2000 ?!?!)
+	lda	#$7e		put code in DP so rest of kernel can
+	sta	<D.BtBug	call kernel printing routine
+	leax	BtDebug,pc
+	stx	<D.BtBug+1
+	sta	<D.Crash	and do the same with the kernel crash 
+	leax	Crash,pc	code
+	stx	<D.Crash+1
+	bra	CCBEND		jump over new kprint & crash routines
+
+	* This is a kernel print routine
+	*   This is added to replace the same routine found in "rel.asm"
+	*   so we get debug output.
+	*   Takes A - charactor to print
+	*   modifies - nothing
+BtDebug pshs	cc,d,x		save the register
+        orcc	#IntMasks	turn IRQ's off
+        ldb	#$3b		block to map in
+        stb	>$FFA0		map the boot screen into block 0
+        ldx	>$0002		where to put the bytes
+        sta	,x+		put the character on-screen
+        stx	>$0002		save updated address
+        clr	>$FFA0		map block 0 in again
+        puls	cc,d,x,pc	restore and return
+	* This routine just prints "!" and loops forever
+Crash	lda	#'!		print a "!"
+	jsr	<D.BtBug
+e	bra	e		loop forever
+CCBEND
+	* end of CCB Addition
+
+	* This code clears the rest of the low block
+	* rel.asm/cocoboot has cleared the DP already.
+	IFNE	H6309
+	ldq	#$01001f00	start address to clear & # bytes to clear
+	leay	<entry+2,pc	point to a 0
+	tfm	y,d+
+	std	<D.CCStk	set pointer to top of global memory to $2000
+	lda	#$01		set task user table to $0100
+	ELSE	
+	ldx	#$100
+	ldy	#$2000-$100
+	clra	
+	clrb	
+L001C	std	,x++
+	leay	-2,y
+	bne	L001C
+	stx	<D.CCStk	Set pointer to top of global memory to $2000
+	inca			D = $0100
+	ENDC	
+		
+* Setup system direct page variables
+	std	<D.Tasks	set Task Structure pointer to 0x100
+	addb	#$20		set Task image table pointer to $0120
+	std	<D.TskIPt
+	clrb			set memory block map pointer to $0200
+	inca	
+	std	<D.BlkMap
+	addb	#$40		set second block map pointer to $0240
+	std	<D.BlkMap+2
+	clrb			set system service dispatch table 
+	inca			pointer to 0x300
+	std	<D.SysDis
+	inca			set user dispatch table pointer to $0400
+	std	<D.UsrDis
+	inca			set process descriptor block pointer to $0500
+	std	<D.PrcDBT
+	inca			set system process descriptor pointer to $0600
+	std	<D.SysPrc
+	std	<D.Proc		set user process descriptor pointer to $0600
+	adda	#$02		set stack pointer to $0800
+	tfr	d,s
+	inca			set system stack base pointer to $0900
+	std	<D.SysStk
+	std	<D.SysMem	set system memory map ptr $0900
+	inca			set module directory start ptr to $0a00
+	std	<D.ModDir
+	std	<D.ModEnd	set module directory end ptr to $0a00
+	adda	#$06		set secondary module directory start to $1000
+	std	<D.ModDir+2
+	std	<D.ModDAT	set module directory DAT pointer to $1000
+	std	<D.CCMem	set pointer to beginning of global memory to $1000
+* In following line, CRC=ON if it is STA <D.CRC, CRC=OFF if it is a STB <D.CRC
+	stb	<D.CRC		set CRC checking flag to off
+		
+* Initialize interrupt vector tables, move pointer data down to DP
+* CCB Change:
+* this line was an error?
+*	leay	<DisTable,pcr   
+	leay	DisTable,pcr	point to table of absolute vector addresses
+*
+*
+	ldx	#D.Clock	where to put it in memory
+	IFNE	H6309
+	ldf	#DisSize	size of the table - E=0 from TFM, above
+	tfm	y+,x+		move it over
+	ELSE	
+	ldb	#DisSize
+l@
+	lda	,y+		load a byte from source
+	sta	,x+		store a byte to dest
+	decb			bump counter
+	bne	l@		loop if we're not done
+	ENDC	
+		
+* initialize D.Flip0 routine in low memory, move funtion down to low
+* memory.
+* Y=ptr to R.Flip0 already
+*         leay  >R.Flip0,pc
+	ldu	#LowSub		move to 0x160
+	stu	<D.Flip0	store fuction pointer to DP area
+	IFNE	H6309
+	ldf	#SubSiz		size of it
+	tfm	y+,u+		copy it over
+	ELSE	
+	ldb	#SubSiz
+Loop2	lda	,y+		load a byte from source
+	sta	,u+		and save to destination
+	decb			bump counter
+	bne	Loop2		loop if not done
+	ENDC	
+		
+*         leau   <Vectors,pc   point to vector
+* fill in the secondard interrupt vectors to all point to 
+	tfr	y,u		move the pointer to a faster register
+L0065	stu	,x++		Set all IRQ vectors to go to Vectors for now
+	cmpx	#D.NMI
+	bls	L0065
+		
+* Initialize user interupt vectors
+	ldx	<D.XSWI2	Get SWI2 (os9 command) service routine pointer
+	stx	<D.UsrSvc	Save it as user service routine pointer
+	ldx	<D.XIRQ		Get IRQ service routine pointer
+	stx	<D.UsrIRQ	Save it as user IRQ routine pointer
+		
+	leax	>SysCall,pc	Setup System service routine entry vector
+	stx	<D.SysSvc
+	stx	<D.XSWI2
+		
+	leax	>S.SysIRQ,pc	Setup system IRQ service vector
+	stx	<D.SysIRQ
+	stx	<D.XIRQ
+		
+	leax	>S.SvcIRQ,pc	Setup in system IRQ service vector
+	stx	<D.SvcIRQ
+	leax	>S.Poll,pc	Setup interrupt polling vector
+	stx	<D.Poll		ORCC #$01;RTS
+	leax	>S.AltIRQ,pc	Setup alternate IRQ vector: pts to an RTS
+	stx	<D.AltIRQ
+		
+	lda	#'K	--- in Kernel
+	jsr	<D.BtBug	---
+		
+	leax	>S.Flip1,pc	Setup change to task 1 vector
+	stx	<D.Flip1
+		
+* Setup System calls
+	leay	>SysCalls,pc	load y with address of table, below
+	lbsr	SysSvc		copy table below into dispatch table
+		
+* Initialize system process descriptor
+	ldu	<D.PrcDBT	get process table pointer
+	ldx	<D.SysPrc	get system process pointer
+* These overlap because it is quicker than trying to strip hi byte from X
+	stx	,u		save it as first process in table
+	stx	1,u		save it as the second as well
+	IFNE	H6309
+	oim	#$01,P$ID,x	Set process ID to 1 (inited to 0)
+	oim	#SysState,P$State,x	Set to system state (inited to 0)
+	ELSE	
+	ldd	#$01*256+SysState
+	sta	P$ID,x		set PID to 1
+	stb	P$State,x	set state to system (*NOT* zero )
+	ENDC	
+	clra			set System task as task #0
+	sta	<D.SysTsk	
+	sta	P$Task,x
+	coma			Setup its priority & age ($FF)
+	sta	P$Prior,x
+	sta	P$Age,x
+	leax	<P$DATImg,x	point to DAT image
+	stx	<D.SysDAT	save it as a pointer in DP
+* actually, since block 0 is tfm'd to be zero, we can skip the next 2 lines
+	IFNE	H6309
+	clrd	
+	ELSE	
+	clra	
+	clrb	
+	ENDC	
+	std	,x++		initialize 1st block to 0 (for this DP)
+		
+* Dat.BlCt-ROMCount-RAMCount
+	lda	#$06		initialize the rest of the blocks to be free
+	ldu	#DAT.Free	
+L00EF	stu	,x++		store free "flag"
+	deca			bump counter
+	bne	L00EF		loop if not done
+		
+	ldu	#$003F		Block $3F is in use, at the top of system DAT image
+	stu	,x
+		
+	ldx	<D.Tasks	Point to task user table
+	inc	,x		mark first 2 in use (system & GrfDrv)
+	inc	1,x
+		
+* Setup system memory map
+	ldx	<D.SysMem	Get system memory map pointer
+	ldb	<D.CCStk	Get MSB of top of CC memory
+L0104	inc	,x+		Mark it as used
+	decb			Done?
+	bne	L0104		No, go back till done
+
+* Calculate memory size
+	* CCB Comment:	
+	* This code only modifies 2 bytes in the x0 blocks (x=doesn't cares)
+	* which at worst will be our DP. Should not effect CCB's prior load of
+	* OS9Boot it can only be loaded into block x1 through x6 and 3f so
+	* we should be safe.
+	ldx	<D.BlkMap	get ptr to 8k block map
+	inc	<$3F,x		mark block $3F as used (kernel)
+	IFNE	H6309
+	ldq	#$00080100	e=Marker, D=Block # to check
+L0111	asld			get next block #
+	stb	>$FFA5		Map block into block 6 of my task
+	ste	>-$6000,x	save marker to that block
+	cmpe	,x		did it ghost to block 0?
+	bne	L0111		No, keep going till ghost is found
+	stb	<D.MemSz	Save # 8k mem blocks that exist
+	addr	x,d		add number of blocks to block map start
+	ELSE	
+	ldd	#$0008		
+L0111	aslb	
+	rola	
+	stb	>$FFA5
+	pshs	a
+	lda	#$01
+	sta	>-$6000,x
+	cmpa	,x
+	puls	a
+	bne	L0111
+	stb	<D.MemSz
+	pshs	x
+	addd	,s++
+	ENDC	
+	std	<D.BlkMap+2	save block map end pointer
+		
+* [D] at this point will contain 1 of the following:
+* $0210 - 128k
+* $0220 - 256k
+* $0240 - 512k
+* $0280 - 1024k
+* $0300 - 2048k
+	bitb	#%00110000	block above 128K-256K?
+	beq	L0170		yes, no need to mark block map
+	tstb			2 meg?
+	beq	L0170		yes, skip this
+* Mark blocks from 128k-256K to block $3F as NOT RAM
+	abx			add maximum block number to block map start
+	leax	-1,x		Skip good blocks that are RAM
+	lda	#NotRAM		Not RAM flag
+	subb	#$3F		Calculate # blocks to mark as not RAM
+L0127	sta	,x+		Mark them all
+	decb	
+	bne	L0127
+		
+L0170
+* CCB - Commented out next two line. we don't have REL or BOOT, so the verify will be only
+* for the memory taken by KRN itself... f000 to ff00	
+*	ldx	#Bt.Start	start address of the boot track in memory
+*	lda	#$12		size of the boot track: B=$00 from L0127 loop, above
+* CCB Addtion - change 2 lines above to:	
+*	ldx	#Where		start address of KRN in memory
+*	ldd	#$f00		size of KRN: B is already 0, A = F, Size=15 sectors (max)
+* end of CCB Addtion
+*	lbsr	I.VBlock	go verify it
+*	bsr	L01D2		go mark system map
+* CCB Change - I'm commenting out this whole section, and replacing it
+	IFEQ	1		
+* See if init module is in memory already
+L01B0	leax	<init,pc	point to 'Init' module name
+	bsr	link		try & link it
+	bcc	L01BF		no error, go on
+L01B8	os9	F$Boot		error linking init, try & load boot file
+	bcc	L01B0		got it, try init again
+	bra	L01CE		error, re-booting do D.Crash
+L01BF	stu	<D.Init		Save init module pointer
+	lda	Feature1,u	Get feature byte #1 from init module
+	bita	#CRCOn		CRC feature on?
+	beq	ShowI		if not, continue
+	inc	<D.CRC		else inc. CRC flag
+ShowI	lda	#'i		found init module
+	jsr	<D.BtBug
+
+L01C1	leax	<krnp2,pc	Point to it's name
+	bsr	link		Try to link it
+	bcc	L01D0		It worked, execute it
+	os9	F$Boot		It doesn't exist try re-booting
+	bcc	L01C1		No error's, let's try to link it again
+L01CE	jmp	<D.Crash	obviously can't do it, crash machine
+L01D0	jmp	,y		execute krnp2
+	ENDC
+
+* CCB we'll replace above with this:
+	ldd	<D.BtSz		get the size of OS9Boot file
+	addd	#$fff		add size of krn and round to higher size
+	clrb
+	pshs	d		save on stack
+	os9	F$SRqMem	get memory - U is our starting address
+	stu	<D.BtPtr	save this just incase something uses it
+	tfr	u,x		setup x for vblock
+	puls	d		setup d for vblock with stacked size
+	lbsr	I.VBlock	verify OS9Boot
+	* this was copied from f$boot
+	* I dont know why we need to do this.  Wouldn't
+	* f$srqmem do this for us?!?!  But the system won't boot without.
+	ldx	<D.SysDAT	get system DAT pointer
+        ldb	$0D,x		get highest allocated block number
+        incb			allocate block 0, too
+        ldx	<D.BlkMap	point to the memory block map
+	bsr	L01DF		and go mark the blocks as used
+	* end of copy from f$boot
+	leax	<init,pc	point to 'Init' module name
+	bsr	link		try & link it
+L01BF	stu	<D.Init		Save init module pointer
+	lda	Feature1,u	Get feature byte #1 from init module
+	bita	#CRCOn		CRC feature on?
+*	beq	ShowI		if not, continue
+	inc	<D.CRC		else inc. CRC flag
+ShowI	lda	#'i		found init module
+	jsr	<D.BtBug
+L01C1	leax	<krnp2,pc	Point to it's name
+	bsr	link		Try to link it
+*e	bra	e
+L01D0	jmp	,y		execute krnp2
+	
+
+* CCB - End of change
+	
+				
+* Mark kernel in system memory map as used memory (256 byte blocks)
+* L01D2	ldx	<D.SysMem	Get system mem ptr
+*	* CCB Change - only mark KRN as used (BOOT and REL don't exist)
+*	ldd	#NotRAM*256+(Bt.Start/256)	B = MSB of start of the boot
+*	ldd	#NotRam*256+(Where/256)		B = MSB of start of REL
+	* CCB Change end
+*	abx			point to Bt.Start - start of boot track
+*	comb			we have $FF-$ED pages to mark as used
+*	sta	b,x		Mark I/O as not RAM
+
+* Mark kernel and boot file in system memory as used - there is no
+* reason this is a routine anymore - only one place calls it, but
+* some speghetti is here... one of the IRQ routines "borrows" this rts.	
+L01DF	lda	#RAMinUse	get in use flag
+L01E1	sta	,x+		save it
+	decb			done?
+	bne	L01E1		no, keep going
+	ldx	<D.BlkMap	get pointer to start of block map
+	sta	<$3f,x		mark kernel block as RAMinUse, instead of ModInBlk
+S.AltIRQ	rts		return
+		
+* Link module pointed to by X
+link	lda	#Systm		Attempt to link system module
+	os9	F$Link
+	rts	
+		
+init	fcs	'Init'
+krnp2	fcs	'krnp2'
+		
+* Service vector call pointers
+SysCalls	fcb	F$Link
+	fdb	FLink-*-2
+	fcb	F$PrsNam
+	fdb	FPrsNam-*-2
+	fcb	F$CmpNam
+	fdb	FCmpNam-*-2
+	fcb	F$CmpNam+SysState
+	fdb	FSCmpNam-*-2
+	fcb	F$CRC
+	fdb	FCRC-*-2
+	fcb	F$SRqMem+SysState
+	fdb	FSRqMem-*-2
+	fcb	F$SRtMem+SysState
+	fdb	FSRtMem-*-2
+	fcb	F$AProc+SysState
+	fdb	FAProc-*-2
+	fcb	F$NProc+SysState
+	fdb	FNProc-*-2
+	fcb	F$VModul+SysState
+	fdb	FVModul-*-2
+	fcb	F$SSvc+SysState
+	fdb	FSSvc-*-2
+	fcb	F$SLink+SysState
+	fdb	FSLink-*-2
+	fcb	F$Boot+SysState
+	fdb	FBoot-*-2
+	fcb	F$BtMem+SysState
+	fdb	FSRqMem-*-2
+	IFNE	H6309
+	fcb	F$CpyMem
+	fdb	FCpyMem-*-2
+	ENDC	
+	fcb	F$Move+SysState
+	fdb	FMove-*-2
+	fcb	F$AllImg+SysState
+	fdb	FAllImg-*-2
+	fcb	F$SetImg+SysState
+	fdb	FFreeLB-*-2
+	fcb	F$FreeLB+SysState
+	fdb	FSFreeLB-*-2
+	fcb	F$FreeHB+SysState
+	fdb	FFreeHB-*-2
+	fcb	F$AllTsk+SysState
+	fdb	FAllTsk-*-2
+	fcb	F$DelTsk+SysState
+	fdb	FDelTsk-*-2
+	fcb	F$SetTsk+SysState
+	fdb	FSetTsk-*-2
+	fcb	F$ResTsk+SysState
+	fdb	FResTsk-*-2
+	fcb	F$RelTsk+SysState
+	fdb	FRelTsk-*-2
+	fcb	F$DATLog+SysState
+	fdb	FDATLog-*-2
+	fcb	F$LDAXY+SysState
+	fdb	FLDAXY-*-2
+	fcb	F$LDDDXY+SysState
+	fdb	FLDDDXY-*-2
+	fcb	F$LDABX+SysState
+	fdb	FLDABX-*-2
+	fcb	F$STABX+SysState
+	fdb	FSTABX-*-2
+	fcb	F$ELink+SysState
+	fdb	FELink-*-2
+	fcb	F$FModul+SysState
+	fdb	FFModul-*-2
+	fcb	F$VBlock+SysState
+	fdb	FVBlock-*-2
+	IFNE	H6309
+	fcb	F$DelRAM
+	fdb	FDelRAM-*-2
+	ENDC	
+	fcb	$80
+		
+* SWI3 vector entry
+XSWI3	lda	#P$SWI3		point to SWI3 vector
+	fcb	$8C		skip 2 bytes
+		
+* SWI vector entry
+XSWI	lda	#P$SWI		point to SWI vector
+	ldx	<D.Proc		get process pointer
+	ldu	a,x		user defined SWI[x]?
+	beq	L028E		no, go get option byte
+GoUser	lbra	L0E5E		Yes, go call users's routine
+		
+* SWI2 vector entry
+XSWI2	ldx	<D.Proc		get current process descriptor
+	ldu	P$SWI2,x	any SWI vector?
+	bne	GoUser		yes, go execute it
+		
+* Process software interupts from a user state
+* Entry: X=Process descriptor pointer of process that made system call
+*        U=Register stack pointer
+L028E	ldu	<D.SysSvc	set system call processor to system side
+	stu	<D.XSWI2
+	ldu	<D.SysIRQ	do the same thing for IRQ's
+	stu	<D.XIRQ
+	IFNE	H6309
+	oim	#SysState,P$State,x	mark process as in system state
+	ELSE	
+	lda	P$State,x
+	ora	#SysState
+	sta	P$State,x
+	ENDC	
+* copy register stack to process descriptor
+	sts	P$SP,x		save stack pointer
+	leas	(P$Stack-R$Size),x	point S to register stack destination
+		
+	IFNE	H6309
+	leau	R$Size-1,s	point to last byte of destination register stack
+	leay	-1,y		point to caller's register stack in $FEE1
+	ldw	#R$Size		size of the register stack
+	tfm	y-,u-
+	leau	,s		needed because the TFM is u-, not -u (post, not pre)
+	ELSE	
+* Note!  R$Size MUST BE an EVEN number of bytes for this to work!
+	leau	R$Size,s	point to last byte of destination register stack
+	lda	#R$Size/2
+Loop3	ldx	,--y
+	stx	,--u
+	deca	
+	bne	Loop3
+	ENDC	
+	andcc	#^IntMasks
+* B=function code already from calling process: DON'T USE IT!
+	ldx	R$PC,u		get where PC was from process
+	leax	1,x		move PC past option
+	stx	R$PC,u		save updated PC to process
+* execute function call
+	ldy	<D.UsrDis	get user dispatch table pointer
+	lbsr	L033B		go execute option
+	IFNE	H6309
+	aim	#^IntMasks,R$CC,u	Clear interrupt flags in caller's CC
+	ELSE	
+	lda	R$CC,u
+	anda	#^IntMasks
+	sta	R$CC,u
+	ENDC	
+	ldx	<D.Proc		get current process ptr
+	IFNE	H6309
+	aim	#^(SysState+TimOut),P$State,x	Clear system & timeout flags
+	ELSE	
+	lda	P$State,x
+	anda	#^(SysState+TimOut)
+	sta	P$State,x
+	ENDC	
+		
+* Check for image change now, which lets stuff like F$MapBlk and F$ClrBlk
+* do the short-circuit thing, too.  Adds about 20 cycles to each system call.
+	lbsr	TstImg		it doesn't hurt to call this twice
+	lda	P$State,x	get current state of the process
+	ora	<P$Signal,x	is there a pending signal?
+	sta	<D.Quick	save quick return flag
+	beq	AllClr		if nothing's have changed, do full checks
+		
+DoFull	bsr	L02DA		move the stack frame back to user state
+	lbra	L0D80		go back to the process
+		
+* add ldu P$SP,x, etc...
+AllClr	equ	*
+	IFNE	H6309
+	inc	<D.QCnt
+	aim	#$1F,<D.QCnt
+	beq	DoFull		every 32 system calls, do the full check
+	ldw	#R$Size		--- size of the register stack
+	ldy	#Where+SWIStack	--- to stack at top of memory
+	orcc	#IntMasks
+	tfm	u+,y+		--- move the stack to the top of memory
+	ELSE	
+	lda	<D.QCnt
+	inca	
+	anda	#$1F
+	sta	<D.QCnt
+	beq	DoFull
+	ldb	#R$Size
+	ldy	#Where+SWIStack
+	orcc	#IntMasks
+Loop4	lda	,u+
+	sta	,y+
+	decb	
+	bne	Loop4
+	ENDC	
+	lbra	BackTo1		otherwise simply return to the user
+		
+* Copy register stack from user to system
+* Entry: U=Ptr to Register stack in process dsc
+L02CB	pshs	cc,x,y,u	preserve registers
+	ldb	P$Task,x	get task #
+	ldx	P$SP,x	get stack pointer
+	lbsr	L0BF3		calculate block offset (only affects A&X)
+	leax	-$6000,x	adjust pointer to where memory map will be
+	bra	L02E9		go copy it
+		
+* Copy register stack from system to user
+* Entry: U=Ptr to Register stack in process dsc
+L02DA	pshs	cc,x,y,u	preserve registers
+	ldb	P$Task,x	get task # of destination
+	ldx	P$SP,x		get stack pointer
+	lbsr	L0BF3		calculate block offset (only affects A&X)
+	leax	-$6000,x	adjust pointer to where memory map will be
+	exg	x,y		swap pointers & copy
+* Copy a register stack
+* Entry: X=Source
+*        Y=Destination
+*        A=Offset into DAT image of stack
+*        B=Task #
+L02E9	leau	a,u		point to block # of where stack is
+	lda	1,u		get first block
+	ldb	3,u		get a second just in case of overlap
+	orcc	#IntMasks	shutdown interupts while we do this
+	std	>$FFA5		map blocks in
+	IFNE	H6309
+	ldw	#R$Size		get size of register stack
+	tfm	x+,y+		copy it
+	ELSE	
+	ldb	#R$Size
+Loop5	lda	,x+
+	sta	,y+
+	decb	
+	bne	Loop5
+	ENDC	
+	ldx	<D.SysDAT	remap the blocks we took out
+	lda	$0B,x
+	ldb	$0D,x
+	std	>$FFA5
+	puls	cc,x,y,u,pc	restore & return
+		
+* Process software interupts from system state
+* Entry: U=Register stack pointer
+SysCall	leau	,s		get pointer to register stack
+	lda	<D.SSTskN	Get system task # (0=SYSTEM, 1=GRFDRV)
+	clr	<D.SSTskN	Force to System Process
+	pshs	a		Save the system task number
+	lda	,u		Restore callers CC register (R$CC=$00)
+	tfr	a,cc		make it current
+	ldx	R$PC,u		Get my caller's PC register
+	leax	1,x		move PC to next position
+	stx	R$PC,u		Save my caller's updated PC register
+	ldy	<D.SysDis	get system dispatch table pointer
+	bsr	L033B		execute system call
+	puls	a		restore system state task number
+	lbra	L0E2B		return to process
+		
+* Entry: X = system call vector to jump to
+Sys.Vec	jmp	,x		execute service call
+		
+* Execute system call
+* Entry: B=Function call #
+*        Y=Function dispatch table pointer (D.SysDis or D.UsrDis)
+L033B		
+	lslb			is it a I/O call? (Also multiplys by 2 for offset)
+	bcc	L0345		no, go get normal vector
+* Execute I/O system calls
+	ldx	IOEntry,y	get IOMan vector
+* Execute the system call
+L034F	pshs	u		preserve register stack pointer
+	jsr	[D.SysVec]	perform a vectored system call
+	puls	u		restore pointer
+L0355	tfr	cc,a		move CC to A for stack update
+	bcc	L035B		go update it if no error from call
+	stb	R$B,u		save error code to caller's B
+L035B	ldb	R$CC,u		get callers CC, R$CC=$00
+	IFNE	H6309
+	andd	#$2FD0		[A]=H,N,Z,V,C [B]=E,F,I
+	orr	b,a		merge them together
+	ELSE	
+	anda	#$2F		[A]=H,N,Z,V,C
+	andb	#$D0		[B]=E,F,I
+	pshs	b
+	ora	,s+
+	ENDC	
+	sta	R$CC,u		return it to caller, R$CC=$00
+	rts	
+		
+* Execute regular system calls
+L0345		
+	clra			clear MSB of offset
+	ldx	d,y		get vector to call
+	bne	L034F		it's initialized, go execute it
+	comb			set carry for error
+	ldb	#E$UnkSvc	get error code
+	bra	L0355		return with it
+		
+	use	freboot.asm
+		
+	use	fssvc.asm
+		
+	use	flink.asm
+		
+	use	fvmodul.asm
+		
+	use	ffmodul.asm
+		
+	use	fprsnam.asm
+		
+	use	fcmpnam.asm
+		
+	use	ccbfsrqmem.asm
+		
+*         use   fallram.asm
+		
+		
+	IFNE	H6309
+	use	fdelram.asm
+	ENDC	
+		
+	use	fallimg.asm
+		
+	use	ffreehb.asm
+		
+	use	fdatlog.asm
+		
+	use	fld.asm
+		
+	IFNE	H6309
+	use	fcpymem.asm
+	ENDC	
+		
+	use	fmove.asm
+		
+	use	fldabx.asm
+		
+	use	falltsk.asm
+		
+	use	faproc.asm
+		
+* System IRQ service routine
+XIRQ	ldx	<D.Proc		get current process pointer
+	sts	P$SP,x		save the stack pointer
+	lds	<D.SysStk	get system stack pointer
+	ldd	<D.SysSvc	set system service routine to current
+	std	<D.XSWI2
+	ldd	<D.SysIRQ	set system IRQ routine to current
+	std	<D.XIRQ
+	jsr	[>D.SvcIRQ]	execute irq service
+	bcc	L0D5B
+		
+	ldx	<D.Proc		get current process pointer
+	ldb	P$Task,x
+	ldx	P$SP,x		get it's stack pointer
+			
+	pshs	u,d,cc		save some registers
+	leau	,s		point to a 'caller register stack'
+	lbsr	L0C40		do a LDB 0,X in task B
+	puls	u,d,cc		and now A ( R$A,U ) = the CC we want
+		
+	ora	#IntMasks	disable it's IRQ's
+	lbsr	L0C28		save it back
+L0D5B	orcc	#IntMasks	shut down IRQ's
+	ldx	<D.Proc		get current process pointer
+	tst	<D.QIRQ		was it a clock IRQ?
+	lbne	L0DF7		if not, do a quick return
+		
+	lda	P$State,x	Get it's state
+	bita	#TimOut		Is it timed out?
+	bne	L0D7C		yes, wake it up
+* Update active process queue
+	ldu	#(D.AProcQ-P$Queue)	point to active process queue
+	ldb	#Suspend	get suspend flag
+L0D6A	ldu	P$Queue,u	get a active process pointer
+	beq	L0D78
+	bitb	P$State,u	is it suspended?
+	bne	L0D6A		yes, go to next one in chain
+	ldb	P$Prior,x	get current process priority
+	cmpb	P$Prior,u	do we bump this one?
+	blo	L0D7C
+		
+L0D78	ldu	P$SP,x
+	bra	L0DB9
+		
+L0D7C	anda	#^TimOut
+	sta	P$State,x
+		
+L0D80	equ	*
+L0D83	bsr	L0D11		activate next process
+		
+	use	fnproc.asm
+		
+* The following routines must appear no earlier than $E00 when assembled, as
+* they have to always be in the vector RAM page ($FE00-$FEFF)
+	
+* CCB: this code (after pad) start assembling *before* 0xfe00, it's too big to
+* fit into the memory as stated above!!!!
+
+PAD	fill	$00,($0df1-*)	fill memory to ensure the above happens
+* Default routine for D.SysIRQ
+S.SysIRQ
+	lda	<D.SSTskN	Get current task's GIME task # (0 or 1)
+	beq	FastIRQ		Use super-fast version for system state
+	clr	<D.SSTskN	Clear out memory copy (task 0)
+	jsr	[>D.SvcIRQ]	(Normally routine in Clock calling D.Poll)
+	inc	<D.SSTskN	Save task # for system state
+	lda	#1		Task 1
+	ora	<D.TINIT	Merge task bit's into Shadow version
+	sta	<D.TINIT	Update shadow
+	sta	>DAT.Task	Save to GIME as well & return
+	bra	DoneIRQ	Check for error and exit
+		
+FastIRQ	jsr	[>D.SvcIRQ]	(Normally routine in Clock calling D.Poll)
+DoneIRQ	bcc	L0E28	No error on IRQ, exit
+	IFNE	H6309
+	oim	#IntMasks,0,s	Setup RTI to shut interrupts off again
+	ELSE	
+	lda	,s
+	ora	#IntMasks
+	sta	,s
+	ENDC	
+L0E28	rti	
+		
+* return from a system call
+L0E29	clra			Force System task # to 0 (non-GRDRV)
+L0E2B	ldx	<D.SysPrc	Get system process dsc. ptr
+	lbsr	TstImg		check image, and F$SetTsk (PRESERVES A)
+	orcc	#IntMasks	Shut interrupts off
+	sta	<D.SSTskN	Save task # for system state
+	beq	Fst2	If task 0, skip subroutine
+	ora	<D.TINIT	Merge task bit's into Shadow version
+	sta	<D.TINIT	Update shadow
+	sta	>DAT.Task	Save to GIME as well & return
+Fst2	leas	,u		Stack ptr=U & return
+	rti	
+		
+* Switch to new process, X=Process descriptor pointer, U=Stack pointer
+L0E4C	equ	*
+	IFNE	H6309
+	oim	#$01,<D.TINIT	switch GIME shadow to user state
+	lda	<D.TINIT
+	ELSE	
+	lda	<D.TINIT
+	ora	#$01
+	sta	<D.TINIT
+	ENDC	
+	sta	>DAT.Task	save it to GIME
+	leas	,y		point to new stack
+	tstb			is the stack at SWISTACK?
+	bne	MyRTI		no, we're doing a system-state rti
+		
+	IFNE	H6309
+	ldf	#R$Size		E=0 from call to L0E8D before
+	ldu	#Where+SWIStack	point to the stack
+	tfm	u+,y+		move the stack from top of memory to user memory
+	ELSE	
+	ldb	#R$Size
+	ldu	#Where+SWIStack	point to the stack
+RtiLoop	lda	,u+
+	sta	,y+
+	decb	
+	bne	RtiLoop
+	ENDC	
+MyRTI	rti			return from IRQ
+		
+		
+* Execute routine in task 1 pointed to by U
+* comes from user requested SWI vectors
+L0E5E	equ	*
+	IFNE	H6309
+	oim	#$01,<D.TINIT	switch GIME shadow to user state
+	ldb	<D.TINIT
+	ELSE	
+	ldb	<D.TINIT
+	orb	#$01
+	stb	<D.TINIT
+	ENDC	
+	stb	>DAT.Task
+	jmp	,u
+		
+* Flip to task 1 (used by GRF/WINDInt to switch to GRFDRV) (pointed to 
+*  by <D.Flip1). All regs are already preserved on stack for the RTI
+S.Flip1	ldb	#2		get Task image entry numberx2 for Grfdrv (task 1)
+	bsr	L0E8D		copy over the DAT image
+	IFNE	H6309
+	oim	#$01,<D.TINIT
+	lda	<D.TINIT	get copy of GIME Task side
+	ELSE	
+	lda	<D.TINIT
+	ora	#$01
+	sta	<D.TINIT
+	ENDC	
+	sta	>DAT.Task	save it to GIME register
+	inc	<D.SSTskN	increment system state task number
+	rti			return
+		
+* Setup MMU in task 1, B=Task # to swap to, shifted left 1 bit
+L0E8D	cmpb	<D.Task1N	are we going back to the same task
+	beq	L0EA3		without the DAT image changing?
+	stb	<D.Task1N	nope, save current task in map type 1
+	ldx	#$FFA8		get MMU start register for process's
+	ldu	<D.TskIPt	get task image pointer table
+	ldu	b,u		get address of DAT image
+L0E93	leau	1,u		point to actual MMU block
+	IFNE	H6309
+	lde	#4		get # banks/2 for task
+	ELSE	
+	lda	#4
+	pshs	a
+	ENDC	
+L0E9B	lda	,u++		get a bank
+	ldb	,u++		and next one
+	std	,x++		Save it to MMU
+	IFNE	H6309
+	dece			done?
+	ELSE	
+	dec	,s
+	ENDC	
+	bne	L0E9B		no, keep going
+	IFEQ	H6309
+	leas	1,s
+	ENDC	
+L0EA3	rts			return
+		
+* Execute FIRQ vector (called from $FEF4)
+FIRQVCT	ldx	#D.FIRQ		get DP offset of vector
+	bra	L0EB8		go execute it
+		
+* Execute IRQ vector (called from $FEF7)
+IRQVCT	orcc	#IntMasks	disasble IRQ's
+	ldx	#D.IRQ	get DP offset of vector
+
+* Execute interrupt vector, B=DP Vector offset
+L0EB8	clra			(faster than CLR >$xxxx)
+	sta	>DAT.Task	Force to Task 0 (system state)
+	IFNE	H6309
+	tfr	0,dp	setup DP
+	ELSE	
+	tfr	a,dp
+	ENDC	
+MapGrf	equ	*
+	IFNE	H6309
+	aim	#$FE,<D.TINIT	switch GIME shadow to system state
+	lda	<D.TINIT	set GIME again just in case timer is used
+	ELSE	
+	lda	<D.TINIT
+	anda	#$FE
+	sta	<D.TINIT
+	ENDC	
+MapT0	sta	>DAT.Task
+	jmp	[,x]		execute it
+		
+* Execute SWI3 vector (called from $FEEE)
+SWI3VCT	orcc	#IntMasks	disable IRQ's
+	ldx	#D.SWI3		get DP offset of vector
+	bra	SWICall		go execute it
+		
+* Execute SWI2 vector (called from $FEF1)
+SWI2VCT	orcc	#IntMasks	disasble IRQ's
+	ldx	#D.SWI2		get DP offset of vector
+		
+* This routine is called from an SWI, SWI2, or SWI3
+* saves 1 cycle on system-system calls
+* saves about 200 cycles (calls to I.LDABX and L029E) on grfdrv-system,
+*  or user-system calls.
+SWICall	ldb	[R$PC,s]	get callcode of the system call
+* NOTE: Alan DeKok claims that this is BAD.  It crashed Colin McKay's
+* CoCo 3.  Instead, we should do a clra/sta >DAT.Task.
+*         clr   >DAT.Task	go to map type 1
+	clra	
+	sta	>DAT.Task
+* set DP to zero
+	IFNE	H6309
+	tfr	0,dp
+	ELSE	
+	tfr	a,dp
+	ENDC	
+		
+* These lines add a total of 81 addition cycles to each SWI(2,3) call,
+* and 36 bytes+12 for R$Size in the constant page at $FExx
+*  It takes no more time for a SWI(2,3) from system state than previously,
+* ... and adds 14 cycles to each SWI(2,3) call from grfdrv... not a problem.
+* For processes that re-vector SWI, SWI3, it adds 81 cycles.  BUT SWI(3)
+* CANNOT be vectored to L0EBF cause the user SWI service routine has been
+* changed
+	lda	<D.TINIT	get map type flag
+	bita	#$01		check it without changing it
+		
+* Change to LBEQ R.SysSvc to avoid JMP [,X]
+* and add R.SysSvc STA >DAT.Task ???
+	beq	MapT0		in map 0: restore hardware and do system service
+	tst	<D.SSTskN	get system state 0,1
+	bne	MapGrf		if in grfdrv, go to map 0 and do system service
+		
+* the preceding few lines are necessary, as all SWI's still pass thru
+* here before being vectored to the system service routine... which
+* doesn't copy the stack from user state.
+	sta	>DAT.Task	go to map type X again to get user's stack
+* a byte less, a cycle more than ldy #$FEED-R$Size, or ldy #$F000+SWIStack
+	leay	<SWIStack,pc	where to put the register stack: to $FEDF
+	tfr	s,u		get a copy of where the stack is
+	IFNE	H6309
+	ldw	#R$Size		get the size of the stack
+	tfm	u+,y+		move the stack to the top of memory
+	ELSE	
+	pshs	b
+	ldb	#R$Size
+Looper	lda	,u+
+	sta	,y+
+	decb	
+	bne	Looper
+	puls	b
+	ENDC	
+	bra	L0EB8		and go from map type 1 to map type 0
+		
+* Execute SWI vector (called from $FEFA)
+SWIVCT	ldx	#D.SWI		get DP offset of vector
+	bra	SWICall		go execute it
+		
+* Execute NMI vector (called from $FEFD)
+NMIVCT	ldx	#D.NMI		get DP offset of vector
+	bra	L0EB8		go execute it
+		
+* The end of the kernel module is here
+	emod	
+eom	equ	*
+		
+* What follows after the kernel module is the register stack, starting
+* at $FEDD (6309) or $FEDF (6809).  This register stack area is used by
+* the kernel to save the caller's registers in the $FEXX area of memory
+* because it doesn't* get "switched out" no matter the contents of the
+* MMU registers.
+SWIStack		
+	fcc	/REGISTER STACK/	same # bytes as R$Size for 6809
+	IFNE	H6309
+	fcc	/63/	if 6309, add two more spaces
+	ENDC	
+		
+	fcb	$55	D.ErrRst
+		
+* This list of addresses ends up at $FEEE after the kernel track is loaded
+* into memory.  All interrupts come through the 6809 vectors at $FFF0-$FFFE
+* and get directed to here.  From here, the BRA takes CPU control to the
+* various handlers in the kernel.
+	bra	SWI3VCT	SWI3 vector comes here
+	nop	
+	bra	SWI2VCT	SWI2 vector comes here
+	nop	
+	bra	FIRQVCT	FIRQ vector comes here
+	nop	
+	bra	IRQVCT	IRQ vector comes here
+	nop	
+	bra	SWIVCT	SWI vector comes here
+	nop	
+	bra	NMIVCT	NMI vector comes here
+	nop	
+
+			
+	end	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/level2/modules/kernel/ccbkrn.txt	Mon Feb 06 15:51:13 2012 -0600
@@ -0,0 +1,142 @@
+* I eliminated the manual padding of the kernel.  I inserted a fill
+  directive much further down in the source between the "regular"
+  module part of the kernel, and the fe00 page code.  Down at that end
+  the assembler will auto-compute the size needed
+
+* At entry, the kernel now pulls the size of the bootfile from the U
+  stack, which is still setup from CCB, and saves it to
+  its proper place in the DP.  Also misc. DP flags are set - if boot
+  was attempted, and CPU speed is set (CCB uses high speed for coco3)
+
+* at entry, the kernel now installs it's own debug printing and crash
+  routines, something that REL used to do.
+
+* there's a place where some IRQ-ish tables are copied down to the DP,
+  where I found a bug: reg Y was being filled with a bogus source
+  address.  I'm NOT good with PCR addressing, but after fixing, my code
+  changes started working....maybe you want to verify this change.
+
+* read comments in the "calculate memory size" section... I got way
+  lucky on this one!
+
+* the biggest functional changes occur at label L0170: 
+
+  - The kernel no longer verifies itself (and hense adds itself to the
+    modules directory), it now verifies itself and the preloaded
+    bootfile together. The kernel no longer reserves it's own memory
+    either, it now simply calls f$srqmem to do this for us and the
+    bootfile together as one big block.  
+
+  - AFTER reserving system memory and verifying, we now mark up the
+    sysDAT... I don't understand why we have to do this.  Shouldn't
+    f$rsysmem do this for us?!?!  
+
+  - we link to init and set CRC checking and jump to krnp2's exec.
+
+* Near commented out label L01D2, I've commented out this section, it
+  no longer needed as f$rsysmem DOES do this for the entire kernel
+  now, not just the bootfile
+
+* the code at L01DF can be "inlined", nothing calls it but one place.
+  One of the IRQ vectors borrow's this routine's  RTS though ... goofy
+  speghetti code!
+
+* AFTER all the normal included system call files, and BEFORE the FE00
+  page stuff near label S.SysIRQ I added automatic padding
+
+* S.SysIRQ which is supposed to be in FE page, assembles at around
+  fdf1 or so.... which according to the comments is a BAD thing.
+  Nothing seems to happen.  Basically, the FE page code it TOO BIG to
+  fit!
+
+
+And in f$srqmem.asm:
+
+* I modified this system call to request memory starting from 0xff00
+  rather than ed00... it might be a touch lesss efficient AFTER
+  booting, but it sure helped DURING booting.  This is how I reused
+  fsrqmem to setup the KRN and OS9BOOT file in one swoop.
+
+* I changed f$boot to just issue a kernel panic.  I'm not sure if this
+  is the thing to do.  KRNP2 calls f$boot on chdir and open default
+  device error.  I'm not sure if anything else calls it.  Maybe it can
+  be it can be deleted and KRNP2 changed just to panic itself rather
+  than system calling to do so.
+
+
+*** All changes were made to a fresh CVS'd copy of Nitros9 Version 3.2.9.
+*** I have no idea if this all works on a coco2 or a 6309
+
+
+*** CoCoBoot / OS9 Contract:
+
+- Size of the pre-loaded bootfile (NOT boot and cckrn) is passed as
+  the top 2 bytes on the U stack.  MSB on top... the usually motorola
+  byte order.  In Forth lingo, the top cell of the data stack is the
+  size of the bootfile. Calling the kernel works and appears just like
+  calling any other forth word, except we don't return, e.i.:
+
+: gotokernel ( u -- ) \ jump to kernel passing it u - the bootfile
+\ size in bytes, this funtion doesn't return.
+
+- Module CCBKRN is loaded to block 0x3f at offset 0x1000, or 0xf000 in
+  cpu-space. CCBKRN must be exactly 0x0f00 in size and be in a
+  standard os9 executable module format.
+
+- The OS9Boot file is loaded on a page boundary just low enough in
+  cpu-space to fit below 0xf000 (the CCBKRN module)  physical blocks
+  are allocated in order starting with block 0x01 (or 0x31 on a 128k
+  machine).  
+
+- The source of OS9Boot and CCBKRN is not guaranteed!
+
+- Register Guarantees:
+    D  - not guaranteed
+    DP - not guaranteed
+    X  - not guaranteed
+    Y  - not guaranteed but usually will be in the 0x3800-0x6000 range
+    U  - set to top of a stack usually in the 0x7e00-0x7f00
+    S  - not guaranteed but usually will be in the 0x7f00 - 0x8000 range
+    CC - not guaranteed.
+    
+- MMU Guarantees:
+  physical block 0x3f will be banked in at 0xe000-0xff00 in cpu-space
+
+
+
+
+*** CoCoBoot does this but maybe CCBKRN should do instead:
+  
+- physical block 0x00 is in cpu-space at 0x0000 upon calling to
+  CCBKRN.  DP is set to 0x00 and the DP area in block 0x00 is cleared.
+
+- CPU interrupts and Pia0 side B's interrupts are disabled.
+
+- memory map is guaranteed to look like this (in hex):
+
+  00 39 3a 3b 3c 3d 3e 3f
+
+- Physical Block 3b will be cleared to spaces except offset 0x0000:
+  will be initialized to 0x0008.  This serves as a screen pointer to
+  kernel debug printing.
+
+- The GIME registers will be set as follows:
+  
+  starting at 0xff90:
+  6c      init0
+  00      init1
+  00      irq enable
+  00      firq enable
+  0900    timer register
+  0000    unused
+  0320    screen settings
+  0000    ????
+  00      ????
+  ec01    physical video address (block 3b offset 0x0008 )
+  00      horizontal offset / scroll
+  
+  A mirror of these bytes will appear at 0x0090-0x009f in the DP
+
+
+
+Brett M. Gordon
\ No newline at end of file
--- a/level2/modules/kernel/fnproc.asm	Sun Feb 05 13:30:35 2012 -0600
+++ b/level2/modules/kernel/fnproc.asm	Mon Feb 06 15:51:13 2012 -0600
@@ -89,7 +89,7 @@
          lbsr  L0E8D      re-map the DAT image, if necessary
 
          ldb   <D.Quick   get quick return flag
-         bra   L0E4C       Go switch GIME over to new process & run
+         lbra  L0E4C       Go switch GIME over to new process & run
 
 * Process a signal (process had no signal trap)
 L0DFD    equ   *