; ; kernel.s ; ; Quartz module support library kernel (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Quartz library. ; ; Quartz 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, or (at your option) ; any later version. ; ; Quartz 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 Quartz. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:swis GET libs:header ;----- External dependencies ------------------------------------------------ ; --- User supplied symbols --- IMPORT quartz_name ;The module's name string IMPORT quartz_help ;The help and version string IMPORT quartz_swiChunk,WEAK ;SWI chunk number IMPORT quartz_swiNames,WEAK ;SWI name table IMPORT quartz_swiTrans,WEAK ;SWI name/number convert code IMPORT quartz_swiCode,WEAK ;Main SWI handling code IMPORT quartz_appCode,WEAK ;Any application code IMPORT |Quartz$$Commands$$Base|,WEAK ; --- Other important objects --- IMPORT |Quartz$$Table$$Base|,WEAK IMPORT |Quartz$$Table$$Limit|,WEAK IMPORT |Quartz$$Service$$Base|,WEAK IMPORT |Quartz$$Service$$Limit|,WEAK ;----- The actual module header --------------------------------------------- AREA |!!!Module$$Header|,CODE,READONLY quartz__base DCD quartz_appCode ;The start entry point DCD quartz__init ;Main initialisation DCD quartz__closeDown ;Close down code DCD quartz__service ;Service call handling DCD quartz_name ;The module name string DCD quartz_help ;Help/version (use setdate!) DCD |Quartz$$Commands$$Base| ;The command table DCD quartz_swiChunk ;The SWI chunk number DCD quartz_swiCode ;The SWI entry point code DCD quartz_swiNames ;The SWI name table DCD quartz_swiTrans ;SWI name/number translation ;----- Initialisation and finalisation code --------------------------------- ; --- quartz_base --- ; ; On entry: -- ; ; On exit: R0 == pointer to module base ; ; Use: Returns a pointer to the module's base EXPORT quartz_base quartz_base ROUT ADR R0,quartz__base ;Point to the module base MOVS PC,R14 ;And return to caller LTORG ; --- quartz__init --- ; ; On entry: R12 == pointer too where to store private word ; ; On exit: -- ; ; Use: Initialises Quartz library and any client modules which feel ; they want to use this mechanism. quartz__init ROUT STMFD R13!,{R0-R9,R14} ;Save some registers MOV R5,R12 ;Keep private word address ; --- Find the amount of workspace we need --- ADR R9,quartz__base ;Find the module base address LDR R7,=|Quartz$$Table$$Base| LDR R8,=|Quartz$$Table$$Limit| ADD R7,R9,R7 ;Convert to actual addresses ADD R8,R9,R8 MOV R0,R7 ;Point at the table start MOV R3,#quartz__wSize ;Get my workspace size 00quartz__init CMP R0,R8 ;Have we finished yet? BGE %05quartz__init ;Yes -- exit this loop LDMIA R0!,{R1,R2,R4,R6} ;Get initialisation stuff ADD R3,R3,R1 ;Add on the workspace size B %00quartz__init ;And loop round again ; --- Allocate the workspace nicely --- 05quartz__init CMP R3,#0 ;Do we want any workspace? BEQ %09quartz__init ;No -- don't allocate any MOV R0,#6 ;Allocate memory from RMA SWI XOS_Module ;Get the memory nicely BVS %99quartz__init ;If it failed, skip to end STR R2,[R12,#0] ;Store the workspace address MOV R12,R2 ;Remember this address STR R12,quartz__wSpace ;Save this address for later ; --- Now initialise the first words --- 09quartz__init MOV R0,R7 ;Point to the table base MOV R6,R12 ;Keep the workspace address MOV R14,#0 ;For zeroing things 10quartz__init CMP R0,R8 ;Have we finished yet? BGE %19quartz__init ;Yes -- exit the loop then LDMIA R0!,{R1-R4} ;Load the table entries CMP R1,#0 ;Does he have any workspace? STRNE R6,[R9,R2] ;Yes -- store workspace addr STRNE R14,[R6,#0] ;And initialise first word ADD R6,R6,R1 ;Move the workspace addr on B %10quartz__init ;Now go round for the rest ; --- Finally initialise all the other sections --- 19quartz__init MOV R6,R7 ;Get the start pointer nicely 20quartz__init CMP R6,R8 ;Have we finished yet? BGE %30quartz__init ;Yes -- wrap it all up LDMIA R6!,{R1-R4} ;Load the initialisation info CMP R3,#0 ;Does he want initialising? MOVNE R14,PC ;Yes -- set up return address ADDNE PC,R9,R3 ;And call his routine BVS %95quartz__init ;Tidy up if it failed ADD R12,R12,R1 ;Move on the workspace addr B %20quartz__init ;Go round for the rest 30quartz__init LDMFD R13!,{R0-R9,PC}^ ;I declare this module open ; --- Tidy up -- it all failed --- 95quartz__init MOV R12,R5 ;Point at private word BL quartz__closeDown ;Close down other sections 99quartz__init ADD R13,R13,#4 ;Don't restore R0 on exit LDMFD R13!,{R1-R9,R14} ;Unstack all the registers ORRS PC,R14,#V_flag ;Return the error to system quartz__wSpace DCD 0 LTORG ; --- quartz__closeDown --- ; ; On entry: R12 == pointer to private word ; ; On exit: -- ; ; Use: Closes down a module. quartz__closeDown ROUT STMFD R13!,{R0-R9,R14} ;Save some registers MOV R5,R12 ;Keep private word pointer LDR R12,[R12,#0] ;Load workspace base address ADR R9,quartz__base ;Find the module base address LDR R7,=|Quartz$$Table$$Base| LDR R8,=|Quartz$$Table$$Limit| ADD R7,R9,R7 ;Convert to actual addresses ADD R8,R9,R8 MOV R6,R7 ;Get the start pointer again LDR R12,quartz__wSpace ;Find the workspace base 10 CMP R6,R8 ;Have we finished yet? BGE %40quartz__closeDown ;Yes -- deallocate memory LDMIA R6!,{R1-R4} ;Load the initialisation info CMP R4,#0 ;Does he want closing down? BEQ %30quartz__closeDown ;No -- ignore it then CMP R1,#0 ;Did he want workspace? BEQ %20quartz__closeDown ;No -- close him down anyway LDR R14,[R12,#0] ;Yes -- load first word CMP R14,#0 ;Has he started up yet? 20 MOVNE R14,PC ;Yes -- set up return address ADDNE PC,R9,R4 ;And call the routine nicely 30 ADD R12,R12,R1 ;Move on the workspace addr B %10quartz__closeDown ;Go round and do some more 40 MOV R0,#7 ;Deallocate workspace LDR R2,[R5,#0] ;Load workspace base address SWI XOS_Module ;Free all my workspace MOV R14,#0 ;Don't have workspace no more STR R14,[R5,#0] ;So zero my private word LDMFD R13!,{R0-R9,PC}^ ;Return to caller LTORG ; --- quartz__service --- ; ; On entry: R1 == service call number ; ; On exit: As returned by service call handlers ; ; Use: Handles service calls quartz__service ROUT STMFD R13!,{R9-R11,R14} ;Save far too few registers ADR R9,quartz__base ;Find module base LDR R10,=|Quartz$$Service$$Base| LDR R11,=|Quartz$$Service$$Limit| ADD R10,R9,R10 ;Convert to actual addresses ADD R11,R9,R11 10 CMP R10,R11 ;Have we finished yet? LDMEQFD R13!,{R9-R11,PC}^ ;Yes -- return (whew) LDMIA R10!,{R12,R14} ;Get the service handler CMP R1,R14 ;Does he want this service? MOVEQ R14,PC ;Yes -- set up return addr ADDEQ PC,R9,R12 ;And call his handler B %10quartz__service ;And go round again LTORG AREA |Quartz$$Commands_|,CODE,READONLY DCD 0 ;Terminate command table ;----- Workspace ------------------------------------------------------------ ^ 0,R12 quartz__wStart # 0 quartz__wSize EQU {VAR}-quartz__wStart ;----- That's all, folks ---------------------------------------------------- END