; 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 DuffEntry * 31*1024*1024+32*1024 ; Never any memory at this address SoftReset * 0 ; Reset types PowerOnReset * 1 ControlReset * 2 ; CMOS RAM resetting stuff: CMOSLimit * &F0 ; Keyboard flags ^ 1 CTRL_Down_Flag # 1 SHIFT_Down_Flag # 1 KB_There_Flag # 1 R_Down_Flag # 1 ; note that these 4 form one word!! T_Down_Flag # 1 Del_Down_Flag # 1 Copy_Down_Flag # 1 KeyDataPtr # 4 [ MorrisSupport Port2Present # 4 ] [ MEMM_Type = "ARM600" ; On ARM600, InitKbdWs is in zero page - check it's big enough ASSERT @ <= ?InitKbdWs | ; Else use PhysRam start InitKbdWs * PhysRam ] [ MEMM_Type <> "ARM600" ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; routine to set up a 32K chunk (for fixed areas) ; Enter with R8 = PageSize, R2 = physram offset, R3 logaddr ; R8 preserved on exit ; This routine is not needed on ARM600, as MemSize sets up the L2PT for the static pages SlapIn32K MOV R12, lr ADRL R1, PageShifts-1 LDRB R1, [R1, R8, LSR #12] MOV R2, R2, LSR R1 ; DivRem R0, R2, R8, R1 ; R2 := cam entry no ADD R5, R3, #32*1024 SlapInNext BL BangCam ADD R2, R2, #1 ADD R3, R3, R8 CMP R3, R5 BNE SlapInNext MOV PC, R12 ] ; AddCamEntries ; ; in: r0 -> appropriate part of CAM map ; r1 = ap (+ CB bits in new world) ; r2 = log address ; r7 = amount of cam map to do ; r8 = PageSize ; ; out: r0, r3-r12 preserved ; r1 corrupted ; r2 updated by relevant amount AddCamEntries ROUT [ ExpandedCamMap Push "r0, lr" MOV lr, r1 ; access privs (PPL) MOV r1, r7 01 STMIA r0!, {r2, lr} ; store logaddr, PPL ADD r2, r2, r8 ; increment address by 1 page SUBS r1, r1, #8 ; decrement count of how much to do BNE %BT01 Pull "r0, pc" | MOV R1, #0 CMP r2, #CursorChunkAddress ORREQ r2, r2, #&10000000 ; appropriate PPL 01 STR R2, [R0, R1] ADD R1, R1, #4 ADD R2, R2, R8 CMP R1, R7 BNE %BT01 MOVS pc, lr ] ; 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" MOV r1, #0 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 Push lr B ConfigureRMA ReadCMOSAndConfigure ROUT ; R0 = index into CMOS RAM of byte with size in ; R1 = place to save amount moved ; R2 = CAM entry number to start at: updated ; R3 = LogRam Address to move memory to ; r11 PPL ; Check for memory left, move as much as poss Push lr BL Read ; CMOS byte -> R0 [ :LNOT: NewStyle_FontArea CMP r3, #FontCacheAddress MOVEQ r0, r0, LSL #12 ; *4K BEQ NotScreen ] AND R0, R0, #127 ; mask to same bitfield as status ConfigureRMA MOV R10, #0 LDR R10, [R10, #Page_Size] MUL R0, R10, R0 ; get size in bytes CMP R3, #ScreenEndAdr ; screen? BNE NotScreen ; quick pokery for sensible screensize BL MassageScreenSize SUB R3, R3, R0 ; step back. NotScreen MOV R5, #0 ; amount moved CMP R0, #0 BEQ NoMoreMemory [ GetPagesFromFreePool ; r0 = amount of memory to move ; r1 = address to store size in ; (r2 = page number to start at, ignored in our method) ; r3 = address of where to put memory ; r10 = page size ; r11 = ap + CB MOV r6, r11 ; r6 = ap + CB MOV r4, #FreePoolDANode LDR r7, [r4, #DANode_Base] LDR r8, [r4, #DANode_Size] ADD r7, r7, r8 ; r7 -> end of free pool +1 10 CMP r8, r10 ; if no free memory left BCC %FT20 ; then tidy up SUB r7, r7, r10 ; move free pool pointer backwards Push "r0, r1" MOV r0, r7 MOV r1, r3 BL MovePageAtR0ToR1WithAccessR6 Pull "r0, r1" ADD r3, r3, r10 ; advance "to" pointer SUB r8, r8, r10 ; one less page of free memory ADD r5, r5, r10 ; one more page done SUBS r0, r0, r10 BNE %BT10 20 STR r8, [r4, #DANode_Size] | LDR R8, [R5, #RAMLIMIT] ; now set R6 = first entry not to use ; R7 = end of gap " " " ; R8 = last entry we can use [ MEMM_Type = "ARM600" MOV r7, #0 LDR r6, [r7, #VideoSize] ; find out how many pages in video area MOV r6, r6, LSR #12 ; = page number of start of skipped bit ASSERT SoftCamMapSize = L2PTSize +4 MOV r7, #L2PTSize LDMIA r7, {r7, lr} ; r7 = L2PTSize, lr = SoftCamMapSize ADD r7, r7, lr ; add sizes together ADD r7, r7, #StaticPagesSize + UndStackSize ; + number of bytes used for other static bits ADD r7, r6, r7, LSR #12 ; r7 = page number after static bit MOV r8, r8, LSR #12 ; make r8 into highest page number+1 | CMP R8, #512*1024 MOVEQ R6, #(512-96)*1024 MOVEQ R7, #512*1024 MOVNE R6, #(512-32)*1024 [ MEMM_Type = "MEMC2" MOVNE R7, #(512+96)*1024 ; if MEMC2, skip L2PT as well | MOVNE R7, #(512+64)*1024 ] Push "R2" ADRL R2, PageShifts-1 LDRB R2, [R2, R10, LSR #12] MOV R6, R6, LSR R2 ; DivRem R6, R6, R10, R2 MOV R7, R7, LSR R2 MOV R8, R8, LSR R2 Pull "R2" ] CAMZapLoop CMP R2, R6 ; if at gap, skip MOVEQ R2, R7 CMP R2, R8 ; if no more memory, give in BEQ NoMoreMemory ADD R5, R5, R10 Push "R0, R1, R6" BL BangCamUpdate Pull "R0, R1, R6" ADD R2, R2, #1 ADD R3, R3, R10 SUBS R0, R0, R10 BGT CAMZapLoop ] NoMoreMemory STR R5, [R1] Pull "PC" ; MassageScreenSize - called from ReadCMOSAndConfigure (above) and also from ; ReadSysInfo MassageScreenSize ROUT CMP r0, #0 BNE CmosScreenWillDo 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 MOV pc, lr LTORG ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Data tables: VIDC := mode 0, all palette black VIDCTAB [ VIDC_Type = "VIDC20" ; Program Control Register first, to clear power-down bit & &E0000400 ; CR: FIFO load 16 words, 1 bpp, ck/1, vclk ; Don't bother programming all 256 palette entries, we'll be here all night ; Since we're setting up a 1 bit-per-pixel mode, just do colours 0 and 1 & &10000000 ; Palette address register = 0 & &00000000 ; Colour 0 = black & &00000000 ; Colour 1 = black & &40000000 ; Border colour = black & &50000000 ; Pointer colour 1 = black & &60000000 ; Pointer colour 2 = black & &70000000 ; Pointer colour 3 = black ; Get a stable display up so we get stable signals & &800003F8 ; HCR = 76 + 88 + 96 + 640 + 96 + 28 & &81000044 ; HSWR = 76 & &82000098 ; HBSR = 76 + 88 & &830000F2 ; HDSR = 76 + 88 + 96 & &84000372 ; HDER = 76 + 88 + 96 + 640 & &850003D8 ; HBER = 76 + 88 + 96 + 640 + 96 & &860000F3 ; HCSR = HDSR & &90000137 ; VCR = 3 + 19 + 16 + 256 + 16 + 2 & &91000002 ; VSWR = 3 & &92000015 ; VBSR = 3 + 19 & &93000025 ; VDSR = 3 + 19 + 16 [ MEMC_Type = "IOMD" [ Simulator & &94000025 ; No displayed lines, so we don't get video FIFO u/flow when simulating | & &94000125 ; VDER = 3 + 19 + 16 + 256 ] | & &94000125 ; VDER = 3 + 19 + 16 + 256 ] & &95000135 ; VBER = 3 + 19 + 16 + 256 + 16 & &96000025 ; VCSR = VDSR & &97000025 ; VCER = VDSR & &B1000001 ; SCR: sound disabled (+use 24MHz clock) & &C00F1003 ; EREG = comp sync, DACs on, ereg output ext lut & &D0000305 ; FSYNREG, clk = (3+1)/(5+1) * 24MHz = 16MHz & &F0013000 ; DCR: bus D[31:0], Hdisc ;RCM 29/9/94: changed from &F0012000 at PSwindells request & &FFFFFFFF ; That's the lot | & &00000000 & &04000000 & &08000000 & &0C000000 & &10000000 & &14000000 & &18000000 & &1C000000 & &20000000 & &24000000 & &28000000 & &2C000000 & &30000000 & &34000000 & &38000000 & &3C000000 & &40000000 & &44000000 ; Cursor -> black & &48000000 & &4C000000 ; Palette programmed (avoid messy screen on reset) & &807FC000 ; HCR Get a stable display up so we get stable signals & &8408C000 ; HSWR & &881B0000 ; HBSR & &94770000 ; HBER & &A04E0000 ; VCR & &A4024000 ; VSWR & &A8050000 ; VBSR & &B44E0000 ; VBER & &C0000100 ; SFR NB. TEST BIT !!! - also DFlynn requested value & &E00000B2 ; CR Set 640*256, 1 bit per pixel, rate of 12MHz ; change bottom byte to 22 for Linear Microvitecs (CS) ; B2 for Monochrome/Philips (SS) & &8C208000 ; HDSR & &90708000 ; HDER & &98258000 ; HCSR & &9C400000 ; HIR & &AC098000 ; VDSR & &B0498000 ; VDER & &B8098000 ; VCSR & &BC498000 ; VCER ; don't mess with the stereo image registers: sound code will set them. & &FFFFFFFF ; That's the lot ] [ MEMM_Type <> "ARM600" GBLL ARM3_Support ] [ :DEF:ARM3_Support ARM3 CP 15 CR0 CN 0 CR_ID CN 0 CR_Flush CN 1 CR_Control CN 2 CR_Cacheable CN 3 CR_Updateable CN 4 CR_Disruptive CN 5 UndefVec * &00000004 ; Default cacheable areas ; ; ROM Cacheable (&03400000..&03FFFFFF) ; I/O Not cacheable (&03000000..&033FFFFF) ; Phys RAM Not cacheable (&02000000..&02FFFFFF) ; Log RAM (screen) Not cacheable (&01E00000..&01FFFFFF) ; Log RAM (RAM Disc) Not cacheable (&01000000..&013FFFFF) ; (No point in caching RAM Disc) ; Log RAM (non-screen) Cacheable (&00000000..&01DFFFFF) Cacheable_Default DCD 2_11111100000000000111110011111111 ; Default updateable areas ; ; ROM/CAM Not updateable (&03800000..&03FFFFFF) ; ROM/DAG Not updateable (&03400000..&037FFFFF) ; I/O Not updateable (&03000000..&033FFFFF) ; Phys RAM Not updateable (&02000000..&02FFFFFF) ; Log RAM (screen) Not updateable (&01E00000..&01FFFFFF) ; Log RAM Updateable (&00000000..&01DFFFFF) Updateable_Default DCD 2_00000000000000000111111111111111 ; Default disruptive areas ; ; CAM Disruptive (&03800000..&03FFFFFF) ; DAG Not disruptive (&03400000..&037FFFFF) ; I/O Not disruptive (&03000000..&033FFFFF) ; Phys RAM Not disruptive (&02000000..&02FFFFFF) ; Log RAM Not disruptive (&00000000..&01FFFFFF) Disruptive_Default * 2_11110000000000000000000000000000 UndefRet MOVS pc, lr ] VIDCPhys * &03400000 ; used to address VIDC when MMU is off ; Entered here after RESET (or BREAK) ; This code must be capable of being executed at a non-ROM address and with the MMU off, ; and running in 32-bit mode up until the call to MemSize. CONT_Break MOV r1, #1 ; parameter passed to InitMEMC, to indicate Break not Reset B Continue CONT ROUT MOV r1, #0 ; parameter passed to InitMEMC, to indicate Reset not Break Continue ; First bang MEMC to ensure safety BL InitMEMC ; initialise MEMC CR, and turn off MMU if it's on ; VInit etc set on ze mode change: no DMA going yet so don't set owt. MOV R1, #VIDCPhys ; Must ALWAYS initialise VIDC on reset or else ADR R2, VIDCTAB ; we may get vsync interrupts that stiff us 10 LDR R0, [R2], #4 ; permanently as VIDC is in an undefined state CMP R0, #-1 ; so have mode 0 with all black palette STRNE R0, [R1] BNE %BT10 ; Now bang IOC (disable all but keyboard interrupts) MOV R1, #IOC MOV R0, #&FF ; all inputs STRB R0, [R1, #IOCControl] ; in case called by Tim MOV R0, #0 STRB R0, [R1, #IOCIRQMSKA] ; kein interrupts STRB R0, [R1, #IOCFIQMSK] ; disable FIQs [ IO_Type = "IOMD" STRB R0, [R1, #IOMD_DMAMSK] ; disable DMA interrupts, too ] [ Keyboard_Type = "PC" :LAND: IO_Type <> "IOMD" MOV R0, #podule_IRQ_bit ; used for PC keyboard h/w on a podule | MOV R0, #KARTRxBit ; used for Archi keyboard or IOMD PC keyboard ] STRB R0, [R1, #IOCIRQMSKB] ; allow communication with kbd, when I_bit gets cleared ; now bits to allow CMOS read/write : need timer LDR R0, =20000-1 ; R0 = Timer delay (units of 0.5 microsecond) ; 20000*0.5E-6 = 0.01 Seconds (100Hz ticker) ; TMD 21-May-93: "-1" correction applied STRB R0, [R1, #Timer0LL] ; Set up the delay MOV R0, R0, LSR #8 STRB R0, [R1, #Timer0LH] STRB R0, [R1, #Timer0GO] ; and start the ticks MOV R0, #timer0_bit STRB R0, [R1, #IOCIRQCLRA] ; Clear pending t0 interrupt j.i.c. ; now size memory BL MemSize ; out: r0 = page size, r1 = memory size, r2 = MEMC CR value, r3-r14 corrupt MOV R8, R0 ; R8 = page size in bytes MOV R13, R1 ; R13 is now the RAM size MOV R9, R2 ; need this to set soft copy right BL TimeCPU ; r7 := CPU speed in kHz/MEMC1a flag ; first ensure nothing dangerous in MEMC [ MEMM_Type <> "ARM600" ; all this stuff is done in MemSize [ {TRUE} ; new code which allows for MEMC2's small pages ADRL r2, PageShifts-1 LDRB r2, [r2, r8, LSR #12] ; get log2(pagesize) MOV R2, R13, LSR R2 ; number of pages=total memory / pagesize CMP R2, #128 ; but if fewer than 128 (eg 64 on A305) MOVCC R2, #128 ; then use 128 (all MEMC1's pages need initialising, ; even if half of them are not in use) | CMP R13, #8*1024*1024 ; if >= 8MBytes, MOVCS R2, R13, LSR #15 ; then there are R13/32K pages MOVCC R2, #128 ; else there are 128 pages ] SUB R2, R2, #1 ; maximum page number LDR R3, =DuffEntry ; a non-existant piece of memory MOV R11, #AP_Duff ; go away, users EmptyCamEntries BL BangCam ; ensure not mapped to anything SUBS R2, R2, #1 ; dangerous BPL EmptyCamEntries ; Put in position all fixed areas of memory ; 32K for cursor etc : CAM entries for 512-32 to 512K in PhysRam ; SlapIn32K needs R8 = pagesize ; This is now already set up, so no need to compute it from ; MEMC CR (which would be wrong on ARM600 anyway) MOV R11, #1 ; user write protected MOV R3, #CursorChunkAddress MOV R2, #(512-32)*1024 BL SlapIn32K MOV R3, #SysHeapChunkAddress ; 32K forced in system heap area ; use phys 512+32 to 512+64K if R13<>512K, 512-96 to 512-64K if R13=512K CMP R13, #512*1024 MOVEQ R2, #(512-96)*1024 MOVNE R2, #(512+32)*1024 MOV r11, #0 BL SlapIn32K MOV R3, #0 ; 32K system work area ; use phys 512 to 512+32K if R13<>512K, 512-64 to 512-32K if R13=512K CMP R13, #512*1024 MOVEQ R2, #(512-64)*1024 MOVNE R2, #512*1024 BL SlapIn32K ] [ :DEF:ARM3_Support MOV r0, #UndefVec LDR r1, [r0] LDR r2, UndefRet MOV r5, #0 STR r2, [r0] MRC ARM3, 0, r5, CR_ID, CR0 STR r1, [r0] AND r5, r5, #&ff00 TEQ r5, #&0300 BNE noarm3 LDR r0, Cacheable_Default LDR r1, Updateable_Default MOV r2, #Disruptive_Default MCR ARM3, 0, r0, CR_Cacheable, CR0 MCR ARM3, 0, r1, CR_Updateable, CR0 MCR ARM3, 0, r2, CR_Disruptive, CR0 MRC ARM3, 0, r3, CR_Cacheable, CR0 MRC ARM3, 0, r4, CR_Updateable, CR0 MRC ARM3, 0, r5, CR_Disruptive, CR0 TEQ r0, r3 TEQEQ r1, r4 TEQEQ r2, r5 BNE noarm3 MOV r0, #3 MCR ARM3, 0, r0, CR_Control, CR0 noarm3 ] ; the fixed areas give us : IRQ stack (in cursor), SVC stack (in sysheap base) ; and bottom block makes most sense done here ; now keyboard initialisation: initialise baud rate, send dummy, read dummy MOV R0, #InitKbdWs MOV R1, #0 STRB R1, [R0, #CTRL_Down_Flag] ; clear CTRL down flag, R down flag STRB R1, [R0, #SHIFT_Down_Flag] STRB R1, [R0, #KB_There_Flag] STR R1, [R0, #R_Down_Flag] ; all CMOS reset flags STR R1, [R0, #KeyDataPtr] [ MorrisSupport STR R1, [R0, #Port2Present] ] B SetUpKbd ; No stack yet so branch and branch back. SetUpKbdReturn ; set up reset interrupt handler (reads, discards keys, setting flags if CTRL or R) ; NB on ARM600 we need to go into 32-bit mode, so we can safely overwrite vectors [ CPU_Type = "ARM600" mrs AL, r0, CPSR_all ; switch into IRQ32, still IRQs disabled BIC r0, r0, #&1F ORR r1, r0, #IRQ32_mode msr AL, CPSR_all, r1 LDR sp_irq, =IRQSTK ; set up sp_irq ADRL R2, MOSROMVecs ; pick up from table LDR R2, [R2, #&18] ; this gets overwritten while active, MOV R3, #0 STR R2, [R3, #&18] ; but hopefully by the same value! ORR r0, r0, #SVC32_mode ; switch into SVC32 BIC r0, r0, #I32_bit ; and enable IRQs msr AL, CPSR_all, r0 ; in SVC32 from now until we've finished poking around with vectors | TEQP pc, #IRQ_mode + I_bit ; set up IRQ stack NOP LDR sp_irq, =IRQSTK ADRL R0, MOSROMVecs ; pick up from table LDR R0, [R0, #&18] ; this gets overwritten while active, MOV R1, #0 ; could have been changed by keyboard initialisation STR R0, [R1, #&18] ; but hopefully by the same value! TEQP pc, #SVC_mode ; Enable interrupts, back to supervisor mode NOP ] [ :LNOT: AlwaysClearRAM ; IF por OR FX200 bit set THEN clear memory MOV R0, #IOC LDRB R1, [R0, #IOCIRQSTAA] ANDS R1, R1, #por_bit BNE %FT20 LDR R0, =OsbyteVars + :INDEX: ESCBREAK LDRB R1, [R0] CMP R1, #2 ; unlike popular rumour, bit 1 ain't CMPNE R1, #3 ; a flag BNE %FT30 20 ] BL ClearPhysRAM 30 MOV r0, #0 STR r9, [r0, #MEMC_CR_SoftCopy] ; set soft copy. STR r7, [r0, #MemorySpeed] ; Remember CPU speed/MEMC1a flag STR r8, [r0, #Page_Size] ; r8 is still page size from way up there STR r13, [r0, #RAMLIMIT] ; save sussed memory size in LogRam LDR sp, =SVCSTK ; set up a stack ; do as much other initialisation as possible, to give keyboard stuff time [ ProcessorVectors ; 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, =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! MOV R0, #4 40 LDR R2, [R1], #4 ; N.B. IRQ handler better be same as the one in there STR R2, [R0], #4 TEQ R0, #EndFiq-MOSROMVecs BNE %BT40 [ CPU_Type = "ARM600" ; Now we have set up the hardware vectors we can drop back to SVC26 mode mrs AL, r0, CPSR_all BIC r0, r0, #&1F ORR r0, r0, #SVC26_mode msr AL, CPSR_all, r0 ] ; Ensure any CMOS operation aborted MOV R1,#16 ; Two bytes in case RTC transmitting 35 BL Start ; Start/clock edge BL Stop SUBS R1,R1,#1 BNE %BT35 [ CacheCMOSRAM BL InitCMOSCache ; initialise cache of CMOS RAM ] ; Now copy the initialised data MOV R0, #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 DatCopy LDR R2, [R1], #4 STR R2, [R0], #4 TEQ R0, #(EndData-StartData+IRQ1V) BNE DatCopy [ ResetIndirected ADR r2, CONT_Break MOV r0, #0 STR r2, [r0, #ResetIndirection] ] [ CPU_Type = "ARM600" MOV r0, #0 ; initialise abort list STR r0, [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] ; now the time/date conversions LDR R0, =SvcTable ADRL R1, ConvertStandardDateAndTime STR R1, [R0, #OS_ConvertStandardDateAndTime*4] ADD R1, R1, #ConvertDateAndTime - ConvertStandardDateAndTime ; SKS STR R1, [R0, #OS_ConvertDateAndTime*4] ; other conversion SWIs, all go through same entry point ADRL R1, despatchConvert MOV R2, #OS_ConvertHex1 conversionSWIfill STR R1, [R0, R2, LSL #2] ADD R2, R2, #1 CMP R2, #OS_ConvertFileSize+1 BNE conversionSWIfill ; Initialise CAO ptr to none. MOV R0, #0 MOV R1, #32*1024*1024 ; nothing will be here!! STR R1, [R0, #Curr_Active_Object] KeyWait * 200000 ; 1/5 sec wait (in microseconds) [ KeyWait <> 0 ; Check for keyboard there every 1/5 sec. but give up after 2 secs. MOV r2, #IOC MOV r3, #10 ; Check for keyboard 10 times (2 secs max). MOV r4, #InitKbdWs kbdwait LDRB r5, [r4, #KB_There_Flag] LDR r0, =KeyWait*2 ; Wait 1/5 second (give keys down a chance to come in). BL DoMicroDelay TEQ r5, #0 ; If keyboard was there 1/5 second ago then BNE kbdthere ; continue reset SUBS r3, r3, #1 ; else wait a maximum of 2 seconds. BNE kbdwait kbdthere ] ; IF power-on bit set in IOC AND R/T/Del/Copy pressed THEN reset CMOS RAM ; note that memory cleared if POR, so key info has had plenty of time! MOV R0, #IOC LDRB R1, [R0, #IOCIRQSTAA] ANDS R1, R1, #por_bit BEQ no_cmos_reset [ CheckProtectionLink LDR r0, =IOMD_MonitorType ; on Issue A's the protection bit is only weakly pulled up, ; so force it high, then read it back LDRB r1, [r0] ORR r1, r1, #IOMD_ProtectionLinkBit STRB r1, [r0] LDRB r1, [r0] TST r1, #IOMD_ProtectionLinkBit BEQ no_cmos_reset ; if zero then CMOS is protected ] MOV R0, #InitKbdWs LDR R7, [R0, #R_Down_Flag] CMP R7, #0 BEQ no_cmos_reset ; power on bit checked again there ADD sp, sp, #4 ; junk CannotReset flag from stack ; CMOS reset detectified. ; ************************************************************************** ; Note: if this CMOS reset code ever needs changing again, it's probably ; better to rewrite it. The Compact apparently has a table of default ; CMOS values; R-p.o. just writes the table, DEL-p.o. zeroes all, then ; writes the table. With skipping of the time CMOS, and post-prodding of ; the sync, that would probably be a better algorithm. ; ************************************************************************** SetBorder R0, R1, 15, 0, 0 ; flash the border as warning! MOVS R3, R7, LSR #16 ; full reset or just system? 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. MOVNE R0, #0 ; even the econet station number MOVEQ R0, #1 | MOV R0, #1 ; leave the econet station number ] MOV R1, #0 ; zero it first cmrlp BL Write ; CMOS(R0) := R1 ADD R0, R0, #1 CMP R0, R3 MOVEQ R0, #&80 ; skip user cmos CMP r0, #YearCMOS ADDEQ r0, r0, #2 CMP r3, #UserCMOS ; system only? BNE skipskipforTC CMP r0, #NewADFSCMOS CMPNE r0, #CountryCMOS ; skip these if so ADDEQ r0, r0, #1 skipskipforTC CMP R0, #CMOSLimit BNE cmrlp [ ChecksumCMOS BL MakeChecksum ; create a valid checksum ] ; now put nice values in where necessary ; first full reset defaults CMP r3, #-1 BNE not_full_reset MOV r0, #CountryCMOS MOV r1, #1 ; country UK BL Write MOV r0, #NewADFSCMOS MOV r1, #&41 ; floppies=1, ST506=0, IDE=1 (changed 01-Sep-93) BL Write not_full_reset ; IF R or Delete pressed THEN set sync 0 ELSE set sync Auto MOV R0, #InitKbdWs LDRB R1, [R0, #R_Down_Flag] CMP R1, #0 LDREQB R1, [R0, #Del_Down_Flag] CMPEQ R1, #0 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 [ MorrisSupport MOV R8, #IOMD_Base LDRB R0, [R8, #IOMD_ID0] CMP R0, #&98 LDRB R0, [R8, #IOMD_ID1] CMPEQ r0, #&5B BNE dont_program_mousetype ; ; Morris based machines use PS2 mice/tracker balls ; MOV R0, #MouseCMOS MOV R1, #PointerDevice_PS2Mouse ;type 3 BL Write [ Select16BitSound ; set print and sound CMOS (16bit sound) B Config16BitSound ] dont_program_mousetype ] [ Select16BitSound LDR r0, =IOMD_MonitorType ; on Issue A's the protection bit is only weakly pulled up, ; so force it high, then read it back LDR r1, [r0] ORR r1, r1, #IOMD_SoundsystemLinkBit STR r1, [r0] LDR r1, [r0] TST r1, #IOMD_SoundsystemLinkBit BEQ Config16BitSound ; if zero, must be Rimmer, so assume 16bit sound hardware present ; set print and sound CMOS (8bit sound) MOV R0, #TutuCMOS MOV R1, #2_0100 ; tbs chars valid, ctrlchars '|x' BL Write B ConfigSoundDone Config16BitSound ; set print and sound CMOS (16bit sound) MOV R0, #TutuCMOS MOV R1, #2_10100100 ; tbs chars valid, ctrlchars '|x' BL Write ConfigSoundDone ] ADR R8, DefaultCMOSTable 50 LDRB R0, [R8], #1 CMP R0, #&FF BEQ hard_reset ; power on bit musta bin set LDRB R1, [R8], #1 BL Write B %BT50 LTORG DefaultCMOSTable ; list of non-zero options wanted : ; byte pairs of offset, value ; terminated by offset &FF = KeyDelCMOS, 32 = FileLangCMOS, 8 = FontCMOS, 16 ; TMD 15-Dec-93: Changed to 64K from 32K - fixes MED-01774 = PigCMOS, 10 = KeyRepCMOS, 8 = RMASizeCMOS, 0 = SpriteSizeCMOS, 0 = MODETVCMOS, &10 ; TV 0,1 = NetFSIDCMOS, 254 = NetPSIDCMOS, 235 = PSITCMOS, (3:SHL:2) :OR: (1:SHL:5) ; Baud 3 ; print 1 = DBTBCMOS, (1:SHL:4) :OR: (4:SHL:5) ; Boot (changed from NoBoot 01-Sept-93) ; Data 4 = StartCMOS, (4:SHL:0) :OR: (2:SHL:3) :OR: (1:SHL:6) ; Drive 4 (changed from Drive 0 01-Sept-93) ; NOCAPS (changed from CAPS 02-May-91) ; NODIR [ NewClockChip ; only on A1's! = NewADFSCMOS+1, &FF ; step 3 for each drive ] = NewADFSCMOS+2, 1 ; ADFSBuffers 1 = SoundCMOS, &F0 ; speaker on, volume 7, channel 1 = LanguageCMOS, ConfiguredLang = YearCMOS, 95 ; changed from 93 to 95 on 12-Jan-95 to fix MED-04318 = YearCMOS+1, 19 [ :LNOT: Select16BitSound = TutuCMOS, 2_0100 ; tbs chars valid, ctrlchars '|x' ] = NetFilerCMOS, (0:SHL:0) :OR: (1:SHL:1) :OR: (0:SHL:2) ; FS list order by name ; Use $.Arthurlib ; Large icons ; = Mode2CMOS, WimpModeAutoBit :OR: CMOSResetBit ;AKA SystemSpeedCMOS - removed by RManby and SCormie 8/3/95 = DesktopCMOS, 2_01000000 ; verbose ON = WimpFlagsCMOS, 2_01101111 ; instant effects, drags off screen = ProtectionCMOS, 2_01110110 ; allow only peek and user RPC = MouseStepCMOS, 2 = FileSwitchCMOS,(1:SHL:0) :OR: (1:SHL:1) :OR: (0:SHL:2) :OR: (0:SHL:3) :OR: (0:SHL:6) ; truncate names ; Use DragASprite (changed 01-Sept-93) ; Interactive file copying ; Wimp dither colours off ; last shutdown ordinary = DesktopFeaturesCMOS,(1:SHL:0) :OR: (8:SHL:1) :OR: (0:SHL:7) ; 3D look ; Homerton.Medium ; tiled window background = SystemSpeedCMOS,(1:SHL:0):OR:(0:SHL:1):OR:(1:SHL:2):OR:(0:SHL:3):OR:(1:SHL:4):OR:(0:SHL:5):OR:(1:SHL:6):OR:(0:SHL:7) ; AUN ROMBoot Enabled ; AUN auto-station numbering off ; Delete-etc reset ; power saving off ; WimpMode auto ; Cache on ; Broadcast loader disabled ; broadcast loader colours off = FontMax2CMOS, &2C ; 32 point = FontMax3CMOS, &38 ; 32 point = AlarmAndTimeCMOS,2_00010000 ; !Alarm autosave on = FSLockCMOS+5, &EA ; Checksum for no password = CDROMFSCMOS, &60 ; drives = 0, buffer size = 32K = &FF ALIGN 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 [ SoftResets TST r1, #por_bit BNE hard_reset ; it was a power-on, so it's a hard reset CMP r0, #0 [ DebugForcedReset MOVNE r2, #Reset_CannotResetFlag ] BNE hard_reset_forced ; IF control pressed OR memory implausible (Check SysHpd, CAM map sensible) THEN hard reset LDR R0, =SysHeapStart LDR R8, [R0, #:INDEX: hpdmagic] LDR R2, =magic_heap_descriptor CMP R8, R2 ; check sysheap initialised [ DebugForcedReset MOVNE r2, #Reset_SysHeapCorrupt ] BNE hard_reset_forced ; also check CAM map sensible [ {TRUE} ; new code which allows for MEMC2's small pages MOV R5, #0 LDR R4, [R5, #Page_Size] ; R4 = page size ADRL R3, PageShifts-1 LDRB R4, [R3, R4, LSR #12] ; R4 = log2(pagesize) LDR R3, [R5, #RAMLIMIT] ; R3 = total RAM size MOV R2, R3, LSR R4 ; number of pages=total memory / pagesize CMP R2, #256 ; but if fewer than 128 (eg 64 on A305) (NB if <256 then <=128) MOVCC R2, #128 ; then use 128 (all MEMC1's pages need initialising, ; even if half of them are not in use) SUB R2, R2, #1 [ MEMM_Type = "ARM600" LDR R3, =CamEntriesForVicky | LDRLS R3, =CamEntries ; if <= 256 pages, then should be using ; low-down cam soft copy LDRHI R3, =CamEntriesForBigMachines ; else should be using hi up one ] LDR R4, [R5, #MaxCamEntry] ; get highest CAM entry LDR R5, [R5, #CamEntriesPointer] ; and pointer to CAM soft copy | MOV R5, #0 LDR R3, [R5, #RAMLIMIT] ; read amount of RAM LDR R4, [R5, #MaxCamEntry] ; and highest CAM entry LDR R5, [R5, #CamEntriesPointer] ; and pointer to CAM soft copy CMP R3, #8*1024*1024 ; if >= 8MBytes then there are MOVCS R2, R3, LSR #15 ; RAM/32k pages MOVCC R2, #128 ; else there are 128 pages SUB R2, R2, #1 ; what highest cam index should be LDRLS R3, =CamEntries ; if <= 8MBytes, should be using ; low-down cam soft copy LDRHI R3, =CamEntriesForBigMachines ; else should be using hi up one ] CMP R5, R3 ; if not the same [ DebugForcedReset MOVNE r2, #Reset_WrongCamMapAddress BNE hard_reset_forced ] CMPEQ R4, R2 ; or number of pages not the same [ DebugForcedReset MOVNE r2, #Reset_WrongNumberOfPages ] BNE hard_reset_forced ; then do a hard reset ; now check all cam contains sensible values MOV R4, #0 LDR R4, [R4, #Page_Size] SUB R4, R4, #1 [ CPU_Type = "ARM600" ORR R4, R4, #&F0000000 ; can have addresses above 64M | ORR R4, R4, #&FC000000 ] CamCheck LDR R3, [R5, R2, LSL #2] BIC r3, r3, #&F0000000 ; remove PPL TST R3, R4 [ DebugForcedReset MOVNE r2, #Reset_CamMapCorrupt ] BNE hard_reset_forced ; wally entry: not pagesize multiple, or >= 32M SUBS R2, R2, #1 BPL CamCheck ; leave CTRL test till last, so the keyboard's had as much time to ; wiggle the wet string as we can give it MOV R0, #InitKbdWs LDRB R1, [R0, #CTRL_Down_Flag] CMP R1, #0 BNE hard_reset soft_reset ; clear out 4K of scratchspace, to use as a reverse CAM soft copy; ; set bytes to indicate page mapped to that address. Can then recalculate ; end of memory. ; This code doesn't currently work on ARM600 versions - ; 4K of workspace isn't enough to do this with a 4K page size ; We'd probably want to do it differently anyway, using the L2PT ; But since we're removing soft resets it's not worth the effort ASSERT MEMM_Type <> "ARM600" MOV R5, #ScratchSpace MOV R1, #4*1024 MOV R2, #0 clrscratch SUBS R1, R1, #4 STRPL R2, [R5, R1] BPL clrscratch LDR R2, [R2, #Page_Size] ADRL R8, PageShifts-1 LDRB R8, [R8, R2, LSR #12] MOV r7, #0 LDR r2, [r7, #RAMLIMIT] MOV r2, r2, LSR r8 ; last valid page SUB r2, r2, #1 LDR R7, [R7, #CamEntriesPointer] LDR R12, =DuffEntry restoreCAMloop LDR R3, [R7, R2, LSL #2] MOV r11, r3, LSR #28 BIC r3, r3, #&F0000000 MOV R0, R3, LSR R8 ; logram page number LDRB R4, [R5, R0] CMP r4, #0 ; check for doubly mapped pages BEQ rclon ORR r3, r12, #&30000000 ; force to invalid place if so. STR r3, [R7, R2, LSL #2] MOV r3, r12 MOV r11, #3 ; protected MOV R0, R3, LSR R8 LDRB R4, [R5, R0] rclon CMP r3, #16*1024*1024 ; in application space? MOVLT r11, #0 ; noprot if so STRLT r3, [R7, R2, LSL #2] ADD R4, R4, #1 STRB R4, [R5, R0] ; sema for interesting pages BL BangCam SUBS R2, R2, #1 BPL restoreCAMloop ; now do post-scan to see if we need to do more CAM bashing to get pages back. ; any entries that aren't validateable should be remapped. MOV R7, #0 MOV R12, #ScratchSpace LDR R2, [R7, #Page_Size] findapplend LDRB R3, [R12], #1 CMP R3, #0 ADDNE R7, R7, R2 BNE findapplend MOV R1, #0 STR R7, [R1, #AplWorkSize] ; verified value LDR R3, [R1, #RAMLIMIT] ; calc last valid page: MOV R3, R3, LSR R8 ; RAMLIMIT >> R8 MOV R11, #0 ; no PPL LDR R4, [R11, #CamEntriesPointer] testforremap SUBS R3, R3, #1 BMI finishedremap LDR R0, [R4, R3, LSL #2] BIC r0, r0, #&F0000000 ; remove PPL ADD R1, R0, R2 SWI XOS_ValidateAddress BCC testforremap Push "R2-R4" MOV R0, R0, LSR R8 ; curr logram page number LDRB R4, [R5, R0] SUB R4, R4, #1 STRB R4, [R5, R0] ; dec sema MOV R2, R3 ; entry no MOV R3, R7 ; addr to set to BL BangCamUpdate Pull "R2-R4" holefilled ADD R7, R7, R2 LDRB R0, [R12], #1 ; reinspect our reverse map CMP R0, #0 BNE holefilled MOV R0, #0 STR R7, [R0, #AplWorkSize] B testforremap finishedremap MOV R12, #NVECTORS-1 LDR R11, =VecPtrTab freenextvec LDR R2, [R11, R12, LSL #2] loseveclink LDR R3, [R2, #TailPtr] BL FreeSysHeapNode MOVVC R2, R3 BVC loseveclink CMP R3, #0 ; were we at the end of the chain? [ DebugForcedReset MOVNE r2, #Reset_VectorChainCorrupt ] BNE hard_reset_forced SUBS R12, R12, #1 BPL freenextvec ; so that's the code for restore default vectors, basically BL InitVectors MOV R0, #0 LDR R1, [R0, #AplWorkSize] STR R1, [R0, #MemLimit] LDR R3, =TickNodeChain LDR R2, [R3] loseticknodes CMP R2, #0 BEQ ticknodesallgone LDR R3, [R2] BL FreeSysHeapNode [ DebugForcedReset MOVVS r2, #Reset_TickNodesCorrupt ] BVS hard_reset_forced MOV R2, R3 B loseticknodes ticknodesallgone ; and now it's time to free the IRQ structures MOV R12, #(NoInterrupt-1)*12+8 ; last device link offset LDR R11, =DefaultIRQ1V-DefaultIRQ1Vcode+Devices freenextdev LDR R2, [R11, R12] losedevlink CMP R2, #0 BEQ stepdevice LDR R3, [R2, #8] BL FreeSysHeapNode [ DebugForcedReset MOVVS r2, #Reset_DeviceVectorCorrupt ] BVS hard_reset_forced MOV R2, R3 B losedevlink stepdevice SUBS R12, R12, #12 BPL freenextdev ; now the PIRQ structures and CallBack_Vector LDR R11, =PIRQ_Chain MOV r4, #PodDesp_Link losepirqchain LDR R2, [R11] CMP r2, #0 ; for CallBack_Vector BEQ doobry losepirqlink LDR R3, [R2, r4] BL FreeSysHeapNode MOVVC R2, R3 BVC losepirqlink CMP R3, #0 ; were we at the end of the chain? [ DebugForcedReset MOVNE r2, #Reset_PoduleOrCallBackCorrupt ] BNE hard_reset_forced LDR R2, =PIRQ_Chain CMP R11, R2 LDR R2, =PFIQasIRQ_Chain MOVEQ R11, R2 CMPNE r11, r2 LDREQ r11, =CallBack_Vector [ PodDesp_Link <> 0 MOVEQ r4, #0 ] BEQ losepirqchain doobry Pull "R1" ; IOCControl restoration MOV R0, #0 STRB R1, [R0, #IOCControlSoftCopy] MOV R0, #IOC ; and bash the hardware STRB R1, [R0, #IOCControl] MOV R0, #SoftReset B ResetPart1Done | ; if soft resets are disabled, drop thru into hard reset code ] ; end of code to do with soft resets hard_reset [ DebugForcedReset MOV r2, #0 ; indicate normal hard reset ] hard_reset_forced [ DebugForcedReset STR r2, [r0, -r0] ; store to logical address zero ] Pull "R2" ; discard old IOC state ; fill in relevant CamMap entries, so can soft start. MOV R8, #0 LDR R8, [R8, #Page_Size] ADRL R1, PageShifts-1 LDRB R1, [R1, R8, LSR #12] [ ExpandedCamMap MOV r2, #0 [ MEMM_Type = "ARM600" LDR r0, [r2, #VideoSize] ; offset from start of physical pages to static part | LDR r0, =480*1024 ] MOV r0, r0, LSR r1 ; r0 := cam entry number MOV r0, r0, LSL #3 ; r0 := offset into CAM map for start of static part MOV R7, #32*1024*8 MOV R7, R7, LSR R1 ; r7 := cam entry offset for 32K | MOV R0, #(512-32)*1024*4 MOV R0, R0, LSR R1 ; r0 := cam entry number * 4 MOV R7, #32*1024*4 MOV R7, R7, LSR R1 ; r7 := cam entry offset for 32K MOV R2, #0 ] LDR R12, [R2, #RAMLIMIT] ; R12 = total RAM size ; new code which allows for MEMC2's small pages MOV R1, R12, LSR R1 ; R1 = number of pages CMP R1, #256 ; but if fewer than 128 (eg 64 on A305) (NB if <256 then <=128) MOVCC R1, #128 ; then use 128 (all MEMC1's pages need initialising, ; even if half of them are not in use) SUB R3, R1, #1 STR R3, [R2, #MaxCamEntry] [ MEMM_Type = "ARM600" LDR R1, =CamEntriesForVicky | LDRLS R1, =CamEntries ; if <=256 pages (was if <=8MBytes) then small CAM copy LDRHI R1, =CamEntriesForBigMachines ; else use big CAM copy ] STR R1, [R2, #CamEntriesPointer] [ MEMM_Type = "ARM600" ; On ARM600 we must zap all the soft CAM map before adding any entries, ; since the old contents are used in BangCamUpdate Push "r0" ADD r2, r1, r3, LSL #3 ; r2 -> last entry to do LDR r0, =DuffEntry MOV lr, #AP_Duff ; PPL = no access WallopDuffOnes STMDA r2!, {r0, lr} ; store address, PPL CMP r2, r1 BCS WallopDuffOnes Pull "r0" ] ADD R0, R0, R1 MOV R2, #CursorChunkAddress LDR r1, =AP_CursorChunk BL AddCamEntries CMP R12, #512*1024 SUBEQ R0, R0, R7 ; previous entries ADDNE R0, R0, R7 ; next entries MOV R2, #0 MOV r1, #AP_PageZero BL AddCamEntries CMP R12, #512*1024 SUBEQ R0, R0, R7 ; previous entries ADDNE R0, R0, R7 ; next entries MOV R2, #SysHeapChunkAddress MOV r1, #AP_SysHeap :OR: PageFlags_Unavailable BL AddCamEntries [ MEMM_Type = "ARM600" ADD R0, R0, R7 ; next entries (ignore 512K machines) MOV r7, #0 LDR r7, [r7, #L2PTSize] MOV r7, r7, LSR #12-3 ; number of pages * 8 LDR R2, =L2PT LDR r1, =AP_L2PT :OR: PageFlags_Unavailable BL AddCamEntries ADD r2, r0, #((L1PT-L2PT):SHR:(12-3)) + 4 ; point at PPL for 1st L1 page LDR r1, =AP_L1PT STR r1, [r2], #8 ; store 4 CAM entries for 4 x 4K = 16K of L1 STR r1, [r2], #8 ; mark them as unavailable for removal STR r1, [r2], #8 STR r1, [r2], #8 ADD R0, R0, R7 ; add on enough pages for L2PT MOV r7, #0 LDR r7, [r7, #SoftCamMapSize] ; number of bytes in soft cam map ADD r7, r7, #UndStackSize MOV r7, r7, LSR #12-3 ; number of bytes of cam map for this LDR R2, =UndStackSoftCamChunk MOV r1, #AP_UndStackSoftCam BL AddCamEntries | [ MEMM_Type = "MEMC2" ; CCs from CMP still valid SUBEQ R0, R0, R7 ; previous entries ADDNE R0, R0, R7 ; next entries LDR R2, =CursorChunkAddress+64*1024 ; 01F10000 MOV r1, #AP_CursorChunk BL AddCamEntries ] ] ; let's boogie with the CMOS for a bit ; read info and move as much memory as we can BL InitDynamicAreas [ NewStyle_Screen Push "r0-r12" MOV r0, #ScreenSizeCMOS BL Read MOV r5, #0 LDR r10, [r5, #Page_Size] ; needed by MassageScreenSize MUL r0, r10, r0 ; convert to bytes LDR r5, [r5, #VideoSize] ; maximum size BL MassageScreenSize MOV r1, #ChangeDyn_Screen ; area number MOV r2, r0 ; initial size MOV r3, #ScreenEndAdr ; base address (start of 2nd copy) LDR r4, =AP_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 Pull "r0-r12" | MOV R2, #0 ; CAM entry number to use (irrelevant for new code) MOV R0, #ScreenSizeCMOS ; CMOS byte to read MOV R3, #ScreenEndAdr ; where to put it (screen fudged) LDR R1, =VduDriverWorkSpace+TotalScreenSize ; variable to save size set MOV r11, #AP_Screen ; Unprotected BL ReadCMOSAndConfigure ; Screen must be done first to get video RAM pages ] [ NewStyle_RMA Push "r0-r12" MOV r1, #ChangeDyn_RMA ; Area number MOV r2, #4096 ; Initial size MOV r3, #RMAAddress ; Base address MOV r4, #AP_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" | MOV R0, #1 ; One page. Unprotected MOV R3, #RMAAddress ADD R1, R3, #:INDEX: hpdend ; see comment about SysHeap! MOV r11, #AP_RMA BL FudgeConfigureRMA ] [ NewStyle_SpriteArea Push "r0-r12" MOV r0, #0 ; initialise SpriteSize to zero STR r0, [r0, #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, #AP_Sprites ; Area flags MOV r5, #-1 ; Maximum size 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" | MOV R0, #SpriteSizeCMOS MOV R3, #SpriteSpaceAddress LDR R1, =SpriteSize ; for Richard. Unprotected MOV r11, #AP_Sprites BL ReadCMOSAndConfigure ] [ NewStyle_RAMDisc Push "r0-r12" MOV r0, #RAMDiscCMOS ; find out how much RAM disc configured BL GetConfiguredSize ; in: r0 = CMOS address, out: r2 = size MOV r1, #ChangeDyn_RamFS ; Area number MOV r3, #-1 ; Base address dynamic MOV r4, #AP_RAMDisc ; Area flags MOV r5, #16*1024*1024 ; Limit maximum size to 16MB until JSR fixes FileCore 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! Pull "r0-r12" | MOV R0, #RAMDiscCMOS MOV R3, #RAMDiscAddress LDR R1, =RAMDiscSize ; for RAMFS MOV r11, #AP_RAMDisc ; protected BL ReadCMOSAndConfigure ] [ NewStyle_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, #AP_FontArea ; Area flags MOV r5, #-1 ; Maximum size 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" | MOV R0, #FontCMOS MOV R3, #FontCacheAddress LDR R1, =FontCacheSize ; for Fontmanager MOV r11, #AP_FontArea BL ReadCMOSAndConfigure ; still protected ] ; get here with R2 = highest CAM entry used (in old model) [ MEMM_Type = "ARM600" LDR R0, =(AplWorkMaxSize-32*1024):SHR:12 ; maximum number of pages in aplspace MOV R3, #32*1024 ; aplwork start LDR R1, =AplWorkSize ; aplwork size MOV r11, #AP_AppSpace BL FudgeConfigureRMA ; put as much as possible in aplspace [ :LNOT: GetPagesFromFreePool ; memory is already in free pool, so don't mess around MOV r0, #0 LDR r0, [r0, #RAMLIMIT] MOV r0, r0, LSR #12 ; only limit on free pool is ram size MOV R3, #FreePoolAddress LDR R1, =FreePoolDANode + DANode_Size MOV r11, #AP_FreePool BL FudgeConfigureRMA ; and the rest in FreePool ] | MOV R0, #4096 ; try and get maximum amount possible MOV R3, #32*1024 ; aplwork start LDR R1, =AplWorkSize ; aplwork size MOV r11, #AP_AppSpace BL FudgeConfigureRMA ; stuff rest on AplWork ] MOV R0, #0 LDR R1, [R0, #AplWorkSize] ADD R1, R1, #32*1024 STR R1, [R0, #AplWorkSize] STR R1, [R0, #MemLimit] [ MEMM_Type <> "ARM600" ; Now add all the NaffEntries to CamEntries ; R2 highest CAM entry used ; NB This is not done on ARM600, as the whole soft CAM map has to be zapped before ; we start, because BangCamUpdate uses the old contents LDR R3, [R0, #MaxCamEntry] ; (R0 still zero from above) CMP R2, R3 BGT CAMallset LDR R0, [R0, #CamEntriesPointer] ; (R0 still zero from above) [ ExpandedCamMap ADD r3, r0, r3, LSL #3 ; r3 -> last pair of words to do ADD r0, r0, r2, LSL #3 ; r0 -> first pair of words to do LDR r1, =DuffEntry ; address MOV r2, #AP_Duff ; PPL WallopDuffOnes STMIA r0!, {r1, r2} ; store address, PPL CMP r0, r3 BLS WallopDuffOnes | LDR R1, =DuffEntry :OR: (AP_Duff :SHL: 28) WallopDuffOnes STR R1, [R0, R2, LSL #2] ADD R2, R2, #1 CMP R2, R3 BLE WallopDuffOnes ] CAMallset ] [ :LNOT: NewCDA ; System heap only initialised here on older software models ; On new ones it's already been initialised by hand in InitDynamicAreas, ; so that we can create dynamic areas above here. MOV R0, #HeapReason_Init ; initialise system heap LDR R1, =SysHeapStart MOV R3, #32*1024 - (SysHeapStart-SysHeapChunkAddress) STR R3, [R1, #:INDEX: hpdend] ; keep ValidateAddress happy SWI XOS_Heap ; tuff if it fails ] BL InitVectors ; ready for OsByte to read mode [ :LNOT: GetPagesFromFreePool MOV R0, #0 ; initialise module list to empty STR R0, [R0, #Module_List] ] LDR R1, =ModuleSWI_HashTab MOV R2, #ModuleSHT_Entries-1 clearmswis STR R0, [R1, R2, LSL #2] SUBS R2, R2, #1 BGE clearmswis [ International MOV R1, #-1 ; We don't have a message file yet ! STRB R1, [R0, #ErrorSemaphore] ; Don't translate errors. STR R0, [R0, #KernelMessagesBlock] ; No message file open. ] MOV R0, #IOC LDRB R1, [R0, #IOCIRQSTAA] ANDS R1, R1, #por_bit STRNEB R1, [R0, #IOCIRQCLRA] ; clear POR if set LDREQ R0, =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 TEQP PC, #SVC_mode + I_bit ; interrupts off since kbd bash done LDR R1, =OsbyteVars + :INDEX: LastBREAK STRB R0, [R1] MOV R1, #InitKbdWs LDRB R0, [R1, #KB_There_Flag] LDRB R1, [R1, #SHIFT_Down_Flag] Push "R0, R1" ; save until after MOSInit ; copy IRQ handler: not done with rest of copying ; because soft break needs the info to free any claimed blocks. LDR R0, =DefaultIRQ1V ADRL R1, DefaultIRQ1Vcode ADRL R2, DefaultIRQ1Vcode_end CopyDefaultIRQ1V LDR R3, [R1], #4 STR R3, [R0], #4 CMP R1, R2 BNE CopyDefaultIRQ1V LDR R0, =PIRQ_Chain ADRL R1, Default_PIRQHandler_Node STR R1, [R0] STR R1, [R0, #PFIQasIRQ_Chain-PIRQ_Chain] ASSERT Default_PFIQasIRQHandler_Node = Default_PIRQHandler_Node MOV R0, #0 ; put in IRQ handler, word at 0 STRB r0, [r0, #FIQclaim_interlock] STRB r0, [r0, #CallBack_Flag] STR r0, [r0, #CallBack_Vector] [ CPU_Type = "ARM600" ; we're poking locations 0 and &18 here, so we'd best go back to SVC32 mrs AL, r2, CPSR_all BIC r3, r2, #&1F ORR r3, r3, #SVC32_mode msr AL, CPSR_all, r3 ] [ DebugForcedReset LDR R1, [R0] TEQ R1, #0 ; if normal hard reset LDREQ R1, BranchThroughZeroInstruction2 ; then get branchthruzero code | LDR R1, BranchThroughZeroInstruction2 ] STR R1, [R0] ; put branch through 0 code at 0 LDR R1, RealIRQHandler STR R1, [R0, #&18] [ CPU_Type = "ARM600" ; now back to SVC26 msr AL, CPSR_all, r2 ] MOV R1, #&100 STR R1, [R0, #RCLimit] STR R0, [R0, #ReturnCode] STR R0, [R0, #TickNodeChain] ;now put in error handler and escape handler BL DEFHAN BL DEFHN2 MOV R0, #ExceptionDumpArea LDR R1, =DUMPER SWI XOS_ChangeEnvironment VDWS WsPtr ; main MOS initialisation BL VduInit BL ExecuteInit BL KeyInit BL MouseInit BL OscliInit ; before initialising modules TEQP pc, #SVC_mode ; enable IRQs NOP 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 BL InitVariables 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 MOV R0, #0 LDR R0, [R0, #Page_Size] MULTIPLY 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 MOV r1, #Service_PostInit ; issue post-initialisation service BL Issue_Service ; New code added here by TMD 01-Apr-92 ; Go into user mode, issue a dummy SWI, then go back into SVC mode TEQP PC, #0 ; enter USR mode (IRQs, FIQs enabled) NOP ; wait for it to take effect SWI XOS_WriteI+0 ; I hope it doesn't generate an error ; otherwise the callback will get deferred! SWI XOS_EnterOS ; switch back to SVC mode (IRQs, FIQs enabled) ; end of added code [ International ; Open the kernel messages file. ADR r0, KernelMessagesBlock+4 ADR r1, MessageFileName MOV r2, #0 ; Use file directly. SWI XMessageTrans_OpenFile MOVVC r0, #-1 STRVC r0, [r0, #KernelMessagesBlock+1] ; Message file is now open. ] SkipHardResetPart2 ; code executed on all types of reset [ International MOV r0, #0 LDR r1, [r0, #KernelMessagesBlock] ; if we've managed to open message file TEQ r1, #0 STRNEB r0, [r0, #ErrorSemaphore] ; then allow errors to be translated ] BL InitialiseMode SWI XOS_WriteS = 10, "$SystemName ", 0 ; now RISC OS (no +) again ALIGN MOV R0, #0 LDR R0, [R0, #RAMLIMIT] [ {TRUE} ; Give startup message in megabytes MOV R0, R0, LSR #20 ; /(1024*1024) LDR R1, =GeneralMOSBuffer MOV R2, #?GeneralMOSBuffer SWI XOS_ConvertInteger4 SWI XOS_Write0 SWI XOS_WriteS = "MB", 10,13, 10, 0 ; title complete ALIGN | MOV R0, R0, LSR #10 ; /1024 LDR R1, =GeneralMOSBuffer MOV R2, #?GeneralMOSBuffer SWI XOS_ConvertInteger4 SWI XOS_Write0 SWI XOS_WriteS = "K", 10,13, 10, 0 ; title complete ALIGN ] MOV r0, #0 ; Set DomainId to 0 every reset STR r0, [r0, #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 MOV R0, #FSControl_Shut ; Open files get closed at reset SWI XOS_FSControl 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! CMP r1, #PowerOnReset BNE %FT75 [ CheckProtectionLink LDR r1, =IOMD_MonitorType ; check link bit again LDRB r1, [r1] ; no need to preload bus, since should TST r1, #IOMD_ProtectionLinkBit ; be still there from earlier BEQ %FT75 ; zero => protected ] ; 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 MOV r3, #0 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 BLVC WriteS_Translated = "MonType:Monitor type reconfigured.",10,13,10,0 ALIGN | SWI XOS_WriteS = 10,"Monitor type reconfigured.",10,13,10,0 ALIGN ] B %FT75 BranchThroughZeroInstruction2 [ ProcessorVectors LDR PC, .+ProcVec_Branch0 | B .+(RESET1-0) ] 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 [ International MessageFileName DCB "Resources:$.Resources.Kernel.Messages",0 ALIGN ] 70 MOV r14, #0 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 MOV r3, #0 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 MOV r0, #0 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_Title] 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 BLVC 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 RealIRQHandler [ ProcessorVectors LDR PC, .-&18+ProcVec_IRQ | B Initial_IRQ_Code+.-&18 ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; 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 ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ [ AddTubeBashers TubeDumpR0 ROUT Push "R1, R2, lr" ADR lr, HexTable TubeChar r0, r1, "MOV r1, #"" """ MOV R1, #7 01 MOV R0, R0, ROR #28 AND R2, R0, #&F TubeChar R0, R1, "LDRB R1, [lr, R2]" SUBS R1, R1, #1 BPL %BT01 TubeChar r0, r1, "MOV r1, #"" """ Pull "R1, R2, PC", ,^ TubeNewl TubeChar R0, R1, "MOV R1, #10" TubeChar R0, R1, "MOV R1, #13" MOVS pc, lr HexTable = "0123456789ABCDEF" ] ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ END