Newer
Older
uBix-Retro / dump / oa-2.0.9 / kernel / init.a65
/****************************************************************************
   
    OS/A65 Version 2.0.0
    Multitasking Operating System for 6502 Computers

    Copyright (C) 1989-1998 Andre Fachat 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

****************************************************************************/


#ifndef MEMINIVAL
#define	MEMINIVAL	0	/* reset value of RAM content */
#endif

#ifndef NOMMU

#ifdef NMIDEV
#echo Warning, nmidev only without mmu - disabling it
#undef NMIDEV
#endif

#ifndef NMIRESET
#echo Warning, no nmireset only without mmu - disabling nmi services
#define NMIRESET
#endif

#endif

/***************************************************************************
 * 
 * Hardware initialization
 *
 */

          .(
	.zero
pz        .word 0
; cnt       .byt 0
	.text

#ifdef MAP_ZERO
	.zero
#else
	.data
#endif
s1        .byt 0
s2        .byt 0

	.text

&notimp	  lda #E_NOTIMP
	  sec
	  rts

&preset   sei 
          cld
/*
 * initializes the hardware memory mapping, the system (preemption) timer
 * and the memory management, if needed. Also the macros 
 * GETFREQ(), LEDPORT, LED_LED, H_ERROR, and CLRTIMER() are defined.
 * It jumps to he_ram if there is not enough RAM available.
 */
#include "kernel/kinit.a65"

;          cmp #MIN_MEM	; memory size at least needed
;          bcc he_ram
;	  sta cnt

/* still a lot TODO! */
#if 0 /* def NOMMU */
	  ;sta cnt
	  sec
	  sbc #>startmem+255
	  tay
	  ldx #>startmem+255
	  jsr binit

	  lda #startzero
	  jsr zinit

	  lda cnt
#endif
          jmp prgstart

he_zero   ldx #HE_ZP
          .byt $2c
he_ram    ldx #HE_RAM
          .byt $2c
;e1        ldx #HE_IMEM
;          .byt $2c
;e2        ldx #HE_IDEV
;          .byt $2c
;e3        ldx #HE_ISTR
;          .byt $2c
;e4        ldx #HE_IENV
;          .byt $2c
erom      ldx #HE_ROM
          .byt $2c
edev      ldx #HE_DEV

          jmp HERROR

/***************************************************************************
 * 
 * ROM initialization
 *
 */

prgstart  /* get system speed */
          GETFREQ()
          sta s1

#ifdef LEDPORT
          jsr LEDOFF
#endif

#ifdef NMIDEV
          jsr ininmi
#endif
	  jsr initthreads
          jsr inienv
          ;bcs e4
#ifndef NO_DEVICE
          lda s1
          jsr inidev
          ;bcs e2
#endif
#ifndef NO_STREAMS
          jsr inistream 
          ;bcs e3
#endif
#ifndef NO_SEM
          jsr inisem
#endif
#ifndef NO_FSM
          jsr fminit     
#endif

#ifdef STARTMEM
	  ; lda cnt
	  STARTMEM()
#endif
;.byt 2
	  lda #<ROMSTART
          sta pz
          lda #>ROMSTART
          sta pz+1

startloop 
;.byt 2
	  ldy #0
          lda (pz),y
          iny
          and (pz),y
          cmp #$ff
          bne slx1
;jmp edev
          jmp pstart
xerr      
	  jmp edev
endloop   jmp erom

slx1      ldy #P_KIND+2
          lda (pz),y
          bpl slx2
          and #$7f
          ; cmp #PK_PRG
          ; beq iprg
          cmp #PK_DEV
          beq idev
          cmp #PK_INIT	; PK_FS
          beq ifs
slx2      jmp inext

idev
          ldy #P_ADDR+2
          lda (pz),y
          tax			;sta PCBUF+REGDEV_ADR
          iny
          lda (pz),y
          tay			;sta PCBUF+REGDEV_ADR+1
          lda #DC_REGDEV
          jsr DEVCMD
          bcs xerr
          jmp inext

ifs       

#if 0
	  ldx #STDNUL
          stx s1
          stx s2
          bne ifs1

iprg      jsr GETSTR
          bcs endloop
          stx s1
          jsr GETSTR
endloopx  bcs endloop
          stx s2
          ldy #P_DEV+2
          lda (pz),y
          tax
          ldy s2
          lda #DC_GS
          jsr DEVCMD
          ldy #P_DEV+2
          lda (pz),y
          tax
          ldy s1
          lda #DC_PS
          jsr DEVCMD
          ldy #P_DEV+2
          lda (pz),y
          pha
          tax
          lda #DC_RX_ON
          jsr DEVCMD
#ifdef CMOSCPU
	  plx
#else
          pla
          tax
#endif
          lda #DC_TX_ON
          jsr DEVCMD


ifs1      lda s2
          sta PCBUF+FORK_STDOUT
          sta PCBUF+FORK_STDERR
          lda s1
          sta PCBUF+FORK_STDIN
#endif

	  lda #STDNUL
          sta PCBUF+FORK_STDERR
          sta PCBUF+FORK_STDOUT
          sta PCBUF+FORK_STDIN

	  ldy #P_PRIORITY+2
	  lda (pz),y
	  sta PCBUF+FORK_PRIORITY

	  ldy #P_RAM+2
	  lda (pz),y
	  sta PCBUF+FORK_SIZE
	  iny
	  lda (pz),y
	  sta PCBUF+FORK_SHARED

          ldy #P_ADDR+2
          lda (pz),y
          sta PCBUF+FORK_ADDR
          iny  
          lda (pz),y
          sta PCBUF+FORK_ADDR+1

	  lda #0
	  sta PCBUF+FORK_NAME
	  sta PCBUF+FORK_NAME+1
#if 0
	  ldy #P_NAME+1
	  ldx #2
cmdn	  iny
	  lda (pz),y
	  sta PCBUF+FORK_NAME-P_NAME-2,y
	  bne cmdn
	  dex
	  bne cmdn
	  iny
#endif
          jsr FORK
#if 0
          ldx s1
          lda #SC_NUL
          jsr STRCMD
          ldx s2
          lda #SC_EOF
          jsr STRCMD
#endif

inext     
	  ldy #0
          lda (pz),y
          tax
          iny
          lda (pz),y
          sta pz+1
          stx pz
          jmp startloop

/***************************************************************************
 * 
 * Error handling
 *
 */

#ifdef LEDPORT
+LEDOFF   lda LEDPORT
          ora #LED_LED
          sta LEDPORT
          rts
#endif

+HERROR   .(        ; xr=Fehlernummer -1=1mal aus, -2=2mal aus etc
#ifdef EMUTEST
.byt 2
#endif
#ifdef LEDPORT
          LDA LEDPORT:EOR #LED_LED
          STA LEDPORT
          LDY #0:TYA
PRE2      ADC #1:BNE PRE2
          INY:BNE PRE2
          LDA LEDPORT:EOR #LED_LED
          STA LEDPORT
          LDA #0:TAY
PRE3      ADC #1:BNE PRE3:INY
          BNE PRE3:inx:BNE HERROR
          ldx #15
          lda #0:tay
pre5      adc #1:bne pre5
          iny:bne pre5
          dex:bne pre5
#else
	  H_ERROR
#endif

#ifdef EMUTEST	/* then save some process info and restart CS/A */
.(
lda #$11
sta $eff2
ldx #0
cp1 lda $eff0,x
sta $2000,x
inx
cpx #16
bcc cp1
pla
sta $2010
pla
sta $2011
tsx
stx $2012
l0 jmp l0
.)

#endif
          JMP RESET 

          .)

/***************************************************************************
 * 
 * NMI handling
 *
 */
          .(
&&pnmi
#ifdef NMIRESET
	jmp RESET
&&ctrlnmi
&&setnmi lda #E_NOTIMP
        sec
        rts
#else
#ifdef  NMIDEV
	jmp (nmiadr)
         
	.data 
nmiadr  .word 0
nmicnt 	.byt 0
	.text

&ininmi   ;lda #<zend
          ;ldy #>zend
	  lda #NMI_ON		; 0
	  sta nmicnt
ininmi2	  lda #<yendnmi
	  ldy #>yendnmi
n1        sta nmiadr
          sty nmiadr+1
          clc
zend      rts

	  ; struct for CTRLNMI
	  .word $ffff
	  .word zend
yendnmi   rti

&&setnmi   jsr memsys
          bcc n2
	  tax
	  lda nmiadr
	  pha
	  lda nmiadr+1
	  pha

	php
	sei
	lda #NMI_OFF
	jsr CTRLNMI	; before we mess with the NMI pointer, switch it off

	txa
        jsr n1

	lda nmiadr
	sec
	sbc #4
	sta tmp
	lda nmiadr+1
	sbc #0
	sta tmp+1

	ldy #0
	lda (tmp),y
	sta tmp2
	iny
	lda (tmp),y
	sta tmp2+1

	tsx
	lda $0102,x	
	sta (tmp2),y
	dey
	lda $0103,x
	sta (tmp2),y

	ldy #2
	lda (tmp),y
	sta tmp2
	iny
	lda (tmp),y
	sta tmp2+1	

	lda #NMI_OFF
 	jsr c2		; init new device with NMI off

	lda #NMI_ON	; now switch on again, if allowed
	jsr CTRLNMI
	plp

	  pla
	  tay
	  pla
          jmp ne
n2        jsr ininmi2
ne        jmp memtask
	  ;jsr memtask
          ;rts        

	.zero
tmp	.word 0
tmp2	.word 0
	.data
cmd	.byt 0
	.text

&&ctrlnmi 
	jsr memsys
	php
	sei
	cmp #NMI_ON
	beq con
	cmp #NMI_OFF
	beq coff
	lda #E_NOTIMP
	.byt $2c
crts	lda #E_OK
	plp
	cmp #1
	jmp memtask
	;jsr memtask
	;rts

con 	lda nmicnt
	beq crts
	dec nmicnt
	bne crts
	lda #NMI_ON
	beq nmicmd2

coff	clc
	lda nmicnt
	inc nmicnt
	cmp #0
	bne crts
	lda #NMI_OFF
nmicmd2
	jsr nmicmd		; nmicmd is only called at state change!
	jmp crts

nmicmd
	sta cmd 
	tya
	pha
	txa
	pha
	lda nmiadr
	ldx nmiadr+1

ctrl0	sec
	sbc #4
	sta tmp
	txa
	sbc #0
	sta tmp+1

	ldy #2
	lda (tmp),y
	sta tmp2
	iny
	lda (tmp),y
	sta tmp2+1

	lda cmd
	jsr c2

	ldy #0
	lda (tmp),y	
	sta tmp2
	iny
	lda (tmp),y
	sta tmp2+1
	and tmp2
	cmp #$ff		; address $ffff ?
	beq ce
	lda (tmp2),y
	tax
	dey
	lda (tmp2),y
	jmp ctrl0

ce	clc
	pla
	tax
	pla
	tay
	lda cmd
	clc
	rts

c2	jmp (tmp2)

#else	/*  NMIDEV */
          rti
&&ctrlnmi
&&setnmi   lda #E_NOTIMP
          sec
          rts
#endif
#endif			/* NMIRESET */
          .)

/***************************************************************************
 * 
 * IRQ handling
 *
 */
          .(
&&pirq     
#ifdef CMOSCPU
	pha
	phx
	phy
#else
	  pha
          txa
          pha
          tya
          pha
#endif
          tsx
          lda $104,x
          and #$10
          beq pb1
&petbrkjmp
          cld
#ifdef EMUTEST
	.byt 2
#endif
          jmp pbrk
&petirqjmp
pb1 
          cld
          jsr memsys

#ifdef SAVEMEM
	  KERNELIRQ()
	  bne taski
	  SAVEMEM
taski
#endif
          
#ifndef NOSYSPORT
          lda SYSPORT    ; save timer-irq state
          pha
#endif

il       
#ifndef NO_DEVICE 
	jsr irqdev
#endif

#ifndef NOSYSPORT
          pla
          ora SYSPORT    ; no timer-irq?
          pha            ; save it
          
	  CLRTIMER()

          jsr testirq    ; irq line still set?
          beq il         ; yes, than back to loop

          pla
          bpl endirq2     ; no timer-irq -> no task switch!
#else

	  CLRTIMER()
#endif

	  KERNELIRQ()
	  bne endirq

#ifdef SAVEMEM
	  RESTOREMEM()
#endif
#ifndef NO_DEVICE
          bit adev       
          bpl endirq     ; Device Interrupted -> no Task-switch
#endif
;jmp endirq
          jmp irqloop

#ifndef NOSYSPORT
endirq2  
#ifdef SAVEMEM
	  KERNELIRQ()
	  bne taski2
	  RESTOREMEM()
taski2
#endif
#endif

endirq
	  jmp retirq
          .)

#ifndef NOSYSPORT
+testirq  .(
          lda SYSPORT
          and #SYS_IRQ
          rts
          .)
#endif
          .)