mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-06-08 05:29:33 +00:00
6822a8d18f
- Misc. code cleanups
2310 lines
44 KiB
NASM
2310 lines
44 KiB
NASM
* $Id: kern.asm,v 1.2 1998/02/22 05:05:45 taubert Exp $
|
|
|
|
* GNO Multitasking environment
|
|
* Low-level Kernel code
|
|
* Context switching, tool patch vector, CDA patches,
|
|
* process ID allocation, etc.
|
|
* Copyright 1991-1998, Procyon Software
|
|
* added select() timeout support - DT - 2/13/96
|
|
|
|
mcopy m/kern.mac
|
|
copy global.equates
|
|
case on
|
|
|
|
TIMESLICE gequ 3
|
|
NUM_DEFER gequ 16
|
|
|
|
;IncBusy gequ $E10064
|
|
;DecBusy gequ $E10068
|
|
BusyFlag gequ $E100FF
|
|
|
|
****************************************************************************
|
|
* Equates - Various equates required by these routines.
|
|
*
|
|
versionNumber gequ $0100 ; The version number of this library.
|
|
|
|
dispatch1 gequ $e10000 ; The first toolbox dispatch vector.
|
|
dispatch2 gequ $e10004 ; The second toolbox dispatch vector.
|
|
ToolPointerTable gequ $e103c0 ; Pointer to the active System TPT.
|
|
UserToolPointerTable gequ $e103c8 ; Pointer to the active User TPT.
|
|
|
|
; Error return values from the routines InstallE10000 and RemoveE10000
|
|
|
|
noError gequ $0000 ; Value returned if no error occurs.
|
|
badHeaderError gequ $8001 ; Patch header wasn't valid.
|
|
headerNotFoundError gequ $8002 ; Header to remove wasn't in the
|
|
; linked list.
|
|
|
|
****************************************************************************
|
|
* CheckPatch - Checks the passed toolbox dispatch vector to see if it
|
|
* points to a valid patch.
|
|
*
|
|
* Input: Passed via the stack following C conventions.
|
|
* newPatchAddr (long) - Address of the patch routine.
|
|
*
|
|
* Output:
|
|
* If newPatchAddr is a valid patch -
|
|
* Carry clear
|
|
* If newPatchAddr is not a valid patch -
|
|
* Carry set
|
|
*
|
|
CheckPatch START
|
|
|
|
zprtl equ $01 ; The address for the rtl on our direct
|
|
; page.
|
|
newPatchAddr equ zprtl+3 ; Address of patch (parameter to this
|
|
; routine).
|
|
|
|
tsc ; Make the stack the direct page after
|
|
; saving
|
|
phd ; the current direct page.
|
|
tcd
|
|
|
|
|
|
lda newPatchAddr+2 ; Simple check to check for a valid
|
|
; pointer.
|
|
and #$ff00
|
|
bne BadPatch ; Wasn't zero, can't be a valid pointer.
|
|
|
|
lda [newPatchAddr] ; Check for the first JML instruction.
|
|
and #$00ff
|
|
cmp #$005c
|
|
bne BadPatch
|
|
|
|
ldy #$04 ; Check for the second JML instruction.
|
|
lda [newPatchAddr],y
|
|
and #$00ff
|
|
cmp #$005c
|
|
bne BadPatch
|
|
|
|
ldy #$08 ; Check for the third JML instruction.
|
|
lda [newPatchAddr],y
|
|
and #$00ff
|
|
cmp #$005c
|
|
bne BadPatch
|
|
|
|
ldy #$0c ; Check for the fourth JML instruction.
|
|
lda [newPatchAddr],y
|
|
and #$00ff
|
|
cmp #$005c
|
|
bne BadPatch
|
|
|
|
ldy #$10 ; Check for the rtl and phk instructions.
|
|
lda [newPatchAddr],y
|
|
cmp #$4b6b
|
|
bne BadPatch
|
|
|
|
iny ; Check for the phk and pea instructions.
|
|
lda [newPatchAddr],y
|
|
cmp #$f44b
|
|
bne BadPatch
|
|
|
|
clc ; Calculate the address of the rtl
|
|
; instruction.
|
|
lda newPatchAddr
|
|
adc #$000f
|
|
ldy #$13 ; Check for address of the rtl
|
|
; instruction.
|
|
cmp [newPatchAddr],y
|
|
bne BadPatch
|
|
|
|
GoodPatch anop
|
|
pld ; Restore the direct page and report
|
|
clc ; that it was a good patch.
|
|
rtl
|
|
|
|
BadPatch anop
|
|
pld ; Restore the direct page and report
|
|
sec ; that something was wrong.
|
|
rtl
|
|
|
|
END
|
|
|
|
****************************************************************************
|
|
* InstallE10000 - Sets the jump vector at $e10000 and $e10004 to point to
|
|
* the passed new toolbox dispatch vector patch. This routine
|
|
* also updates the linked lists so that more than one routine
|
|
* can be patched into the dispatch vectors.
|
|
*
|
|
* Input: Passed via the stack following C conventions.
|
|
* newPatchAddr (long) - Address of the patch routine.
|
|
*
|
|
|
|
* Output:
|
|
* If an error occurred -
|
|
* Carry set, Accumulator contains one of the following error codes:
|
|
* badHeaderError
|
|
* If no error occurred and patch was installed successfully -
|
|
* Carry clear, Accumulator contains zero.
|
|
*
|
|
InstallE10000 START
|
|
|
|
oldPatchAddr equ $01 ; Address of existing patch.
|
|
zprtl equ oldPatchAddr+4 ; The address for the rtl.
|
|
zpsize equ zprtl-oldPatchAddr ; Size of direct page we'll have on
|
|
; the stack.
|
|
newPatchAddr equ zprtl+3 ; Address of patch (parameter to
|
|
; this routine).
|
|
|
|
tsc ; Move the stack pointer to point beyond
|
|
sec ; the direct page variables that we'll
|
|
sbc #zpsize ; place on the stack.
|
|
tcs
|
|
phd ; Save the direct page register.
|
|
tcd ; Set the direct page.
|
|
php ; Disable interrupts
|
|
sei
|
|
|
|
pei newPatchAddr+2 ; Check if patch header is valid.
|
|
pei newPatchAddr
|
|
jsl CheckPatch
|
|
plx ; Remove the parameters from the stack.
|
|
plx
|
|
bcc x1 ; Report the badHeaderError if detected.
|
|
ldy #badHeaderError
|
|
jmp Exit
|
|
|
|
x1 lda >dispatch1 ; Set up the next1Vector in the new patch.
|
|
sta [newPatchAddr] ; The JML instruction and low byte.
|
|
lda >dispatch1+2
|
|
ldy #$02
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
lda >dispatch2 ; Set up the next2Vector in the new patch.
|
|
ldy #$04
|
|
sta [newPatchAddr],y ; The JML instruction and low byte.
|
|
lda >dispatch2+2
|
|
ldy #$06
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
lda >dispatch1+3 ; See if there's already a patch in
|
|
; dispatch1.
|
|
and #$00ff
|
|
sta oldPatchAddr+2
|
|
pha ; High byte of possible header address.
|
|
lda >dispatch1+1
|
|
sec
|
|
sbc #$0011
|
|
sta oldPatchAddr
|
|
pha ; Low byte of possible header address.
|
|
jsl CheckPatch
|
|
plx
|
|
plx
|
|
bcs First ; JIF this will be the first patch
|
|
; installed.
|
|
|
|
ldy #$08 ; Set up the dispatch1Vector in the new
|
|
; patch.
|
|
lda [oldPatchAddr],y
|
|
sta [newPatchAddr],y ; The JML instruction and low byte.
|
|
ldy #$0a
|
|
lda [oldPatchAddr],y
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
ldy #$0c ; Set up the dispatch2Vector in the new
|
|
; patch.
|
|
lda [oldPatchAddr],y
|
|
sta [newPatchAddr],y ; The JML instruction and low byte.
|
|
ldy #$0e
|
|
lda [oldPatchAddr],y
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
bra PatchIt ; Now patch dispatch1 and dispatch2.
|
|
|
|
First ldy #$08 ; Set up the dispatch1Vector in the new
|
|
; patch.
|
|
lda >dispatch1
|
|
sta [newPatchAddr],y ; The JML instruction and low byte.
|
|
ldy #$0a
|
|
lda >dispatch1+2
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
ldy #$0c ; Set up the dispatch2Vector in the new
|
|
; patch.
|
|
lda >dispatch2
|
|
sta [newPatchAddr],y ; The JML instruction and low byte.
|
|
ldy #$0e
|
|
lda >dispatch2+2
|
|
sta [newPatchAddr],y ; The middle and upper bytes.
|
|
|
|
PatchIt anop
|
|
clc ; Calculate the address of the new
|
|
; dispatch2.
|
|
lda newPatchAddr
|
|
adc #$0015
|
|
sta newPatchAddr
|
|
xba
|
|
and #$ff00 ; Mask in the JML instruction.
|
|
ora #$005c
|
|
sta >dispatch2 ; The JML instruction and low byte.
|
|
lda newPatchAddr+1
|
|
sta >dispatch2+2 ; The middle and upper bytes.
|
|
|
|
sec ; Calculate the address of the new
|
|
; dispatch1.
|
|
lda newPatchAddr
|
|
sbc #$0004
|
|
sta newPatchAddr
|
|
xba
|
|
and #$ff00 ; Mask in the JML instruction.
|
|
ora #$005c
|
|
sta >dispatch1 ; The JML instruction and low byte.
|
|
lda newPatchAddr+1
|
|
sta >dispatch1+2 ; The middle and upper bytes.
|
|
|
|
ldy #noError ; Report that all went well.
|
|
|
|
Exit plp ; Restore the interrupt state.
|
|
pld ; Restore the previous direct page
|
|
; register.
|
|
tsc ; Restore the stack pointer.
|
|
clc
|
|
adc #zpsize
|
|
tcs
|
|
tya ; Value to return.
|
|
beq noerr
|
|
sec ; Report that there was an error.
|
|
rtl
|
|
noerr clc ; Report that there was no error.
|
|
rtl
|
|
|
|
END
|
|
|
|
|
|
****************************************************************************
|
|
* RemoveE10000 - Removes the specified patch from the dispatch1 and dispatch2
|
|
* vectors and updates the linked lists for the remaining
|
|
* toolbox patches.
|
|
*
|
|
* Input: Passed via the stack following C conventions.
|
|
* patchToRemove (long) - Address of the patch to remove.
|
|
*
|
|
* Output:
|
|
* If an error occurred -
|
|
* Carry set, Accumulator contains one of the following error codes:
|
|
* badHeaderError
|
|
* headerNotFoundError
|
|
* If no error occurred and patch was removed successfully -
|
|
* Carry clear, Accumulator contains zero.
|
|
*
|
|
RemoveE10000 START
|
|
|
|
patchDispAddr equ $01 ; Address of existing patch (and 1
|
|
; extra byte).
|
|
prevHeader equ patchDispAddr+5 ; Used to search through the
|
|
; linked list.
|
|
zprtl equ prevHeader+4 ; The address for the rtl.
|
|
zpsize equ zprtl-patchDispAddr ; Size of direct page we'll have
|
|
; on the stack.
|
|
patchToRemove equ zprtl+3 ; Address of patch (parameter to
|
|
; this routine).
|
|
|
|
tsc ; Move the stack pointer to point beyond
|
|
sec ; the direct page variables that we'll
|
|
sbc #zpsize ; place on the stack.
|
|
tcs
|
|
phd ; Save the direct page register.
|
|
tcd ; Set the direct page.
|
|
php ; Disable interrupts
|
|
sei
|
|
|
|
pei patchToRemove+2 ; Check if patch header we were asked to
|
|
pei patchToRemove ; remove is a valid header.
|
|
jsl CheckPatch
|
|
plx ; Remove the parameters from the stack.
|
|
plx
|
|
bcc x1 ; Report the badHeaderError if detected.
|
|
ldy #badHeaderError
|
|
jmp Exit
|
|
|
|
x1 clc ; Create the JML instruction that would
|
|
; exist
|
|
lda patchToRemove ; if the patchToRemove was installed.
|
|
adc #$0011
|
|
sta patchDispAddr+1
|
|
lda patchToRemove+2
|
|
sta patchDispAddr+3
|
|
lda patchDispAddr ; Mask in the JML instruction.
|
|
and #$ff00
|
|
ora #$005c
|
|
sta patchDispAddr
|
|
|
|
cmp >dispatch1 ; Check if the patch to remove is the
|
|
; first
|
|
bne NotFirstOne ; patch installed.
|
|
lda >dispatch1+2
|
|
cmp patchDispAddr+2
|
|
bne NotFirstOne
|
|
|
|
lda [patchToRemove] ; Restore the Dispatch1 vector.
|
|
sta >dispatch1
|
|
ldy #$02
|
|
lda [patchToRemove],y
|
|
sta >dispatch1+2
|
|
|
|
|
|
ldy #$04 ; Restore the Dispatch2 vector.
|
|
lda [patchToRemove],y
|
|
sta >dispatch2
|
|
ldy #$06
|
|
lda [patchToRemove],y
|
|
sta >dispatch2+2
|
|
|
|
bra NoErr ; Everything went well.
|
|
|
|
NotFirstOne anop
|
|
sec ; Assume that whatever is in dispatch1 is
|
|
lda >dispatch1+1 ; patch and get the address of its header.
|
|
sbc #$0011
|
|
sta prevHeader ; Low and middle bytes.
|
|
lda >dispatch1+3
|
|
and #$00ff
|
|
sta prevHeader+2 ; Upper byte of header address.
|
|
|
|
loop pei prevHeader+2 ; Check if it really is a valid header.
|
|
pei prevHeader
|
|
jsl CheckPatch
|
|
plx ; Remove the parameters from the stack.
|
|
plx
|
|
bcc x2 ; Report that the patch that we asked to
|
|
ldy #headerNotFoundError ; remove wasn't found.
|
|
bra Exit
|
|
|
|
x2 lda [prevHeader] ; See if this patch points to patch we
|
|
cmp patchDispAddr ; want to remove.
|
|
bne nope
|
|
ldy #$02
|
|
lda [prevHeader],y
|
|
cmp patchDispAddr+2
|
|
bne nope
|
|
|
|
lda [patchToRemove] ; Restore the next1Vector.
|
|
sta [prevHeader]
|
|
ldy #$02
|
|
lda [patchToRemove],y
|
|
sta [prevHeader],y
|
|
|
|
ldy #$04 ; Restore the next2Vector.
|
|
lda [patchToRemove],y
|
|
sta [prevHeader],y
|
|
ldy #$06
|
|
lda [patchToRemove],y
|
|
sta [prevHeader],y
|
|
|
|
bra NoErr ; Everything went well.
|
|
|
|
nope ldy #$02 ; Get the address of the next patch
|
|
; header.
|
|
lda [prevHeader],y
|
|
tax
|
|
lda [prevHeader]
|
|
sta prevHeader
|
|
stx prevHeader+2
|
|
|
|
sec
|
|
lda prevHeader+1
|
|
sbc #$11
|
|
sta prevHeader
|
|
lda prevHeader+3
|
|
and #$00ff
|
|
sta prevHeader+2
|
|
|
|
|
|
bra loop ; Now check this header.
|
|
|
|
NoErr ldy #noError ; Report that all went well.
|
|
|
|
Exit plp ; Restore the interrupt state.
|
|
pld ; Restore the previous direct page
|
|
; register.
|
|
tsc ; Restore the stack pointer.
|
|
clc
|
|
adc #zpsize
|
|
tcs
|
|
tya ; Value to return.
|
|
beq xnoerr
|
|
sec ; Report that there was an error.
|
|
rtl
|
|
xnoerr clc ; Report that there was no error.
|
|
rtl
|
|
END
|
|
|
|
toolV2Dat DATA KERN2
|
|
t2Stack ds 128*32
|
|
END
|
|
|
|
****************************************************************************
|
|
* PatchHeader - Header required of all routines that will be patched
|
|
* into the toolbox dispatch vectors.
|
|
*
|
|
* Note: The code between next1Vector and NewDispatch2 must be included
|
|
* for all calls. The code below NewDispatch2 only needs to be
|
|
* included for patches that want to post patch the calls.
|
|
*
|
|
PatchHeader START
|
|
using toolV2Dat
|
|
using KernelStruct
|
|
|
|
next1Vector ENTRY ; Where dispatch1 should go when
|
|
; finished.
|
|
jml next1Vector ; (Filled in by InstallE10000).
|
|
next2Vector ENTRY ; Where dispatch2 should go when
|
|
; finished.
|
|
jml next2Vector ; (Filled in by InstallE10000).
|
|
dispatch1Vector ENTRY ; Holds the JML instruction from
|
|
; $e10000.
|
|
jml dispatch1Vector ; (Filled in by InstallE10000).
|
|
dispatch2Vector ENTRY ; Holds the JML instruction from
|
|
; $e10004.
|
|
jml dispatch2Vector ; (Filled in by InstallE10000).
|
|
|
|
anRtl rtl ; An RTL instruction. Its address
|
|
; will be
|
|
* ; pushed on the stack for dispatch1
|
|
; calls.
|
|
|
|
NewDispatch1 ENTRY ; Entry point for dispatch1 toolbox
|
|
; vector.
|
|
|
|
phk ; Push program bank.
|
|
pea anRtl-1 ; Push the address of a RTL.
|
|
|
|
NewDispatch2 ENTRY ; Entry point for dispatch2 toolbox
|
|
; vector.
|
|
|
|
; The following code should be included in the PatchHeader if the patch wants
|
|
; to perform post patching. This code will determine if the call that was
|
|
; made actually exists and if it does, post patching can occur. If the call
|
|
; doesn't exist, any pre-call routines can be executed, but the post patching
|
|
; shouldn't be attempted because the dispatcher will remove the second return
|
|
; address from the stack, thus not returning to your post patching routines.
|
|
; Stack equates for this routine.
|
|
|
|
aLong equ $0001 ; A temporary long value.
|
|
oldDP equ aLong+4 ; Where the direct page is saved to.
|
|
oldTM equ oldDP+2 ; Where the tool call number is saved.
|
|
|
|
phx ; Save the call that's being made.
|
|
phd ; Save the current direct page.
|
|
lda >ToolPointerTable+2 ; Get the TPT to determine the number
|
|
pha ; of tool sets loaded.
|
|
lda >ToolPointerTable
|
|
pha
|
|
tsc ; Set the direct page to the stack.
|
|
tcd
|
|
txa ; See if this tool set exits.
|
|
and #$00ff
|
|
cmp [aLong] ; Is it larger than the number of tool
|
|
; sets?
|
|
bcs noCall ; JIF this tool set doesn't exist.
|
|
asl a
|
|
asl a
|
|
tay ; Now get the pointer to the FPT.
|
|
lda [aLong],y
|
|
tax
|
|
iny
|
|
iny
|
|
lda [aLong],y
|
|
sta aLong+2
|
|
stx aLong
|
|
lda oldTM ; Get the function number.
|
|
and #$ff00
|
|
xba
|
|
cmp [aLong] ; Compare it to the number of entries in
|
|
; table.
|
|
noCall anop
|
|
pla ; Remove aLong from the stack.
|
|
pla
|
|
pld ; Restore the original direct page.
|
|
plx ; Recover the tool number.
|
|
bcs noCall2 ; don't pre patch, because we
|
|
* ; cannot post-patch
|
|
|
|
; At this point the carry flag is set if the tool call doesn't exist and clear
|
|
; if the tool call exits. No post patching must occur if the carry flag is
|
|
; set.
|
|
|
|
php
|
|
sei
|
|
phb
|
|
phk
|
|
plb ; 5,s
|
|
pha ; 3,s
|
|
phx ; 1,s
|
|
|
|
jsl incBusy
|
|
|
|
ldx curProcInd
|
|
lda t2StackPtr,x
|
|
asl a
|
|
asl a
|
|
clc
|
|
adc curProcInd ; add current proc offset
|
|
tax
|
|
lda 7,s
|
|
sta >t2Stack,x
|
|
short m
|
|
lda 9,s
|
|
sta >t2Stack+2,x
|
|
long m
|
|
ldx curProcInd
|
|
inc t2StackPtr,x
|
|
|
|
* Now, put our return address on the stack instead
|
|
|
|
short m
|
|
lda #^t2Return-1
|
|
sta 9,s
|
|
long m
|
|
lda #t2Return-1
|
|
sta 7,s
|
|
plx
|
|
pla
|
|
plb
|
|
plp
|
|
noCall2 anop
|
|
jmp next2Vector ; Go to the original $e10004 jump
|
|
; instruction.
|
|
t2Return anop
|
|
phb
|
|
pha ; space for return address
|
|
|
|
php ; 6,s
|
|
sei
|
|
phb ; 5,s
|
|
phk
|
|
plb
|
|
pha ; 3,s
|
|
phx ; 1,s
|
|
|
|
ldx curProcInd
|
|
lda t2StackPtr,x
|
|
dec a
|
|
sta t2StackPtr,x
|
|
asl a
|
|
asl a
|
|
clc
|
|
adc curProcInd
|
|
tax
|
|
short m
|
|
lda >t2Stack+2,x
|
|
sta 9,s
|
|
long m
|
|
lda >t2Stack,x
|
|
sta 7,s
|
|
plx
|
|
pla
|
|
plb
|
|
plp
|
|
jmp >decBusy
|
|
; jsl decBusy
|
|
; rtl
|
|
|
|
END
|
|
|
|
SaveAllPatch START
|
|
using toolV2Dat
|
|
using KernelStruct
|
|
using IgnoreInfo
|
|
|
|
php
|
|
sei
|
|
long ai
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
pha
|
|
phx
|
|
phy
|
|
; jsl incBusy
|
|
|
|
lda curProcInd
|
|
sta tcurProcInd
|
|
lda truepid
|
|
sta ttruepid
|
|
lda #0
|
|
sta curProcInd
|
|
sta truepid
|
|
lda gsosDebug
|
|
sta tgsosDebug
|
|
stz gsosDebug
|
|
|
|
|
|
* we need to move some tool stack info to make it look like the kernel
|
|
* process called "SaveAll".
|
|
ldx tcurProcInd
|
|
lda t2StackPtr,x
|
|
dec a
|
|
sta t2StackPtr,x
|
|
asl a
|
|
asl a
|
|
clc
|
|
adc tcurProcInd
|
|
tax
|
|
lda >t2Stack,x
|
|
sta tstack
|
|
lda >t2Stack+2,x
|
|
sta tstack+2
|
|
|
|
lda t2StackPtr
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda tstack
|
|
sta >t2Stack,x
|
|
lda tstack+2
|
|
sta >t2Stack+2,x
|
|
lda t2StackPtr
|
|
inc a
|
|
sta t2StackPtr
|
|
|
|
pushword #$0000 ; system tool set
|
|
pushword #$0C ; texttools
|
|
pushlong >oldTextTT ; thar she blows
|
|
_SetTSPtr
|
|
ply
|
|
plx
|
|
pla
|
|
plb
|
|
plp
|
|
OLDSAVEALL ENTRY
|
|
jmp >$000000
|
|
|
|
RestAllPatch ENTRY
|
|
php
|
|
sei
|
|
long ai
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
pha
|
|
phx
|
|
phy
|
|
phd
|
|
|
|
lda tcurProcInd
|
|
sta curProcInd
|
|
lda ttruepid
|
|
sta truepid
|
|
lda tgsosDebug
|
|
sta gsosDebug
|
|
|
|
* we need to move some tool stack info to make it look like the interrupted
|
|
* process called "RestoreAll".
|
|
lda t2StackPtr
|
|
dec a
|
|
sta t2StackPtr
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda >t2Stack,x
|
|
sta tstack
|
|
lda >t2Stack+2,x
|
|
sta tstack+2
|
|
|
|
ldx tcurProcInd
|
|
lda t2StackPtr,x
|
|
asl a
|
|
asl a
|
|
clc
|
|
adc tcurProcInd
|
|
tax
|
|
lda tstack
|
|
sta >t2Stack,x
|
|
lda tstack+2
|
|
sta >t2Stack+2,x
|
|
ldx tcurProcInd
|
|
lda t2StackPtr,x
|
|
inc a
|
|
sta t2StackPtr,x
|
|
|
|
; set the flag to ignore the next occurrences of those
|
|
; particular tools that are grieving us right now.
|
|
; for ROM 01 this works, as they only try to restore IN OUT, not ERR.
|
|
|
|
lda #1
|
|
sta ignSetInDev
|
|
sta ignSetInGlo
|
|
sta ignSetOutDev
|
|
sta ignSetOutGlo
|
|
pushword #$0000 ; system tool set
|
|
pushword #$0C ; texttools
|
|
pushlong #TTtable ; thar she blows
|
|
_SetTSPtr
|
|
|
|
; jsl decBusy
|
|
pld
|
|
ply
|
|
plx
|
|
pla
|
|
plb
|
|
plp
|
|
|
|
; ldx #0
|
|
; ldy #0
|
|
; jmp tool_exit
|
|
|
|
OLDRESTALL ENTRY
|
|
jmp >$000000
|
|
|
|
savedCDAInfo ENTRY
|
|
ttruepid dc i2'0'
|
|
tcurProcInd dc i2'0'
|
|
tgsosDebug dc i2'0'
|
|
tstack dc i4'0'
|
|
END
|
|
|
|
cdaPatch START
|
|
using KernelStruct
|
|
|
|
php
|
|
lda >reschedFlag
|
|
inc a
|
|
sta >reschedFlag
|
|
lda 4,s
|
|
sta >rtlSave+2
|
|
lda 1,s
|
|
sta 4,s
|
|
long m
|
|
lda 2,s
|
|
sta >rtlSave
|
|
pla
|
|
short m
|
|
pla
|
|
plp
|
|
|
|
; jsl oldCDAVect
|
|
|
|
php
|
|
php
|
|
php
|
|
php
|
|
short m
|
|
lda >rtlSave+2
|
|
sta 4,s
|
|
long m
|
|
lda >rtlSave
|
|
sta 2,s
|
|
lda >reschedFlag
|
|
dec a
|
|
sta >reschedFlag
|
|
plp
|
|
rtl
|
|
rtlSave dc i4'0'
|
|
END
|
|
|
|
; BrkVect
|
|
; kills the offending process
|
|
; gets info on the BRK by doing a GetInterruptState
|
|
|
|
BrkVect START
|
|
using KernelStruct
|
|
|
|
sei
|
|
clc ; (might not be necessary, but fuck it)
|
|
xce
|
|
phk
|
|
plb
|
|
long ai
|
|
jsl incBusy
|
|
|
|
lda >curProcInd
|
|
tax
|
|
lda >lastTool,x
|
|
sta >brkState+20
|
|
|
|
pushlong #brkState
|
|
pushword #$14
|
|
_GetInterruptState
|
|
|
|
lda 4,s ; copy PC into record
|
|
sta brkState+13
|
|
lda 2,s
|
|
sta brkState+14
|
|
tsc ; copy S into record
|
|
sta brkState+6
|
|
|
|
pushlong #brkState
|
|
tsc
|
|
pha
|
|
jsl PRINTBRK
|
|
bra brkproc
|
|
BrkVect1 ENTRY
|
|
Using KernelStruct
|
|
|
|
sei
|
|
clc ; (might not be necessary, but fuck it)
|
|
xce
|
|
phk
|
|
plb
|
|
long ai
|
|
jsl incBusy
|
|
|
|
lda >curProcInd
|
|
tax
|
|
lda >lastTool,x
|
|
sta >brkState+20
|
|
|
|
pushlong #brkState
|
|
pushword #$14
|
|
_GetInterruptState
|
|
|
|
lda 2,s
|
|
sta brkState+$0E
|
|
short a
|
|
lda 4,s
|
|
sta brkState+$0D
|
|
long a
|
|
|
|
pushlong #brkState
|
|
tsc
|
|
pha
|
|
jsl PRINTBRK
|
|
; jsr FlexBeep
|
|
|
|
; kill() now resets mutex to 0 if prog crashes in mutex
|
|
brkproc anop
|
|
tsc
|
|
sta >$604
|
|
|
|
pha
|
|
pha
|
|
jsl KERNgetpid ; this is #pragma toolparms 1
|
|
pea 9
|
|
ph4 #killerr
|
|
jsl KERNkill ; this is #pragma toolparms 1
|
|
pla
|
|
oops bra oops
|
|
|
|
killerr dc i2'0'
|
|
brkState ds 32
|
|
END
|
|
|
|
; since the kernel null process doesn't _resched, we won't get in
|
|
; an 'exploding time slice' situation. Make sure null process never calls
|
|
; _resched
|
|
|
|
CopVect START
|
|
using IntState
|
|
using KernelStruct
|
|
|
|
clc
|
|
xce
|
|
long mx
|
|
php
|
|
phb
|
|
|
|
sta >int_A ; save accumulator
|
|
lda #0 ; 0 indicates COP
|
|
sta >intType
|
|
|
|
* start saving off the registers
|
|
short m
|
|
pla
|
|
sta >int_B ; save data bank
|
|
pla
|
|
sta >int_P ; save status of 'e' bit
|
|
|
|
lda >$E0C02D
|
|
sta >int_SLTROM
|
|
lda >$E0C068
|
|
sta >int_STATEREG
|
|
long a
|
|
|
|
* the value of s that's saved shouldn't differ from the value upon
|
|
* entry
|
|
tsc
|
|
sta >int_S ; save stack pointer
|
|
|
|
tdc
|
|
sta >int_D ; save direct page
|
|
phk
|
|
plb
|
|
stx int_X
|
|
sty int_Y ; save X & Y
|
|
lda >$E0C035
|
|
and #%1111111111110111 ; don't ever change SHR shadowing
|
|
sta int_state
|
|
jsl contextSwitch
|
|
; restore stuff
|
|
newViaCOP ENTRY
|
|
long mx ; just for kicks
|
|
lda >$E0C035 ; don't ever change SHR shadowing
|
|
and #%0000000000001000 ; get old SHR shadow bit
|
|
ora >int_state
|
|
sta >$E0C035
|
|
lda >int_Y
|
|
tay
|
|
lda >int_X
|
|
tax
|
|
lda >int_D
|
|
tcd
|
|
|
|
short m
|
|
lda >int_B
|
|
pha
|
|
plb
|
|
lda >int_SLTROM
|
|
sta >$E0C02D
|
|
lda >int_STATEREG
|
|
sta >$E0C068
|
|
|
|
lda >int_P
|
|
pha
|
|
|
|
long m
|
|
lda >int_A
|
|
plp
|
|
xce
|
|
rti
|
|
END
|
|
|
|
longa on
|
|
longi on
|
|
InitKernel START
|
|
using KernelStruct
|
|
; TO CONSOLE
|
|
; using InOutData
|
|
phb
|
|
phk
|
|
plb
|
|
|
|
move3 $E10071,oldBrk+1
|
|
; move3 #BrkVect,$E10071
|
|
|
|
pha
|
|
pha
|
|
pea $5
|
|
_GetVector
|
|
pl4 oldCop
|
|
|
|
; move3 $E10015,oldCop
|
|
pea $5
|
|
ph4 #CopVect
|
|
_SetVector
|
|
; move3 #CopVect,$E10015
|
|
|
|
; pha
|
|
; _MMStartUp
|
|
; pla
|
|
; sta userID
|
|
; kp->userID set in main.c
|
|
|
|
; TO CONSOLE
|
|
; jsl InOutStart ; good enough here....
|
|
jsl patchGSOS
|
|
jsr PatchText
|
|
jsl initvar
|
|
jsl patchRM
|
|
|
|
ldx #0
|
|
loop lda #0
|
|
sta ParentProc,x
|
|
sta ProcessState,x
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
cpx #(procEntSize*NPROC)
|
|
bcc loop
|
|
lda #pRunning
|
|
sta ProcessState
|
|
; let's do it, dude!
|
|
|
|
pushlong #alarmHB
|
|
_SetHeartBeat
|
|
|
|
php ; jb 6/23/91
|
|
sei ; jb 6/23/91
|
|
move3 $E10069,oldDecBusy+1
|
|
move3 #newDecBusy,$E10069
|
|
move3 $E10011,oldInt+1
|
|
move3 #IntHndl,$E10011
|
|
; mv4 >$E10048,oldCDAvect
|
|
; move3 #CDAPatch,>$E10049
|
|
|
|
ph4 #PatchHeader
|
|
jsl InstallE10000
|
|
ply
|
|
ply
|
|
plp ; jb 6/23/91
|
|
plb
|
|
rtl
|
|
|
|
DeInitKern ENTRY
|
|
pushlong #alarmHB
|
|
_DelHeartBeat
|
|
|
|
pea $4 ; Interrupt Manager
|
|
ph4 oldInt+1
|
|
_SetVector
|
|
pea $5 ; COP Manager
|
|
ph4 oldCop
|
|
_SetVector
|
|
|
|
ph4 #PatchHeader
|
|
jsl RemoveE10000
|
|
ply
|
|
ply
|
|
move3 oldDecBusy+1,$E10069
|
|
move3 oldBrk+1,$E10071
|
|
; mv4 oldCDAvect,>$E10048
|
|
|
|
jsl unPatchRM
|
|
jsl unpatchGSOS
|
|
jsr UnPatchText
|
|
; TO CONSOLE
|
|
; jsl InOutEnd
|
|
rtl
|
|
oldInt ENTRY
|
|
jmp >$000000
|
|
dc i2'0' ; buffer space!
|
|
oldBrk ENTRY
|
|
jmp >$000000
|
|
oldCop dc i4'0'
|
|
oldTool1 dc i4'0'
|
|
;oldCDAvect ENTRY
|
|
; dc i4'0'
|
|
oldDecBusy ENTRY
|
|
jmp >$000000
|
|
END
|
|
|
|
mapPID START
|
|
using KernelStruct
|
|
retval equ 0
|
|
subroutine (2:pid),2
|
|
|
|
ldx #0
|
|
lp anop
|
|
lda ProcessState,x
|
|
beq trynext ; no process here, don't check
|
|
lda flpid,x
|
|
cmp pid
|
|
beq gotit
|
|
trynext anop
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
cmp #(procEntSize*NPROC)
|
|
bcs notfound
|
|
tax
|
|
bra lp
|
|
gotit txa
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
|
|
goaway anop
|
|
sta retval
|
|
return 2:retval
|
|
notfound lda #-1
|
|
bra goaway ; my stupidity amazes me. NOT gotit
|
|
END
|
|
|
|
allocPID START
|
|
using KernelStruct
|
|
retval equ 0
|
|
subroutine (0:foo),2
|
|
|
|
jsl incBusy
|
|
lp0 anop
|
|
ldx #0
|
|
lp anop
|
|
lda ProcessState,x
|
|
beq nextent
|
|
lda floatingPID
|
|
cmp flpid,x
|
|
beq trynext
|
|
nextent anop ; inc x to next entry
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
cmp #(procEntSize*NPROC)
|
|
bcs gotone
|
|
tax
|
|
bra lp
|
|
trynext lda floatingPID
|
|
inc a
|
|
bpl inrange
|
|
lda #1
|
|
inrange sta floatingPID
|
|
bra lp0
|
|
gotone lda floatingPID
|
|
sta retval
|
|
inc a
|
|
bpl inrange2
|
|
lda #1
|
|
inrange2 sta floatingPID
|
|
jsl decBusy
|
|
return 2:retval
|
|
END
|
|
|
|
IntState DATA
|
|
int_A dc i2'0'
|
|
int_X dc i2'0'
|
|
int_Y dc i2'0'
|
|
int_S dc i2'0'
|
|
int_D dc i2'0'
|
|
int_B dc i2'0'
|
|
|
|
int_P dc i2'0' ; needed to go back to emulation mode
|
|
intType dc i2'0'
|
|
int_state dc i2'0'
|
|
int_SLTROM dc i1'0'
|
|
int_STATEREG dc i1'0'
|
|
END
|
|
|
|
IntHndl START
|
|
using IntState
|
|
using KernelStruct
|
|
|
|
; bvc nobrk
|
|
; jsr FlexBeep
|
|
; jmp BrkVect1
|
|
nobrk anop
|
|
clc
|
|
xce
|
|
bcs ohmygod
|
|
php
|
|
short a
|
|
pha
|
|
lda $E1C046
|
|
and #$08
|
|
bne gotVBL
|
|
tofw pla
|
|
plp
|
|
ohmygod xce
|
|
jmp oldInt
|
|
|
|
gotVBL anop
|
|
|
|
; lda >reschedFlag
|
|
; sta >$E00626
|
|
lda >timeleft
|
|
beq noMoreTime
|
|
dec a
|
|
sta >timeleft
|
|
bne tofw
|
|
|
|
noMoreTime anop
|
|
lda #1 ;1 indicates VBL
|
|
sta >intType
|
|
pla
|
|
; sei
|
|
|
|
long ai
|
|
sta >int_A ; save accumulator
|
|
|
|
short a
|
|
lda >$E0C02D
|
|
sta >int_SLTROM
|
|
lda >$E0C068
|
|
sta >int_STATEREG
|
|
pla
|
|
sta >int_P
|
|
phb
|
|
pla
|
|
sta >int_B ; save data bank
|
|
long a
|
|
tsc
|
|
sta >int_S ; save stack pointer
|
|
tdc
|
|
sta >int_D ; save direct page
|
|
|
|
phk ; set up kernel's databank
|
|
plb
|
|
|
|
txa
|
|
sta >int_X
|
|
tya
|
|
sta >int_Y ; save X & Y
|
|
|
|
ldx curProcInd ; update the process'
|
|
lda ticks,x
|
|
adc #TIMESLICE
|
|
sta ticks,x
|
|
bcc nocarry
|
|
inc ticks+2,x
|
|
nocarry anop
|
|
|
|
lda >$E0C035
|
|
and #%1111111111110111
|
|
sta >int_state
|
|
jsl contextSwitch
|
|
; restore stuff
|
|
newViaVBL ENTRY
|
|
long mx
|
|
lda >$E0C035
|
|
and #%0000000000001000
|
|
ora >int_state
|
|
; lda >int_state
|
|
sta >$E0C035
|
|
lda >int_Y
|
|
tay
|
|
lda >int_X
|
|
tax
|
|
lda >int_D
|
|
tcd
|
|
|
|
short a
|
|
lda >int_B
|
|
pha
|
|
plb
|
|
lda >int_SLTROM
|
|
sta >$E0C02D
|
|
lda >int_STATEREG
|
|
sta >$E0C068
|
|
lda >int_P
|
|
pha
|
|
|
|
long a
|
|
lda >int_A
|
|
plp
|
|
xce
|
|
jmp oldInt
|
|
END
|
|
|
|
* Databank MUST be set up before entry
|
|
|
|
contextSwitch Start
|
|
Using KernelStruct
|
|
Using IntState
|
|
|
|
; there used to be a LONG here, but it's unnecessary
|
|
|
|
lda >BusyFlag
|
|
beq humph
|
|
brl goaway
|
|
|
|
humph anop
|
|
|
|
lda #TIMESLICE
|
|
sta timeleft ; run me again please
|
|
|
|
ldx curProcInd
|
|
jsr GetInterruptState
|
|
|
|
ldx curProcInd
|
|
tsc
|
|
; sta irq_S1,x
|
|
|
|
; if the process state isn't Running, the kernel wants to change it's status,
|
|
; so oblige it by not changing it to 'Ready'
|
|
|
|
lda ProcessState,x
|
|
cmp #pRunning ; change of state?
|
|
bne findit
|
|
|
|
spcl anop
|
|
lda #pReady
|
|
sta ProcessState,x
|
|
findit jsr FindNextEntry
|
|
stx curProcInd
|
|
txa
|
|
clc
|
|
adc #KernelStruct
|
|
sta >procPtr
|
|
lda #^KernelStruct
|
|
adc #0
|
|
sta >procPtr+2
|
|
|
|
txa
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a ; divide by 128 to get true pid
|
|
lsr a
|
|
sta truepid
|
|
|
|
* Repair SANE's DP space
|
|
phd
|
|
lda >$E103CA
|
|
pha
|
|
lda >$E103C8
|
|
pha
|
|
tsc
|
|
tcd
|
|
ldy #$A*4
|
|
ldx curProcInd
|
|
lda SANEwap,x
|
|
sta [1],y
|
|
pla
|
|
pla
|
|
pld
|
|
|
|
lda ProcessState,x
|
|
cmp #pNew
|
|
bne okay
|
|
|
|
; the following code is hopelessly obtuse, but it basically creates information
|
|
; on the stack to simulate an interrupt, so that the new process starts it's
|
|
; time slice like every other one does
|
|
|
|
lda #pRunning
|
|
sta ProcessState,x
|
|
dec irq_S,x ; make room on new stack
|
|
dec irq_S,x ;
|
|
dec irq_S,x ;
|
|
dec irq_S,x ;
|
|
jsr SetInterruptState ; set up A,X,Y, etc
|
|
lda irq_D,x
|
|
tcd
|
|
lda irq_S,x ; new proc's stack
|
|
tcs ;
|
|
lda irq_P,x ;
|
|
and #%11111011 ; make sure interrupts are on when
|
|
sta 1,S ; we start the new process
|
|
lda irq_PC,x ; fake an interrupt
|
|
sta 2,S ; on the new process' stack
|
|
short a
|
|
lda irq_K,x
|
|
sta 4,s
|
|
pha
|
|
plb
|
|
long a
|
|
lda >intType
|
|
bne vbl
|
|
jmp newViaCOP ; this is required in order to
|
|
vbl jmp newViaVBL ; turn off VBL if one occurred
|
|
|
|
longa on ; grr stupid stupid m/x 816
|
|
longi on ; fricken bits
|
|
|
|
okay anop
|
|
* ; we'll return to COP or int hndl
|
|
jsr SetInterruptState
|
|
ldx curProcInd
|
|
lda #pRunning
|
|
sta ProcessState,x
|
|
; lda irq_S1,x
|
|
; clc
|
|
; adc #3
|
|
lda irq_S,x
|
|
tcs
|
|
lda >intType
|
|
bne vbl1
|
|
jmp newViaCOP ; this is required in order to
|
|
vbl1 jmp newViaVBL ; turn off VBL if one occurred
|
|
|
|
goaway anop ; well, so much for that!
|
|
rtl
|
|
temp dc i4'0'
|
|
timState dc i2'0'
|
|
stat dc i2'0'
|
|
END
|
|
|
|
longa on
|
|
longi on
|
|
|
|
GetInterruptState START
|
|
using KernelStruct
|
|
using IntState
|
|
|
|
lda int_A
|
|
sta irq_A,x
|
|
lda int_X
|
|
sta irq_X,x
|
|
lda int_Y
|
|
sta irq_Y,x
|
|
lda int_B
|
|
sta irq_B,x
|
|
lda int_P
|
|
sta irq_P,x
|
|
lda int_D
|
|
sta irq_D,x
|
|
lda int_S
|
|
sta irq_S,x
|
|
lda int_state
|
|
sta irq_state,x
|
|
lda int_SLTROM
|
|
sta irq_SLTROM,x
|
|
rts
|
|
END
|
|
|
|
SetInterruptState START
|
|
using KernelStruct
|
|
using IntState
|
|
|
|
lda irq_A,x
|
|
sta int_A
|
|
lda irq_X,x
|
|
sta int_X
|
|
lda irq_Y,x
|
|
sta int_Y
|
|
lda irq_B,x
|
|
sta int_B
|
|
lda irq_P,x
|
|
sta int_P
|
|
lda irq_D,x
|
|
sta int_D
|
|
lda irq_S,x
|
|
sta int_S
|
|
lda irq_state,x
|
|
sta int_state
|
|
lda irq_SLTROM,x
|
|
sta int_SLTROM
|
|
rts
|
|
END
|
|
|
|
; we need FindNextEntry to return x -> ProcessState,x
|
|
; When we're of a mind to, rewrite this to support priority scheduling
|
|
; (it will involve keeping a queue of 'Ready' processes).
|
|
|
|
FindNextEntry Start
|
|
Using KernelStruct
|
|
ldx curProcInd
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
cpx #(procEntSize*NPROC)
|
|
bmi loop
|
|
ldx #0
|
|
loop lda ProcessState,x
|
|
cmp #pReady
|
|
beq found
|
|
cmp #pNew
|
|
beq found
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
|
|
cpx #(procEntSize*NPROC)
|
|
bcc loop
|
|
ldx #0
|
|
bra loop
|
|
found rts
|
|
End
|
|
|
|
* if X is -1 then the FindEmptyEntry call failed
|
|
* this needs to return offset in ProcessState otherwise
|
|
|
|
FindEmptyEntry Start
|
|
Using KernelStruct
|
|
ldx #procEntSize
|
|
loop lda ProcessState,x
|
|
cmp #pUnused
|
|
beq found
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
cpx #(procEntSize*NPROC)
|
|
bcc loop
|
|
notfound ldx #$FFFF
|
|
found rts
|
|
End
|
|
|
|
|
|
; the NASTY assembly interface to the process tables
|
|
; currently, eight process entries are defined, and this must be set
|
|
; manually if NUMPROC in the system header files are changed. Kinda yucky,
|
|
; but then there's no other way.
|
|
|
|
KernelStruct DATA
|
|
CKernData ENTRY
|
|
ParentProc dc i2'-1' ;0
|
|
ProcessState dc i2'0' ;2
|
|
procUserID dc i2'0' ;4
|
|
ttyID dc i2'0' ;6
|
|
irq_A dc i2'0' ;8
|
|
irq_X dc i2'0' ;10
|
|
irq_Y dc i2'0' ;12
|
|
irq_S dc i2'0' ;14
|
|
irq_D dc i2'0' ;16
|
|
irq_B dc i2'0' ;18
|
|
irq_P dc i2'0' ;20
|
|
irq_state dc i2'0' ;22
|
|
irq_PC dc i2'0' ;24
|
|
irq_K dc i2'0' ;26
|
|
psem dc i2'0' ;28
|
|
prefixh dc i4'0' ;30
|
|
argsp dc i4'0' ;34
|
|
env dc i4'0' ;38
|
|
siginfo dc i4'0' ;42
|
|
irq_SLTROM dc i1'0' ;46
|
|
irq_STATEREG dc i1'0' ;47
|
|
resapp anop
|
|
lastTool dc i2'0' ;48
|
|
ticks dc i4'0' ;50
|
|
flags dc i2'0' ;54
|
|
openFiles dc i4'0' ;56
|
|
pgrp dc i2'0' ;60
|
|
exitCode dc i2'0' ;62
|
|
LInfo dc i4'0' ;64
|
|
stoppedState dc i2'0' ;68
|
|
alarmCount dc i4'0' ;70
|
|
executeHook dc i4'0' ;74
|
|
queueLink dc i2'0' ;78
|
|
waitq dc i4'0' ;80
|
|
waitdone dc i2'0' ;84
|
|
flpid dc i2'1' ;86
|
|
retStack dc i4'0' ;88
|
|
t2StackPtr dc i2'0' ;92
|
|
p_uid dc i2'0' ;94
|
|
p_gid dc i2'0' ;96
|
|
p_euid dc i2'0' ;98
|
|
p_egid dc i2'0' ;100
|
|
SANEwap dc i2'0' ;102
|
|
msg dc i4'0' ;104
|
|
childTicks dc i4'0' ;108
|
|
p_waitvec dc i4'0' ;112
|
|
p_slink dc i2'0' ;116
|
|
p_link dc i4'0' ;118
|
|
p_rlink dc i4'0' ;122
|
|
p_prio dc i2'0' ;126
|
|
procEntSize gequ *-CKernData
|
|
|
|
ProcessQueue ds 128*31 ; more o' the above
|
|
curProcInd dc i2'0' ; basically current process ID
|
|
userID dc i2'0' ; kernel userID
|
|
mutexNOMO dc i2'0' ; system-wide mutex flag.
|
|
timeleft dc i2'TIMESLICE' ; number of ticks left in timeslice
|
|
numProcs dc i2'1' ; number of processes active (inc.Null)
|
|
truepid dc i2'0' ; curProcInd/128
|
|
shutdown dc i2'0' ; should the null process exit?
|
|
gsosDebug dc i2'0' ; GS/OS Debug level
|
|
floatingPID dc i2'2' ; next pid to allocate
|
|
reschedFlag dc i2'0'
|
|
END
|
|
|
|
_asmresched START
|
|
using KernelStruct
|
|
|
|
* give process our remaining time plus theirs
|
|
lda >timeleft
|
|
inc a
|
|
sta >timeleft
|
|
cop $7f ; force a context switch
|
|
rts
|
|
END
|
|
|
|
vogue DATA
|
|
dc c'TIDDLYWINKS000000',h'00'
|
|
END
|
|
|
|
NullProcess START
|
|
using KernelStruct
|
|
using sigQueue
|
|
using deferdata
|
|
|
|
itself anop
|
|
|
|
; check for deferred actions (probably from an interrupt handler to wake
|
|
; up a process) and execute them until no more are left.
|
|
defer_loop lda defer_num
|
|
beq no_defer
|
|
jsl exec_defer
|
|
bra defer_loop
|
|
no_defer anop
|
|
|
|
* if a CDA event is pending across two consecutive runs of the nullprocess,
|
|
* GetNextEvent to initiate the CDA.
|
|
* Only do the check every four invocations of NullProcess to avoid
|
|
* unnecessary overhead
|
|
|
|
dec loopcnt
|
|
bne noCDA
|
|
lda #4
|
|
sta loopcnt
|
|
|
|
pha
|
|
pea $0400
|
|
ph4 #evtRecord
|
|
_EventAvail
|
|
pla
|
|
cmp #0
|
|
beq noCDA
|
|
lda cdaFlag
|
|
cmp #1
|
|
bcc justInc
|
|
pha
|
|
pea $0400
|
|
ph4 #evtRecord
|
|
_GetNextEvent
|
|
pla
|
|
stz cdaFlag
|
|
bra noCDA
|
|
|
|
justInc inc a
|
|
sta cdaFlag
|
|
|
|
noCDA lda sighead
|
|
cmp sigtail
|
|
beq nosigs
|
|
jsl incBusy
|
|
lda sighead
|
|
asl a
|
|
tax
|
|
|
|
pha
|
|
lda procs,x
|
|
pha
|
|
lda sigs,x
|
|
pha
|
|
ph4 #sigerr
|
|
jsl KERNkill ; this is #pragma toolparms 1
|
|
pla
|
|
|
|
lda sighead
|
|
inc a
|
|
sta sighead
|
|
cmp #32
|
|
bcc inrange
|
|
stz sighead
|
|
inrange jsl decBusy
|
|
|
|
nosigs anop
|
|
lda shutdown
|
|
bne endGNO ; kill() will shut down processes before this
|
|
jsl readyEntry
|
|
cpx #0 ; if it only found us, loop to avoid
|
|
beq jumpfuck ; interrupt overhead
|
|
cop $7f ; otherwise, let that process run
|
|
jumpfuck jmp itself
|
|
endGNO anop
|
|
rtl
|
|
sigerr dc i2'0'
|
|
loopcnt dc i2'4'
|
|
cdaFlag dc i2'0'
|
|
evtRecord ds 16
|
|
END
|
|
|
|
sigQueue DATA
|
|
sighead dc i2'0'
|
|
sigtail dc i2'0'
|
|
sigs ds 64
|
|
procs ds 64
|
|
END
|
|
|
|
queueSignal START
|
|
using sigQueue
|
|
pha
|
|
phx
|
|
lda sigtail
|
|
asl a
|
|
tax
|
|
lda 1,s
|
|
sta sigs,x
|
|
lda 3,s
|
|
sta procs,x
|
|
|
|
lda sigtail
|
|
inc a
|
|
sta sigtail
|
|
cmp #32
|
|
bcc inrange
|
|
stz sigtail
|
|
|
|
inrange plx
|
|
pla
|
|
rts
|
|
END
|
|
|
|
longa off
|
|
alarmHB DATA
|
|
dc i4'0'
|
|
ALtimer dc i2'6'
|
|
dc h'5AA5'
|
|
END
|
|
alarmRoutine START
|
|
using alarmHB
|
|
using KernelStruct
|
|
using SelTimStruct
|
|
|
|
php
|
|
long ai
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
; re-activate our heart beat entry
|
|
lda #6
|
|
sta ALtimer
|
|
|
|
; check for SIGALRM timeouts
|
|
ldx #0
|
|
loop anop
|
|
lda ProcessState,x
|
|
cmp #pUnused
|
|
beq nextProc
|
|
lda alarmCount,x
|
|
ora alarmCount+2,x
|
|
beq nextProc
|
|
lda alarmCount,x
|
|
sec
|
|
sbc #1
|
|
sta alarmCount,x
|
|
lda alarmCount+2,x
|
|
sbc #0
|
|
sta alarmCount+2,x
|
|
ora alarmCount,x
|
|
bne nextProc
|
|
phx
|
|
lda flpid,x
|
|
ldx #14
|
|
jsr queueSignal
|
|
plx
|
|
nextProc anop
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
cpx #(procEntSize*NPROC)
|
|
bcc loop
|
|
|
|
; check for select() timeouts
|
|
ldx #0
|
|
selloop anop
|
|
lda SelTimTimeout,x
|
|
ora SelTimTimeout+2,x
|
|
beq nextSel
|
|
lda SelTimTimeout,x
|
|
sec
|
|
sbc #1
|
|
sta SelTimTimeout,x
|
|
lda SelTimTimeout+2,x
|
|
sbc #0
|
|
sta SelTimTimeout+2,x
|
|
ora SelTimTimeout,x
|
|
bne nextSel
|
|
lda #1
|
|
sta SelTimExpired,x
|
|
phx
|
|
lda SelTimPID,x ; wake up this PID
|
|
pha
|
|
pea 0 ; no collision
|
|
jsl selwakeup
|
|
plx
|
|
nextSel anop
|
|
txa
|
|
clc
|
|
adc #8
|
|
tax
|
|
cpx #(8*NPROC)
|
|
bcc selloop
|
|
|
|
plb
|
|
plp
|
|
rtl
|
|
END
|
|
|
|
* AHHA!
|
|
* The remarkably simple new Kernel mutex method
|
|
* is totally based off of BusyFlag. Now things seem to work much
|
|
* smoother, and I can accomplish all sorts of stuff now.
|
|
* Yea, right, you dumbshit (jb 7/5/93)
|
|
|
|
incBusy START
|
|
disableps ENTRY
|
|
jmp >$E10064
|
|
decBusy ENTRY
|
|
enableps ENTRY
|
|
jmp >$E10068
|
|
END
|
|
|
|
newDecBusy START
|
|
using KernelStruct
|
|
|
|
php
|
|
pha
|
|
jsl oldDecBusy
|
|
lda >timeleft
|
|
bne stillmore
|
|
lda >BusyFlag
|
|
bne stillmore
|
|
lda >reschedFlag
|
|
bne stillmore ; don't reschedule
|
|
|
|
* We now allow a context switch when interrupts are off - this
|
|
* allows flawless execution of semaphore sleep code, etc.
|
|
|
|
lda 3,s ; check the P reg- is the
|
|
bit #4 ; i bit set? if so, do not task
|
|
bne stillmore ; switch
|
|
|
|
lda >$E100CB
|
|
and #$FF
|
|
bne stillmore ; we're in an interrupt handler!
|
|
|
|
tsc
|
|
and #$FF00
|
|
cmp #$0100
|
|
beq stillmore
|
|
|
|
pla
|
|
plp
|
|
jsl fakeACop
|
|
; cop $7f ; we're out o' time
|
|
rtl
|
|
stillmore pla
|
|
plp
|
|
rtl
|
|
|
|
END
|
|
|
|
ttyStruct START
|
|
pgrp dc 38i2'0'
|
|
END
|
|
|
|
* BGCheck MUST MUST MUST be called only if the busy flag is zero
|
|
* otherwise, the process will not be suspended before it does the
|
|
* I/O procedure.
|
|
* Note that the use of this routine in TextTools to generate an error code
|
|
* is okay, because the only way for a program to have blocked or ignored
|
|
* the signal is to be aware of GNO, and if they do that they should check for
|
|
* errors from these texttools calls (which they should check for anyway).
|
|
* Input: A = signal number
|
|
* X = TTY device number
|
|
* needs to be in the kernel segment
|
|
|
|
BGCheck START
|
|
using KernelStruct
|
|
|
|
retval equ 1
|
|
signum equ 1
|
|
signum2 equ 5
|
|
sigptr equ 1
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
phd
|
|
pha ; push input parameter
|
|
tsc
|
|
tcd
|
|
|
|
txa
|
|
asl a
|
|
tax
|
|
lda ttyStruct,x
|
|
beq nopgrp
|
|
ldx curProcInd
|
|
cmp pgrp,x
|
|
beq nopgrp ; it's the foreground process
|
|
lda siginfo+2,x
|
|
pha
|
|
lda siginfo,x
|
|
pha
|
|
tsc
|
|
tcd
|
|
lda #$0010
|
|
ldy signum2
|
|
cpy #21
|
|
beq noasl
|
|
asl a
|
|
noasl ldy #2
|
|
and [sigptr],y
|
|
bne sigblocked
|
|
lda signum2
|
|
dec a
|
|
asl a
|
|
asl a
|
|
clc
|
|
adc #8
|
|
tay
|
|
lda [sigptr],y
|
|
cmp #1
|
|
bne notign
|
|
iny2
|
|
lda [sigptr],y
|
|
cmp #0
|
|
bne notign
|
|
* the signal is ignored or blocked, so do not send the signal, and
|
|
* tell the caller that we did not.
|
|
sigblocked pla
|
|
pla
|
|
pla
|
|
lda #-1
|
|
pld
|
|
plb
|
|
rtl
|
|
* the signal was not ignored or blocked, so send the signal,
|
|
* tell the caller that we did, and return
|
|
|
|
notign lda pgrp,x
|
|
pha
|
|
pei (signum2)
|
|
jsl asmkillpg
|
|
cop $7F
|
|
pla
|
|
pla
|
|
pla
|
|
lda #1
|
|
pld
|
|
plb
|
|
rtl
|
|
* the caller was indeed in the TTY's process group, and so should be left
|
|
* quite alone.
|
|
nopgrp pla
|
|
lda #0
|
|
pld
|
|
plb
|
|
rtl
|
|
END
|
|
|
|
asmkillpg START
|
|
using KernelStruct
|
|
subroutine (2:pg,2:signum),0
|
|
|
|
ldx #128 ; don't EVER signal the kernel
|
|
sigloop lda ProcessState,x
|
|
cmp #pUnused
|
|
beq nextproc
|
|
lda pgrp,x
|
|
cmp pg
|
|
bne nextproc
|
|
|
|
phx
|
|
lda flpid,x
|
|
ldx signum
|
|
jsr queueSignal
|
|
plx
|
|
|
|
nextproc anop
|
|
txa
|
|
clc
|
|
adc #128
|
|
tax
|
|
cpx #4096 ; oops!
|
|
bcc sigloop
|
|
return
|
|
END
|
|
|
|
extQSignal START
|
|
using KernelStruct
|
|
space equ 0
|
|
subroutine (2:s,2:p),space
|
|
lda p
|
|
ldx s
|
|
jsr queueSignal
|
|
return
|
|
END
|
|
|
|
ttyQSignal START
|
|
using KernelStruct
|
|
space equ 0
|
|
subroutine (2:s,2:tty),space
|
|
|
|
lda tty
|
|
asl a
|
|
tax
|
|
lda ttyStruct,x
|
|
beq noSignal ; no process group
|
|
pha
|
|
ldx #128 ; don't EVER signal the kernel
|
|
sigloop lda ProcessState,x
|
|
cmp #pUnused
|
|
beq nextproc
|
|
lda pgrp,x
|
|
cmp 1,s
|
|
bne nextproc
|
|
|
|
phx
|
|
lda >flpid,x
|
|
ldx s
|
|
jsr queueSignal
|
|
plx
|
|
nextproc anop
|
|
txa
|
|
clc
|
|
adc #128
|
|
tax
|
|
cpx #4096 ; oops!
|
|
bcc sigloop
|
|
pla
|
|
noSignal return
|
|
END
|
|
|
|
snooperInfo DATA KERN2
|
|
blockLen dc i2'len-blockLen'
|
|
nameString str '~PROCYON~GNO~SNOOPER'
|
|
s_procTable dc i4'CKernData'
|
|
s_pipeTable dc i4'pipeRecord'
|
|
refTrack dc i4'pipeData' ; lots of dereffing, but hey!
|
|
queueSig dc i4'extQSignal'
|
|
info1 dc i4'savedCDAInfo'
|
|
reftty dc i4'ttyStruct'
|
|
refpgrp dc i4'pgrpInfo'
|
|
refRefTab dc i4'pipeData'
|
|
len equ *
|
|
END
|
|
|
|
* At this point, the process RTL address is on the stack. Push the P
|
|
* register to complete simulating the interrupt environment.
|
|
|
|
fakeACop START
|
|
php
|
|
sei
|
|
long m
|
|
pha
|
|
lda 4,s
|
|
inc a ; 'fix' rti address
|
|
sta 4,s
|
|
pla
|
|
jmp >CopVect
|
|
END
|
|
|
|
readyEntry Start KERN2
|
|
Using KernelStruct
|
|
|
|
ldx #(1*procEntSize)
|
|
loop lda >ProcessState,x
|
|
cmp #pReady
|
|
beq found
|
|
cmp #pNew
|
|
beq found
|
|
txa
|
|
clc
|
|
adc #procEntSize
|
|
tax
|
|
|
|
cpx #(procEntSize*NPROC)
|
|
bcc loop
|
|
ldx #0
|
|
rtl
|
|
found rtl
|
|
End
|
|
|
|
sleepbusy START KERN2
|
|
php
|
|
sei
|
|
short m
|
|
lda >$E100FF
|
|
pha
|
|
lda #0
|
|
sta >$E100FF
|
|
cop $7F
|
|
pla
|
|
sta >$E100FF
|
|
plp
|
|
rtl
|
|
END
|
|
|
|
longa on
|
|
longi on
|
|
|
|
exec_defer START
|
|
using deferdata
|
|
proc equ 0
|
|
val1 equ 4
|
|
val2 equ 6
|
|
|
|
subroutine (0:foo),8
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
|
|
php
|
|
sei
|
|
ldy defer_tail
|
|
tya
|
|
iny
|
|
cpy #NUM_DEFER
|
|
bne nowrap
|
|
ldy #0
|
|
nowrap sty defer_tail
|
|
dec defer_num
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda defertab,x
|
|
sta proc
|
|
lda defertab+2,x
|
|
sta proc+2
|
|
lda defertab+4,x
|
|
sta val1
|
|
lda defertab+6,x
|
|
sta val2
|
|
plp
|
|
|
|
; pass params in 'C' format
|
|
pei (val2)
|
|
pei (val1)
|
|
; push return address
|
|
phk
|
|
pea |comeback-1
|
|
; push routine address
|
|
short m
|
|
lda proc+2
|
|
pha
|
|
long m
|
|
lda proc
|
|
dec a
|
|
pha
|
|
rtl
|
|
|
|
comeback anop
|
|
plb
|
|
return
|
|
|
|
END
|
|
|
|
defer START
|
|
using deferdata
|
|
subroutine (4:procPtr,2:val1,2:val2),
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
|
|
php
|
|
sei
|
|
lda defer_num
|
|
cmp #NUM_DEFER
|
|
beq fail
|
|
|
|
ldy defer_head
|
|
tya
|
|
iny
|
|
cpy #NUM_DEFER
|
|
bne nowrap
|
|
ldy #0
|
|
nowrap sty defer_head
|
|
inc defer_num
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda procPtr
|
|
sta defertab,x
|
|
lda procPtr+2
|
|
sta defertab+2,x
|
|
lda val1
|
|
sta defertab+4,x
|
|
lda val2
|
|
sta defertab+6,x
|
|
fail1 plp
|
|
|
|
plb
|
|
return
|
|
fail anop
|
|
short m
|
|
lda >$E0C034
|
|
and #$F0
|
|
pha
|
|
lda >$E0C034
|
|
inc a
|
|
and #$F
|
|
ora 1,s
|
|
sta >$E0C034
|
|
pla
|
|
long m
|
|
bra fail1
|
|
END
|
|
|
|
deferdata DATA
|
|
defer_head dc i2'0'
|
|
defer_tail dc i2'0'
|
|
defer_num dc i2'0'
|
|
defertab ds 8*NUM_DEFER
|
|
END
|
|
|
|
k_sleep START
|
|
using KernelStruct
|
|
|
|
hv equ 0
|
|
last equ 2
|
|
pid128 equ 4
|
|
|
|
subroutine (2:pid,2:pri,4:vec),6
|
|
|
|
jsl disableps
|
|
|
|
lda vec hv = hash_vector(vec);
|
|
and #$3F
|
|
sta hv
|
|
lda pid
|
|
and #$00FF
|
|
xba
|
|
lsr a
|
|
sta pid128
|
|
tax
|
|
lda vec
|
|
sta >p_waitvec,x
|
|
lda vec+2
|
|
sta >p_waitvec+2,x
|
|
|
|
lda hv
|
|
asl a
|
|
tax
|
|
lda >hv_tab,x
|
|
sta last
|
|
cmp #0
|
|
bne addtoend
|
|
lda pid
|
|
sta >hv_tab,x
|
|
bra skip1
|
|
|
|
addtoend anop
|
|
and #$FF
|
|
xba
|
|
lsr a
|
|
tax
|
|
lda >p_slink,x
|
|
bne addtoend
|
|
|
|
; last proc index is in X
|
|
|
|
lda pid
|
|
sta >p_slink,x
|
|
skip1 lda #0
|
|
ldx pid128
|
|
sta >p_slink,x
|
|
pei (pid)
|
|
jsl dosleep
|
|
jsl sleepbusy
|
|
jsl enableps
|
|
return
|
|
END
|
|
|
|
longa on
|
|
longi on
|
|
* used to be in signal.c, orig. C source still is
|
|
Kreceive START KERN2
|
|
using KernelStruct
|
|
|
|
tmp equ 0
|
|
subroutine (4:errnoptr),4
|
|
|
|
lda >curProcInd
|
|
tax
|
|
|
|
php
|
|
sei
|
|
lda #2
|
|
sta >waitdone,x
|
|
lda >flags,x
|
|
bit #$0080 ; FL_MSGRECVD
|
|
bne gotmsg
|
|
lda #3
|
|
sta >ProcessState,x
|
|
jsl sleepbusy
|
|
gotmsg lda >waitdone,x
|
|
cmp #2
|
|
bne huhwhat
|
|
lda >msg,x
|
|
sta tmp
|
|
lda >msg+2,x
|
|
sta tmp+2
|
|
lda >flags,x
|
|
; and #$0080.EOR.$FFFF
|
|
and #$FF7F
|
|
sta >flags,x
|
|
bra what2
|
|
huhwhat lda #$FFFF
|
|
sta tmp
|
|
sta tmp+2
|
|
what2 plp
|
|
return 4:tmp
|
|
END
|