OS-9 Level I V1.2 kernal, part 1
The OS-9 kernel is split into two parts. On ROM-based systems, part 1 resides from address $F800 to $FFFF. Included in the kernel are the reset- and interrupt vectors at $FFF2 and upwards.
nam OS-9 Level I V1.2 kernal, part 1
ttl System Type definitions
use defsfile
ifeq (CPUType-GIMIX)*(CPUType-EXORSR)
opt l
else
opt -l
endc
ttl Names & tables
opt -c
page
************************************************************
* *
* OS-9 Level I V1.2 - Kernal, part 1 *
* *
************************************************************
* Copyright 1980 by Motorola, Inc., and Microware Systems Corp.,
* Reproduced Under License
*
* This source code is the proprietary confidential property of
* Microware Systems Corporation, and is provided to licensee
* solely for documentation and educational purposes. Reproduction,
* publication, or distribution in any form to any party other than
* the licensee is strictly prohibited!!
*
*****
*
* Module Header
*
Type set SYSTM+OBJCT
Revs set REENT+1
mod OS9End,OS9Nam,Type,Revs,COLD,0
OS9Nam fcs /OS9p1/
fcb 12 Edition number
*************************
* Edition History
*
* Ed. 8 - Beginning of history (V1.1 final version)
*
* Ed. 9 - First V1.2 version minor cosmetic changes
* Ed byte immediately following module name
* Version ID all same length WGP 11/25/82
*
* Ed. 10 - SetSVC now checks service no. for validity
* SetPRC checks for zero data area size WGP 12/20/82
*
* Ed. 11 - Parse name system call made compatible w/LII
* ??? ??/??/82
*
* Ed. 12 - CNAM change made at RETCS1 to save one byte of code
* S09 cpu datinit changed to save one byte of code
* These were to allow S09 version to fit in $800
* WGP 01/10/83
*********
* Version Id
*
ifeq CPUType-EXORSR
fcc / Exor / Version name
RamLimit set $E000
endc
ifeq CPUType-MM19
fcc / MM19 / Version name
RamLimit set $E800
endc
ifeq CPUType-GIMIX
fcc / Gmx / Version name
RamLimit set $E000
endc
ifeq CPUType-SWTC
fcc /Swtpc / Version name
RamLimit set $E000
endc
ifeq CPUType-S09
fcc /SwtMem/ Version name
RamLimit set $E000
endc
ifeq CPUType-SSB
fcc /Smoke / Version name
RamLimit set $E800
endc
ifeq CPUType-PERCOM
fcc /Percom/ Version name
RamLimit set $E800
endc
ifeq CPUType-CMS9609
fcc / CMS / Version name
RamLimit set $E000
endc
ifeq CPUType-CMS9619
fcc / CMS / Version name
RamLimit set $F000
endc
ifeq CPUType-HELIX
fcc /Helix /
RamLimit set $E000
endc
ifeq CPUType-ELEKTRA
fcc /Elekt / AAA chicago cpu
RamLimit set $E000
endc
ifeq CPUType-DIGALOG
fcc /Diglog/ Digalog cpu
RamLimit set $E000
endc
ifeq CPUType-SAT96
fcc /SAT96 / Sat-96 board
RamLimit set $E600
endc
CNFSTR fcs /Init/ Configuration module name
OS9STR fcs /OS9p2/ Kernal, part 2 name
page
*****
*
* System Service Routine Table
*
SVCTBL equ *
fcb F$LINK
fdb LINK-*-2
fcb F$FORK
fdb FORK-*-2
fcb F$Chain
fdb USRCHN-*-2
fcb F$Chain+$80
fdb SYSCHN-*-2
fcb F$PrsNam
fdb PNAM-*-2
fcb F$CmpNam
fdb CNAM-*-2
fcb F$SchBit
fdb SBIT-*-2
fcb F$AllBit
fdb ABIT-*-2
fcb F$DelBit
fdb DBIT-*-2
fcb F$CRC
fdb CRCGen-*-2
fcb F$SRqMem+$80
fdb SRQMEM-*-2
fcb F$SRtMem+$80
fdb SRTMEM-*-2
fcb F$AProc+$80
fdb APRC-*-2
fcb F$NProc+$80
fdb NXTPRC-*-2
fcb F$VModul+$80
fdb VMOD-*-2
fcb F$SSVC
fdb SSVC-*-2
fcb $80
ttl COLD Start
page
*
* Clear System Memory, Skipping First 32 Bytes
*
LORAM set $20
HIRAM set $300
RAMMSK set $F0 Initial bit map mask
COLD ldx #LORAM Set ptr
ldy #HIRAM-LORAM Set byte count
clra CLEAR D
clrb
COLD05 std ,X++ Clear two bytes
leay -2,Y Count down
bne COLD05
inca ONE Page for direct page
std D.FMBM Set free memory bit map
addb #BMAPSZ Add map size
std D.FMBM+2
addb #2 Reserve i/o routine entry
std D.SysDis Set system service request table
addb #SVCTSZ+2 Add table size
std D.UsrDis Set user service request table
clrb SET Module directory address
inca
std D.ModDir Set module directory address
stx D.ModDir+2 Set end
leas $100,X get initial stack
*
* Find End Of Ram
*
COLD10 leay 0,X Copy current ptr
ldd 0,Y Get current value
ldx #$00FF Get bit pattern
stx 0,Y Store it
cmpx 0,Y Is it there?
bne COLD15 If not, end of ram
ldx #$FF00 Try a different pattern
stx 0,Y Store it
cmpx 0,Y Did it take?
bne COLD15 If not, eor
std 0,Y Replace current value
leax 256,Y Try next page
cmpx #RamLimit
bcs COLD10 Branch if more
leay 0,X Copy end-of-ram ptr
COLD15 leax 0,Y Copy eor ptr
ifeq CPUType-EXORSR
*** >>> Patch For Exorciser Environment <<< ***
*
leax NMI,pcr
stx $FFFC
leax SWIRQ,pcr
stx $FFFA
leax IRQ,PCR get irq vector
stx $FFF8 set hardware vector
leax SWI2RQ,PCR get swi2 vector
stx $FFF4 set hardware vector
leax SWI3RQ,PCR get swi3 vector
stx $FFF2 set hardware vector
EndRAM equ $A50 This must be greater than the size
* of ctlrmod+bootmod+os9p2+*
leax -EndRAM,PCR get artificial end-of-ram
stx D.BtLo
stx D.BtHi
*
*** >>> End Of Exorciser Patch <<< ***
endc
stx D.MLIM Set memory limit
*
* Search Memory For Modules, Build Module Directory
*
COLD20 lbsr VALMOD Look for valid module
bcs COLD30 Branch if bad module
ldd M$SIZE,X Get module size
leax D,X Skip module
bra COLD35
COLD30 cmpb #E$KwnMod Is it known module
beq COLD40 Branch on first duplicate
leax 1,X Try next location
COLD35 bne COLD20
COLD40 leay SYSVEC,PCR Get interrupt entries
leax ROMEnd,PCR get vector offset
pshs X save it
ldx #D.SWI3 Get vector address
COLD45 ldd ,Y++ get vector
addd 0,S add offset
std ,X++ init dp vector
cmpx #D.NMI end of dp vectors?
bls COLD45 branch if not
leas 2,S return scratch
leax USRIRQ,PCR Get user interrupt routine
stx D.UsrIRQ
leax USRREQ,PCR Get user service routine
stx D.UsrSVC
leax SYSIRQ,PCR Get system interrupt routine
stx D.SysIRQ
stx D.SvcIRQ Set interrupts to system state
leax SYSREQ,PCR Get system service routine
stx D.SysSVC
stx D.SWI2 Set service to system state
leax IOPOLL,PCR Set irq polling routine
stx D.POLL
*
* Initialize Service Routine Dispatch Table
*
leay SVCTBL,PCR Get ptr to service routine table
lbsr SETSVC Set service table entries
lda #SYSTM Get system type module
leax CNFSTR,PCR Get initial module name ptr
OS9 F$LINK Link to configuration module
lbcs COLD Retry if error
stu D.Init Save ptr
ldd MAXMEM+1,U Get memory limit
clrb ROUND Down
cmpd D.MLIM Does ram go that high?
bcc COLD50 Branch if not
std D.MLIM Set given memory limit
COLD50 ldx D.FMBM Get bit map ptr
ldb #RAMMSK Get initial mask
stb 0,X
clra GET Beginning page number
ldb D.MLIM
negb GET Page count
tfr D,Y
negb GET Page number
lbsr ALOCAT
leax OS9STR,PCR
lda #SYSTM+OBJCT Get object type
OS9 F$LINK
lbcs COLD
jmp 0,Y Let os9 part two finish
ttl INTERRUPT Service handlers
page
*****
*
* Swi3 Interrupt Routine
*
SWI3RQ jmp [D.SWI3] Go thru page zero vector
*****
*
* Swi2 Interrupt Routine
*
SWI2RQ jmp [D.SWI2] Go thru page zero vector
*****
*
* Firq Interrupt Handler
*
FIRQ jmp [D.FIRQ] Go thru page zero vector
*****
*
* Irq Interrupt Routine
*
IRQ jmp [D.IRQ] Go thru page zero vector
*****
*
* Swi Interrupt Routine
*
SWIRQ jmp [D.SWI] Go thru page zero vector
*****
*
* Nmi Interrupt Routine
*
NMI jmp [D.NMI] Go thru page zero vector
page
*****
*
* Swi3 Handler
*
SWI3HN pshs B,X,PC Save registers
ldb #P$SWI3 Use swi3 vector
bra SWIH10
*****
*
* Swi2 Handler
*
SWI2HN pshs B,X,PC Save registers
ldb #P$SWI2 Use swi2 vector
bra SWIH10
*****
*
* Firq Handler
*
FIRQHN rti
*****
*
* Irq Handler
*
IRQHN jmp [D.SvcIRQ] Go to interrupt service
*****
*
* Swi Handler
*
SWIHN pshs B,X,PC Save registers
ldb #P$SWI Use swi vector
SWIH10 ldx >D.PROC Get process descriptor ptr
ldx B,X Get entry point address
stx 3,S Save it
puls B,X,PC Restore registers & jump
*****
*
* Nmi Handler
*
NMIHN equ FIRQHN
page
*****
*
* Interrupt Service Routine Usrirq
*
* Handles Irq While In User State
*
USRIRQ leay <USRI10,PCR Get post-switch routine
SWITCH clra SET Direct page
tfr A,DP
ldx D.PROC Get process
ldd D.SysSVC Get system request routine
std D.SWI2
ldd D.SysIRQ Get system irq routine
std D.SvcIRQ
leau 0,S Copy user stack ptr
stu P$SP,X
lda P$State,X Set system state
ora #SysState
sta P$State,X
jmp 0,Y Go to post-switch routine
USRI10 jsr [D.POLL] Call irq polling routine
bcc USRI20 branch if interrupt identified
ldb R$CC,S get condition codes
orb #IRQMask set interrupt mask
stb R$CC,S update condition codes
USRI20 lbra USRRET
*****
*
* Interrupt Routine Sysirq
*
* Handles Irq While In System State
*
SYSIRQ clra clear direct page
tfr A,DP
jsr [D.POLL] Call irq polling
bcc SYSI10 branch if interrupt identified
ldb R$CC,S get condition codes
orb #IRQMask set interrupt mask
stb R$CC,S update condition codes
SYSI10 rti
*****
*
* Interrupt Polling Default
*
IOPOLL comb set carry
rts
page
*****
*
* Clock Tick Routine
*
* Wake Sleeping Processes
*
TICK ldx D.SProcQ Get sleeping queue ptr
beq SLICE Branch if none
lda P$State,X Get process status
bita #TimSleep Is it in timed sleep?
beq SLICE Branch if not
ldu P$SP,X Get stack ptr
ldd R$X,U Get tick count
subd #1 Count down
std R$X,U Update tick count
bne SLICE Branch if ticks left
TICK10 ldu P$Queue,X Get next process ptr
bsr ACTPRC Activate process
leax 0,U Copy process ptr
beq TICK20 Branch if end of queue
lda P$State,X Get process status
bita #TimSleep In timed sleep?
beq TICK20 Branch if not
ldu P$SP,X Get stack ptr
ldd R$X,U Get tick count
beq TICK10 Branch if time
TICK20 stx D.SProcQ Update sleep queue ptr
*
* Update Time Slice counter
*
SLICE dec D.Slice Count tick
bne SLIC10 Branch if slice not over
lda D.TSlice Get ticks/time-slice
sta D.Slice Reset slice tick count
*
* If Process not in System State, Give up Time-Slice
*
ldx D.PROC Get current process ptr
beq SLIC10 Branch if none
lda P$State,X Get status
ora #TIMOUT Set time-out flag
sta P$State,X Update process status
bpl SLIC20 Branch if user state
SLIC10 rti
SLIC20 leay USRRET,PCR Set transfer ptr
bra SWITCH Switch to system state
page
*****
*
* Subroutine Actprc
*
* Put Process In Active Process Queue
*
APRC ldx R$X,U
ACTPRC pshs Y,U Save registers
*
* Age Active Processes
*
ldu #D.AProcQ-P$Queue Fake process ptr
bra ACTP20
ACTP10 ldb P$AGE,U Get age
incb
beq ACTP20 Branch if highest
stb P$AGE,U
ACTP20 ldu P$Queue,U Get next process
bne ACTP10 Branch if more
*
* Sort New Process Into Queue
*
ldu #D.AProcQ-P$Queue Fake process ptr
lda P$Prior,X Get process priority/age
sta P$AGE,X Set age to priority
orcc #IRQMask+FIRQMask Set interrupt masks
ACTP30 leay 0,U Copy ptr to this process
ldu P$Queue,U Get ptr to next process
beq ACTP40 Branch if no more
cmpa P$AGE,U Who has bigger priority?
bls ACTP30 Branch if queue process
ACTP40 stu P$Queue,X Insert into list
stx P$Queue,Y
clrb CLEAR Carry
puls Y,U,PC
page
*****
*
* Subroutine Usrreq
*
* User Service Request Handling Routine
*
USRREQ leay <USRR10,PCR Get post-switch routine
orcc #IRQMask+FIRQMask Set interrupt masks
lbra SWITCH Switch to system state
USRR10 andcc #$FF-IRQMask-FIRQMask Clear interrupt masks
ldy D.UsrDis Get user service routine table
bsr DISPCH Go do request
USRRET ldx D.PROC Get process ptr
beq NXTPRC Branch if none
orcc #IRQMask+FIRQMask Set interrupt masks
ldb P$State,X Clear system state
andb #$FF-SysState
stb P$State,X Update status
bitb #TIMOUT Is time-slice over?
beq CURPRC Branch if not
andb #$FF-TIMOUT Clear time-out flag
stb P$State,X Update status
USRR20 bsr ACTPRC Put in active queue
bra NXTPRC Start next process
*****
*
* Subroutine Sysreq
*
SYSREQ clra clear direct page
tfr A,DP
leau 0,S Copy stack ptr
ldy D.SysDis Get system service routine table
bsr DISPCH Call service routine
rti
page
*****
*
* Subroutine Dispch
*
* Service Routine Dispatch
*
DISPCH pshs U Save register ptr
*
* Get Service Request Code
*
ldx R$PC,U Get program counter
ldb ,X+ Get service code
stx R$PC,U Update program counter
*
* Get Service Routine Address
*
aslb SHIFT For two byte table entries
bcc DISP10 Branch if not i/o
rorb RE-ADJUST Byte
ldx -2,Y Get i/o routine
bra DISP20
DISP10 cmpb #SVCTSZ Code in range?
bcc BADSVC
ldx B,Y Get routine address
beq BADSVC Branch if none
DISP20 jsr 0,X Call routine
*
* Return Condition Codes To Caller
*
DISP25 puls U Retrieve register ptr
tfr CC,A Copy condition codes
bcc DISP30 Branch if no error
stb R$B,U Return error code
DISP30 ldb R$CC,U Get condition codes
andb #$F0 Clear n, z, v, c
stb R$CC,U Save it
anda #$0F Clear e, f, h, i
ora R$CC,U Return conditions
sta R$CC,U
rts
BADSVC comb SET Carry
ldb #E$UnkSvc Unknown service code
bra DISP25
page
*****
*
* Routine Nxtprc
*
* Starts next Process in Active Queue
* If no Active Processes, Wait for one
*
NXTOUT ldb P$State,X Get process status
orb #SysState Set system state
stb P$State,X Update status
ldb P$Signal,X Return fatal signal
andcc #$FF-IRQMask-FIRQMask Clear interrupt masks
OS9 F$EXIT Terminate process
NXTPRC clra
clrb
std D.PROC Clear current process
bra NXTP06
*
* Loop until there is a Process in the Active Queue
*
NXTP04 cwai #$FF-IRQMask-FIRQMask Clear interrupt masks & wait
NXTP06 orcc #IRQMask+FIRQMask Set interrupt masks
ldx D.AProcQ Get first process in active queue
beq NXTP04 Branch if none
*
* Remove Process from Active Queue
*
ldd P$Queue,X Get next process ptr
std D.AProcQ Remove first from active queue
stx D.PROC Set current process
lds P$SP,X Get stack ptr
*
* Check Process Status, check for Signal pending
*
CURPRC ldb P$State,X Is process in system state?
bmi NXTP30 Branch if so
bitb #CONDEM Is process condemmed?
bne NXTOUT Branch if so
ldb P$Signal,X Is a signal waiting?
beq NXTP20 Branch if not
decb Wake-up Signal?
beq NXTP10 Branch if so
*
* Signal is pending; If an Intercept has been set
* Build an Interrupt Stack for User
*
ldu P$SigVec,X Get intercept vector
beq NXTOUT Branch if none
ldy P$SigDat,X Get intercept data address
ldd R$Y,S Get user y register
pshs D,Y,U Build partial stack
ldu R$X+6,S Get user x register
lda P$Signal,X Get signal
ldb R$DP+6,S Get direct page
tfr D,Y Copy registers
ldd R$CC+6,S Get registers
pshs D,Y,U Complete stack
clrb
NXTP10 stb P$Signal,X Clear signal
*
* Switch to User State
*
NXTP20 ldd P$SWI2,X Get user service request
std D.SWI2
ldd D.UsrIRQ Get user irq
std D.SvcIRQ
NXTP30 rti Start next process
page
*****
*
* Subroutine Link
*
* Search Module Directory & Return Module Address
*
* Input: U = Register Package
* Output: Cc = Carry Set If Not Found
* Local: None
* Global: D.ModDir
*
LINK pshs U Save register package
ldd R$D,U Get revision, type
ldx R$X,U Get name ptr
lbsr FMODUL Search directory
bcc LINK10
ldb #E$MNF Err: link non-existing module
bra LINKXit
LINK10 ldy 0,U Get module address
ldb M$REVS,Y get attributes/revision
bitb #REENT is this sharable
bne LINK20 branch if so
tst 2,U is it in use?
beq LINK20 branch if not
comb set carry
ldb #E$ModBsy err: module busy
bra LINKXit
LINK20 inc 2,U count use
ldu 0,S Get register ptr
stx R$X,U
sty R$U,U
ldd M$TYPE,Y Get type/lang & attr/revs
std R$D,U
ldd M$EXEC,Y Get execution offset
leax D,Y Make entry ptr
stx R$Y,U Return it to user
LINKXit puls U,PC
*****
*
* Subroutine Valmod
*
* Validate Module
*
VMOD pshs U Save register ptr
ldx R$X,U Get new module ptr
bsr VALMOD Validate module
puls Y Retrieve register ptr
stu R$U,Y Return directory entry
VMOD10 rts
VALMOD bsr IDCHK Check sync & chksum
bcs VALM40 Branch if not module
lda M$TYPE,X Get module type
pshs A,X Save module type & ptr
ldd M$NAME,X Get name ptr
leax D,X
puls A Retrieve type
lbsr FMODUL Search directory
puls X Retrieve module ptr
bcs VALM10 Branch if not found
ldb #E$KwnMod Get known module error code
cmpx 0,U Is it same module?
beq BADVAL Branch if so
lda M$REVS,X Get new revision level
anda #Revsmask
pshs A Save it
ldy 0,U Get old module ptr
lda M$REVS,Y Get old revision level
anda #Revsmask
cmpa ,S+ Which is higher?
bcc BADVAL Branch if old
pshs X,Y Save registers
ldb 2,U module in use?
bne VALM15 branch if so
ldx 0,U Get module ptr
cmpx D.BTLO Is it rom/system module?
bcc VALM15 Branch if so
ldd M$SIZE,X
addd #$FF
tfr A,B
clra
tfr D,Y
ldb 0,U
ldx D.FMBM
OS9 F$DelBit Clear bit map
clr 2,U
VALM15 puls X,Y
VALM20 stx 0,U Install new module
VALM30 clrb CLEAR Carry
VALM40 rts
VALM10 leay 0,U Free directory entry?
bne VALM20 Branch if so
ldb #E$DirFul Err: directory full
BADVAL coma SET Carry
rts
IDCHK ldd 0,X Get first two bytes
cmpd #M$ID12 Check them
bne IDCH10 Branch if not module
leay 8,X Get header end ptr
bsr PARITY Check header parity
bcc IDCH30 Branch if good
IDCH10 comb SET Carry
ldb #E$BMID Err: illegal id block
IDCH20 rts
IDCH30 pshs X Save module ptr
ldy M$SIZE,X Get module size
bsr CRCCHK Check crc code
puls X,PC
*****
*
* Subroutine Parity
*
* Check Vertical Parity
*
PARITY pshs X,Y Save registers
clra
PARI10 eora ,X+ Add parity of next byte
cmpx 2,S Done?
bls PARI10 Branch if not
cmpa #$FF Parity good?
puls X,Y,PC
*****
*
* Subroutine Crcchk
*
* Check Module Crc
*
CRCCHK ldd #$FFFF
pshs D Init crc register
pshs D
leau 1,S Get crc register ptr
CRCC10 lda ,X+ Get next byte
bsr CRCCAL Calculate crc
leay -1,Y count byte
bne CRCC10 branch if more
clr -1,U Clear msb-1
lda 0,U Get crc
cmpa #$80 Is it good?
bne CRCC20 Branch if not
ldd 1,U Get crc
cmpd #$0FE3 Is it good?
beq CRCC30 Branch if so
CRCC20 comb SET Carry
ldb #E$BMCRC Err: bad crc
CRCC30 puls X,Y,PC
*****
*
* Subroutine Crcgen
*
* Generate Crc
*
CRCGen ldx R$X,U get data ptr
ldy R$Y,U get byte count
beq CRCGen20 branch if none
ldu R$U,U get crc ptr
CRCGen10 lda ,X+ get next data byte
bsr CRCCAL update crc
leay -1,Y count byte
bne CRCGen10 branch if more
CRCGen20 clrb clear carry
rts
*****
*
* Subroutine Crccal
*
* Calculate Next Crc Value
*
CRCCAL eora 0,U Add crc msb
pshs A save it
ldd 1,U Get crc mid & low
std 0,U Shift to high & mid
clra
ldb 0,S Get old msb
lslb SHIFT D
rola
eora 1,U Add old lsb
std 1,U Set crc mid & low
clrb
lda 0,S Get old msb
lsra SHIFT D
rorb
lsra SHIFT D
rorb
eora 1,U Add new mid
eorb 2,U Add new low
std 1,U Set crc mid & low
lda 0,S Get old msb
lsla
eora 0,S Add old msb
sta 0,S
lsla
lsla
eora 0,S Add altered msb
sta 0,S
lsla
lsla
lsla
lsla
eora ,S+ Add altered msb
bpl CRCC99
ldd #$8021
eora 0,U
sta 0,U
eorb 2,U
stb 2,U
CRCC99 rts
*****
*
* Subroutine Fmodul
*
* Search Directory For Module
*
* Input: A = Type
* X = Name String Ptr
* Output: U = Directory Entry Address
* Cc = Carry Set If Not Found
* Local: None
* Global: D.ModDir
FMODUL ldu #0 Return zero if not found
tfr A,B Copy type
anda #TypeMask Get desired type
andb #LangMask Get desired language
pshs D,X,Y,U Save registers
bsr SKIPSP Skip leading spaces
cmpa #'/ Is there leading '/'
beq FMOD35
lbsr PRSNAM Parse name
bcs FMOD40 Branch if bad name
ldu D.ModDir Get module directory ptr
FMOD10 pshs B,Y,U Save count, end-of-name, & directory
ldu 0,U Get module ptr
beq FMOD20 Branch if not used
ldd M$NAME,U Get name offset
leay D,U Get name ptr
ldb 0,S Get character count
lbsr CHKNAM Compare names
bcs FMOD30 Branch if different
lda 5,S Get desired type
beq FMOD14 Branch if any
eora M$TYPE,U Get type difference
anda #TypeMask
bne FMOD30 Branch if different
FMOD14 lda 6,S Get desired language
beq FMOD16 Branch if any
eora M$TYPE,U Get language difference
anda #LangMask
bne FMOD30 Branch if different
FMOD16 puls B,X,U Retrieve registers
stu 6,S Return directory entry
bsr SKIPSP Skip spaces
stx 2,S Return updated ptr
clra CLEAR Carry
bra FMOD40
FMOD20 ldd 11,S Free entry found?
bne FMOD30 Branch if so
ldd 3,S Return this entry
std 11,S
FMOD30 puls B,Y,U Retrieve registers
leau 4,U Move to next entry
cmpu D.ModDir+2 End of directory?
bcs FMOD10 Branch if not
FMOD35 comb SET Carry
FMOD40 puls D,X,Y,U,PC
SKIPSP lda #' get space
SKIP10 cmpa ,X+ Is there a space
beq SKIP10
lda ,-X Get not space
rts
page
*****
*
* Subroutine Fork
*
* Creates New Child Process
*
FORK ldx D.PrcDBT Get process block ptr
OS9 F$ALL64 Get new process descriptor
bcs PRCFUL Branch if none left
ldx D.PROC Get parent process ptr
pshs X Save parent process ptr
ldd P$USER,X Copy user index
std P$USER,Y
lda P$Prior,X Copy priority
clrb CLEAR Age
std P$Prior,Y
ldb #SysState Get system state flag
stb P$State,Y Set infant state
sty D.PROC Make child current process
*
* Pass I/O Defaults & Paths 0, 1, And 2
* From Parent To Child
*
leax P$DIO,X Get parent path ptr
leay P$DIO,Y Get child path ptr
ldb #DefIOSiz Get byte count
FORK10 lda ,X+ Get parent byte
sta ,Y+ Pass to child
decb COUNT Down
bne FORK10 Branch if more
ldb #3 Get number of paths
FORK20 lda ,X+ Get path number
OS9 I$DUP Duplicate path
bcc FORK25
clra CLEAR Path number
FORK25 sta ,Y+ Pass path to child
decb COUNT Down
bne FORK20 Branch if more
bsr SETPRC Set up process
bcs FORK40 Branch if error
puls Y Retrieve parent process ptr
sty D.PROC Make parent current process
lda P$ID,X Get child id
sta R$A,U Return to parent
ldb P$CID,Y Get youngest child id
sta P$CID,Y Set new child
lda P$ID,Y Get parent id
std P$PID,X Set parent & sibling ids
ldb P$State,X Get child state
andb #$FF-SysState Clear system state
stb P$State,X Update child state
OS9 F$AProc Activate child process
rts
FORK40 pshs B Save error code
OS9 F$EXIT Terminate child
comb SET Carry
puls B,X Retrieve error code & parent process ptr
stx D.PROC Make parent current process
rts
PRCFUL comb SET Carry
ldb #E$PrcFul Err: process table full
rts
*****
*
* Subroutine Usrchn
*
* User Chain Routine
*
USRCHN bsr CHAIN Do chain
bcs BADCHN Branch if error
orcc #IRQMask+FIRQMask Set interrupt masks
ldb P$State,X Clear system state
andb #$FF-SysState
stb P$State,X
USRC10 OS9 F$AProc Put process in active queue
OS9 F$NProc Start next process
*****
*
* Subroutine Syschn
*
* System Chain Routine
*
SYSCHN bsr CHAIN Do chain
bcc USRC10 Branch if no error
BADCHN pshs B Save error code
stb P$Signal,X Set error status
ldb P$State,X Get process status
orb #CONDEM Condem process
stb P$State,X
ldb #$FF Set high priority
stb P$Prior,X
comb
puls B,PC
*****
*
* Subroutine Chain
*
* Execute Overlay
*
CHAIN pshs U Save register ptr
ldx D.PROC Get process ptr
ldu P$PModul,X Get primary module ptr
OS9 F$Unlink
ldu 0,S Retrieve register ptr
bsr SETPRC Set up process
puls U,PC Clean stack
page
*****
*
* Subroutine Setprc
*
* Set Up Process Descriptor
*
SETPRC ldx D.PROC Get process ptr
pshs X,U Save process & register ptr
ldd D.UsrSVC Get user service request
std P$SWI,X Reset swi vector
std P$SWI2,X Reset swi2 vector
std P$SWI3,X Reset swi3 vector
clra
clrb
sta P$Signal,X Clear signal
std P$SigVec,X Clear signal vector ptr
lda R$A,U Get type
ldx R$X,U Get name ptr
OS9 F$LINK
bcc SETP10 Branch if found
OS9 F$LOAD Try loading it
bcs SETP50 Branch if not loadable
SETP10 ldy D.PROC Get process ptr
stu P$PModul,Y Save primary module ptr
cmpa #PRGRM+OBJCT is it program object?
beq SETP15 branch if so
cmpa #SYSTM+OBJCT is it system object?
beq SETP15 branch if so
comb set carry
ldb #E$NEMod err: non-executable module
bra SETP50
SETP15 leay 0,U Copy module ptr
ldu 2,S Get register ptr
stx R$X,U Return updated ptr
lda R$B,U Get memory over-ride
clrb
cmpd M$Mem,Y Is it big enough?
bcc SETP20
ldd M$Mem,Y Get memory required
SETP20 addd #0 Req for zero data mem?
bne SETP25 bra if not
comb
ldb #E$DelSP Error process must have at least one page mem
bra SETP50
SETP25 OS9 F$MEM Mem to correct size
bcs SETP50 Branch if no memory
subd #R$SIZE Deduct stack room
subd R$Y,U Deduct parameter count
bcs BADPAR Branch if not available
ldx R$U,U Get parameter beginning
ldd R$Y,U Get parameter count
pshs D Save parameter count
beq SETP40 Branch if no parameters
leax D,X Get parameter end ptr
SETP30 lda ,-X Get parameter byte
sta ,-Y Pass it
cmpx R$U,U Done?
bhi SETP30 Branch if not
SETP40 ldx D.PROC Get process ptr
sty R$X-R$SIZE,Y
leay -R$SIZE,Y
sty P$SP,X Set stack ptr
lda P$ADDR,X Set beginning address
clrb
std R$U,Y
sta R$DP,Y Get direct page ptr
adda P$PagCnt,X Get end prt
std R$Y,Y
puls D Retrieve parameter byte count
std R$D,Y Pass to process
ldb #ENTIRE Set cc entire bit
stb R$CC,Y
ldu P$PModul,X Get module ptr
ldd M$EXEC,U
leau D,U Get module entry
stu R$PC,Y Set new program counter
clrb CLEAR Carry
BADPAR ldb #E$IForkP Err: illegal fork parameters
SETP50 puls X,U,PC
page
*****
*
* Subroutine Srqmem
*
* System Memory Request
*
SRQMEM ldd R$D,U Get byte count
addd #$FF Round up to page
clrb
std R$D,U Return size to user
ldx D.FMBM+2 Get end of bit map
ldd #$1FF Set mask & bit number
pshs D Save them
bra SRQM20
SRQM10 dec 1,S Count page number down
ldb 1,S Save it
SRQM15 lsl 0,S Shift mask
bcc SRQM25 Branch if no byte change
rol 0,S Move mask to low bit
SRQM20 leax -1,X Move to next map byte
cmpx D.FMBM End of map?
bcs SRQM30
SRQM25 lda 0,X Get map byte
anda 0,S Get map bit
bne SRQM10 Branch if allocated
dec 1,S Count page number down
subb 1,S Get number of free pages
cmpb R$A,U Compare to requested number
rora SAVE Carry
addb 1,S Restore high page bound
rola RESTORE Carry
bcs SRQM15 Branch if not enough
ldb 1,S Get page number
clra
incb
SRQM30 leas 2,S Return scratch
bcs MEMFUL Branch if not enough
ldx D.FMBM Get free memory ptr
tfr D,Y Copy page number
ldb R$A,U Get page count
clra
exg D,Y Switch page count & number
bsr ALOCAT Allocate memory
exg A,B Convert page number to address
std R$U,U Return ptr to memory
SRQMXX clra CLEAR Carry
rts
MEMFUL comb SET Carry
ldb #E$MemFul Get error code
rts
page
*****
*
* Subroutine Srtmem
*
* System Memory Return
*
SRTMEM ldd R$D,U Get byte count
addd #$FF Round up to page
tfr A,B Make page count
clra
tfr D,Y Copy page count
ldd R$U,U Get address
beq SRQMXX Branch if returning nothing
tstb IS Address good?
beq SRTM10 Branch if so
BADPAG comb SET Carry
ldb #E$BPAddr
rts
SRTM10 exg A,B Convert address to page number
ldx D.FMBM Get free memory ptr
bra DEALOC Deallocate memory
page
*****
*
* Subroutine Alocat
*
* Set Bits In Bit Map
*
* Input: D = Beginning Page Number
* X = Bit Map Address
* Y = Page Count
* Output: None
* Local: None
* Global: None
*
ABIT ldd R$D,U Get beginning bit number
leau R$X,U
pulu X,Y Get bit map addr & bit count
ALOCAT pshs D,X,Y Save registers
bsr FNDBIT Adjust map ptr & get bit mask
tsta TEST Mask
pshs A Save mask
bmi ALOC15 Branch if first bit of byte
lda 0,X Get map byte
ALOC10 ora 0,S Set bit
leay -1,Y Decrement page count
beq ALOC35 Branch if done
lsr 0,S Shift mask
bcc ALOC10 Branch if more in this byte
sta ,X+ Restore byte
ALOC15 tfr Y,D Copy page count
sta 0,S Save msb
lda #$FF Get eight pages worth
bra ALOC25
ALOC20 sta ,X+ Get eight pages
ALOC25 subb #8 Are there eight left?
bcc ALOC20 Branch if so
dec 0,S Any msb left?
bpl ALOC20 Branch if so
ALOC30 asla MAKE Final mask
incb MOVE Count to zero
bne ALOC30 Branch if not done
ora 0,X Set final bits
ALOC35 sta 0,X Set byte
clra CLEAR Carry
leas 1,S Return scratch
puls D,X,Y,PC
page
*****
*
* Subroutine Fndbit
*
* Make Page Number Into Ptr & Mask
*
* Input: D = Page Number
* X = Map Beginning Address
* Output: A = Bit Mask
* B = 0
* X = Byte Address
* Local: None
* Global: None
*
FNDBIT pshs B Save lsb
lsra PAGE/2
rorb
lsra PAGE/4
rorb
lsra PAGE/8
rorb
leax D,X Get byte address
puls B Get lsb
lda #$80 Get mask
andb #7 Page modulo 8
beq FNDB20 Branch if done
FNDB10 lsra SHIFT Mask
decb
bne FNDB10
FNDB20 rts
page
*****
*
* Subroutine Dealoc
*
* Deallocates Space In Bit Map
*
* Input: D = Beginning Page Number
* X = Bit Map Address
* Y = Page Count
* Output: None
* Local: None
* Global: None
*
DBIT ldd R$D,U Get beginning bit number
leau R$X,U
pulu X,Y Get bit map addr & bit count
DEALOC pshs D,X,Y Save registers
bsr FNDBIT Adjust map ptr & get bit mask
coma REVERSE Mask
pshs A save it
bpl DEAL10 branch if first bit of byte
lda 0,X get map byte
DEAL05 anda 0,S Clear bit
leay -1,Y Decrement page count
beq DEAL30 Branch if done
asr 0,S Shift mask
bcs DEAL05 Branch if more
sta ,X+ Store map byte
DEAL10 tfr Y,D Copy page count
bra DEAL20
DEAL15 clr ,X+ Clear map byte
DEAL20 subd #8 Are there eight left?
bhi DEAL15 Branch if so
beq DEAL30 Branch if done
DEAL25 asla MAKE Final mask
incb
bne DEAL25
coma REVERSE Mask
anda 0,X Clear map bits
DEAL30 sta 0,X Store map byte
clr ,S+ Clear carry & return scratch
puls D,X,Y,PC
page
*****
*
* Subroutine Floblk
*
* Find Free Block Searching Up
*
* Same As Fhiblk
*
SBIT pshs U Save register ptr
ldd R$D,U Get beginning bit number
ldx R$X,U Get bit map ptr
ldy R$Y,U Get bit count
ldu R$U,U Get map end addr
bsr FLOBLK Search bit map
puls U Retrieve register ptr
std R$D,U Return bit number
sty R$Y,U return bits found
rts
FLOBLK pshs D,X,Y,U Save registers
pshs D,Y Copy beginning page number & size
clr 8,S Clear size found
clr 9,S
tfr D,Y Copy beginning page number
bsr FNDBIT Adjust map ptr & get bit mask
pshs A Save mask
bra FLOB20
FLOB10 leay 1,Y Move beginning bit number
sty 5,S Save beginning block number
FLOB15 lsr 0,S Shift mask
bcc FLOB25 Branch if mask okay
ror 0,S Shift mask around end
leax 1,X Move map ptr
FLOB20 cmpx 11,S End of map?
bcc FLOB30 Branch if so
FLOB25 lda 0,X Get map byte
anda 0,S Mask bit
bne FLOB10 Branch if in use
leay 1,Y Move page number
tfr Y,D Copy page number
subd 5,S Subtract beginning page number
cmpd 3,S Block big enough?
bcc FLOB35 Branch if so
cmpd 9,S Biggest so far?
bls FLOB15 Branch if not
std 9,S Save size
ldd 5,S Copy beginning page number
std 1,S
bra FLOB15
FLOB30 ldd 1,S Get beginning page number of largest
std 5,S Return it
coma SET Carry
bra FLOB40
FLOB35 std 9,S Return size
FLOB40 leas 5,S Return scratch
puls D,X,Y,U,PC
page
***************
* Parse Path Name
*
* Passed: (X)=Pathname Ptr
* Returns: (X)=Skipped Past Prefix '/'
* (Y)=Ptr To 1St Delim In Pathname
* (A)=Delimiter Character
* (B)=Number Of Characters Found <=255
* Cc=Set If No Characters Found
* Unaffects: U
*
PNAM ldx R$X,U Get string ptr
bsr PRSNAM Call parse name
std R$D,U Return byte & size
bcs PNam.x branch if error
stx R$X,U Return updated string ptr
PNam.x sty R$Y,U Return name end ptr
rts
PRSNAM lda 0,X Get first char
cmpa #'/ Slash?
bne PRSNA1 ..no
leax 1,X ..yes; skip it
PRSNA1 leay 0,X
clrb
lda ,Y+
anda #$7F
bsr ALPHA 1st character must be alphabetic
bcs PRSNA4 Branch if bad name
PRSNA2 incb INCREMENT Character count
lda -1,Y End of name (high bit set)?
bmi PRSNA3 ..yes; quit
lda ,Y+ Get next character
anda #$7F Strip high order bit
bsr ALFNUM Alphanumeric?
bcc PRSNA2 ..yes; count it
lda ,-Y Backup to unknown
PRSNA3 andcc #^CARRY clear carry
rts RETURN (carry clear)
PRSNA4 cmpa #', Comma (skip if so)?
bne PRSNA6 ..no
PRSNA5 lda ,Y+ Get next character
PRSNA6 cmpa #$20 Space?
beq PRSNA5 ..yes; skip
lda ,-Y Backup to non-delim char
comb (NAME Not found)
ldb #E$BNam
rts RETURN Carry set
* Check For Alphanumeric Character
*
* Passed: (A)=Char
* Returns: Cc=Set If Not Alphanumeric
* Destroys None
*
ALFNUM cmpa #'. period?
beq RETCC branch if so
cmpa #'0 Below zero?
blo RETCS ..yes; return carry set
cmpa #'9 Numeric?
bls RETCC ..yes
cmpa #'_ Underscore?
beq RETCC ..yes
ALPHA cmpa #'A
blo RETCS
cmpa #'Z Upper case alphabetic?
bls RETCC ..yes
cmpa #$61 Below lower case a?
blo RETCS ..yes
cmpa #$7A Lower case?
bls RETCC ..yes
RETCS orcc #CARRY Set carry
rts
* Compare Pathname With Module Name
*
* Passed: (X)=Pathname
* (Y)=Module Name (High Bit Set Delim)
* (B)=Length Of Pathname
* Returns: Cc=Set If Names Not Equal
*
CNAM ldb R$B,U Get size
leau R$X,U
pulu X,Y Get string ptrs
CHKNAM pshs D,X,Y Save registers
CHKN10 lda ,Y+ Get (next) char of module name
bmi CHKN20 Branch if last module char
decb DECREMENT Char count
beq RETCS1 Branch if last character
eora ,X+ Equal pathname char?
anda #$FF-$20 Match upper/lower case
beq CHKN10 ..yes; repeat
RETCS1 comb Set carry
puls D,X,Y,PC
CHKN20 decb LAST Char of pathname?
bne RETCS1 Branch if not
eora 0,X Does last one match?
anda #$FF-$A0 Match upper/lower & high order bit
bne RETCS1 ..no; return carry set
puls D,X,Y Restore regs
RETCC andcc #$FF-CARRY Clear carry
rts
page
*****
*
* Subroutine Ssvc
*
* Set Entries In Service Routine Dispatch Tables
*
SSVC ldy R$Y,U Get table address
bra SETSVC
SETS10 tfr B,A copy routine offset
anda #$7F mask upper bit
cmpa #$7F Is routine Ioman?
beq SETS30 Bra if so
cmpa #SVCTSZ/2 Is routine offset legal?
bcs SETS30 Bra if so
comb set carry
ldb #E$ISWI return error
rts
SETS30 aslb MAKE Table offset
ldu D.SysDis Get system service table
leau B,U Get entry ptr
ldd ,Y++ Get table relative offset
leax D,Y Get routine address
stx 0,U Put in system routine table
bcs SETSVC Branch if system only
stx SVCTSZ+2,U Put in user routine table
SETSVC ldb ,Y+ Get next routine offset
cmpb #$80 End of table code?
bne SETS10 Branch if not
rts
page
ifne (CPUType-GIMIX)*(CPUType-EXORSR)
opt l
endc
ifeq CPUType-GIMIX
*
* Dynamic Address Translator Initialization
*
DATINT clr $E231 Clear m58167 interrupts
ldx #$FFF0
ldb #$D
DAT10 stb B,X Init dat register
decb Next Dat mask
bpl DAT10 branch if more
ldb #$FE Get extended rom address
stb $E,X Set dat image
incb
stb $F,X Set dat image
lbra COLD
endc
ifeq CPUType-SWTC
*
* Dynamic Address Translator Initialization
*
DATINT ldx #$FFF0 Get dat address
ldb #$0F Get dat mask
DAT10 stb ,X+ Init dat register
decb Change Dat mask
bpl DAT10 Branch if mo'
lbra COLD dat stuff done
endc
ifeq CPUType-SSB
*
* Dynamic Address Translator Initialization
*
DATINT clra Set Task number
ldx #$FFF0 Get dat address
sta -1,X Set dat task register
ldb #$D
DAT10 stb B,X Init dat register
decb Next Dat mask
bpl DAT10 branch if more
ldb #$FE Get extended rom address
stb $E,X Set dat image
incb
stb $F,X Set dat image
sta $F711 Clear clock interrupts
lbra COLD
endc
ifeq CPUType-S09
*
* Dynamic Address Translator Initialization
*
DATINT ldx #$FFF0 Get dat ptr
ldb #$10 First dat mask
DAT10 lda #4 Init four blocks per board segment
DAT20 decb NEXT Mask
stb ,X+ Init dat register
deca COUNT Down
bne DAT20 Branch if more
addb #$14 Next board segment
cmpx #$FFF0 End of dat?
bcc DAT10 Branch if not
inca
clrb D now = $0100 set upper 8K to high addresses
std $FFFE
lbra COLD
endc
ifeq CPUType-HELIX
*
* Dynamic Address Translator Initialization
*
DATINT ldx #$FFF0
ldb #$D
DAT10 stb B,X Init dat register
decb Next Dat mask
bpl DAT10 branch if more
ldb #$FE Get extended rom address
stb $E,X Set dat image
incb
stb $F,X Set dat image
lbra COLD
endc
emod
OS9End equ *
page
ifeq CPUType-CMS9619
*****
* CMS 9619 CPU patch
*
* This CPU uses the area between $FF80 and $FFDF for I/O
*
* This patch puts garbage in the ROM at these addresses
*
fcc /9999999999999999/
fcc /9999999999999999/
fcc /9999999999999999/
fcc /9999999999999999/
fcc /9999999999999999/
fcc /9999999999999999/
endc
*****
*
* Interrupt Vector Package
*
* Generate Rtses to $FFE0
*
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D0
fcc /9999999999999999/
endc
ifle *-$7D8
fcc /99999999/
endc
ifle *-$7DC
fcc /9999/
endc
ifle *-$7DE
fcc /99/
endc
ifle *-$7DF
fcc /9/
endc
*
* Os-9 System Entries
*
fdb TICK+$FFE0-* Clock tick handler
SYSVEC fdb SWI3HN+$FFE2-* Swi3 handler
fdb SWI2HN+$FFE4-* Swi2 handler
fdb FIRQHN+$FFE6-* Fast irq handler
fdb IRQHN+$FFE8-* Irq handler
fdb SWIHN+$FFEA-* Swi handler
fdb NMIHN+$FFEC-* Nmi handler
fdb 0 Reserved
* Actual Vector Entries
fdb 0 Reserved
fdb SWI3RQ+$FFF2-* Swi3
fdb SWI2RQ+$FFF4-* Swi2
fdb FIRQ+$FFF6-* Firq
fdb IRQ+$FFF8-* Irq
fdb SWIRQ+$FFFA-* Swi
fdb NMI+$FFFC-* Nmi
ifeq (CPUType-MM19)*(CPUType-PERCOM)*(CPUType-CMS9609)*(CPUType-ELEKTRA)*(CPUType-DIGALOG)*(CPUType-SAT96)
fdb COLD+$FFFE-* Restart
else
ifeq (CPUType-EXORSR)*(CPUType-CMS9619)
fdb COLD+$FFFE-*
else
fdb DATINT+$FFFE-* Dynamic address translator initialization
endc
endc
ROMEnd equ *
end