home *** CD-ROM | disk | FTP | other *** search
- SETTYPE "MODULE"
- OBJECT "!YAMU.Initiator"
- ORG 0
- ASSUME PC,0
- ASSUME R12,&10000000
-
- SET VSTR,"1.00"
-
- DD LANGUAGE,0,0,SERVICE,TITLE,HELP,0,0,0,0,0
-
- TITLE DB "Initiator",0
- ALIGN
-
- HELP DB "Initiator",9,"`VSTR` (",OSVAR "Sys$Date" RIGHT 6," ",OSVAR "Sys$Year",")",0
- ALIGN
-
- TASKDESC
- DB "Init",0
- ALIGN
-
- LANGUAGE
- LOCALS
- MOV R11,R0
-
- ; Claim memory
-
- MOV R0,#6
- LIT R3,WEND-WSTART
- SWI "OS_Module"
- STR R2,[R12]
- STR R12,[R2]
- MOV R12,R2
-
- ; Initialise variables
-
- MOV R0,#0
- ST R0,MEMORYMAPVETOED
- ST R0,OUTBUFFERREAD
- ST R0,OUTBUFFERWRITE
- ST R0,MESSAGES
- ST R0,SUSPENDED
- ST R0,TERMINATING
- ST R0,HANDLESUSED
-
- ; Register as Wimp task
-
- MOV R0,#200
- LIT R1,&4B534154
- ADR R2,TASKDESC
- SWI "Wimp_Initialise"
- ST R1,TASKHANDLE
-
- ; Calculate appropriate (initial) slot size. This is not calculated
- ; in any special way, it just tries to allocate a reasonable amount
- ; of space. The newer applications ask the Wimp for more space if
- ; they run out.
-
- MVN R0,#0
- MVN R1,#0
- SWI "Wimp_SlotSize"
- ADD R0,R0,R1
- ADD R0,R0,R2
- CMP R0,#512*1024
- MOVGE R0,#512*1024
- SUBLT R0,R0,#64*1024
- CMP R0,#0
- MOVLE R0,#16*1024
- MVN R1,#0
- SWI "Wimp_SlotSize"
-
- ; Initialise environment, so that funny things don't happen when the
- ; background task calls the exit handler, etc. In fact the exit
- ; handler has to come back into this code in order for us to tidy up.
-
- MOV R0,#6 ; Error handler
- ADR R1,ERRORHANDLER
- MOV R2,R12
- ADR R3,ERRORBUFFER
- SWI "OS_ChangeEnvironment"
- ADR R0,OLDERRORHANDLER
- STMIA R0,{R1-R3}
-
- MOV R0,#11 ; Exit handler
- ADR R1,EXITHANDLER
- MOV R2,R12
- MOV R3,#0
- SWI "OS_ChangeEnvironment"
- ADR R0,OLDEXITHANDLER
- STMIA R0,{R1-R3}
-
- ; Set interruption of background task
-
- BL SETCALLAFTER
- BL CLAIMVECS
-
- ; And start the task off
-
- MOV R0,R11
- SWI "OS_Write0" ; This just writes the name of the command
- SWI "OS_NewLine" ; run into the output buffer.
- MOV R0,R11
- SWI "OS_CLI" ; Execute the * command that runs the task.
-
- ; This may return, if no application is started. In this case, there
- ; is an outstanding ticker event to cancel, but apart from that we
- ; just exit.
-
- ADR R13,USRSTACK
- BL CANCELTICKER ; Cancel the descheduling time-out.
- BL RELEASEVECS ; Release vectors we have claimed.
- B KILLMODULE
-
- MAINLOOP
- BL RELEASEVECS ; Must release all vectors before polling.
- A
- MOV R0,#0
- ADR R1,POLLBLOCK
- SWI "Wimp_Poll"
- TEQ R0,#0
- BLNE NONIDLEPOLL
- ADR R13,USRSTACK
- BL RECEIVEMESSAGES
- BNE A
-
- ; See whether the output buffer is empty - if not we wait until it
- ; has been emptied before running the task again.
-
- LD R0,OUTBUFFERREAD
- LD R1,OUTBUFFERWRITE
- TEQ R0,R1
- BNE A
-
- ; If the task has been stopped by the controlling task, don't
- ; reschedule it.
-
- LD R0,SUSPENDED
- TEQ R0,#0
- BNE A
-
- ; Set up conditions for re-entering task
-
- BL SETCALLAFTER ; Create a new CallAfter event
- BL CLAIMVECS ; and claim the vectors again.
-
- ; If the task is being terminated, get ready to call OS_Exit
-
- LD R0,TERMINATING
- TEQ R0,#0
- MOV R0,#0
- ST R0,TERMINATING
-
- ; Back into the task again. When restoring the registers, note that
- ; the correct method for doing this is very dependent on the current
- ; processor mode - what is shown is NOT a general way of restoring
- ; a register dump after an exception.
-
- ADR R0,REGBUF
- LDMEQIA R0,{R0-PC}^ ; Restore the task's registers.
- LDMIA R0,{R0-R14}
- MOV R0,#0
- LIT R1,&58454241
- MOV R2,#2
- SWI "OS_Exit" ; Task is being terminated. Note how we can
- ; even call OS_Exit "within" a CallBack handler.
-
- ; General rubbish to do with being a Wimp task, nothing amazing here.
-
- NONIDLEPOLL
- TEQ R0,#17
- TEQNE R0,#18
- MOVNES PC,R14
- LD R0,POLLBLOCK+16
- TEQ R0,#0 ; Message_Quit
- MOVNES PC,R14
- ADR R13,USRSTACK
- BL CANCELTICKER
- MOV R0,#0
- ST R0,OUTBUFFERREAD
- ST R0,OUTBUFFERWRITE
-
- ; and continue into KILLMODULE, below.
-
- ; Code to kill the module off. Nothing here that you don't get in
- ; other modules, the only point worthy of note is that we hang around
- ; in this routine until all the characters have been read out of the
- ; circular buffer.
-
- KILLMODULE
- LOCALS
-
- ; Restore environment
-
- MOV R0,#6 ; Error handler
- ADR R1,OLDERRORHANDLER
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
-
- MOV R0,#11 ; Exit handler
- ADR R1,OLDEXITHANDLER
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
-
- ; Write the return code into the message word, for the foreground
- ; task
-
- LD R0,RETURNCODE
- ORR R0,R0,#&80000000
- ST R0,MESSAGES
-
- ; Now call Wimp_Poll until all the characters have been removed from
- ; the buffer and the return code has been read
-
- A
- MOV R0,#0
- ADR R1,POLLBLOCK
- SWI "Wimp_Poll"
- LD R0,OUTBUFFERREAD
- LD R1,OUTBUFFERWRITE
- TEQ R0,R1
- BNE A
- LD R0,MESSAGES
- TEQ R0,#0
- BNE A
-
- ; Finish off as a Wimp task
-
- LD R0,TASKHANDLE
- LIT R1,&4B534154
- SWI "Wimp_CloseDown"
-
- ; Release workspace
-
- MOV R0,#7
- MOV R2,R12
- SWI "OS_Module"
-
- ; Zero private word so RISC OS doesn't free it again!!
-
- LD R0,PRIVATEWORD
- MOV R1,#0
- STR R1,[R0]
-
- ; ExitAndDie to end program and kill module; don't set return code
- ; as this was set by foreground task.
-
- MOV R0,#0
- MOV R1,#0
- MOV R2,#0
- ADR R3,TITLE
- SWI "OS_ExitAndDie"
-
- ; Just a standard service call handler. Traps Service_Memory so we
- ; get to keep the memory that the pre-empted task will run in!
-
- SERVICE
- ; Nothing to do here except veto attempts by the Wimp to remove all
- ; our memory - this is tried once at the start.
-
- TEQ R1,#&11 ; Service_Memory
- MOVNES PC,R14
- STMFD R13!,{R0,R12,R14}
- LDR R12,[R12]
- LD R0,MEMORYMAPVETOED
- TEQ R0,#0
- LDMNEFD R13!,{R0,R12,PC}^
- MOV R1,#0
- MOV R0,#1
- ST R0,MEMORYMAPVETOED
- LDMFD R13!,{R0,R12,PC}^
-
- ; Claim write character (so we redirect the program's output into
- ; the circular buffer) and open file (so we know what files the
- ; program has open, so we can close them again if it is killed).
-
- CLAIMVECS
- MOV R0,#3 ; WrchV
- ADR R1,WRCHV
- MOV R2,R12
- SWI "OS_Claim"
-
- MOV R0,#&D ; FindV
- ADR R1,FINDV
- MOV R2,R12
- SWI "OS_Claim"
-
- MOVS PC,R14
-
- RELEASEVECS
- MOV R0,#3 ; WrchV
- ADR R1,WRCHV
- MOV R2,R12
- SWI "OS_Release"
-
- MOV R0,#&D ; FindV
- ADR R1,FINDV
- MOV R2,R12
- SWI "OS_Release"
-
- MOVS PC,R14
-
- ; Schedule a descheduling event.
-
- SETCALLAFTER
- MOV R0,#20
- ADR R1,INTERRUPT
- MOV R2,R12
- SWI "OS_CallAfter"
- MOVS PC,R14
-
- CANCELTICKER
- STMFD R13!,{R0,R1,R14}
- ADR R0,INTERRUPT
- MOV R1,R12
- SWI "OS_RemoveTickerEvent"
- LDMFD R13!,{R0,R1,PC}^
-
- WRCHV
- STMFD R13!,{R1-R2}
- LD R1,OUTBUFFERREAD
- LD R2,OUTBUFFERWRITE
- ADD R2,R2,#2
- BIC R2,R2,#&400
- TEQ R1,R2
- BLEQ CANCELTICKER
- BLEQ SETCALLBACK
- LD R1,OUTBUFFERWRITE
- ADR R2,OUTBUFFER
- STRB R0,[R1,R2]
- ADD R1,R1,#1
- BIC R1,R1,#&400
- ST R1,OUTBUFFERWRITE
- LDMFD R13!,{R1-R2}
- LDMFD R13!,{PC}^
-
- FINDV
- LOCALS
- TEQ R0,#0 ; Closing a file
- BEQ A
- STMFD R13!,{R12}
- STMFD R13!,{PC}
- MOVS PC,R14
- MOV R0,R0 ; Our code is re-entered a word further down, so we waste
- ; this word.
- LDMFD R13!,{R12}
- LDMVSFD R13!,{PC}
- STMFD R13!,{R2,R3}
- ADR R2,HANDLES
- LD R3,HANDLESUSED
- TEQ R3,#32
- MOVEQ R3,#31
- STR R0,[R2,R3,LSL #2]
- ADD R3,R3,#1
- ST R3,HANDLESUSED
- LDMFD R13!,{R2,R3}
- LDMFD R13!,{PC}^
- A
- TEQ R1,#0 ; Closing all files
- BEQ B
- STMFD R13!,{R2,R8,R9,R14}
- LD R8,HANDLESUSED
- ADR R9,HANDLES
- C
- TEQ R8,#0
- LDMEQFD R13!,{R2,R8,R9,PC}^
- LDR R2,[R9],#4
- SUB R8,R8,#1
- TEQ R1,R2
- BNE C
- MOV R2,#0
- STR R2,[R9,#-4]
- LDMFD R13!,{R2,R8,R9,PC}^
- B
- STMFD R13!,{R0,R14}
- MOV R0,#0
- ST R0,HANDLESUSED
- LDMFD R13!,{R0,PC}^
-
- INTERRUPT
- ; Remember that we must not corrupt R14svc, so we have to mess about
- ; with changing processor mode.
-
- STMFD R13!,{R0,R14} ; R14irq goes onto irq stack.
- MOVS R0,PC ; Preserve old processor mode.
- TEQP PC,#3
- MOV R0,R0
- STMFD R13!,{R14}
- BL SETCALLBACK ; Use CallBack code.
- LDMFD R13!,{R14}
- TEQP R0,#0
- MOV R0,R0
- LDMFD R13!,{R0,PC}^
-
- ; The following is just standard CallBack code, it restores the
- ; handler address to its old value before returning to the main
- ; program loop.
-
- SETCALLBACK
- STMFD R13!,{R0-R3,R14}
- MOV R0,#7 ; CallBack
- ADR R1,CALLBACKHANDLER
- MOV R2,R12
- ADR R3,REGBUF
- SWI "OS_ChangeEnvironment"
- ADR R14,OLDCALLBACK
- STMIA R14,{R1-R3}
- SWI "OS_SetCallBack"
- LDMFD R13!,{R0-R3,PC}^
-
- CALLBACKHANDLER
- TEQP PC,#0
- MOV R0,R0
- MOV R0,#7
- ADR R1,OLDCALLBACK
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
- B MAINLOOP
-
- ; If we get an error reported, we write it into the circular buffer
- ; and kill the program.
-
- ERRORHANDLER
- MOV R12,R0
- MOV R0,#2
- ST R0,RETURNCODE
- SWI "OS_NewLine"
- ADR R0,ERRORBUFFER+8
- SWI "OS_Write0"
- SWI "OS_NewLine"
- ADR R13,USRSTACK
- BL CANCELTICKER
- BL RELEASEVECS
- B KILLMODULE
-
- ; If the program exits, we tidy up.
-
- EXITHANDLER
- ST R2,RETURNCODE
- ADR R13,USRSTACK
- BL CANCELTICKER
- BL RELEASEVECS
- B KILLMODULE
-
- ; These messages control the pre-empted task. They allow the
- ; controlling process to stop and restart it, terminate it (which
- ; invokes the program's exit handler) and kill it (which will never
- ; reschedule it, and just closes all its files before shutting down).
-
- RECEIVEMESSAGES
- LOCALS
- STMFD R13!,{R0,R14}
- LD R0,MESSAGES
- STMFD R13!,{R0}
- TST R0,#&80000000
- MOVEQ R0,#0
- ST R0,MESSAGES
- LDMFD R13!,{R0}
- TEQ R0,#1 ; Suspend
- BEQ A
- TEQ R0,#2 ; Restart
- BEQ B
- TEQ R0,#3 ; Terminate
- BEQ C
- TEQ R0,#4 ; Kill
- BEQ D
- LDMFD R13!,{R0,PC}^
- A
- MOV R0,#1
- ST R0,SUSPENDED
- LDMFD R13!,{R0,PC}^
- B
- MOV R0,#0
- ST R0,SUSPENDED
- LDMFD R13!,{R0,PC}^
- C
- MOV R0,#1
- ST R0,TERMINATING
- LDMFD R13!,{R0,PC}^
- D
- MOV R9,#0
- LD R10,HANDLESUSED
- ADR R11,HANDLES
- E
- TEQ R10,#0
- BEQ F
- MOV R0,#0
- LDR R1,[R11],#4
- TEQ R1,#0
- ADDNE R9,R9,#1
- SWINE "OS_Find"
- SUB R10,R10,#1
- B E
- F
- BL CLAIMVECS
- SWI "OS_WriteS"
- DB 13,10,10,"Killed",13,10,0
- ALIGN
- MOV R0,R9
- ADR R1,ERRORBUFFER
- MOV R2,#16
- SWI "OS_ConvertCardinal4"
- SWI "OS_Write0"
- SWI "OS_WriteS"
- DB " file(s) closed",13,10,0
- ALIGN
- BL RELEASEVECS
- MOV R0,#2
- ST R0,RETURNCODE
- B KILLMODULE
-
- DSECT
- ORG &10000000
- WSTART
-
-
- PRIVATEWORD ALLOC 4
- MESSAGES ALLOC 4 ; Messages are written here by a controlling
- ; task.
- OUTBUFFERREAD ALLOC 4
- OUTBUFFERWRITE ALLOC 4
- OUTBUFFER ALLOC 1024 ; The output circular buffer
- TASKHANDLE ALLOC 4
- MEMORYMAPVETOED ALLOC 4
- SUSPENDED ALLOC 4
- TERMINATING ALLOC 4
- HANDLESUSED ALLOC 4
- RETURNCODE ALLOC 4
- REGBUF ALLOC 4*16
- OLDCALLBACK ALLOC 4*3
- OLDERRORHANDLER ALLOC 4*3
- OLDEXITHANDLER ALLOC 4*3
- HANDLES ALLOC 4*32
- POLLBLOCK ALLOC 256
- ERRORBUFFER ALLOC 256+4+4
-
- ALLOC 64
- USRSTACK
-
-
- WEND
- DEND
-
- END
-