; 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 scan KbdFlag_Ctrl * 1:SHL:0 KbdFlag_Shift * 1:SHL:1 KbdFlag_R * 1:SHL:4 KbdFlag_T * 1:SHL:5 KbdFlag_Delete * 1:SHL:6 KbdFlag_Copy * 1:SHL:7 KbdFlag_Present * 1:SHL:30 KbdFlag_Done * 1:SHL:31 ; 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 ; FudgeSomeAppSpace - move pages from free pool to application space ; 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 FudgeSomeAppSpace 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 r2, r3, r10 ; end of clear MOV lr, #0 MOV ip, lr 15 STMIA r3!, {ip,lr} ; advance "to" pointer STMIA r3!, {ip,lr} STMIA r3!, {ip,lr} STMIA r3!, {ip,lr} TEQ r2, r3 BNE %BT15 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 ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Entry point from HALInit Continue_after_HALInit ; 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 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] BEQ %FT41 DebugTX "InitCMOSCache done" B %FT42 41 DebugTX "InitCMOSCache failed" 42 ] ; Now copy the initialised data LDR R0, =ZeroPage+IRQ1V 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 ; zero-initialise abort list, and other key workspace STR r3, [r0, #AbortIndirection] [ CompatibilityPage STRB r3, [r0, #CompatibilityPageEnabled] ] ; 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] ; let's boogie with the CMOS for a bit ; read info and move as much memory as we can DebugTX "InitDynamicAreas" 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, =(512*1024):SHR:12 ; 512k 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, #AppSpaceStart ; aplwork start LDR R1, =ZeroPage+AplWorkSize ; aplwork size MOV r11, #AreaFlags_AppSpace BL FudgeSomeAppSpace ; put some memory in aplspace LDR R0, =ZeroPage LDR R1, [R0, #AplWorkSize] ADD R1, R1, #AppSpaceStart 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 [ International [ ZeroPage <> 0 LDR R2, =ZeroPage ] 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 ] ] ; Make the choice between PowerOn and Hard reset based purely on ; the state of the POR bit and NOT on whether memory was cleared. LDR R0, =ZeroPage+HAL_StartFlags LDR R1, [R0] TST R1, #OSStartFlag_POR MOVNE R0, #PowerOnReset MOVEQ R0, #ControlReset LDR R1, =ZeroPage+OsbyteVars + :INDEX: LastBREAK STRB R0, [R1] 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] STR r0, [r3, #TickNodeChain] ; 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] 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] ; 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 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 AddressHAL CallHAL HAL_KbdScanDependencies MOV r5, r0 DebugTX "ModuleInitForKbdScan" BL ModuleInitForKbdScan ; minimal post module setup for keyboard scan BL KeyPostInit ; scan keyboard for interesting keypresses R/T/Delete/End + Ctrl/Shift or timeout LDR r3, =ZeroPage LDR r6, [r3, #HAL_StartFlags] TST r6, #OSStartFlag_RAMCleared MOVEQ r6, #0 ; RAM clear from start of free pool MOVNE r6, #-1 ; RAM clear not needed LDR r3, [r3, #MetroGnome] ADD r3, r3, #300 ; timeout (cs) 02 CMP r5, #-1 ; HAL gave no KbdScan details BEQ %FT04 TST r4, #KbdFlag_Present BNE %FT03 LDR r0, =ZeroPage+KeyWorkSpace LDRB r0, [r0, #:INDEX:KbId] ; check if anyone registered with KeyV CMP r0, #&20 ; same limit as GetCountry BCS %FT04 ORR r4, r4, #KbdFlag_Present DebugTX "KbdFlag_Present" 03 MOV r0, #OsByte_INKEY MOV r1, #0 :EOR: &7F ; scan from shift upwards MOV r2, #255 SWI XOS_Byte TEQ r1, #0 ORREQ r4, r4, #KbdFlag_Shift TEQ r1, #1 ORREQ r4, r4, #KbdFlag_Ctrl TEQ r1, #51 ORREQ r4, r4, #KbdFlag_R TEQ r1, #35 ORREQ r4, r4, #KbdFlag_T TEQ r1, #89 ORREQ r4, r4, #KbdFlag_Delete TEQ r1, #105 ORREQ r4, r4, #KbdFlag_Copy 04 SWI XOS_LeaveOS SWI XOS_EnterOS ; callbacks ; Prior to getting here, ClearWkspRAM cleared low OS workspace & ScratchSpace, and ; Init_MapInRAM_Clear has selectively cleared other early allocations. That leaves ; everything from InitDynamicAreas ; RMA => not cleared, it's in use ; Screen => not cleared, the next CLS will do that ; SpriteArea, RAMDisc, FontArea => not cleared, clients write their own data structures ; and ; Application space (from FudgeSomeAppSpace) => cleared unconditionally ; Free pool => clear now if HAL didn't ; left to do. MOV r0, r6 BL ClearFreePoolSection MOV r6, r0 CMP r6, #-1 BNE %BT02 ; the show's not over until the RAM clear is done CMP r5, #-1 BEQ %FT05 ; HAL gave no KbdScan details TST r4, #KbdFlag_Shift :OR: KbdFlag_Ctrl :OR: KbdFlag_R :OR: KbdFlag_T :OR: KbdFlag_Delete BNE %FT05 ; exciting key press beats a timeout LDR r0, =ZeroPage LDR r0, [r0, #MetroGnome] CMP r0, r3 ; timed out? BCC %BT02 05 ORR r4, r4, #KbdFlag_Done Push "r4" ; save until after MOSInit ; Clear temp ws skipped earlier LDR R0, =ZeroPage+InitWsStart MOV R1, #0 MOV R2, #InitWsEnd - InitWsStart BL memset cmos_checks MOV R3, #-1 ; do all CMOS if we do any [ ValidateCMOS ; Do a POR if some super-critical values are shagged or if checksum is invalid. BL ValChecksum ; Always check the checksum BNE cmos_reset ] ; IF power-on bit set AND R/T/Del/Copy pressed THEN reset CMOS RAM 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 TST R4, #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 R4, #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" 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 R4, [SP] TST R4, #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 init_other_modules no_cmos_reset MOV r0, #SystemSpeedCMOS BL Read BIC r1, r0, #CMOSResetBit ; clear bit indicating CMOS reset MOV r0, #SystemSpeedCMOS BL Write init_other_modules ; now go back and load the other modules, scan podules, accounting for frugal bits DebugTX "ModuleInit" BL ModuleInit 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 [ DebugROMInit SWI XOS_WriteS = "Service_PostInit",0 SWI XOS_NewLine ] MOV r1, #Service_PostInit ; issue post-initialisation service BL Issue_Service [ DebugROMInit SWI XOS_WriteS = "callbacks",0 SWI XOS_NewLine ] SWI XOS_LeaveOS SWI XOS_EnterOS ; switch back to SVC mode (IRQs, FIQs enabled) [ International ; Open the kernel messages file. LDR r0, =ZeroPage+KernelMessagesBlock+4 ADRL r1, MessageFileName MOV r2, #0 ; Use file directly. SWI XMessageTrans_OpenFile MOVVC r0, #-1 LDRVC lr, =ZeroPage STRVC r0, [lr, #KernelMessagesBlock] ; Message file is now open. ASSERT (ZeroPage :AND: 255) = 0 ; if we've managed to open message file STRVCB lr, [lr, #ErrorSemaphore] ; then allow errors to be translated ] ; 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) ; ; Must also be after Service_PostInit to give TerritoryManager opportunity ; to load disc based territories. MOV R0, #9 MOV R1, #2 SWI XOS_ReadSysInfo [ UseNewFX0Error ; Also, *FX 0 BL InitNewFX0Error ] [ CompatibilityPage ; Enable low zero page compatibility page MOV R0, #OSMemReason_Compatibility MOV R1, #1 SWI XOS_Memory ] 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, #OsByte_ClearEscape 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 SWI 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 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 MOV r0, #OsByte_RW_LastResetType MOV r1, #0 MOV r2, #&FF SWI XOS_Byte CMP r1, #PowerOnReset BNE %FT70 LDR r1, =ZeroPage+HAL_StartFlags LDR r1, [r1] TST r1, #OSStartFlag_NoCMOSReset BNE %FT70 ; if any keypad-numeric key pressed, reconfigure monitor type MOV r0, #OsByte_ScanKeyboard ; 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 give up ADR r2, MonitorKeypadTable 62 LDRB r14, [r2], #2 ; search for key in table TEQ r14, #&FF BEQ %FT70 ; give up, key not in table 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 %FT70 RealIRQHandler LDR PC, .-&18+ProcVec_IRQ 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 ; Deal with SHIFT pressed/SHIFT-BREAK configured: ; do appropriate FSControl if wanted Pull "R4" ; recover KbdFlag bits TST R4, #KbdFlag_Present ; first check kbd there BNE shifty_boot [ International BL WriteS_Translated = "NoKbd:No keyboard present - autobooting", 10,13,0 ALIGN | SWI XOS_WriteS = 7, "No keyboard present - autobooting", 10,13,0 ALIGN ] B Hortoculture_Kicking shifty_boot MOV R0, #OsByte_RW_StartupOptions MOV R1, #0 MOV R2, #&FF ; read shifty state SWI XOS_Byte TST R4, #KbdFlag_Shift EORNE R1, R1, #8 ; invert sense TST R1, #8 BNE %FT80 ; no boot when set 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 keypad-* pressed, drop into * prompt MOV r0, #OsByte_INKEY MOV r1, #KeyScan_NumPadStar :AND: &FF MOV r2, #&FF SWI XOS_Byte TEQ r1, #&FF TEQEQ r2, #&FF BEQ DoStartSuper ; EQ -> start up supervisor ; 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 END