; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; SUBT => NewReset ; Reset types SoftReset * 0 PowerOnReset * 1 ControlReset * 2 ; CMOS RAM resetting stuff: CMOSLimit * &F0 ; Keyboard flags ^ 1 KbdScanActive # 1 # 2 KbdFlags # 4 ; On ARM600, InitIRQWs is in zero page - check it's big enough ASSERT @ <= ?InitIRQWs ; GetConfiguredSize - convert CMOS address into amount of memory ; in: r0 = CMOS address ; out: r0 corrupted ; r2 = amount in bytes ; NB this routine doesn't do screen size mangling (yet!) GetConfiguredSize Entry "r1" LDR r1, =ZeroPage LDR r1, [r1, #Page_Size] ADRL lr, PageShifts-1 LDRB r1, [lr, r1, LSR #12] ; r1 = log2 pagesize MOV r2, #127 ; mask of value TEQ r0, #FontCMOS ; if fontsize MOVEQ r1, #12 ; then in units of 4K, not pagesize MOVEQ r2, #255 ; and use full byte BL Read ; read CMOS ram AND r2, r0, r2 ; value anded with mask MOV r2, r2, LSL r1 ; and shifted up accordingly EXIT ; FudgeConfigureRMA - move pages from free pool to somewhere ; r0 = number of pages to attempt to move ; r1 = where to store number of bytes moved ; r3 = base address of where to put memory ; r11 = ap + CB FudgeConfigureRMA Push lr LDR R10, =ZeroPage LDR R10, [R10, #Page_Size] MUL R0, R10, R0 ; get size in bytes MOV R5, #0 ; amount moved CMP R0, #0 BEQ NoMoreMemory LDR r4, =ZeroPage+FreePoolDANode LDR r7, [r4, #DANode_PMP] LDR r8, [r4, #DANode_PMPSize] 10 CMP r8, #0 ; if no free memory left BEQ %FT20 ; then tidy up SUB r8, r8, #1 ; move free pool pointer backwards MOV lr, #-1 LDR r2, [r7, r8, LSL #2] STR lr, [r7, r8, LSL #2] BL Call_CAM_Mapping ADD r3, r3, r10 ; advance "to" pointer ADD r5, r5, r10 ; one more page done SUBS r0, r0, r10 BNE %BT10 20 STR r8, [r4, #DANode_PMPSize] NoMoreMemory STR R5, [R1] Pull "PC" ; MassageScreenSize - called from screen DA creation and ReadSysInfo MassageScreenSize ROUT Push lr LDR lr, =ZeroPage LDR lr, [lr, #VideoSizeFlags] TST lr, #OSAddRAM_VRAMNotForGeneralUse MOVNE r0, lr, LSR #12 MOVNE r0, r0, LSL #12 Pull pc, NE CMP r0, #0 BNE CmosScreenWillDo [ ZeroPage <> 0 LDR r0, =ZeroPage ] LDR r0, [r0, #RAMLIMIT] CMP r0, #512*1024 MOVEQ r0, #80*1024 MOVNE r0, #160*1024 CmosScreenWillDo CMP r0, #20*1024 ; ensure mode 0 gettable ADDCC r0, r0, r10 ; if not, then add another page BCC CmosScreenWillDo CMP r0, #ScreenMaxSize MOVHI r0, #ScreenMaxSize Pull pc LTORG ! 0, "*** DUMMY CONT_Break, soft breaks/resets will not work yet with HAL" CONT_Break AddressHAL MOV a1, #1 LDR a2, =L1PT CallHAL HAL_Reset Continue_after_HALInit ;StrongARM: OK, there is quite a bit of code poking below, to various addresses. We'll ; defer IMB consideration till the poking's done, then do a full IMB (full ; data cache clean). This avoids various little IMB's and removes chance of leaving ; some unnoticed poked code in data cache. The deferral should be safe, because none ; of the poked code will be used yet awhile (given that current IRQ hardware vector is ; not actually changed below). ; Copy default processor vector table and default preveneers. ; Code relies on preveneers being immediately after processor vector table ; but could easily be changed into 2 copy loops. ASSERT ProcVecPreVeneers = ProcVec_End ASSERT DefaultPreVeneers = DefaultProcVecs+ProcVec_End-ProcVec_Start ADRL R0, DefaultProcVecs LDR R1, =ZeroPage+ProcVec_Start MOV R2, #ProcVec_End-ProcVec_Start+ProcVecPreVeneersSize 39 LDR R3, [R0], #4 STR R3, [R1], #4 SUBS R2, R2, #4 BNE %BT39 ; copy handler addresses ADRL R1, MOSROMVecs+4 ; don't copy to 0: key stuff is using ; it as workspace! LDR R0, =ZeroPage+4 LDR R3, =ZeroPage+EndMOSROMVecs-MOSROMVecs 40 LDR R2, [R1], #4 ; N.B. IRQ handler better be same as the one in there STR R2, [R0], #4 TEQ R0, R3 BNE %BT40 ChangedProcVecs r0 [ CacheCMOSRAM DebugTX "InitCMOSCache entry" BL InitCMOSCache ; initialise cache of CMOS RAM DebugTX "InitCMOSCache done" TEQ R0, #0 ; returns zero on failure [ ZeroPage <> 0 LDREQ R0, =ZeroPage ] LDREQ R1, [R0, #HAL_StartFlags] ORREQ R1, R1, #OSStartFlag_NoCMOS STREQ R1, [R0, #HAL_StartFlags] ] ; Now copy the initialised data LDR R0, =ZeroPage+IRQ1V ; first save IOC soft copy so can restore it LDRB R2, [R0, #IOCControlSoftCopy-IRQ1V] Push "R2" LDRB R2, [R0, #CannotReset-IRQ1V] Push "R2" ADRL r1, StartData LDR R3, =ZeroPage+(EndData-StartData+IRQ1V) DatCopy LDR R2, [R1], #4 STR R2, [R0], #4 TEQ R0, R3 BNE DatCopy ADR r2, CONT_Break LDR r0, =ZeroPage STR r2, [r0, #ResetIndirection] MOV r3, #0 ; initialise abort list STR r3, [r0, #AbortIndirection] ; Now the SWI despatch + low part of SWI table ADRL R3, DirtyBranch LDR R0, =SWIDespatch SVCTabCopy ; so copy the table LDR R2, [R1], #4 STR R2, [R0], #4 TEQ R1, R3 BNE SVCTabCopy ; pad to 1K table here, rather than use ROM space ADRL R2, NoSuchSWI LDR R4, =1024+SvcTable ; end of table PadSVCTable CMP R0, R4 STRNE R2, [R0], #4 BNE PadSVCTable ; now the dirty branch LDR R1, [R1] STR R1, [R0] ; conversion SWIs all go through same despatch point LDR R0, =SvcTable ADRL R1, despatchConvert STR R1, [R0, #OS_ConvertStandardDateAndTime * 4] STR R1, [R0, #OS_ConvertDateAndTime * 4] MOV R2, #OS_ConvertHex1 conversionSWIfill STR R1, [R0, R2, LSL #2] ADD R2, R2, #1 CMP R2, #OS_ConvertVariform BLS conversionSWIfill ; OK, that completes the poking around, some of which is code. Now let's ; do a full IMB type thing, to be safe ; LDR r0, =ZeroPage ARMop IMB_Full,,,r0 DebugTX "IMB_Full done" [ CacheablePageTables ; If we want cacheable page tables, now is a good time to enable them ; (can't easily enable them earlier on due to the page tables being temporarily ; doubly-mapped during MMU init) BL MakePageTablesCacheable ] ; Initialise CAO ptr to none. LDR R0, =ZeroPage LDR R1, =DuffEntry ; nothing will be here!! STR R1, [R0, #Curr_Active_Object] KeyWait * 200000 ; 1/5 sec wait (in microseconds) us * 1 AddressHAL MOV r6, #25 ; Check for keyboard 25 times (5 secs max). LDR r4, =ZeroPage+InitIRQWs kbdwait CallHAL HAL_KbdScan STR r0, [r4, #KbdFlags] TST r0, #KbdFlag_Done BNE kbddone LDR r0, =KeyWait*us ; Wait 1/5 second (give keys down a chance to come in). CallHAL HAL_CounterDelay SUBS r6, r6, #1 ; else wait a maximum of 5 seconds. BNE kbdwait kbddone MSR CPSR_c, #I32_bit+SVC32_mode CallHAL HAL_KbdScanFinish LDR r1, =ZeroPage+InitIRQWs MOV r0, #0 STRB r0, [r1, #KbdScanActive] MSR CPSR_c, #SVC32_mode DebugTX "Keyboard scan complete" [ ValidateCMOS ; Do a POR if some super-critical values are shagged or if checksum is invalid. MOV R3, #-1 ; do all RAM if we do any BL ValChecksum ; Always check the checksum BNE cmos_reset ] ; IF power-on bit set AND R/T/Del/Copy pressed THEN reset CMOS RAM ; note that memory cleared if POR, so key info has had plenty of time! LDR R0, =ZeroPage+HAL_StartFlags LDR R1, [R0] TST R1, #OSStartFlag_NoCMOS ; If no CMOS, reset for sensible cache BNE cmos_reset TST R1, #OSStartFlag_POR BEQ no_cmos_reset ; not a power on reset DebugTX "POR detected" TST R1, #OSStartFlag_NoCMOSReset BNE no_cmos_reset TST R1, #OSStartFlag_CMOSReset BNE cmos_reset LDR R0, =ZeroPage+InitIRQWs LDR R7, [R0, #KbdFlags] TST R7, #KbdFlag_R:OR:KbdFlag_T:OR:KbdFlag_Delete:OR:KbdFlag_Copy LDRNE R3, =ZeroPage MOVNE R14, #1 STRNEB R14, [R3, #MentionCMOSReset] BEQ no_cmos_reset ; power on bit checked again there ; CMOS reset detectified. ; Wipe it, then squirt in the MOS's table of default values TST R7, #KbdFlag_Copy:OR:KbdFlag_Delete MOVNE R3, #-1 ; Del or Copy does all RAM MOVEQ R3, #UserCMOS ; R or T just system [ ChecksumCMOS BL ValChecksum ; unless the CMOS ram's corrupt .. MOVNE R3, #-1 ; .. then blast it anyway. ] cmos_reset DebugTX "Reset CMOS" ADD sp, sp, #4 ; junk CannotReset flag from stack MOV R4, #0 cmrlp CMP R3, #-1 BEQ cmrall ; ignore system-only wipe checks CMP R4, #UserCMOS MOVEQ R4, #&50 ; skip User (30-45) & 3rd party (46-59) & high podules (60-79) BEQ cmrall CMP R4, #PoduleCMOS MOVEQ R4, #&80 ; skip low podules (112-127) BEQ cmrall TEQ R4, #NewADFSCMOS ; documented in 'Troubleshooting' in TEQNE R4, #CountryCMOS ; the RISC OS 3.7 user guide as preserved BEQ cmrskip cmrall MOV R1, R4 BL NVMemory_ResetValue ; get the reset value MOVS R1, R2 ; when -ve, leave alone MOVPL R0, R4 BLPL Write ; CMOS(R0) := R1 cmrskip ADD R4, R4, #1 CMP R4, #CMOSLimit BCC cmrlp ; IF R or Delete pressed THEN set sync 0 ELSE set sync Auto LDR R0, =ZeroPage+InitIRQWs LDR R1, [R0, #KbdFlags] TST R1, #KbdFlag_R:OR:KbdFlag_Delete MOV R0, #VduCMOS MOVNE R1, #MonitorTypeAuto :OR: Sync_Auto ; if R or Del MOVEQ R1, #MonitorTypeAuto :OR: Sync_Separate ; if T or Copy BL Write [ ChecksumCMOS BL MakeChecksum ; create a valid checksum ] B hard_reset ; CMOS reset only checked on power on, so was hard no_cmos_reset ; R1 has por_bit set if power on Push "r1" MOV r0, #SystemSpeedCMOS BL Read BIC r1, r0, #CMOSResetBit ; clear bit indicating CMOS reset MOV r0, #SystemSpeedCMOS BL Write Pull "r1" Pull r0 ; always pull CannotReset flag hard_reset hard_reset_forced LDR r8, =ZeroPage Pull "R2" ; discard old IOC state DebugTX "InitDynamicAreas" ; let's boogie with the CMOS for a bit ; read info and move as much memory as we can BL InitDynamicAreas ; RMA Push "r0-r12" MOV r1, #ChangeDyn_RMA ; Area number MOV r2, #4096 ; Initial size MOV r3, #RMAAddress ; Base address MOV r4, #AreaFlags_RMA ; Area flags MOV r5, #RMAMaxSize ; Maximum size ADRL r6, DynAreaHandler_RMA ; Pointer to handler MOV r7, r3 ; Workspace ptr points at area itself ADRL r8, AreaName_RMA ; Title string - node will have to be reallocated ; after module init, to internationalise it BL DynArea_Create ; ignore any error, we're stuffed if we get one! Pull "r0-r12" ; Screen Push "r0-r12" MOV r0, #ScreenSizeCMOS BL Read LDR r5, =ZeroPage LDR r10, [r5, #Page_Size] ; needed by MassageScreenSize MUL r0, r10, r0 ; convert to bytes LDR r5, [r5, #VideoSizeFlags] ; maximum size MOV r5, r5, LSR #12 MOV r5, r5, LSL #12 BL MassageScreenSize MOV r1, #ChangeDyn_Screen ; area number MOV r2, r0 ; initial size MOV r3, #-1 ; Base address dynamic LDR r4, =AreaFlags_Screen ; area flags ADRL r6, DynAreaHandler_Screen ; handler VDWS r7 ; workspace pointer MOV r8, #0 STR r8, [r7, #CursorFlags] ; put zero in CursorFlags as an indication that VDU not yet inited STR r2, [r7, #TotalScreenSize] ADRL r8, AreaName_Screen ; area name BL DynArea_Create STR r3, [r7, #ScreenEndAddr] Pull "r0-r12" ; SpriteArea Push "r0-r12" MOV r0, #0 ; initialise SpriteSize to zero [ ZeroPage = 0 STR r0, [r0, #SpriteSize] ; (fixes bug MED-00811) | LDR r1, =ZeroPage STR r0, [r1, #SpriteSize] ; (fixes bug MED-00811) ] MOV r0, #SpriteSizeCMOS ; find out how much spritesize configured BL GetConfiguredSize ; in: r0 = CMOS address, out: r2 = size MOV r1, #ChangeDyn_SpriteArea ; Area number MOV r3, #-1 ; Base address dynamic MOV r4, #AreaFlags_Sprites ; Area flags MOV r5, #16*1024*1024 ; Maximum size (changed from -1, address space preservation) ADRL r6, DynAreaHandler_Sprites ; Pointer to handler MOV r7, #-1 ; Use base address as workspace ptr ADRL r8, AreaName_SpriteArea ; Title string - node will have to be reallocated ; after module init, to internationalise it BL DynArea_Create ; ignore any error, we're stuffed if we get one! Pull "r0-r12" ; RAMDisc Push "r0-r12" MOV r1, #ChangeDyn_RamFS ; Area number MOV r3, #-1 ; Base address dynamic ARM_read_ID r4 AND r4, r4, #&F000 CMP r4, #&A000 MOVEQ r4, #AreaFlags_RAMDisc_SA ; Area flags, if StrongARM (introduced for Ursula) MOVNE r4, #AreaFlags_RAMDisc ; Area flags [ PMPRAMFS MOV r5, #PMPRAMFS_Size*4096 ORR r4, r4, #DynAreaFlags_PMP MOV r2, #0 ORR r4, r4, #DynAreaFlags_NeedsSpecificPages MOV r9, #0 | MOV r0, #RAMDiscCMOS ; find out how much RAM disc configured BL GetConfiguredSize ; in: r0 = CMOS address, out: r2 = size MOV r5, #MaxRAMFS_Size*1024*1024 ; A trade off between nice big disc and complete waste of address space ] ADRL r6, DynAreaHandler_RAMDisc ; Pointer to handler MOV r7, #-1 ; Use base address as workspace ptr ADRL r8, AreaName_RAMDisc ; Title string - node will have to be reallocated ; after module init, to internationalise it BL DynArea_Create ; ignore any error, we're stuffed if we get one! [ PMPRAMFS ; Currently, physical memory pools must be created with 0 size, then resized afterwards MOV r0, #RAMDiscCMOS ; find out how much RAM disc configured BL GetConfiguredSize ; in: r0 = CMOS address, out: r2 = size MOVS r1, r2 MOV r0, #ChangeDyn_RamFS SWINE XOS_ChangeDynamicArea ] Pull "r0-r12" ; FontArea Push "r0-r12" MOV r0, #FontCMOS ; find out how much font cache configured BL GetConfiguredSize ; in: r0 = CMOS address, out: r2 = size MOV r1, #ChangeDyn_FontArea ; Area number MOV r3, #-1 ; Base address dynamic MOV r4, #AreaFlags_FontArea ; Area flags MOV r5, #32*1024*1024 ; Maximum size changed from -1 for Ursula (limit address ; space usage on large memory machines) ADRL r6, DynAreaHandler_FontArea ; Pointer to handler MOV r7, #-1 ; Use base address as workspace ptr ADRL r8, AreaName_FontArea ; Title string - node will have to be reallocated ; after module init, to internationalise it BL DynArea_Create ; ignore any error, we're stuffed if we get one! Pull "r0-r12" LDR R0, =(1024*1024):SHR:12 ; 1MB of RAM in aplspace should be plenty for ROM init. Theoretically we don't need any at all, but having some there should make it easier to debug any ROM init failures. MOV R3, #32*1024 ; aplwork start LDR R1, =ZeroPage+AplWorkSize ; aplwork size MOV r11, #AreaFlags_AppSpace BL FudgeConfigureRMA ; put some memory in aplspace LDR R0, =ZeroPage LDR R1, [R0, #AplWorkSize] ADD R1, R1, #32*1024 STR R1, [R0, #AplWorkSize] STR R1, [R0, #MemLimit] DebugTX "InitVectors" BL InitVectors ; ready for OsByte to read mode LDR R1, =ZeroPage+ModuleSWI_HashTab MOV R2, #ModuleSHT_Entries [ ZeroPage <> 0 MOV R0, #0 ] clearmswis SUBS R2, R2, #1 STR R0, [R1, R2, LSL #2] BGT clearmswis [ ZeroPage <> 0 LDR R2, =ZeroPage ] [ International MOV R1, #-1 ; We don't have a message file yet ! STRB R1, [R2, #ErrorSemaphore] ; Don't translate errors. STR R0, [R2, #KernelMessagesBlock] ; No message file open. [ CacheCommonErrors STR R0, [R2, #CachedErrorBlocks] ; No cached errors ] ] LDR R0, =ZeroPage+HAL_StartFlags LDR R1, [R0] TST R1, #OSStartFlag_POR ; Make the choice between PowerOn and Hard reset based purely on ; the state of the POR bit and NOT on whether memory was cleared. [ {FALSE} LDREQ R0, =ZeroPage+OsbyteVars + :INDEX: LastBREAK LDREQB R0, [R0] TSTEQ R0, #&80 ; tbs set if memory cleared ] MOVNE R0, #PowerOnReset MOVEQ R0, #ControlReset ResetPart1Done ; R0 is reset type WritePSRc SVC_mode + I_bit, r1 ; interrupts off since kbd bash done LDR R1, =ZeroPage+OsbyteVars + :INDEX: LastBREAK STRB R0, [R1] LDR R1, =ZeroPage+InitIRQWs LDR R0, [R1, #KbdFlags] AND R1, R0, #KbdFlag_Shift AND R0, R0, #KbdFlag_Present Push "R0, R1" ; save until after MOSInit DebugTX "InitIRQ1" BL InitialiseIRQ1Vtable LDR R3, =ZeroPage ADRL R1, Default_PIRQHandler_Node STR R1, [R3, #PIRQ_Chain] STR R1, [R3, #PFIQasIRQ_Chain] ASSERT Default_PFIQasIRQHandler_Node = Default_PIRQHandler_Node MOV R0, #0 ; put in IRQ handler, word at 0 STRB r0, [r3, #FIQclaim_interlock] STRB r0, [r3, #CallBack_Flag] STR r0, [r3, #CallBack_Vector] ; Create the Branch Through 0 Trampoline in the system heap MOV R3, #Branch0_Trampoline_Size BL ClaimSysHeapNode ADRVCL R0, Branch0_Trampoline ASSERT Branch0_Trampoline_Init = 20 LDMVCIA R0, {R1,R3,R4,R5,R14} STMVCIA R2, {R1,R3,R4,R5,R14} LDRVC R0, =ZeroPage STRVC R2, [R0, #ProcVec_Branch0] LDR R1, BranchThroughZeroInstruction2 STR R1, [R0] ; put branch through 0 code at 0 LDR R1, RealIRQHandler STR R1, [R0, #&18] LDR R2, =ZeroPage+InitIRQWs ; clear temp ws MOV R3, #0 MOV R4, #0 STMIA R2!, {R3,R4} STMIA R2!, {R3,R4} DebugTX "IMB_Full" ;we need to do an IMB type thing for modifying code in vector area, ;and for copying irq handler code ; ARMop IMB_Full,,,r0 ChangedProcVecs r0 LDR r0,=ZeroPage MOV R1, #&100 STR R1, [R0, #RCLimit] MOV R1, #0 STR R1, [R0, #ReturnCode] STR R1, [R0, #TickNodeChain] ; clear the keyboard workspace (tidy!) ADD R0, R0, #&1C MOV R2, #InitWsEnd - &1C BL memset ;now put in error handler and escape handler BL DEFHAN BL DEFHN2 MOV R0, #ExceptionDumpArea LDR R1, =ZeroPage+DUMPER SWI XOS_ChangeEnvironment VDWS WsPtr ; main MOS initialisation DebugTX "VduInit" BL VduInit DebugTX "ExecuteInit" BL ExecuteInit DebugTX "KeyInit" BL KeyInit DebugTX "MouseInit" BL MouseInit DebugTX "OscliInit" BL OscliInit ; before initialising modules DebugTX "Enabling IRQs" WritePSRc SVC_mode, R14 ; enable IRQs DebugTX "IRQs on" [ DebugTerminal MOV R0, #RdchV ADRL R1, DebugTerminal_Rdch LDR R2, =ZeroPage LDR R2, [R2, #HAL_Workspace] SWI XOS_Claim MOV R0, #WrchV ADRL R1, DebugTerminal_Wrch SWI XOS_Claim DebugTX "Debug terminal on" ] BL InitialiseMode ; select correct screen mode, in case any ; module prints anything in initialisation MOV R0, #&FD ; read last reset type MOV R1, #0 MOV R2, #&FF SWI XOS_Byte CMP R1, #SoftReset ; soft reset? BEQ SkipHardResetPart2 ; HardResetPart2 DebugTX "HAL_InitDevices" AddressHAL MOV R0, #0 [ ZeroPage = 0 STR R0, [R0, #DeviceCount] STR R0, [R0, #DeviceTable] | LDR R1, =ZeroPage STR R0, [R1, #DeviceCount] STR R0, [R1, #DeviceTable] ] CallHAL HAL_InitDevices ; get HAL to register any devices it has BL LookForHALCacheController DebugTX "InitVariables" BL InitVariables DebugTX "AMBControl_Init" BL AMBControl_Init ; initialise AMBControl section DebugTX "ModuleInit" BL ModuleInit ; initialise modules ; scan podules, copy modules. MOV R0, #0 ; shrink sysheap as far as will go. SUB R1, R0, #4*1024*1024 SWI XOS_ChangeDynamicArea MOV R0, #ReadCMOS MOV R1, #SysHeapCMOS SWI XOS_Byte AND R2, R2, #2_111111 ; mask to same size as status LDR R0, =ZeroPage LDR R0, [R0, #Page_Size] MUL R3, R0, R2 ; size spare wanted BL ClaimSysHeapNode MOV R0, #HeapReason_Free SWI XOS_Heap MOV R0, #ReadCMOS MOV R1, #FileLangCMOS SWI XOS_Byte MOV R1, R2 MOV R0, #FSControl_SelectFS ; set configured filing system SWI XOS_FSControl ; Update RTC now all the modules are running SWI XOS_ResyncTime ; OS_ReadSysInfo 9,2 now relies on the Territory module, which may ; enable IRQs. But the PRMs say OS_ReadSysInfo shouldn't alter the IRQ ; state. So call it once here just to initialise the string which it ; uses the Territory module to generate. ; This won't account for any modules using it during ModuleInit, but ; that should be pretty rare (or at least rare from within IRQ-sensitive ; code) MOV R0, #9 MOV R1, #2 SWI XOS_ReadSysInfo [ UseNewFX0Error ; Also, *FX 0 BL InitNewFX0Error ] [ DebugROMInit SWI XOS_WriteS = "Service_PostInit",0 SWI XOS_NewLine ] MOV r1, #Service_PostInit ; issue post-initialisation service BL Issue_Service ; New code added here by TMD 01-Apr-92 ; Changed to use OS_LeaveOS 16-Oct-02 [ DebugROMInit SWI XOS_WriteS = "callbacks",0 SWI XOS_NewLine ] SWI XOS_LeaveOS SWI XOS_EnterOS ; switch back to SVC mode (IRQs, FIQs enabled) ; end of added code [ International ; Open the kernel messages file. LDR r0, =ZeroPage+KernelMessagesBlock+4 ADR r1, MessageFileName MOV r2, #0 ; Use file directly. SWI XMessageTrans_OpenFile MOVVC r0, #-1 [ ZeroPage = 0 STRVC r0, [r0, #KernelMessagesBlock+1] ; Message file is now open. | LDR lr, =ZeroPage STRVC r0, [lr, #KernelMessagesBlock] ; Message file is now open. ] ] SkipHardResetPart2 ; code executed on all types of reset [ International LDR r0, =ZeroPage LDR r1, [r0, #KernelMessagesBlock] ; if we've managed to open message file TEQ r1, #0 ASSERT (ZeroPage :AND: 255) = 0 STRNEB r0, [r0, #ErrorSemaphore] ; then allow errors to be translated ] BL InitialiseMode LDR R0, =ZeroPage LDRB R14, [R0, #MentionCMOSReset] TEQ R14, #0 BEQ %FT12 [ International SWI XOS_WriteI+10 BVS %FT09 BL WriteS_Translated = "CmosRst:CMOS RAM reset, press ESCAPE to continue",0 ALIGN 09 | SWI XOS_WriteS = 10,"CMOS RAM reset, press ESCAPE to continue",0 ALIGN ] 10 SWI XOS_ReadEscapeState BCC %BT10 MOV R0, #124 SWI XOS_Byte ; Clear the condition SWI XOS_WriteI+12 ; Clear the screen 12 SWI XOS_WriteS = 10, "$SystemName ", 0 ; now RISC OS (no +) again ALIGN MOV R0, #8 ORR R0, R0, #&500 SWI XOS_Memory ; returns amount of soft ROM (pages) in r1 MOVVS R1, #0 LDR R0, =ZeroPage LDR R0, [R0, #RAMLIMIT] MLA R0, R1, R2, R0 ; convert pages to bytes and add in MOV R0, R0, LSR #20 ; /(1024*1024) down to megabytes LDR R1, =GeneralMOSBuffer MOV R2, #?GeneralMOSBuffer SWI XOS_ConvertInteger4 SWI XOS_Write0 SWI XOS_WriteS = "MB", 10,13, 10, 0 ; title complete ALIGN BL ARM_PrintProcessorType MOV r0, #0 ; Set DomainId to 0 every reset [ ZeroPage = 0 STR r0, [r0, #DomainId] ; before calling anyone | LDR r1, =ZeroPage STR r0, [r1, #DomainId] ; before calling anyone ] ; issue reset service call MOV R1, #Service_Reset SWI XOS_ServiceCall ; now set up the default FIQ owner MOV R1, #Service_ClaimFIQ SWI XOS_ServiceCall MOV R1, #Service_ReleaseFIQ SWI XOS_ServiceCall BL PostInit MOV r0, #&FD ; read last reset type (again!) MOV r1, #0 MOV r2, #&FF SWI XOS_Byte CMP r1, #SoftReset ; a softie? SWINE XOS_WriteI+7 ; go beep! Yaay! ; Now that ROM modules have mostly finished allocating memory, move a large ; chunk of the free memory from the free pool into application space so that ; the boot sequence and configured language have something to play around with ; (particularly if booting into BASIC!) ; However be careful not to move everything, otherwise anything which locks ; application space during boot could cripple important background processes ; like USB Push "r1" LDR r0, =ZeroPage LDR r1, [r0, #AplWorkSize] LDR r0, [r0, #FreePoolDANode+DANode_PMPSize] CMP r0, #DynArea_PMP_BigPageCount MOVLO r0, r0, LSL #12 LDRHS r0, =DynArea_PMP_BigByteCount SUB r1, r1, #32*1024 SUB r1, r1, r0 MOV r1, r1, ASR #1 ; 50% each sounds fair MOV r0, #ChangeDyn_FreePool SWI XOS_ChangeDynamicArea Pull "r1" CMP r1, #PowerOnReset BNE %FT75 LDR r1, =ZeroPage+HAL_StartFlags LDR r1, [r1] TST r1, #OSStartFlag_NoCMOSReset BNE %FT75 ; if any monitor key pressed, reconfigure, otherwise hang around for a bit ; till keys get a chance to come in again after being reset for the umpteenth ; time by yet another keyboard handler! SKS 07-Jun-88 LDR r3, =ZeroPage LDR r3, [r3, #MetroGnome] ADD r3, r3, #10 ; Hang about for a little while KeypadStar_key * -92 HorologicalDelayLoop1 MOV r0, #&79 ; scan keyboard MOV r1, #&FF ; starting at (&FF + 1) AND &FF 60 ADD r1, r1, #1 AND r1, r1, #&FF SWI XOS_Byte TEQ r1, #&FF ; if no key down BEQ %FT70 ; then check if we've run out of time ADR r2, MonitorKeypadTable 62 LDRB r14, [r2], #2 ; search for key in table TEQ r14, #&FF BEQ %FT70 TEQ r1, r14 BNE %BT62 LDRB r3, [r2, #-1] ; get corresponding CMOS bits MOV r0, #ReadCMOS MOV r1, #VduCMOS SWI XOS_Byte BIC r2, r2, #MonitorTypeBits ORR r2, r2, r3 MOV r0, #WriteCMOS SWI XOS_Byte TEQ r3, #MonitorTypeAuto ; if we're setting monitortype auto BNE %FT64 ADRL r0, ModeCMOSTable +8 ; then configure mode auto LDR r2, [r0, #-8] ; (load auto value) BL WriteMultiField ADRL r0, SyncCMOSTable +8 ; and configure sync auto LDR r2, [r0, #-8] ; (load auto value) BL WriteMultiField 64 BL InitialiseMode [ International SWI XOS_WriteI+10 BVS %FT65 BL WriteS_Translated = "MonType:Monitor type reconfigured",10,13,10,0 ALIGN 65 | SWI XOS_WriteS = 10,"Monitor type reconfigured",10,13,10,0 ALIGN ] B %FT75 BranchThroughZeroInstruction2 LDR PC, .+ProcVec_Branch0 LTORG MonitorKeypadTable ; internal key number, CMOS bits = 106, MonitorType0 = 107, MonitorType1 = 124, MonitorType2 = 108, MonitorType3 = 122, MonitorType4 = 123, MonitorType5 = 26, MonitorType6 = 27, MonitorType7 = 42, MonitorType8 = 43, MonitorType9 = 76, MonitorTypeAuto ; keypad dot = &FF ALIGN 32 [ International MessageFileName DCB "Resources:$.Resources.Kernel.Messages",0 ALIGN ] 70 LDR r14, =ZeroPage LDR r14, [r14, #MetroGnome] CMP r14, r3 BLO HorologicalDelayLoop1 75 ; Deal with SHIFT pressed/SHIFT-BREAK configured: ; do appropriate FSControl if wanted Pull "R0" ; first check kbd there CMP R0, #0 BEQ AutoBootCosNoKbd MOV R0, #&FF MOV R1, #0 MOV R2, #&FF ; read shifty state SWI XOS_Byte AND R0, R1, #8 ; picka da bit EOR R0, R0, #8 ; invert sense Pull "R1" CMP R1, #0 MOVNE R1, #8 EORS R1, R1, R0 BEQ %FT80 Hortoculture_Kicking MOV R0, #FSControl_BootupFS SWI XOS_FSControl BVC %FT80 Push "r3,r4" ADD r1, r0, #4 ; Set Boot$Error if it failed (Desktop will report it). ADR r0, str_booterror MOV r2, #1024 ; Big enough that terminator will be reached. MOV r3, #0 MOV r4, #VarType_String SWI XOS_SetVarVal SUBVS r0, r1, #4 ; If setting Boot$Error failed then report original error as before. BLVS PrintError SWIVS XOS_NewLine Pull "r3,r4" 80 ; if either * pressed, drop into * prompt, otherwise hang around for a bit ; till keys get a chance to come in again after being reset for the umpteenth ; time by yet another keyboard handler! SKS 01-Jun-88 LDR r3, =ZeroPage LDR r3, [r3, #MetroGnome] ADD r3, r3, #10 ; Hang about for a little while HorologicalDelayLoop2 MOV r1, #KeypadStar_key :AND: &FF BL IsKeyPressedAtReset BEQ DoStartSuper ; EQ -> start up supervisor LDR r0, =ZeroPage LDR r0, [r0, #MetroGnome] CMP r0, r3 BLO HorologicalDelayLoop2 ; Start configured language module if keypad-* wasn't pressed MOV R0, #ReadCMOS MOV R1, #LanguageCMOS SWI XOS_Byte MOV R0, #ModHandReason_GetNames SUB R1, R2, #1 MOV R2, #0 ; preferred incarnation SWI XOS_Module ADRVSL R3, UtilityMod LDR R2, [R3, #Module_TitleStr] CMP R2, #0 ADDNE R1, R3, R2 DoStartSuper ADREQL R1, UtilModTitle ; ALWAYS enter via SWI: sets CAO etc. MOV R0, #ModHandReason_Enter ADRL R2, crstring ; no environment SWI XOS_Module CMP r0, r0 ; set EQ if failed to enter config.lang B DoStartSuper ; -> force Super entry str_booterror DCB "Boot$$Error",0 ALIGN AutoBootCosNoKbd [ International SWI XOS_WriteI+7 BVS %FT81 BL WriteS_Translated = "NoKbd:No keyboard present - autobooting", 10,13,0 ALIGN 81 | SWI XOS_WriteS = 7, "No keyboard present - autobooting", 10,13,0 ALIGN ] B Hortoculture_Kicking RealIRQHandler LDR PC, .-&18+ProcVec_IRQ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; In r1 = INKEY -ve key code to look for ; Out EQ: key pressed ; NE: key not pressed IsKeyPressedAtReset Entry "r0-r2" MOV r0, #129 MOV r2, #&FF SWI XOS_Byte TEQ r1, #&FF TEQEQ r2, #&FF EXIT END