1 1.1 jdolecek REM > BtNetBSD 2 1.7 andvar REM $NetBSD: BtNetBSD,v 1.7 2025/08/18 20:59:54 andvar Exp $ 3 1.1 jdolecek REM 4 1.1 jdolecek REM Copyright (c) 2000, 2001, 2002 Reinoud Zandijk 5 1.1 jdolecek REM Copyright (c) 1998, 1999, 2000 Ben Harris 6 1.1 jdolecek REM ELF file reading based on work by Ben Harris 7 1.1 jdolecek REM All rights reserved. 8 1.1 jdolecek REM 9 1.1 jdolecek REM Redistribution and use in source and binary forms, with or without 10 1.1 jdolecek REM modification, are permitted provided that the following conditions 11 1.1 jdolecek REM are met: 12 1.1 jdolecek REM 1. Redistributions of source code must retain the above copyright 13 1.1 jdolecek REM notice, this list of conditions and the following disclaimer. 14 1.1 jdolecek REM 2. Redistributions in binary form must reproduce the above copyright 15 1.1 jdolecek REM notice, this list of conditions and the following disclaimer in the 16 1.1 jdolecek REM documentation and/or other materials provided with the distribution. 17 1.1 jdolecek REM 3. The name of the author may not be used to endorse or promote products 18 1.1 jdolecek REM derived from this software without specific prior written permission. 19 1.1 jdolecek REM 20 1.1 jdolecek REM THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 1.1 jdolecek REM IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 1.1 jdolecek REM OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 1.1 jdolecek REM IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 1.1 jdolecek REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 1.1 jdolecek REM NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 1.1 jdolecek REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 1.1 jdolecek REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 1.1 jdolecek REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 1.1 jdolecek REM THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 1.1 jdolecek REM 31 1.1 jdolecek REM This file is part of NetBSD/acorn32 -- a port of NetBSD to ARM6+ machines 32 1.1 jdolecek REM This source contains pieces of code by Ben Harris (file structure) 33 1.1 jdolecek REM and Mark Brinicombe (DRAM/VRAM search) 34 1.1 jdolecek REM 35 1.1 jdolecek REM Purpose : Trying to boot NetBSD/acorn32 !! 36 1.1 jdolecek 37 1.1 jdolecek 38 1.1 jdolecek ON ERROR REPORT:PRINT " at line ";ERL: PRINT'"Press key":QQ=GET:END 39 1.1 jdolecek 40 1.1 jdolecek debug% = 0 41 1.1 jdolecek emulateVRAM% = 0 42 1.1 jdolecek emulateDRAMsize% = 0 43 1.1 jdolecek extradebug% = 0 44 1.1 jdolecek startdelay% = 5 45 1.1 jdolecek 46 1.1 jdolecek REM For Kinetic cards 47 1.1 jdolecek SDRAM_ADDR_START% = 512*1024*1024 48 1.1 jdolecek REM For debugging only : 49 1.1 jdolecek REM SDRAM_ADDR_START% = &18000000 50 1.1 jdolecek 51 1.1 jdolecek 52 1.1 jdolecek REM set pretty screen for printing without scrolling 53 1.1 jdolecek SYS "XWimp_CommandWindow", -1: VDU 26 54 1.1 jdolecek SYS "XHourglass_Smash" 55 1.1 jdolecek MODE MODE 56 1.1 jdolecek COLOUR 128+4:CLS 57 1.1 jdolecek scwidth% = FNvdu_var(256): scheigth% = FNvdu_var(257) 58 1.1 jdolecek width% = INT(scwidth%*0.75*0.5)*2: heigth% = INT(scheigth%*0.75*0.5)*2 59 1.1 jdolecek VDU 4, 28, (scwidth%-width%)/2, (scheigth%+heigth%)/2, (scwidth%+width%)/2, (scheigth%-heigth%)/2 60 1.1 jdolecek COLOUR 128:CLS 61 1.1 jdolecek 62 1.1 jdolecek PRINT'' 63 1.3 bjh21 PROCcenter("BtNetBSD 0.99b") 64 1.1 jdolecek PROCcenter("booting NetBSD/acorn32 on a RiscPC/A7000/NC") 65 1.1 jdolecek PRINT'' 66 1.1 jdolecek 67 1.1 jdolecek REM get argument string 68 1.1 jdolecek SYS "OS_GetEnv" TO args$ 69 1.1 jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE 70 1.1 jdolecek IF LEFT$(args$, 5)="BASIC" THEN args$=MID$(args$, 6) 71 1.1 jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE 72 1.1 jdolecek IF LEFT$(args$, 5)="-quit" THEN args$=MID$(args$, 6) 73 1.1 jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE 74 1.1 jdolecek prog$ = LEFT$(args$, INSTR(args$, " ")-1) 75 1.1 jdolecek args$ = MID$(args$, LEN(prog$)+1) 76 1.1 jdolecek WHILE LEFT$(args$, 1)=" ": args$=MID$(args$,2):ENDWHILE 77 1.1 jdolecek 78 1.1 jdolecek REM get kernel name 79 1.1 jdolecek file$ = LEFT$(args$, INSTR(args$, " ")-1) 80 1.3 bjh21 81 1.3 bjh21 PRINT "Press return to boot now, any other key for boot prompt" 82 1.3 bjh21 PRINT "Booting ";file$;" ";args$ 83 1.3 bjh21 PRINT "Starting in "; 84 1.3 bjh21 c% = FNawaitkey(5) 85 1.3 bjh21 IF c% <> 13 AND c% <> 0 THEN 86 1.3 bjh21 INPUT "Boot: " cmd$ 87 1.3 bjh21 IF LEFT$(cmd$, 1) = "-" THEN 88 1.3 bjh21 REM just add an option 89 1.3 bjh21 args$ += " " + cmd$ 90 1.3 bjh21 ELSE 91 1.3 bjh21 args$ = cmd$ 92 1.3 bjh21 file$ = LEFT$(args$, INSTR(args$, " ") - 1) 93 1.3 bjh21 ENDIF 94 1.3 bjh21 PRINT "Booting ";file$;" ";args$ 95 1.3 bjh21 ENDIF 96 1.3 bjh21 PRINT'' 97 1.1 jdolecek 98 1.1 jdolecek 99 1.1 jdolecek IF FNtolower(LEFT$(file$,9))="unixfs:$." THEN 100 1.1 jdolecek kernelname$=MID$(file$, 10) 101 1.1 jdolecek ELSE 102 1.1 jdolecek kernelname$="netbsd" : REM RISC OS file namen zeggen niets XXX 103 1.1 jdolecek ENDIF 104 1.1 jdolecek 105 1.1 jdolecek 106 1.1 jdolecek REM Get some space to mess with 107 1.1 jdolecek REM Declare a large array ... and then wipe it/map it in in the OS_Mem loop 108 1.1 jdolecek REM the difference is that RO4 won't map it in by default and 109 1.1 jdolecek REM that could trigger a OS_Memory bug ... 110 1.1 jdolecek SYS "OS_Memory", 6 TO ,memorytablesize%, nbpp% : REM get tablesize% 111 1.1 jdolecek memory_image_size% = HIMEM-512*1024 : REM keep a 512 Kb for vars 112 1.1 jdolecek DIM memory_image% memory_image_size% : REM claim the space 113 1.1 jdolecek 114 1.1 jdolecek bot_memory% = memory_image% 115 1.1 jdolecek top_memory% = memory_image% + memory_image_size% 116 1.1 jdolecek 117 1.1 jdolecek KERNEL_BASE = &F0000000 118 1.1 jdolecek 119 1.1 jdolecek MAX_RELOCPAGES = 4096 120 1.1 jdolecek MAX_DRAMBANKS = 32 121 1.1 jdolecek MAX_VRAMBANKS = 16 122 1.1 jdolecek 123 1.1 jdolecek twirl% = 0 124 1.1 jdolecek firstpage% = (bot_memory% DIV nbpp%)+1 125 1.1 jdolecek lastpage% = (top_memory% DIV nbpp%)-1 126 1.1 jdolecek totalpages% = lastpage% - firstpage% 127 1.1 jdolecek PRINT "I got a ";totalpages%;" memory pages to mess with" 128 1.1 jdolecek 129 1.1 jdolecek relocsize% = (MAX_RELOCPAGES+1)*12 130 1.1 jdolecek DIM relocinstr% relocsize% 131 1.1 jdolecek relocpos% = relocinstr%+4 : REM first word in number of relocations 132 1.1 jdolecek relocnr% = 0: relocoff% = 0 133 1.1 jdolecek 134 1.1 jdolecek REM this memory block contains all information about the memory layout 135 1.1 jdolecek REM maybe a bug in BASIC but if I DIM this variable in a procedure it 136 1.1 jdolecek REM gets on the stack or so ? It malfunctions if I pass this on as a 137 1.1 jdolecek REM procedure variable. 138 1.1 jdolecek DIM memoryblock% (totalpages%*12+4) 139 1.1 jdolecek 140 1.1 jdolecek PROCget_memory_configuration 141 1.1 jdolecek PROCget_memory_map 142 1.1 jdolecek 143 1.1 jdolecek PROCload_kernel(file$) 144 1.1 jdolecek PROCcreate_initial_pagetables 145 1.1 jdolecek PROCadd_pagetables 146 1.1 jdolecek PROCcreate_configuration 147 1.1 jdolecek 148 1.1 jdolecek REM now only the relocation code itself and then copying the relocation table itself 149 1.1 jdolecek !relocinstr% = relocnr% 150 1.1 jdolecek PROCcreate_relocate_mechanism 151 1.1 jdolecek PRINT " " 152 1.1 jdolecek 153 1.1 jdolecek REM start the kernel 154 1.1 jdolecek A% = FNblock_paddr(configurationbasepage%) 155 1.1 jdolecek B% = physical_start_address% - FNblock_vaddr(relocatebasepage%) + FNblock_paddr(relocatebasepage%) 156 1.1 jdolecek C% = FNblock_paddr(relocatebasepage%) + nbpp% : REM one page after the code 157 1.1 jdolecek D% = L1pages_phys% 158 1.1 jdolecek E% = entry% 159 1.1 jdolecek 160 1.1 jdolecek IF debug% THEN 161 1.1 jdolecek IF ((relocpos%-(relocinstr%+4)) MOD 12)<>0 THEN ERROR 0,"Sanity check for relocation entries failed!" 162 1.1 jdolecek PRINT"Entering kernel at 0x";~entry% 163 1.1 jdolecek REM OSCLI("Memoryi "+STR$~(FNblock_vaddr(start_kernelpage%)+(entry% MOD nbpp%))) 164 1.1 jdolecek REM PRINT"Go for it (key)":qq=GET 165 1.1 jdolecek ENDIF 166 1.1 jdolecek 167 1.1 jdolecek REM get ECID for each podule 168 1.1 jdolecek FOR pod% =-1 TO 8 169 1.1 jdolecek SYS "XPodule_ReadID",,,,pod% 170 1.1 jdolecek NEXT 171 1.1 jdolecek 172 1.1 jdolecek REM shut down RiscOS 173 1.1 jdolecek SYS "XOS_CLI", "RMKill UnixFS" 174 1.1 jdolecek SYS "OS_FSControl", 23 : REM close files etc. 175 1.1 jdolecek SYS "OS_ServiceCall",, &45 : REM prereset 176 1.1 jdolecek 177 1.1 jdolecek REM Remove all cursors 178 1.1 jdolecek *pointer 0 179 1.1 jdolecek SYS "OS_RemoveCursors" 180 1.1 jdolecek 181 1.5 reinoud REM Change screen's base address (VDU/displayed) to offset 0 182 1.1 jdolecek DIM buf 8 183 1.5 reinoud buf?3 = 3: buf!4 = 0: SYS "OS_Word", 22, buf+3 184 1.1 jdolecek 185 1.1 jdolecek CALL relocate_entry% 186 1.1 jdolecek 187 1.1 jdolecek END 188 1.1 jdolecek 189 1.1 jdolecek 190 1.1 jdolecek DEF PROCload_kernel(file$) 191 1.1 jdolecek LOCAL file%, magic% 192 1.1 jdolecek file% = OPENIN(file$) 193 1.1 jdolecek IF file% = 0 THEN ERROR EXT 1, "Can't open kernel" 194 1.1 jdolecek DIM magic% 3 195 1.1 jdolecek SYS "OS_GBPB", 3, file%, magic%, 4, 0 196 1.1 jdolecek IF magic%?0 = 127 AND magic%?1 = ASC("E") AND magic%?2 = ASC("L") AND magic%?3 = ASC("F") THEN 197 1.1 jdolecek PROCload_kernel_elf(file%) 198 1.1 jdolecek ELSE 199 1.1 jdolecek PROCload_kernel_aout(file%) 200 1.1 jdolecek ENDIF 201 1.1 jdolecek CLOSE#file% 202 1.1 jdolecek ENDPROC 203 1.1 jdolecek 204 1.1 jdolecek 205 1.1 jdolecek 206 1.1 jdolecek REM ***************************************************************************** 207 1.1 jdolecek REM * ELF LOADER * 208 1.1 jdolecek REM ***************************************************************************** 209 1.1 jdolecek 210 1.1 jdolecek 211 1.1 jdolecek DEF PROCload_kernel_elf(file%) 212 1.1 jdolecek REM read header 213 1.1 jdolecek DIM hdr% 52 214 1.1 jdolecek SYS "OS_GBPB", 3, file%, hdr%, 52, 0 215 1.1 jdolecek 216 1.1 jdolecek REM check if its a correct kernel to load 217 1.1 jdolecek IF hdr%?4 <> 1 THEN ERROR 1, "Not a 32-bit ELF file" 218 1.1 jdolecek IF hdr%?5 <> 1 THEN ERROR 1, "Not an LSB ELF file" 219 1.1 jdolecek IF hdr%?6 <> 1 THEN ERROR 1, "Not a version-1 ELF file" 220 1.1 jdolecek REM hdr%?7 is EI_OSABI. Should it be 255 (ELFOSABI_STANDALONE)? 221 1.1 jdolecek IF (hdr%!16 AND &FFFF) <> 2 THEN ERROR 1, "Not an executable ELF file" 222 1.1 jdolecek IF (hdr%!18 AND &FFFF) <> 40 THEN ERROR 1, "Not an ARM ELF file" 223 1.1 jdolecek 224 1.1 jdolecek PRINT "(ELF) "; 225 1.1 jdolecek REM read kernel characteristics and headers 226 1.1 jdolecek entry% = hdr%!24 227 1.1 jdolecek phoff% = hdr%!28 228 1.1 jdolecek shoff% = hdr%!32 229 1.1 jdolecek phentsize% = hdr%!42 AND &FFFF 230 1.1 jdolecek phnum% = hdr%!44 AND &FFFF 231 1.1 jdolecek shentsize% = hdr%!46 AND &FFFF 232 1.1 jdolecek shnum% = hdr%!48 AND &FFFF 233 1.1 jdolecek DIM phdrs% phnum% * phentsize% - 1 : REM array with headers ? 234 1.1 jdolecek SYS "OS_GBPB", 3, file%, phdrs%, phnum% * phentsize%, phoff% 235 1.1 jdolecek IF phnum% = 0 THEN ERROR 1, "No program headers" 236 1.1 jdolecek 237 1.1 jdolecek REM start loading ! 238 1.1 jdolecek freepagesbase% = first_mapped_DRAM_index% : REM == first virt address in DRAM0a 239 1.1 jdolecek start_kernelpage% = freepagesbase% 240 1.1 jdolecek pv_offset% = KERNEL_BASE - DRAM_addr%(0) : REM XXX hardcoded 241 1.1 jdolecek 242 1.1 jdolecek REM load the program blocks 243 1.1 jdolecek first% = TRUE 244 1.1 jdolecek FOR ph% = phdrs% TO phdrs% + (phnum% - 1) * phentsize% STEP phentsize% 245 1.1 jdolecek IF ph%!0 = 1 THEN 246 1.1 jdolecek REM We only do PT_LOAD 247 1.1 jdolecek IF NOT first% THEN PRINT "+"; 248 1.1 jdolecek first% = FALSE 249 1.1 jdolecek offset% = ph%!4 250 1.1 jdolecek vaddr% = ph%!8 251 1.1 jdolecek REM physaddr% = ph%!12 252 1.1 jdolecek filesz% = ph%!16 253 1.1 jdolecek memsz% = ph%!20 254 1.1 jdolecek flags% = ph%!24 255 1.1 jdolecek PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%) 256 1.1 jdolecek REM freepagesbase% is updated 257 1.1 jdolecek 258 1.1 jdolecek vfreebase% = vaddr% + memsz% : REM memsz% is the real size.... filesz can be only Text f.e. 259 1.1 jdolecek ENDIF 260 1.1 jdolecek NEXT 261 1.1 jdolecek 262 1.1 jdolecek txtbase% = 0 263 1.1 jdolecek txtsize% = 0 264 1.1 jdolecek database% = 0 265 1.1 jdolecek datasize% = 0 266 1.1 jdolecek bssbase% = 0 267 1.1 jdolecek bsssize% = 0 268 1.1 jdolecek ssym% = 0 269 1.1 jdolecek esym% = 0 270 1.1 jdolecek 271 1.1 jdolecek DIM shdrs% shnum% * shentsize% - 1 272 1.1 jdolecek SYS "OS_GBPB", 3, file%, shdrs%, shnum% * shentsize%, shoff% 273 1.1 jdolecek IF shnum% <> 0 THEN 274 1.1 jdolecek havesyms% = FALSE 275 1.1 jdolecek FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize% 276 1.1 jdolecek IF sh%!4 = 2 THEN havesyms% = TRUE 277 1.1 jdolecek NEXT 278 1.1 jdolecek IF havesyms% THEN 279 1.1 jdolecek IF INSTR(args$, "symtab")=0 THEN havesyms% = FALSE 280 1.1 jdolecek IF debug% THEN 281 1.1 jdolecek IF havesyms% PRINT ;" (symbols avail) "; ELSE PRINT ;" (ignoring symbols) "; 282 1.1 jdolecek ENDIF 283 1.1 jdolecek ENDIF 284 1.1 jdolecek REM freepagesbase% points to first free relocation page 285 1.1 jdolecek IF havesyms% THEN 286 1.1 jdolecek REM vfreebase points to first free address in relocated area 287 1.1 jdolecek PRINT "+["; 288 1.1 jdolecek 289 1.1 jdolecek REM First, we have the munged ELF header 290 1.1 jdolecek ssym% = vfreebase% 291 1.1 jdolecek ssympage% = freepagesbase% 292 1.1 jdolecek PROCload_chunk(file%, 0, ssym%, 52, 52) 293 1.1 jdolecek !(FNblock_vaddr(ssympage%) + 32) = 52: REM PROCwrite_word(ssym%+32, 52) 294 1.1 jdolecek vfreebase% += 52 295 1.1 jdolecek 296 1.1 jdolecek REM then, the munged section headers 297 1.1 jdolecek mshdrs% = vfreebase% 298 1.1 jdolecek mshdrspage% = freepagesbase% 299 1.1 jdolecek PRINT "+"; 300 1.1 jdolecek PROCload_chunk(file%, shoff%, mshdrs%, shnum% * shentsize%, shnum% * shentsize%) 301 1.1 jdolecek vfreebase% += shnum% * shentsize% 302 1.1 jdolecek FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize% 303 1.1 jdolecek IF sh%!4 = 2 OR sh%!4 = 3 THEN 304 1.1 jdolecek PRINT "+"; 305 1.1 jdolecek PROCload_chunk(file%, sh%!16, vfreebase%, sh%!20, sh%!20) 306 1.1 jdolecek !(FNblock_vaddr(mshdrspage%) + sh% - shdrs% + 16) = vfreebase% - ssym% 307 1.1 jdolecek vfreebase% += FNroundup(sh%!20, 4) 308 1.1 jdolecek ENDIF 309 1.1 jdolecek NEXT 310 1.1 jdolecek esym% = vfreebase% 311 1.1 jdolecek PRINT "]"; 312 1.1 jdolecek ENDIF 313 1.1 jdolecek ENDIF 314 1.1 jdolecek PRINT " "; 315 1.1 jdolecek 316 1.1 jdolecek kernelpages% = freepagesbase% - start_kernelpage% 317 1.1 jdolecek IF extradebug% THEN PRINT ''"Number of kernel pages ";kernelpages%;" (";kernelpages%*nbpp%;" bytes)" 318 1.1 jdolecek 319 1.1 jdolecek PROCfinish_relocationtable 320 1.1 jdolecek ENDPROC 321 1.1 jdolecek 322 1.1 jdolecek 323 1.1 jdolecek DEF PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%) 324 1.1 jdolecek LOCAL paddr%, ppn%, fragaddr%, fragsz% 325 1.1 jdolecek 326 1.1 jdolecek REM offset% offset in file 327 1.1 jdolecek REM vaddr% indicates virtual address where stuff needs to be relocated to 328 1.1 jdolecek REM filesz% number of bytes to read of `file' for this chunk 329 1.1 jdolecek REM memsz% number of bytes to clear for this chunk 330 1.1 jdolecek PRINT ;filesz%; 331 1.1 jdolecek IF extradebug% PRINT ;" (";~vaddr%;"-";~(vaddr%+memsz%);" [till base+";INT((vaddr%+memsz%-&F0000000)/1024);"k]) "; 332 1.1 jdolecek WHILE filesz% > 0 333 1.1 jdolecek REM freepagesbase% is first page index in freepages list 334 1.1 jdolecek fragsz% = nbpp% 335 1.1 jdolecek IF fragsz% > filesz% THEN fragsz% = filesz% 336 1.1 jdolecek 337 1.1 jdolecek fragaddr% = FNblock_vaddr(freepagesbase%) 338 1.1 jdolecek SYS "OS_GBPB", 3, file%, fragaddr%, fragsz%, offset% 339 1.1 jdolecek 340 1.1 jdolecek REM create a relocation block 341 1.1 jdolecek relocpos%!0 = FNblock_paddr(freepagesbase%) 342 1.1 jdolecek relocpos%!4 = vaddr% - pv_offset% 343 1.1 jdolecek relocpos%!8 = fragsz% 344 1.1 jdolecek relocpos% += 12: relocnr%+=1: relocoff%+=1 345 1.1 jdolecek freepagesbase% += 1 346 1.1 jdolecek 347 1.1 jdolecek offset% += fragsz% 348 1.1 jdolecek vaddr% += fragsz% 349 1.1 jdolecek filesz% -= fragsz% 350 1.1 jdolecek memsz% -= fragsz% 351 1.1 jdolecek PROCtwirl 352 1.1 jdolecek ENDWHILE 353 1.1 jdolecek 354 1.1 jdolecek IF memsz% > 0 PRINT "+";memsz%; 355 1.1 jdolecek WHILE memsz% > 0 356 1.1 jdolecek REM freepagesbase% is first page index in freepages list 357 1.1 jdolecek fragsz% = nbpp% 358 1.1 jdolecek IF fragsz% > memsz% THEN fragsz% = memsz% 359 1.1 jdolecek 360 1.1 jdolecek PROCbzero(FNblock_vaddr(freepagesbase%), fragsz%) 361 1.1 jdolecek 362 1.1 jdolecek REM create a relocation block 363 1.1 jdolecek relocpos%!0 = FNblock_paddr(freepagesbase%) 364 1.1 jdolecek relocpos%!4 = vaddr% - pv_offset% 365 1.1 jdolecek relocpos%!8 = fragsz% 366 1.1 jdolecek relocpos% += 12: relocnr%+=1: relocoff%+=1 367 1.1 jdolecek freepagesbase% += 1 368 1.1 jdolecek 369 1.1 jdolecek offset% += fragsz% 370 1.1 jdolecek vaddr% += fragsz% 371 1.1 jdolecek filesz% -= fragsz% 372 1.1 jdolecek memsz% -= fragsz% 373 1.1 jdolecek PROCtwirl 374 1.1 jdolecek ENDWHILE 375 1.1 jdolecek ENDPROC 376 1.1 jdolecek 377 1.1 jdolecek 378 1.1 jdolecek REM ***************************************************************************** 379 1.1 jdolecek REM * A.OUT LOADER * 380 1.1 jdolecek REM ***************************************************************************** 381 1.1 jdolecek 382 1.1 jdolecek DEF PROCload_kernel_aout(file%) 383 1.1 jdolecek LOCAL hdr% 384 1.1 jdolecek DIM hdr% 32 385 1.1 jdolecek ssym% = 0 : esym% = 0 386 1.1 jdolecek SYS "OS_GBPB", 3, file%, hdr%, 32, 0 387 1.1 jdolecek bemagic% = (hdr%?0 << 24) OR (hdr%?1 <<16) OR (hdr%?2 << 8) OR hdr%?3 388 1.1 jdolecek CASE bemagic% AND &0000FFFF OF 389 1.1 jdolecek WHEN &0107 390 1.1 jdolecek PRINT "(OMAGIC) "; 391 1.1 jdolecek WHEN &0108 392 1.1 jdolecek PRINT "(NMAGIC) "; 393 1.1 jdolecek WHEN &010B 394 1.1 jdolecek PRINT "(ZMAGIC) "; 395 1.1 jdolecek WHEN &00CC 396 1.1 jdolecek PRINT "(QMAGIC) "; 397 1.1 jdolecek ENDCASE 398 1.1 jdolecek REM XXX: Assume ZMAGIC 399 1.1 jdolecek 400 1.1 jdolecek REM foooff% is byte offset in file. foobasepage% is base page in RAM. 401 1.1 jdolecek txtoff% = 0 : REM in arm26 its 4096 402 1.1 jdolecek txtbasepage% = first_mapped_DRAM_index% : REM == first virt address in DRAM0a 403 1.1 jdolecek start_kernelpage% = txtbasepage% 404 1.1 jdolecek 405 1.1 jdolecek txtsize% = hdr%!4 406 1.1 jdolecek IF txtsize% MOD nbpp% <> 0 THEN 407 1.1 jdolecek ERROR EXT 1, "Text size not a multiple of page size" 408 1.1 jdolecek ENDIF 409 1.1 jdolecek txtpages% = txtsize% DIV nbpp% 410 1.1 jdolecek dataoff% = txtoff% + txtsize% 411 1.1 jdolecek databasepage% = txtbasepage% + txtpages% 412 1.1 jdolecek database% = databasepage% * nbpp% 413 1.1 jdolecek datasize% = hdr%!8 414 1.1 jdolecek IF datasize% MOD nbpp% <> 0 THEN 415 1.1 jdolecek ERROR EXT 1, "Data size not a multiple of page size" 416 1.1 jdolecek ENDIF 417 1.1 jdolecek datapages% = datasize% DIV nbpp% 418 1.1 jdolecek bssbasepage% = databasepage% + datapages% 419 1.1 jdolecek bssbase% = bssbasepage% * nbpp% 420 1.1 jdolecek bsspages% = FNroundup(hdr%!12, nbpp%) DIV nbpp% 421 1.1 jdolecek bsssize% = bsspages% * nbpp% 422 1.1 jdolecek IF bsssize% MOD nbpp% <> 0 THEN 423 1.1 jdolecek ERROR EXT 1, "Bss size not a multiple of page size" 424 1.1 jdolecek ENDIF 425 1.1 jdolecek 426 1.1 jdolecek entry% = hdr%!20 427 1.1 jdolecek IF debug% THEN PRINT "Entry point at ";~entry% 428 1.1 jdolecek 429 1.1 jdolecek REM kernelpages without syms table is : 430 1.1 jdolecek kernelpages% = txtpages% + datapages% + bsspages% : REM 431 1.1 jdolecek 432 1.1 jdolecek REM symbasepage% = bssbasepage% + bsspages%-1 : REM REAL size... not in pages 433 1.1 jdolecek symoff% = dataoff% + datasize% 434 1.1 jdolecek symsize% = hdr%!16 435 1.1 jdolecek stringtablesize% = EXT#file% - (txtsize% + datasize% + symsize%) 436 1.1 jdolecek IF INSTR(args$, "symtab")>0 THEN 437 1.1 jdolecek kernelpages% += FNroundup(stringtablesize% + symsize% + 4, nbpp%) DIV nbpp% 438 1.1 jdolecek ELSE 439 1.1 jdolecek symsize% = 0 440 1.1 jdolecek stringtablesize% = 0 441 1.1 jdolecek ENDIF 442 1.1 jdolecek REM reserve 1 extra word for the length 443 1.1 jdolecek symbolsize% = symsize% + stringtablesize% + 4 444 1.1 jdolecek symbolpages% = FNroundup(symbolsize%, nbpp%) DIV nbpp% 445 1.1 jdolecek IF debug% PRINT '"Stringtablesize = 0x";~stringtablesize%;" symsize = 0x";~symsize% 446 1.1 jdolecek 447 1.1 jdolecek PRINT '"A total of about ";kernelpages%;" pages need to be relocated" 448 1.1 jdolecek IF (kernelpages%+40)*nbpp% > memory_image_size% THEN 449 1.1 jdolecek REM 40 is an estimation ... 450 1.1 jdolecek ERROR EXT 1, "Not enough memory free... please increase WimpSlot in the configuration file" 451 1.1 jdolecek ENDIF 452 1.1 jdolecek 453 1.1 jdolecek PRINT ;txtsize%; 454 1.1 jdolecek new_hdr% = FNblock_vaddr(txtbasepage%) 455 1.1 jdolecek FOR pg% = 0 TO txtpages%-1 456 1.1 jdolecek SYS "OS_GBPB", 3, file%, FNblock_vaddr(txtbasepage%+pg%), nbpp%, txtoff% + pg%*nbpp% 457 1.1 jdolecek relocpos%!0 = FNblock_paddr(txtbasepage%+pg%) 458 1.1 jdolecek relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1 459 1.1 jdolecek relocpos%!8 = nbpp% 460 1.1 jdolecek relocpos% += 12 461 1.1 jdolecek PROCtwirl 462 1.1 jdolecek NEXT 463 1.1 jdolecek 464 1.1 jdolecek PRINT "+";datasize%; 465 1.1 jdolecek FOR pg% = 0 TO datapages%-1 466 1.1 jdolecek SYS "OS_GBPB", 3, file%, FNblock_vaddr(databasepage%+pg%), nbpp%, dataoff% + pg%*nbpp% 467 1.1 jdolecek relocpos%!0 = FNblock_paddr(databasepage%+pg%) 468 1.1 jdolecek relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1 469 1.1 jdolecek relocpos%!8 = nbpp% 470 1.1 jdolecek relocpos% += 12 471 1.1 jdolecek PROCtwirl 472 1.1 jdolecek NEXT 473 1.1 jdolecek REM PRINT;"(";off%;" gaps)"; 474 1.1 jdolecek 475 1.1 jdolecek PRINT "+";bsssize%; 476 1.1 jdolecek FOR pg% = 0 TO bsspages%-1 : REM overshoot is safe 477 1.1 jdolecek PROCbzero(FNblock_vaddr(bssbasepage%+pg%), nbpp%) 478 1.1 jdolecek relocpos%!0 = FNblock_paddr(bssbasepage%+pg%) 479 1.1 jdolecek relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1 480 1.1 jdolecek relocpos%!8 = nbpp% 481 1.1 jdolecek relocpos% += 12 482 1.1 jdolecek PROCtwirl 483 1.1 jdolecek NEXT 484 1.1 jdolecek REM PRINT;"(";off%;" gaps)"; 485 1.1 jdolecek 486 1.1 jdolecek freepagesbase% = bssbasepage% + bsspages% 487 1.1 jdolecek 488 1.1 jdolecek IF INSTR(args$, "symtab")>0 THEN 489 1.1 jdolecek symbasepage% = freepagesbase% 490 1.1 jdolecek 491 1.1 jdolecek REM put a page for the value of symsize just after bss% 492 1.1 jdolecek symDaddr% = !(relocpos%-8) + ((hdr%!12) AND (nbpp%-1)) 493 1.1 jdolecek 494 1.1 jdolecek symstartpagaddrV% = FNblock_vaddr(symbasepage%) 495 1.1 jdolecek PROCbzero(symstartpagaddrV%, nbpp%) 496 1.1 jdolecek !symstartpagaddrV% = symsize% 497 1.1 jdolecek 498 1.1 jdolecek relocpos%!0 = FNblock_paddr(symbasepage%) 499 1.1 jdolecek relocpos%!4 = symDaddr% : relocnr%+=1: relocoff%+=1 500 1.1 jdolecek relocpos%!8 = nbpp% : REM XXX 501 1.1 jdolecek relocpos% += 12 502 1.1 jdolecek symDaddr% += 4 503 1.1 jdolecek 504 1.1 jdolecek REM update the symbasepage !! ... we used one! 505 1.1 jdolecek symbasepage%+=1 506 1.1 jdolecek 507 1.1 jdolecek PRINT "+";symbolsize%; 508 1.1 jdolecek REM now fill in rest of the file 509 1.1 jdolecek FOR pg% = 0 TO symbolpages%-1 : REM => due to first page to hold offset 510 1.1 jdolecek SYS "OS_GBPB", 3, file%, FNblock_vaddr(symbasepage%+pg%), nbpp%, symoff% + pg%*nbpp% 511 1.1 jdolecek relocpos%!0 = FNblock_paddr(symbasepage%+pg%) 512 1.1 jdolecek relocpos%!4 = symDaddr% + nbpp%*pg%: relocnr%+=1: relocoff%+=1 513 1.1 jdolecek relocpos%!8 = nbpp% 514 1.1 jdolecek relocpos% += 12 515 1.1 jdolecek PROCtwirl 516 1.1 jdolecek NEXT 517 1.1 jdolecek 518 1.1 jdolecek freepagesbase% = symbasepage% + symbolpages% + 4 : REM XXX 519 1.1 jdolecek ENDIF 520 1.1 jdolecek 521 1.1 jdolecek REM update new header structure 522 1.1 jdolecek new_hdr%!16 = symsize% 523 1.1 jdolecek 524 1.1 jdolecek REM mark highest virtual address free in NetBSD's mapping 525 1.1 jdolecek vfreebase% = KERNEL_BASE + nbpp%*relocoff% 526 1.1 jdolecek 527 1.1 jdolecek REM `patch' symbol table stuff 528 1.1 jdolecek ssym% = 0 529 1.1 jdolecek esym% = 0 530 1.1 jdolecek 531 1.1 jdolecek PROCfinish_relocationtable 532 1.1 jdolecek ENDPROC 533 1.1 jdolecek 534 1.1 jdolecek 535 1.1 jdolecek REM ***************************************************************************** 536 1.1 jdolecek REM * Common loader and relocate stuff * 537 1.1 jdolecek REM ***************************************************************************** 538 1.1 jdolecek 539 1.1 jdolecek DEF PROCfinish_relocationtable 540 1.1 jdolecek REM align vfreebase% to a page 541 1.1 jdolecek vfreebase% = FNroundup(vfreebase%, nbpp%) 542 1.1 jdolecek relocoff% = (vfreebase% - KERNEL_BASE) DIV nbpp% 543 1.1 jdolecek 544 1.1 jdolecek IF vfreebase% > (nbpp%*relocoff% + KERNEL_BASE) THEN 545 1.1 jdolecek PRINT ''"WHOOAH!' : 0x", ~vfreebase%;" > 0x";~(nbpp%*relocoff%+KERNEL_BASE) 546 1.1 jdolecek freepagesbase% += 16 547 1.1 jdolecek kernelpages% += 16 548 1.1 jdolecek relocoff% += 16 549 1.1 jdolecek ENDIF 550 1.1 jdolecek 551 1.1 jdolecek IF INSTR(args$, "oldkernel")>0 THEN 552 1.1 jdolecek REM place the arguments in a block ... for the old bootloader's sake 553 1.1 jdolecek argsbasepage% = freepagesbase% 554 1.1 jdolecek argspages% = 1 555 1.1 jdolecek argvirtualbase% = nbpp%*relocoff% + KERNEL_BASE 556 1.1 jdolecek relocpos%!0 = FNblock_paddr(argsbasepage%) 557 1.1 jdolecek relocpos%!4 = kernel_phys_start% + nbpp%*relocoff%: relocnr%+=1: relocoff%+=1 558 1.1 jdolecek relocpos%!8 = nbpp% 559 1.1 jdolecek relocpos% += 12 560 1.1 jdolecek $(FNblock_vaddr(argsbasepage%)) = args$+CHR$0 561 1.1 jdolecek freepagesbase% += argspages% 562 1.1 jdolecek kernelpages% += argspages% 563 1.1 jdolecek IF debug% THEN PRINT "Args at 0x";~argvirtualbase% 564 1.1 jdolecek ELSE 565 1.1 jdolecek REM reserve some space for the MDF file 566 1.1 jdolecek REM XXX not implemented yet XXX 567 1.1 jdolecek ENDIF 568 1.1 jdolecek 569 1.1 jdolecek REM I give it a 48k scratch space 570 1.1 jdolecek scratchbasepage% = freepagesbase% 571 1.1 jdolecek scratchpages% = 12 572 1.1 jdolecek scratchvirtualbase% = nbpp%*relocoff% + KERNEL_BASE 573 1.1 jdolecek freepagesbase% += scratchpages% 574 1.1 jdolecek kernelpages% += scratchpages% 575 1.1 jdolecek 576 1.1 jdolecek REM Create one page for the initial vectors 577 1.1 jdolecek initvectorbasepage% = freepagesbase% 578 1.1 jdolecek initvectorpages% = 1 579 1.1 jdolecek relocpos%!0 = FNblock_paddr(initvectorbasepage%) 580 1.1 jdolecek relocpos%!4 = top_physdram% - 1*1024*1024 : relocnr%+=1 581 1.1 jdolecek relocpos%!8 = nbpp% 582 1.1 jdolecek relocpos% += 12 583 1.1 jdolecek freepagesbase% += initvectorpages% 584 1.1 jdolecek 585 1.1 jdolecek P%=FNblock_vaddr(initvectorbasepage%) 586 1.1 jdolecek FOR vec=0 TO &20 STEP 4 587 1.1 jdolecek [OPT 2: MOVS PC, r14:] 588 1.1 jdolecek NEXT 589 1.1 jdolecek ENDPROC 590 1.1 jdolecek 591 1.1 jdolecek 592 1.1 jdolecek DEF PROCadd_pagetables 593 1.1 jdolecek REM DESTINATION MUST BE ON A 16kb boundary!!! (!!!!) 594 1.1 jdolecek REM get 4 pages on the top of physical memory (top_physdram%) and copy PT's in it 595 1.1 jdolecek addr% = top_physdram% - 4*nbpp% 596 1.1 jdolecek IF (addr% AND (16*1024-1)) <> 0 ERROR EXT 0, "L1 pages not on 16Kb boundary" 597 1.1 jdolecek FOR pg%=0 TO 3 598 1.1 jdolecek PROCcopy(FNblock_vaddr(freepagesbase% + pg%), bootpagetables% + pg%*nbpp%, nbpp%) 599 1.1 jdolecek relocpos%!0 = FNblock_paddr(freepagesbase%+pg%) 600 1.1 jdolecek relocpos%!4 = addr%+pg%*nbpp%: relocnr%+=1 601 1.1 jdolecek relocpos%!8 = nbpp% 602 1.1 jdolecek relocpos% += 12 603 1.1 jdolecek NEXT 604 1.1 jdolecek L1pages_phys% = addr% 605 1.1 jdolecek freepagesbase% = freepagesbase%+pg% 606 1.1 jdolecek ENDPROC 607 1.1 jdolecek 608 1.1 jdolecek 609 1.1 jdolecek DEF PROCcreate_initial_pagetables 610 1.1 jdolecek LOCAL I%, addr%, kaddr%, mapped_screenmemory% 611 1.1 jdolecek DIM bootpagetables% 16*1024 612 1.1 jdolecek REM linear translation on the whole domain 00 in blocks of 1Mb 613 1.1 jdolecek REM AP=%01, CB=%00 for easy initial setup, dom=0 614 1.1 jdolecek FOR I%=0 TO 4*1024-1 615 1.1 jdolecek bootpagetables%!(I%*4) = (I%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0 616 1.1 jdolecek NEXT 617 1.1 jdolecek 618 1.1 jdolecek REM video memory is mapped 1:1 in the DRAM section or in VRAM section 619 1.1 jdolecek 620 1.1 jdolecek REM map 1Mb from top of memory to bottom 1Mb of virt. memmap 621 1.1 jdolecek addr% = (top_physdram%/1024/1024) -1 622 1.1 jdolecek bootpagetables%!0 = (addr%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0 623 1.1 jdolecek 624 1.1 jdolecek REM map 16 Mb of DRAM0a (kernel space) to 0xf0000000 625 1.1 jdolecek FOR I%=0 TO 15 626 1.1 jdolecek addr% = (kernel_phys_start% >> 20) + I% 627 1.1 jdolecek kaddr% = &F00 + I% : REM &F0000000 LSR #20 + I% 628 1.1 jdolecek bootpagetables%!(kaddr%*4) = (addr%<<20) + (0<<11)+(1<<10) + (1<<4) + (0<<3) + (0<<2) + (1<<1) + 0 629 1.1 jdolecek NEXT 630 1.1 jdolecek ENDPROC 631 1.1 jdolecek 632 1.1 jdolecek 633 1.1 jdolecek DEF PROCcreate_relocate_mechanism 634 1.1 jdolecek REM relocate mechanism relies on a contigunous space of the relocator + tables 635 1.1 jdolecek REM this isn't finished yet 636 1.1 jdolecek 637 1.1 jdolecek relocatesize% = nbpp% + relocsize% : REM just ONE code page + relocation table 638 1.1 jdolecek PRINT ;"+";relocatesize%; 639 1.1 jdolecek relocatepages% = FNroundup(relocatesize%, nbpp%) DIV nbpp% 640 1.1 jdolecek relocatebasepage% = freepagesbase% 641 1.1 jdolecek pg%=0 642 1.1 jdolecek WHILE pg%<relocatepages% 643 1.1 jdolecek IF pg%>0 THEN 644 1.1 jdolecek PROCcopy(FNblock_vaddr(relocatebasepage%+pg%), relocinstr%+(pg%-1)*nbpp%, nbpp%) 645 1.1 jdolecek ENDIF 646 1.1 jdolecek PROCtwirl 647 1.1 jdolecek 648 1.1 jdolecek IF pg%<>relocatepages%-1 THEN 649 1.1 jdolecek IF FNblock_paddr(relocatebasepage%+pg%+1)-FNblock_paddr(relocatebasepage%+pg%)<>nbpp% THEN 650 1.1 jdolecek REM Help! non contigunous relocate area => try again 651 1.1 jdolecek REM ERROR EXT 0, "Help! non contigunous relocate area" 652 1.1 jdolecek PRINT ;"*"; 653 1.1 jdolecek relocatebasepage% = freepagesbase% + pg% : REM try again from this page 654 1.1 jdolecek pg%=-1 : REM will be auto incremented later ... 655 1.1 jdolecek ENDIF 656 1.1 jdolecek ENDIF 657 1.1 jdolecek pg%+=1 658 1.1 jdolecek ENDWHILE 659 1.1 jdolecek PROCassemble_relocate_code(FNblock_vaddr(relocatebasepage%), FNblock_paddr(relocatebasepage%), entry%, L1pages_phys%) 660 1.1 jdolecek ENDPROC 661 1.1 jdolecek 662 1.1 jdolecek 663 1.1 jdolecek DEF PROCcreate_configuration 664 1.1 jdolecek PRINT ;"+";nbpp%; 665 1.1 jdolecek configurationbasepage% = freepagesbase% 666 1.1 jdolecek configurationpages% = 1 667 1.1 jdolecek freepagesbase% += configurationpages% 668 1.1 jdolecek 669 1.1 jdolecek REM fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id)); 670 1.1 jdolecek SYS "OS_ReadSysInfo", 2 TO r0,r1,r2, machineId% 671 1.1 jdolecek 672 1.1 jdolecek IF INSTR(args$, "oldkernel")>0 THEN 673 1.1 jdolecek PROCold_configuration_structure 674 1.1 jdolecek ELSE 675 1.1 jdolecek PROCnew_configuration_structure 676 1.1 jdolecek ENDIF 677 1.1 jdolecek ENDPROC 678 1.1 jdolecek 679 1.1 jdolecek 680 1.1 jdolecek DEF PROCnew_configuration_structure 681 1.1 jdolecek FOR opt%=0 TO 2 STEP 2 682 1.1 jdolecek P% = FNblock_vaddr(configurationbasepage%) 683 1.1 jdolecek [OPT opt% 684 1.1 jdolecek ; u_int magic 685 1.1 jdolecek EQUD &43112233 ; BOOTCONFIG_MAGIC 686 1.1 jdolecek ; u_int bootconfig_version 687 1.1 jdolecek EQUD 2 688 1.1 jdolecek 689 1.1 jdolecek ; u_char machine_id[4] 690 1.1 jdolecek EQUD machineId% 691 1.1 jdolecek ; char kernelname[80] 692 1.1 jdolecek EQUS LEFT$(kernelname$+CHR$0+STRING$(80, " "), 80) 693 1.1 jdolecek ; char args[512] 694 1.1 jdolecek EQUS args$+CHR$0 695 1.1 jdolecek ]: P% += 512 - LEN(args$+CHR$0): [ OPT opt% 696 1.1 jdolecek 697 1.1 jdolecek ; u_int kernvirtualbase /* not used now */ 698 1.1 jdolecek EQUD 0 699 1.1 jdolecek ; u_int kernphysicalbase /* not used now */ 700 1.1 jdolecek EQUD 0 701 1.1 jdolecek ; u_int kernsize 702 1.1 jdolecek EQUD kernelpages% * nbpp% 703 1.1 jdolecek ; u_int scratchvirtualbase 704 1.1 jdolecek EQUD scratchvirtualbase% 705 1.1 jdolecek ; u_int scratchphysicalbase 706 1.1 jdolecek EQUD scratchvirtualbase% 707 1.1 jdolecek ; u_int scratchsize 708 1.1 jdolecek EQUD scratchpages% * nbpp% 709 1.1 jdolecek 710 1.1 jdolecek ; u_int ksym_start 711 1.1 jdolecek EQUD ssym% 712 1.1 jdolecek ; u_int ksym_end 713 1.1 jdolecek EQUD esym% 714 1.1 jdolecek 715 1.1 jdolecek ; u_int MDFvirtualbase 716 1.1 jdolecek EQUD 0 717 1.1 jdolecek ; u_int MDFphysicalbase 718 1.1 jdolecek EQUD 0 719 1.1 jdolecek ; u_int MDFsize 720 1.1 jdolecek EQUD 0 721 1.1 jdolecek 722 1.1 jdolecek ; u_int display_phys 723 1.1 jdolecek EQUD videomem_start% 724 1.1 jdolecek ; u_int display_start 725 1.1 jdolecek EQUD videomem_start% ; screenstart (149) 726 1.1 jdolecek ; u_int display_size 727 1.1 jdolecek EQUD display_size% ; screensize (150) 728 1.1 jdolecek ; u_int width 729 1.1 jdolecek EQUD FNvdu_var(11) ; acorn32 port needs 0..x-1 730 1.1 jdolecek ; u_int heigth 731 1.1 jdolecek EQUD FNvdu_var(12) ; acorn32 port needs 0..y-1 732 1.1 jdolecek ; u_int log2_bpp 733 1.1 jdolecek EQUD FNvdu_var(9) ; acorn32 port needs log(bitsperpixel)/log(2) 734 1.1 jdolecek ; u_int framerate 735 1.1 jdolecek EQUD 56 ; XXX why? 736 1.1 jdolecek 737 1.1 jdolecek ; char reserved[512] 738 1.1 jdolecek ]: P% += 512: [ OPT opt% 739 1.1 jdolecek 740 1.1 jdolecek ; u_int pagesize 741 1.1 jdolecek EQUD nbpp% 742 1.1 jdolecek ; u_int drampages 743 1.1 jdolecek EQUD totaldrampages% 744 1.1 jdolecek ; u_int vrampages; 745 1.1 jdolecek EQUD totalvrampages% 746 1.1 jdolecek ; u_int dramblocks 747 1.1 jdolecek EQUD dramblocks% 748 1.1 jdolecek ; u_int vramblocks 749 1.1 jdolecek EQUD vramblocks% 750 1.1 jdolecek 751 1.1 jdolecek ] 752 1.1 jdolecek REM phys_mem dram[DRAM_BLOCKS] <- 32 753 1.1 jdolecek FOR I%=0 TO MAX_DRAMBANKS-1 754 1.1 jdolecek [OPT opt% 755 1.1 jdolecek ; address% : EQUD DRAM_addr%(I%) 756 1.1 jdolecek ; length% : EQUD DRAM_pages%(I%) 757 1.1 jdolecek ; flags% : EQUD 0 758 1.1 jdolecek ] 759 1.1 jdolecek NEXT 760 1.1 jdolecek REM phys_mem vram[VRAM_BLOCKS] <- 16 761 1.1 jdolecek FOR I%=0 TO MAX_VRAMBANKS-1 762 1.1 jdolecek [OPT opt% 763 1.1 jdolecek ; address% : EQUD VRAM_addr%(I%) 764 1.1 jdolecek ; length% : EQUD VRAM_pages%(I%) 765 1.1 jdolecek ; flags% : EQUD 0 766 1.1 jdolecek ] 767 1.1 jdolecek NEXT 768 1.1 jdolecek NEXT 769 1.1 jdolecek ENDPROC 770 1.1 jdolecek 771 1.1 jdolecek 772 1.1 jdolecek DEF PROCold_configuration_structure 773 1.1 jdolecek FOR opt%=0 TO 2 STEP 2 774 1.1 jdolecek P% = FNblock_vaddr(configurationbasepage%) 775 1.1 jdolecek [OPT opt% 776 1.1 jdolecek ;kernvirtualbase% 777 1.1 jdolecek EQUD 0 ; not used 778 1.1 jdolecek ;kernphysicalbase% 779 1.1 jdolecek EQUD 0 ; not used 780 1.1 jdolecek ;kernsize% 781 1.1 jdolecek EQUD kernelpages% * nbpp% 782 1.1 jdolecek ;argvirtualbase 783 1.1 jdolecek EQUD argvirtualbase% 784 1.1 jdolecek ;argphysicalbase 785 1.1 jdolecek EQUD FNblock_paddr(argsbasepage%) 786 1.1 jdolecek ;argsize% 787 1.1 jdolecek EQUD nbpp% 788 1.1 jdolecek ;scratchvirtualbase% 789 1.1 jdolecek EQUD scratchvirtualbase% 790 1.1 jdolecek ;scratchphysicalbase% 791 1.1 jdolecek EQUD scratchvirtualbase% 792 1.1 jdolecek ;scratchsize% 793 1.1 jdolecek EQUD scratchpages% * nbpp% 794 1.1 jdolecek ;display_start% 795 1.1 jdolecek EQUD videomem_start% ; screenstart (149) 796 1.1 jdolecek ;display_size% 797 1.1 jdolecek EQUD display_size% ; screensize (150) 798 1.1 jdolecek ;width% 799 1.1 jdolecek EQUD FNvdu_var(11) ; arm32 port needs 0..x-1 800 1.1 jdolecek ;height% 801 1.1 jdolecek EQUD FNvdu_var(12) ; arm32 port needs 0..y-1 802 1.1 jdolecek ;bitsperpixel 803 1.1 jdolecek EQUD FNvdu_var(9) ; arm32 port needs log(bitsperpixel)/log(2) 804 1.1 jdolecek ] 805 1.1 jdolecek REM for compatibility for now just 4 DRAM and 1 VRAM 806 1.1 jdolecek FOR I%=0 TO 3 807 1.1 jdolecek [OPT opt% 808 1.1 jdolecek ;address% : EQUD DRAM_addr%(I%) 809 1.1 jdolecek ;length% : EQUD DRAM_pages%(I%) 810 1.1 jdolecek ] 811 1.1 jdolecek NEXT 812 1.1 jdolecek REM current config structure only wants 1 VRAM entry ! 813 1.1 jdolecek FOR I%=0 TO 0 814 1.1 jdolecek [OPT opt% 815 1.1 jdolecek ;address% : EQUD VRAM_addr%(I%) 816 1.1 jdolecek ;length% : EQUD VRAM_pages%(I%) 817 1.1 jdolecek ] 818 1.1 jdolecek NEXT 819 1.1 jdolecek [OPT opt% 820 1.1 jdolecek ;c_dramblocks% 821 1.1 jdolecek EQUD dramblocks% 822 1.1 jdolecek ;c_vramblocks% 823 1.1 jdolecek EQUD vramblocks% 824 1.1 jdolecek ;pagesize% 825 1.1 jdolecek EQUD nbpp% 826 1.1 jdolecek ;drampages% 827 1.1 jdolecek EQUD totaldrampages% 828 1.1 jdolecek ;vrampages% 829 1.1 jdolecek EQUD totalvrampages% 830 1.1 jdolecek ;kernelname% 831 1.1 jdolecek EQUS LEFT$(kernelname$+CHR$0+STRING$(80, " "), 80) 832 1.1 jdolecek ;framerate% 833 1.1 jdolecek EQUD 56 ; XXXXX 834 1.1 jdolecek ;machine_id% 835 1.1 jdolecek EQUD machineId% 836 1.1 jdolecek ;magic% 837 1.1 jdolecek EQUD &43112233 ; BOOTCONFIG_MAGIC 838 1.1 jdolecek ;display_phys% 839 1.1 jdolecek EQUD videomem_start% 840 1.1 jdolecek ] 841 1.1 jdolecek NEXT opt% 842 1.1 jdolecek ENDPROC 843 1.1 jdolecek 844 1.1 jdolecek 845 1.1 jdolecek REM XXXX a bit messy still 846 1.1 jdolecek DEF PROCassemble_relocate_code(virtaddress%, physaddress%, entry%, L1pages_phys%) 847 1.1 jdolecek FOR opt%=0 TO 2 STEP 2 848 1.1 jdolecek P%=virtaddress% 849 1.1 jdolecek [OPT opt% 850 1.1 jdolecek ; entry conditions : 851 1.1 jdolecek ; - on RiscOS page tables in usr26 mode on virt address .... 852 1.1 jdolecek ; - R0 pointer to configuration structure 853 1.1 jdolecek ; - R1 pointer to physical restart point 854 1.1 jdolecek ; - R2 pointer to physical relocation table 855 1.1 jdolecek ; - R3 pointer to physical new L1 page address 856 1.1 jdolecek ; - R4 new virt adres of kernel entry% 857 1.1 jdolecek .relocate_entry% 858 1.1 jdolecek ; Enter sup26 mode 859 1.1 jdolecek SWI "OS_EnterOS" 860 1.1 jdolecek 861 1.1 jdolecek ; move args up in register bank 862 1.1 jdolecek STMFD r13!, {r0-r4} 863 1.1 jdolecek LDMFD r13!, {r8-r12} 864 1.1 jdolecek 865 1.1 jdolecek ; r8 = config structure address 866 1.1 jdolecek ; r9 = physical restart point address 867 1.1 jdolecek ; r10 = physical relocation table address 868 1.1 jdolecek ; r11 = physical address of new L1page 869 1.1 jdolecek ; r12 = kernel entry point in new virt. map 870 1.1 jdolecek 871 1.1 jdolecek ; go to sup32 mode with IRQ + FIQ disabled 872 1.1 jdolecek EQUD %11100001000011110000000000000000 ; MRS R0, CPSR 873 1.1 jdolecek BIC r0, r0, #&1F ; clear proc. mode 874 1.1 jdolecek ORR r0, r0, #(1<<7) + (1<<6) ; set FIQ + IRQ disable 875 1.1 jdolecek ORR r0, r0, #%10011 ; superv. 32 bit 876 1.1 jdolecek EQUD %11100001001010011111000000000000 ; MSR CPSR, r0 877 1.1 jdolecek MOV r0, r0 878 1.1 jdolecek MOV r0, r0 ; nops ... nessisary? 879 1.1 jdolecek 880 1.1 jdolecek ; flush data cache 881 1.1 jdolecek ; just read a 64kb app space in the cache 882 1.1 jdolecek MOV r0, #&8000 883 1.1 jdolecek ADD r1, r0, r0 884 1.1 jdolecek .loop_flush1 885 1.1 jdolecek LDR r2, [r0], #4 886 1.1 jdolecek SUBS r1, r1, #4 887 1.1 jdolecek BNE loop_flush1 888 1.1 jdolecek 889 1.1 jdolecek ; determine processor type ... nessisary for correct copro instr .. store in r13 890 1.1 jdolecek EQUD %11101110000100000000111100010000 ; MRC cp15, 0, r0, c0, c0, 0 ; read CPU Id in r0 891 1.1 jdolecek MOV r13, r0 ; store in r13 892 1.1 jdolecek 893 1.1 jdolecek ; determine if its a StrongARM 894 1.1 jdolecek MOV r14, #1 ; r14 flags if its a StrongARM ... assume one 895 1.1 jdolecek 896 1.1 jdolecek ; detecting an ARM6 needs a special mask 897 1.1 jdolecek MOV r0, #&FF000000 ; get processor discr. mask in r0 898 1.1 jdolecek ADD r0, r0, #&00000F00 ; 899 1.1 jdolecek 900 1.1 jdolecek MOV r1, #&41000000 ; check for 0x41xxx6xx => ARM6 901 1.1 jdolecek ADD r1, r1, #&00000600 902 1.1 jdolecek AND r2, r13, r0 ; mask with discr. mask 903 1.1 jdolecek CMP r2, r1 ; is it a ARM6 ? 904 1.1 jdolecek MOVEQ r14, #0 ; ifso ... then its a v3 905 1.1 jdolecek 906 1.1 jdolecek ; newer ARMs need a different mask 907 1.1 jdolecek MOV r0, #&FF000000 ; get processor discr. mask in r0 908 1.1 jdolecek ADD r0, r0, #&0000F000 ; 909 1.1 jdolecek 910 1.1 jdolecek MOV r1, #&41000000 ; check for 0x41xx7xxx => ARM7 911 1.1 jdolecek ADD r1, r1, #&00007000 912 1.1 jdolecek AND r2, r13, r0 ; mask with discr. mask 913 1.1 jdolecek CMP r2, r1 ; is it a ARM7 ? 914 1.1 jdolecek MOVEQ r14, #0 ; ifso ... then its a v3 915 1.1 jdolecek 916 1.1 jdolecek ; MOV r1, #&44000000 ; check for 0x44xxaxxx => Strong ARM 917 1.1 jdolecek ; ADD r1, r1, #&0000a000 918 1.1 jdolecek ; AND r2, r13, r0 ; mask with discr. mask 919 1.1 jdolecek ; CMP r2, r1 ; is it a StrongARM ? 920 1.1 jdolecek 921 1.1 jdolecek ; switch off MMU, IDcache and WB and branch to physical code !! 922 1.1 jdolecek CMP r14, #0 923 1.1 jdolecek EQUD %00011110000100010000111100010000 ; MRCNE cp15, 0, r0, c1, c0, 0 ; read control register 924 1.1 jdolecek BICNE r0, r0, #&3F ; clear only known bits please ! 925 1.1 jdolecek MOVEQ r0, #0 ; ARM6/7 only have these 926 1.1 jdolecek ORR r0, r0, #%0001110000 927 1.1 jdolecek ; RSB1DPWCAM 928 1.1 jdolecek MOV r13, r0 ; save this value in r13 929 1.1 jdolecek MOV r1, #0 930 1.1 jdolecek CMP r14, #0 931 1.1 jdolecek EQUD %11101110000000010000111100010000 ; MCR cp15, 0, r0, c1, c0, 0 ; write control register 932 1.1 jdolecek EQUD %00011110000001110001111100010101 ; MCRNE cp15, 0, r1, c7, c5, 0 ; write 0 in v4 MMU disable 933 1.1 jdolecek MOV pc, r9 ; call rest of code in physical mem ... not flat 934 1.1 jdolecek 935 1.1 jdolecek .physical_start_address% 936 1.1 jdolecek ; should now be running in physical space 937 1.1 jdolecek ; this relocate code can be heavyly optimised ... but it is used only once ... and is fast enough 938 1.1 jdolecek ; relocate kernel (physical to physical) + debug in screenmemory 939 1.1 jdolecek MOV r5, r10 ; load PC relative r5 = startreloc table 940 1.1 jdolecek LDR r6, [r5], #4 ; r4 = number of relocated pages 941 1.1 jdolecek .loop_relocate_pages% 942 1.1 jdolecek LDR r2, [r5], #4 ; r2 = from address 943 1.1 jdolecek LDR r3, [r5], #4 ; r3 = to address 944 1.5 reinoud LDR r7, [r5], #4 ; r7 = number of bytes to travel 945 1.1 jdolecek MOV r1, #0 ; r1 = offset in page 946 1.1 jdolecek .loop_one_page% 947 1.1 jdolecek LDRB r0, [r2, r1] 948 1.1 jdolecek STRB r0, [r3, r1] 949 1.1 jdolecek ADD r1, r1, #1 950 1.1 jdolecek CMP r1, r7 ; all bytes copied ? 951 1.1 jdolecek BNE loop_one_page% 952 1.1 jdolecek SUBS r6, r6, #1 953 1.1 jdolecek BNE loop_relocate_pages% 954 1.1 jdolecek 955 1.1 jdolecek ; switch over to the new L1 pages 956 1.1 jdolecek 957 1.1 jdolecek ; disable clockswitching for SA110 (WHY?) 958 1.1 jdolecek MOV r0, #0 ; write 0 959 1.1 jdolecek CMP r14, #0 ; check v4 .. or SA110 specific ? 960 1.1 jdolecek EQUD %00011110000011110000111101010010 ; MCRNE cp15, 0, r0, c15, c2, 2 ; from Linux loader 961 1.1 jdolecek 962 1.1 jdolecek ; flush ID cache 963 1.1 jdolecek MOV r0, #0 964 1.1 jdolecek CMP r14, #0 965 1.1 jdolecek EQUD %00001110000001110000111100010000 ; MCREQ cp15, 0, r0, c7, c0, 0 ; flush v3 ID cache 966 1.1 jdolecek EQUD %00011110000001110000111100010111 ; MCRNE cp15, 0, r0, c7, c7, 0 ; flush v4 ID cache 967 1.1 jdolecek 968 1.1 jdolecek ; drain WB (v4) 969 1.1 jdolecek MOV r0, #0 970 1.1 jdolecek CMP r14, #0 971 1.1 jdolecek EQUD %00011110000001110000111110011010 ; MCRNE cp15, 0, r0, c7, c10, 4; drain WB v4 from Linux loader 972 1.1 jdolecek 973 1.1 jdolecek ; flush TLB 974 1.1 jdolecek EQUD %11101110000001010000111100010000 ; MCR cp15, 0, r0, c5, c0, 0 ; flush v3 TLB 975 1.1 jdolecek 976 1.1 jdolecek ; set new TLB address 977 1.1 jdolecek MOV r0, r11 978 1.1 jdolecek EQUD %11101110000000100000111100010000 ; MCR cp15, 0, r0, c2, c0, 0 ; write TLB base 979 1.1 jdolecek 980 1.1 jdolecek ; switch on MMU, IDcache and WB and keep on running (flat *translated*) 981 1.1 jdolecek ; in r13 last written value 982 1.1 jdolecek ORR r0, r13, #%0001111101 983 1.1 jdolecek ; RSB1DPWCAM 984 1.1 jdolecek ORR r0, r0, #%1000000000 985 1.1 jdolecek CMP r14, #0 986 1.1 jdolecek EQUD %11101110000000010000111100010000 ; MCR cp15, 0, r0, c1, c0, 0 ; write control register 987 1.1 jdolecek MOV r0, r0 ; flat 988 1.1 jdolecek MOV r0, r0 ; flat 989 1.1 jdolecek ; not flat anymore ... but it doesnt matter 990 1.1 jdolecek ] 991 1.1 jdolecek IF extradebug% THEN 992 1.1 jdolecek [OPT opt% 993 1.1 jdolecek MOV r6, #videomem_start% 994 1.1 jdolecek MOV r7, #videomem_pages% * nbpp% 995 1.1 jdolecek MOV r5, #KERNEL_BASE 996 1.1 jdolecek .loop_testing% 997 1.1 jdolecek LDR r0, [r5], #4 998 1.1 jdolecek STR r0, [r6], #4 999 1.1 jdolecek SUBS r7, r7, #4 1000 1.1 jdolecek BNE loop_testing% 1001 1.1 jdolecek ] 1002 1.1 jdolecek ENDIF 1003 1.1 jdolecek [OPT opt% 1004 1.1 jdolecek ; call kernel in new virtual space ... start() 1005 1.1 jdolecek 1006 1.1 jdolecek MOV r0, r8 1007 1.1 jdolecek MOV pc, r12 1008 1.1 jdolecek ] 1009 1.1 jdolecek NEXT 1010 1.1 jdolecek ENDPROC 1011 1.1 jdolecek 1012 1.1 jdolecek 1013 1.1 jdolecek DEF FNblock_vaddr(pagenr%) 1014 1.1 jdolecek =!(memoryblock% + pagenr%*12 + 4) 1015 1.1 jdolecek 1016 1.1 jdolecek 1017 1.1 jdolecek DEF FNblock_paddr(pagenr%) 1018 1.1 jdolecek =!(memoryblock% + pagenr%*12 + 8) 1019 1.1 jdolecek 1020 1.1 jdolecek 1021 1.1 jdolecek DEF PROCget_memory_map 1022 1.1 jdolecek PRINT '"Getting actual memory mapping "; 1023 1.1 jdolecek FOR pg%=0 TO totalpages%-1 1024 1.1 jdolecek pos% = memoryblock% + 12*pg% 1025 1.1 jdolecek pos%!0 = 0 1026 1.1 jdolecek pos%!4 = (firstpage% + pg%) * nbpp% 1027 1.1 jdolecek pos%!8 = 0 1028 1.1 jdolecek REM force paging in this page in RO4 1029 1.1 jdolecek IF (pg% MOD 5)=0 THEN PROCtwirl 1030 1.1 jdolecek !(pos%!4) = 0: REM PROCbzero(pos%!4, nbpp%) 1031 1.1 jdolecek NEXT 1032 1.1 jdolecek PRINT ;" " 1033 1.1 jdolecek 1034 1.1 jdolecek os_memory_GIVEN_LOG_ADDR = &200 1035 1.1 jdolecek os_memory_RETURN_PAGE_NO = &800 1036 1.1 jdolecek os_memory_RETURN_PHYS_ADDR = &2000 1037 1.1 jdolecek SYS "OS_Memory", os_memory_GIVEN_LOG_ADDR+os_memory_RETURN_PAGE_NO+os_memory_RETURN_PHYS_ADDR, memoryblock%, totalpages% 1038 1.1 jdolecek 1039 1.1 jdolecek PROCsort_memory_map(memoryblock%, totalpages%) 1040 1.1 jdolecek 1041 1.1 jdolecek REM Get first DRAM index 1042 1.1 jdolecek PRINT '"Found memory blocks "; 1043 1.1 jdolecek first_mapped_DRAM_index%=-1 1044 1.1 jdolecek pg% = 0 1045 1.1 jdolecek WHILE pg%<totalpages% 1046 1.1 jdolecek addr% = !(memoryblock% + pg%*12 + 8) 1047 1.1 jdolecek PRINT "[";"0x";~addr%; 1048 1.1 jdolecek num_seq_pag%=0 1049 1.1 jdolecek WHILE (!(memoryblock% + pg%*12 + 12 + 8) - addr%)=nbpp% 1050 1.1 jdolecek IF first_mapped_DRAM_index%<0 AND (addr%>=DRAM_addr%(0)) THEN first_mapped_DRAM_index% = pg% 1051 1.1 jdolecek num_seq_pag%+=1 1052 1.1 jdolecek pg%+=1 1053 1.1 jdolecek addr% = !(memoryblock% + pg%*12 + 8) 1054 1.1 jdolecek ENDWHILE 1055 1.1 jdolecek PRINT;"-0x";~(!(memoryblock% + pg%*12 + 8) + nbpp%-1);"]"; 1056 1.1 jdolecek PRINT ;" "; 1057 1.1 jdolecek pg%+=1 1058 1.1 jdolecek ENDWHILE 1059 1.1 jdolecek PRINT' 1060 1.1 jdolecek IF extradebug% THEN PRINT '"First DRAM index found at index ";first_mapped_DRAM_index%;" DRAM_addr%(0)=0x";~DRAM_addr%(0) 1061 1.6 wiz IF first_mapped_DRAM_index%<0 THEN ERROR EXT 1, "No (S)DRAM mapped in this program (weird) ... increase Wimpslot!" 1062 1.1 jdolecek ENDPROC 1063 1.1 jdolecek 1064 1.1 jdolecek 1065 1.1 jdolecek DEF PROCget_memory_configuration 1066 1.1 jdolecek REM Get memory distribution 1067 1.1 jdolecek PRINT "Getting memory configuration "; 1068 1.1 jdolecek DIM DRAM_addr%(MAX_DRAMBANKS), DRAM_pages%(MAX_DRAMBANKS) 1069 1.1 jdolecek DIM VRAM_addr%(MAX_VRAMBANKS), VRAM_pages%(MAX_VRAMBANKS) 1070 1.1 jdolecek DIM memorytable% memorytablesize% 1071 1.1 jdolecek SYS "OS_Memory", 7, memorytable% : REM read table 1072 1.1 jdolecek dramblocks% = 0: vramblocks% = 0: currentpages% = 0: currentadr% = 0 1073 1.1 jdolecek currentpage% = -1: loop%=0 1074 1.1 jdolecek WHILE loop% < memorytablesize%*2 1075 1.1 jdolecek page% = memorytable%!(loop% DIV 2) 1076 1.1 jdolecek IF loop% MOD 2 THEN page% = page% >> 4 1077 1.1 jdolecek page% = page% AND &07 1078 1.1 jdolecek IF page% <> currentpage% THEN 1079 1.1 jdolecek IF currentpage% = 1 THEN 1080 1.1 jdolecek DRAM_addr%(dramblocks%) = currentaddr% * nbpp% 1081 1.1 jdolecek DRAM_pages%(dramblocks%) = currentpages% 1082 1.1 jdolecek dramblocks% +=1 1083 1.1 jdolecek ENDIF 1084 1.1 jdolecek IF currentpage%=2 THEN 1085 1.1 jdolecek VRAM_addr%(vramblocks%) = currentaddr% * nbpp% 1086 1.1 jdolecek VRAM_pages%(vramblocks%) = currentpages% 1087 1.1 jdolecek vramblocks% +=1 1088 1.1 jdolecek ENDIF 1089 1.1 jdolecek currentpage% = page% 1090 1.1 jdolecek currentaddr% = loop% 1091 1.1 jdolecek currentpages% = 0 1092 1.1 jdolecek ENDIF 1093 1.1 jdolecek currentpages% += 64 1094 1.1 jdolecek loop% += 64 1095 1.1 jdolecek PROCtwirl 1096 1.1 jdolecek ENDWHILE 1097 1.1 jdolecek 1098 1.1 jdolecek IF emulateDRAMsize% > 0 THEN 1099 1.1 jdolecek REM emulate HACK 1100 1.1 jdolecek DRAM0% = DRAM_addr%(0) 1101 1.1 jdolecek DRAM_addr%() = 0 1102 1.1 jdolecek DRAM_pages%() = 0 1103 1.1 jdolecek DRAM_addr%(0) = DRAM0% 1104 1.1 jdolecek DRAM_pages%(0) = (emulateDRAMsize%*1024*1024)/nbpp% 1105 1.1 jdolecek dramblocks% = 1 1106 1.1 jdolecek REM END HACK 1107 1.1 jdolecek ENDIF 1108 1.1 jdolecek 1109 1.1 jdolecek REM find top of DRAM pages 1110 1.1 jdolecek I%=8: WHILE (I%>=0) AND DRAM_addr%(I%)=0: I%-=1: ENDWHILE 1111 1.1 jdolecek 1112 1.1 jdolecek IF I%>=0 THEN top_drambank% = I% ELSE ERROR EXT 0, "Reality check: No DRAM banks??" 1113 1.1 jdolecek top_physdram% = DRAM_addr%(top_drambank%) + DRAM_pages%(top_drambank%)*nbpp% 1114 1.1 jdolecek 1115 1.1 jdolecek PRINT " " 1116 1.1 jdolecek PRINT' 1117 1.1 jdolecek 1118 1.1 jdolecek REM Emulate VRAM by reporting different memory sizes 1119 1.1 jdolecek REM XXX assumption : no VRAM => screen is located in bottom DRAM; leave it there 1120 1.1 jdolecek IF (VRAM_pages%(0)=0) OR emulateVRAM% THEN 1121 1.1 jdolecek mapped_screenmemory% = 1024*1024 : REM Max allowed on RiscPC 1122 1.1 jdolecek videomem_start% = DRAM_addr%(0) 1123 1.1 jdolecek videomem_pages% = mapped_screenmemory% DIV nbpp% 1124 1.1 jdolecek display_size% = FNvdu_var(150) AND NOT(nbpp%-1) 1125 1.1 jdolecek DRAM_addr%(0) += videomem_pages% * nbpp% 1126 1.1 jdolecek DRAM_pages%(0) -= videomem_pages% 1127 1.1 jdolecek ELSE 1128 1.1 jdolecek mapped_screenmemory% = 0 1129 1.1 jdolecek videomem_start% = VRAM_addr%(0) 1130 1.1 jdolecek videomem_pages% = VRAM_pages%(0) 1131 1.1 jdolecek display_size% = videomem_pages% * nbpp% 1132 1.1 jdolecek ENDIF 1133 1.1 jdolecek 1134 1.1 jdolecek IF mapped_screenmemory%>0 THEN PRINT "Used 1st Mb of DRAM at 0x";RIGHT$("00000000"+STR$~videomem_start%,8);" for video memory" 1135 1.1 jdolecek 1136 1.1 jdolecek totaldrampages% = 0 1137 1.1 jdolecek FOR I%=0 TO dramblocks%-1 1138 1.1 jdolecek totaldrampages% += DRAM_pages%(I%) 1139 1.1 jdolecek PRINT "Found "; 1140 1.1 jdolecek IF (DRAM_addr%(I%) >= SDRAM_ADDR_START%) PRINT ;"SDRAM"; ELSE PRINT ;" DRAM"; 1141 1.1 jdolecek PRINT " (";I%;") at 0x";RIGHT$("00000000"+STR$~DRAM_addr%(I%),8);" for ";,DRAM_pages%(I%)*nbpp%/1024;" k" 1142 1.1 jdolecek NEXT 1143 1.1 jdolecek 1144 1.1 jdolecek totalvrampages% = 0 1145 1.1 jdolecek FOR I%=0 TO vramblocks%-1 1146 1.1 jdolecek totalvrampages% += VRAM_pages%(I%) 1147 1.1 jdolecek PRINT "Found VRAM (";I%;") at 0x";RIGHT$("00000000"+STR$~VRAM_addr%(I%),8);" for ";,VRAM_pages%(I%)*nbpp%/1024;" k" 1148 1.1 jdolecek NEXT 1149 1.1 jdolecek 1150 1.1 jdolecek kernel_phys_start% = DRAM_addr%(0) 1151 1.1 jdolecek 1152 1.1 jdolecek REM Expirimental Kinetic support 1153 1.1 jdolecek IF INSTR(args$, "kinetic")>0 THEN 1154 1.1 jdolecek REM The Kinetic card has SDRAM on the processor module ... first fix is to only use this memory 1155 1.4 wiz REM for VRAM emulation and only pass it through as buffer memory for the DRAM is the only one 1156 1.7 andvar REM with DMA capabilities. 1157 1.1 jdolecek 1158 1.1 jdolecek PRINT ''"Kinetic support asked ... "; 1159 1.1 jdolecek 1160 1.1 jdolecek REM find SDRAM start... DRAM is under 512 Mb, SDRAM is above it 1161 1.1 jdolecek first_SDRAM% = -1 1162 1.2 chris FOR I%=0 TO MAX_DRAMBANKS 1163 1.1 jdolecek IF (DRAM_addr%(I%) >= SDRAM_ADDR_START%) AND (first_SDRAM%<0) THEN first_SDRAM% = I% 1164 1.1 jdolecek NEXT 1165 1.1 jdolecek IF first_SDRAM% >= 0 THEN 1166 1.1 jdolecek PRINT ;"granted" 1167 1.1 jdolecek REM put kernel pointer to the first SDRAM module and update DRAM reporting (yeah ...more clear than fast) 1168 1.1 jdolecek FOR I%=0 TO first_SDRAM%-1 1169 1.1 jdolecek PRINT "Moving DRAM at 0x";RIGHT$("00000000"+STR$~DRAM_addr%(I%),8);" for ";,DRAM_pages%(I%)*nbpp%/1024;" k" 1170 1.1 jdolecek REM save this block 1171 1.1 jdolecek DRAM_addr% = DRAM_addr%(I%): DRAM_pages% = DRAM_pages%(I%) 1172 1.1 jdolecek REM move everything down 1173 1.2 chris FOR J%=I% TO MAX_DRAMBANKS-1 1174 1.1 jdolecek DRAM_addr%(J%) = DRAM_addr%(J%+1): DRAM_pages%(J%) = DRAM_pages%(J%+1) 1175 1.1 jdolecek NEXT 1176 1.2 chris DRAM_addr%(MAX_DRAMBANKS) = 0: DRAM_pages%(MAX_DRAMBANKS) = 0 1177 1.1 jdolecek REM fill in the moved block at the top of the structure 1178 1.1 jdolecek DRAM_addr%(dramblocks%-1) = DRAM_addr%: DRAM_pages%(dramblocks%-1) = DRAM_pages% 1179 1.1 jdolecek NEXT 1180 1.1 jdolecek REM XXX kernel is loaded per definition in dram[0] 1181 1.1 jdolecek first_SDRAM% = 0 1182 1.1 jdolecek kernel_phys_start% = DRAM_addr%(first_SDRAM%) 1183 1.1 jdolecek ELSE 1184 1.1 jdolecek PRINT ;"ignored; no SDRAM found" 1185 1.1 jdolecek ENDIF 1186 1.1 jdolecek PRINT 1187 1.1 jdolecek ENDIF 1188 1.1 jdolecek ENDPROC 1189 1.1 jdolecek 1190 1.1 jdolecek 1191 1.1 jdolecek DEF PROCsort_memory_map(memoryblock%, totalpages%) 1192 1.1 jdolecek LOCAL out%, in%, outp%, inp% 1193 1.1 jdolecek 1194 1.1 jdolecek DIM code% 1024 1195 1.1 jdolecek FOR opt%=0 TO 2 STEP 2 1196 1.1 jdolecek P%=code% 1197 1.1 jdolecek [OPT opt% 1198 1.1 jdolecek .sortit% 1199 1.1 jdolecek STMFD r13!, {r0-r12} 1200 1.1 jdolecek ; R0 = A% = memory block% 1201 1.1 jdolecek ; R1 = B% = totalpages% 1202 1.1 jdolecek ; r2 = out% 1203 1.1 jdolecek ; r3 = inp% 1204 1.1 jdolecek ; R12 = limit r3 1205 1.1 jdolecek SUB r2, r1, #2 1206 1.1 jdolecek .loop_outer% 1207 1.1 jdolecek MOV r3, r0 1208 1.1 jdolecek MOV r4, #12 1209 1.1 jdolecek MLA r12, r2, r4, r0 1210 1.1 jdolecek .loop_inner% 1211 1.1 jdolecek LDR r4, [r3, #8] 1212 1.1 jdolecek LDR r5, [r3, #20] 1213 1.1 jdolecek CMP r4, r5 1214 1.1 jdolecek BLT not_bigger% 1215 1.1 jdolecek LDMIA r3, {r6, r7, r8} 1216 1.1 jdolecek ADD r4, r3, #12 1217 1.1 jdolecek LDMIA r4, {r9, r10, r11} 1218 1.1 jdolecek STMIA r3, {r9, r10, r11} 1219 1.1 jdolecek STMIA r4, {r6, r7, r8} 1220 1.1 jdolecek .not_bigger% 1221 1.1 jdolecek ADD r3, r3, #12 1222 1.1 jdolecek CMP r3, r12 1223 1.1 jdolecek BLE loop_inner% 1224 1.1 jdolecek SUBS r2, r2, #1 1225 1.1 jdolecek BPL loop_outer% 1226 1.1 jdolecek LDMFD r13!, {r0-r12} 1227 1.1 jdolecek MOV pc, r14 1228 1.1 jdolecek ] 1229 1.1 jdolecek NEXT 1230 1.1 jdolecek 1231 1.1 jdolecek A% = memoryblock% 1232 1.1 jdolecek B% = totalpages% 1233 1.1 jdolecek CALL sortit% 1234 1.1 jdolecek 1235 1.1 jdolecek ENDPROC 1236 1.1 jdolecek 1237 1.1 jdolecek 1238 1.1 jdolecek DEF PROCcenter(line$) 1239 1.1 jdolecek PRINT STRING$((width%-LEN(line$))/2, " ");line$ 1240 1.1 jdolecek ENDPROC 1241 1.1 jdolecek 1242 1.1 jdolecek 1243 1.1 jdolecek DEF PROCbzero(addr%, len%) 1244 1.1 jdolecek LOCAL a% 1245 1.1 jdolecek FOR a% = 0 TO len%-4 STEP 4 1246 1.1 jdolecek addr%!a% = 0 1247 1.1 jdolecek NEXT 1248 1.1 jdolecek ENDPROC 1249 1.1 jdolecek 1250 1.1 jdolecek 1251 1.1 jdolecek DEF PROCcopy(dest%, src%, len%) 1252 1.1 jdolecek LOCAL a% 1253 1.1 jdolecek FOR a% = 0 TO len%-4 STEP 4 1254 1.1 jdolecek dest%!a% = src%!a% 1255 1.1 jdolecek NEXT 1256 1.1 jdolecek ENDPROC 1257 1.1 jdolecek 1258 1.1 jdolecek 1259 1.1 jdolecek DEF PROCtwirl 1260 1.1 jdolecek PRINT MID$("|/-\", twirl%+1, 1)+CHR$(8); 1261 1.1 jdolecek twirl% += 1 1262 1.1 jdolecek twirl% = twirl% MOD 4 1263 1.1 jdolecek ENDPROC 1264 1.1 jdolecek 1265 1.1 jdolecek 1266 1.1 jdolecek DEF FNvdu_var(var%) 1267 1.1 jdolecek LOCAL b% 1268 1.1 jdolecek DIM b% 7 1269 1.1 jdolecek b%!0 = var% 1270 1.1 jdolecek b%!4 = -1 1271 1.1 jdolecek SYS "OS_ReadVduVariables", b%, b% 1272 1.1 jdolecek = b%!0 1273 1.1 jdolecek 1274 1.1 jdolecek 1275 1.1 jdolecek DEF FNroundup(val%, size%) 1276 1.1 jdolecek =val% + (size% - 1) AND NOT (size% - 1) 1277 1.1 jdolecek 1278 1.1 jdolecek 1279 1.1 jdolecek DEF FNtolower(name$) 1280 1.1 jdolecek LOCAL A$, Ch$, i% 1281 1.1 jdolecek FOR i%=1 TO LEN(name$) 1282 1.1 jdolecek Ch$ = LEFT$(name$,1) 1283 1.1 jdolecek IF Ch$>="A" AND Ch$<="Z" THEN 1284 1.1 jdolecek A$ += CHR$(ASC(Ch$)+ASC("a")-ASC("A")) 1285 1.1 jdolecek ELSE 1286 1.1 jdolecek A$ += Ch$ 1287 1.1 jdolecek ENDIF 1288 1.1 jdolecek name$ = MID$(name$, 2) 1289 1.1 jdolecek NEXT 1290 1.1 jdolecek = A$ 1291 1.3 bjh21 1292 1.3 bjh21 DEF FNawaitkey(timeout%) 1293 1.3 bjh21 LOCAL i%, i$, c% 1294 1.3 bjh21 REM Flush keyboard buffer first 1295 1.3 bjh21 REPEAT UNTIL INKEY(0) = -1 1296 1.3 bjh21 FOR i% = timeout% TO 1 STEP -1 1297 1.3 bjh21 i$ = STR$(i%) 1298 1.3 bjh21 PRINT ; i% STRING$(LEN(i$), CHR$(8)); 1299 1.3 bjh21 c% = INKEY(100) 1300 1.3 bjh21 IF c% <> -1 THEN 1301 1.3 bjh21 PRINT 1302 1.3 bjh21 = c% 1303 1.3 bjh21 ENDIF 1304 1.3 bjh21 NEXT 1305 1.3 bjh21 PRINT "0" 1306 1.3 bjh21 = 0 1307