root/arch/m68k/kernel/head.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 /* -*- mode: asm -*-
   2 **
   3 ** head.S -- This file contains the initial boot code for the the
   4 **           Linux/68k kernel.
   5 **
   6 ** Copyright 1993 by Hamish Macdonald
   7 **
   8 ** 68040 fixes by Michael Rausch
   9 ** 68060 fixes by Roman Hodek
  10 **
  11 ** Atari support by Andreas Schwab, using ideas of Robert de Vries
  12 ** and Bjoern Brauel
  13 **
  14 ** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
  15 ** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari 
  16 ** ++ Bjoern & Roman: ATARI-68040 support for the Medusa
  17 ** 96/04/26 G|nther Kelleter: fixed identity mapping for Falcon with
  18 **                            Magnum- and FX-alternate ram
  19 **
  20 ** This file is subject to the terms and conditions of the GNU General Public
  21 ** License.  See the file README.legal in the main directory of this archive
  22 ** for more details.
  23 **
  24 */
  25 
  26 /*
  27  * Linux startup code.
  28  *
  29  * At this point, the boot loader has:
  30  * Disabled interrupts
  31  * Disabled caches
  32  * Put us in supervisor state.
  33  *
  34  * The kernel setup code takes the following steps:
  35  *   Raise interrupt level
  36  *   Set up initial kernel memory mapping.
  37  *      This sets up a mapping of the 4M of memory the kernel
  38  *      is located in.  It also does a mapping of any initial
  39  *      machine specific areas.
  40  * Note that the kernel is located at virtual address 0x1000 == _start
  41  *   Enable cache memories
  42  *   Jump to kernel startup
  43  *
  44  * Register d6 contains the CPU flags and d4 the machine type
  45  * from the boot_info information for most of this file.
  46  * The upper word of d6 contains a bit for '040 or '060, since these two
  47  * are quite similar for initial mm setup. Another bit in d6 allows
  48  * distinction of the '060. The lower word of d6 contains the cache mode
  49  * that should be applied to pages containing descriptors. This mode is
  50  * non-cached/non-serialized for the '040 and cacheable/write-through for
  51  * the '060.
  52  */
  53 
  54 #include <linux/linkage.h>
  55 #include <asm/bootinfo.h>
  56 
  57 .text
  58 .globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
  59 .globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
  60 .globl SYMBOL_NAME(m68k_pgtable_cachemode)
  61 .globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
  62 
  63 PAGESIZE = 4096
  64 BI_CPU = 4
  65 BI_MACH = 0
  66 BI_AMIGA_ECLK = 1234
  67 LF   = 10
  68 CR   = 13
  69 BI_BIT040 = 2   /* CPU bits in bootinfo */
  70 BI_BIT060 = 3
  71 BIT0460   = 16  /* indicates '0[46]0 in d6 */
  72 BIT060    = 17  /* indicates '060 in d6 */
  73 D6VAL_040 = 0x00010000
  74 D6VAL_060 = 0x00030000
  75 /* BIT040 = 2 */
  76 
  77      /* Some definitions for the special registers of the 68040.
  78       * (MMU, caches)
  79       */
  80 
  81 /* Translation control register */
  82 TC_ENABLE = 0x8000
  83 TC_PAGE8K = 0x4000
  84 TC_PAGE4K = 0x0000
  85 
  86 /* Transparent translation registers */
  87 TTR_ENABLE = 0x8000
  88 
  89 /* Some bits used in the page and table descriptors as well as in the 
  90  * special registers.
  91  */
  92 
  93 CM_CACHE_WT     = 0x0000          /* cacheable, write-through */
  94 CM_CACHE_CB     = 0x0020          /* cacheable, copyback */
  95 CM_NONCACHE_SER = 0x0040          /* noncacheable, serialized */
  96 CM_NONCACHE     = 0x0060          /* noncacheable */
  97 CM_MASK         = 0xffffff9f      /* mask */
  98 
  99 MODIFIED        = 0x0010
 100 WRITE_PROT      = 0x0004
 101 USED            = 0x0008
 102 GLOBAL          = 0x0400
 103 SV_ONLY         = 0x0080
 104 PAGEDESC        = 0x0001
 105 TABLEDESC       = 0x0002
 106 INVALID         = 0x0000
 107 
 108 /* Cache enabling */
 109 I_HALF          = 0x00002000    /* half-cache mode for I-cache ('060) */
 110 I_FREEZE        = 0x00004000    /* freeze I-cache ('060) */
 111 I_ENABLE        = 0x00008000    /* enable I-cache */
 112 BC_CLRU         = 0x00200000    /* clear user entries in branch cache ('060) */
 113 BC_CLRA         = 0x00400000    /* clear all entries in branch cache ('060) */
 114 BC_ENABLE       = 0x00800000    /* enable branch cache ('060) */
 115 D_HALF          = 0x08000000    /* half-cache mode for D-cache ('060) */
 116 PUSH_DPI        = 0x10000000    /* disable CPUSH invalidation ('060) */
 117 SB_ENABLE       = 0x20000000    /* enable store buffer ('060) */
 118 D_FREEZE        = 0x40000000    /* freeze D-cache ('060) */
 119 D_ENABLE        = 0x80000000    /* enable D-cache */
 120 
 121 /* Miscellaneous definitions */
 122 PAGE_MASK       = (~(PAGESIZE-1))
 123 
 124 ROOT_TABLE_SIZE = 128
 125 PTR_TABLE_SIZE  = 128
 126 PAGE_TABLE_SIZE = 64
 127 ROOT_INDEX_SHIFT = 25
 128 PAGE_INDEX_SHIFT = 12
 129 
 130 ENTRY(_stext)
 131 ENTRY(_start)
 132         bras    1f /* Jump over bootinfo version numbers */
 133 /*
 134  * Version numbers of the bootinfo interface
 135  */
 136 
 137         .long   BOOTINFOV_MAGIC
 138         .long   MACH_AMIGA, AMIGA_BOOTI_VERSION
 139         .long   MACH_ATARI, ATARI_BOOTI_VERSION
 140         .long   0
 141 
 142 1:
 143 
 144 /*
 145  * raise interrupt level
 146  */
 147 
 148         movew   #0x2700,%sr
 149 
 150 /*
 151  * Setup initial stack pointer
 152  */
 153         lea     %pc@(SYMBOL_NAME(_start)),%sp
 154 
 155 /* clear the fpu */
 156         lea     %pc@(mmu),%a0
 157         clrl    %a0@
 158         frestore %a0@
 159 
 160 /*
 161  * Copy bootinfo from position after BSS to final resting place
 162  */
 163         lea     %pc@(SYMBOL_NAME(_end)),%a0
 164         lea     %pc@(SYMBOL_NAME(boot_info)),%a1
 165         movel   %pc@(SYMBOL_NAME(bisize)),%d0
 166         subql   #1,%d0
 167 1:      moveb   %a0@+,%a1@+
 168         dbra    %d0,1b
 169 
 170 /*
 171  * Record the CPU and machine type.
 172  */
 173         lea     %pc@(SYMBOL_NAME(boot_info)),%a0
 174         movel   %a0@(BI_MACH),%d4
 175         movel   %a0@(BI_CPU),%d0
 176         movel   %a0@(BI_CPU),%d6      /* !!!!!!!!!!!!!!!! */
 177 
 178         btst    #BI_BIT060,%d0
 179         beq     1f
 180         /* '060: d6 := BIT0460|BIT060, cache mode 0x60 (no-cache/non-ser) */
 181         movel   #(D6VAL_060+CM_NONCACHE),%d6
 182         bra     2f
 183 1:      btst    #BI_BIT040,%d0
 184         beq     1f
 185         /* '040: d6 := BIT0460, cache mode 0x00 (write-through) */
 186         movel   #(D6VAL_040+CM_CACHE_WT),%d6
 187         bra     2f
 188 1:      /* '020 or '030: d6 := no CPU bit, cache mode unused */
 189         moveq   #0,%d6
 190 
 191 2:      lea     %pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
 192         movel   %d6,%a0@                /* save cache mode for page tables */
 193         andl    #0x0000ffff,%a0@
 194 
 195 /*
 196  * Initialize serial port
 197  */
 198         jbsr Lserial_init
 199 
 200         moveq   #CR,%d7
 201         jbsr    Lserial_putc
 202         moveq   #LF,%d7
 203         jbsr    Lserial_putc
 204         moveq   #'A',%d7
 205         jbsr    Lserial_putc
 206 
 207 /*
 208  * Get address at end of kernel code/data/bss and
 209  * mask off at a page boundary.
 210  */
 211         lea     %pc@(SYMBOL_NAME(_end)),%a0
 212         movel   %a0,%d0
 213         addl    #(PAGESIZE-1),%d0
 214         andl    #PAGE_MASK,%d0
 215         movel   %d0,%a6
 216 
 217         moveq   #'B',%d7
 218         jbsr    Lserial_putc
 219 
 220 /*
 221  * initialize the kernel root table.
 222  */
 223         lea     %pc@(SYMBOL_NAME(kernel_pg_dir)),%a4
 224         movel   %a4,%a0
 225         moveq   #0,%d0
 226         moveq   #(ROOT_TABLE_SIZE-1),%d1
 227 1:      movel   %d0,%a0@+
 228         dbra    %d1,1b
 229 
 230         /*
 231          * Initialize root table descriptor pointing to the kernel pointer
 232          * table.
 233          */
 234         movel   %a6,%a5
 235         addw    #PAGESIZE,%a6
 236 
 237         movel   %a5,%a0
 238         addql   #TABLEDESC,%a0
 239         movel   %a0,%a4@
 240 
 241         moveq   #'C',%d7
 242         jbsr    Lserial_putc
 243 
 244 /*
 245  * Initialize the pointer tables referred to above.  They either point
 246  * to page tables in the case of the 680[46]0 or contain early
 247  * termination page descriptors in the case of the 68851 or 68030.
 248  *
 249  * Each pointer table entry points to a 64 entry page table.  16 of these
 250  * page tables are grouped to form a single 1024 entry page table which
 251  * fits in a single 4096 byte page.
 252  *
 253  * Some register usages:
 254  *    a0 -> pointer table descriptor address
 255  *    a1 -> pointer table descriptor
 256  *    d1 -> counter
 257  *    d2 -> pointer table descriptor increment (varies according to CPU)
 258  */
 259 
 260         /* clear the kernel pointer table */
 261         movel   %a5,%a0
 262         moveq   #0,%d0
 263         moveq   #(PTR_TABLE_SIZE-1),%d1
 264 1:      movel   %d0,%a0@+
 265         dbra    %d1,1b
 266 
 267         movel   %a5,%a0
 268         moveq   #15,%d1
 269 
 270         /*
 271          * base value of pointer table descriptor is either
 272          * the address of the first page table (680[46]0)
 273          * or the base address of physical memory (68030).
 274          */
 275         btst    #BIT0460,%d6
 276         bne     1f
 277 
 278         /* 680[23]0 */
 279         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1  /* base address */
 280         addql   #PAGEDESC,%a1   /* descriptor type */
 281         movel   #0x40000,%d2    /* increment */
 282         bra     2f
 283 
 284 1:      /* 680[46]0 */
 285         movel   %a6,%a1         /* base address */
 286         addw    #PAGESIZE,%a6   /* allocate the page table */
 287         lea     %pc@(SYMBOL_NAME(kpt)),%a3
 288         movel   %a1,%a3@                /* save address of page table */
 289         addql   #TABLEDESC,%a1  /* descriptor type */
 290         movel   #256,%d2        /* increment */
 291 
 292 2:      movel   %a1,%a0@+
 293         addl    %d2,%a1
 294         dbra    %d1,2b
 295 
 296         moveq   #'D',%d7
 297         jbsr    Lserial_putc
 298 
 299 /*
 300  * If we are running on a 680[46]0, we have a kernel page table and
 301  * must initialize it.  Make the entries point to the first
 302  * 4M of physical memory (the memory we are residing in).
 303  * Set the cache mode bits to Cacheable, Copyback.  Set the Global bits
 304  * in the descriptors also.
 305  */
 306 
 307         btst    #BIT0460,%d6
 308         jeq     Lnot040
 309 
 310         moveq   #'F',%d7
 311         jbsr    Lserial_putc
 312 
 313         movel   %pc@(SYMBOL_NAME(kpt)),%a0
 314         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1
 315 
 316         addw    #(GLOBAL+CM_CACHE_CB+PAGEDESC),%a1
 317         movew   #((PAGESIZE/4)-1),%d1
 318         movel   #PAGESIZE,%d2
 319 
 320 1:      movel   %a1,%a0@+
 321         addl    %d2,%a1
 322         dbra    %d1,1b
 323 
 324         /*
 325          * on the 68040, pages used to hold mmu tables should
 326          * be initialized as noncachable; the '060 allows write-through.
 327          * Do this for the root table page (which also contains
 328          * all pointer tables utilized thus far) and the
 329          * kernel page table.
 330          */
 331         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
 332         movel   %a4,%d0         /* address of root table */
 333         subl    %a0,%d0         /* determine offset of root table page */
 334         moveq   #PAGE_INDEX_SHIFT,%d1   /* determine offset into kernel page table */
 335         lsrl    %d1,%d0         /* i.e. page number of the address offset */
 336         movel   %pc@(SYMBOL_NAME(kpt)),%a0
 337         lea     %a0@(%d0:l:4),%a0
 338         movel   %a0@,%d1
 339         andl    #CM_MASK,%d1
 340         orw     %d6,%d1
 341         movel   %d1,%a0@+
 342 
 343         movel   %a0@,%d1        /* do the same for the kernel page table */
 344         bclr    #5,%d1          /* the kernel page table resides in the  */
 345         bset    #6,%d1          /* page after the page containing the    */
 346         movel   %d1,%a0@        /* root table                            */
 347 
 348 Lnot040:
 349 /*
 350  * Do any machine specific page table initializations.
 351  */
 352         moveq   #MACH_AMIGA,%d0
 353         cmpl    %d4,%d0
 354         bne     Lnotami
 355 
 356 /*
 357  * On the Amiga:
 358  * Our current stack (in CHIP ram) may become invalid after the remapping
 359  * of the kernel virtual address space, so set it to point to PAGE_SIZE.
 360  * This will be in CHIP ram until after the remapping, and in the unused
 361  * first page (temporarily) after that.
 362  *
 363  * Setup a mapping of the first 16M of physical address space at virtual
 364  * address 0x80000000, using early termination page descriptors for the
 365  * 68030, and proper page tables for the 680[46]0.  Set this area as
 366  * non-cacheable.
 367  */
 368 
 369         moveq   #'H',%d7
 370         jbsr    Lserial_putc
 371 
 372         move.w  #PAGESIZE,%sp
 373 
 374         btst    #BIT0460,%d6
 375         bne     Lspami68040
 376 
 377 
 378         /*
 379          * for the 68030, just setup a translation to map in the first
 380          * 32M of physical address space at virtual address 0x80000000
 381          * using an early termination page descriptor.
 382          */
 383 
 384         moveq   #'I',%d7
 385         jbsr    Lserial_putc
 386 
 387         moveq   #0x41,%d0
 388         movel   %d0,%a4@(64*4)
 389 
 390         bra     Lmapphys
 391 
 392 Lspami68040:
 393 
 394         /*
 395          * for the 680[46]0, use another pointer table, and allocate 4 more
 396          * page tables.  Initialize the pointer table to point to the
 397          * page tables.  Then initialize the page tables to point to
 398          * the first 16M of memory, with no caching (noncachable/serialized).
 399          */
 400 
 401         /* clear the amiga pointer table */
 402         lea     %a5@(512),%a0
 403         moveq   #0,%d0
 404         moveq   #(PTR_TABLE_SIZE-1),%d1
 405 1:      movel   %d0,%a0@+
 406         dbra    %d1,1b
 407 
 408         /* allocate 4 page tables */
 409         movel   %a6,%a3
 410         addw    #(4*PAGESIZE),%a6
 411 
 412         /* initialize the pointer table */
 413         lea     %a5@(512),%a0
 414         movel   %a3,%a1
 415         addql   #TABLEDESC,%a1  /* base descriptor */
 416         movel   #256,%d2        /* increment */
 417         moveq   #(PAGE_TABLE_SIZE-1),%d1
 418 
 419 1:      movel   %a1,%a0@+
 420         addl    %d2,%a1
 421         dbra    %d1,1b
 422 
 423         /* ensure that the root table points to the pointer table */
 424         lea     %a5@(512),%a0
 425         addql   #TABLEDESC,%a0
 426         movel   %a0,%a4@(256)   /* 0x80000000>>(ROOT_INDEX_SHIFT-2) doesn't
 427                                    work */
 428 
 429         /*
 430          * initialize the page tables
 431          * descriptor bits include noncachable/serialized and global bits.
 432          */
 433         movel   %a3,%a0
 434         movew   #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
 435         movel   #PAGESIZE,%d2
 436         movew   #PAGESIZE-1,%d1
 437 
 438 1:      movel   %a1,%a0@+
 439         addl    %d2,%a1
 440         dbra    %d1,1b
 441 
 442         /*
 443          * Finally, since we just allocated 4 page tables, make sure that
 444          * the virtual mapping of the 4 page tables indicates
 445          * noncachable/serialized.
 446          */
 447         movel   %a3,%d0         /* ami page table start address */
 448         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
 449         subl    %a0,%d0         /* determine offset of root table page */
 450         moveq   #PAGE_INDEX_SHIFT,%d1   /* determine offset into kernel page table */
 451         lsrl    %d1,%d0
 452         movel   %pc@(SYMBOL_NAME(kpt)),%a0
 453         movel   #3,%d2
 454 1:      lea     %a0@(%d0:l:4),%a1
 455         movel   %a1@,%d1
 456         bclr    #5,%d1
 457         bset    #6,%d1
 458         movel   %d1,%a1@
 459         addql   #1,%d0
 460         dbra    %d2,1b
 461 
 462         bra     Lmapphys
 463 
 464 
 465 Lnotami:        /* other machines specific mappings go here! */
 466 
 467         moveq   #MACH_ATARI,%d0
 468         cmpl    %d4,%d0
 469         bne     Lnotatari
 470 
 471         move.w  #PAGESIZE,%sp
 472 
 473 /* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
 474    the last 16 MB of virtual address space to the first 16 MB (i.e.
 475    0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is
 476    needed. I/O ranges are marked non-cachable.
 477 
 478    For the Medusa it is better to map the I/O region transparently
 479    (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
 480    accessible only in the high area. The test whether it is a Medusa
 481    is done by writing to the byte at phys. 0x0. This should result
 482    in a bus error on all other machines.
 483 
 484    ...should, but doesn't. The Afterburner040 for the Falcon has the
 485    same behaviour (0x0..0x7 are no ROM shadow). So we have to do
 486    another test to distinguish Medusa and AB040. This is a
 487    read attempt for 0x00ff82fe phys. that should bus error on a Falcon
 488    (+AB040), but is in the range where the Medusa always asserts DTACK.
 489 */
 490 
 491         moveq   #0,%d3                  /* base addr for others: 0x00000000 */
 492         movec   %d3,%vbr
 493         lea         %pc@(Ltest_berr),%a0
 494         movel   %a0,0x8
 495         movel   %sp,%a0
 496         moveb   0x0,%d1
 497         clrb    0x0
 498         nop
 499         moveb   %d1,0x0
 500         nop
 501         tstb    0x00ff82fe
 502         nop
 503         movel   #0xff000000,%d3         /* Medusa base addr: 0xff000000 */
 504 Ltest_berr:
 505         movel   %a0,%sp
 506         lea     %pc@(SYMBOL_NAME(is_medusa)),%a0
 507         movel   %d3,%a0@
 508 
 509         /* Let the root table point to the new pointer table */
 510         lea     %a5@(512),%a0
 511         addl    #TABLEDESC,%a0
 512         movel   %a0,%a4@(508)           /* 0xFE000000 - 0xFFFFFFFF */
 513 
 514         /* clear lower half of the pointer table (0xfexxxxxx) */
 515         lea     %a5@(512),%a0
 516         movel   #0,%d0
 517         movel   #63,%d2
 518 1:      movel   %d0,%a0@+
 519         dbra    %d2,1b
 520 
 521         btst    #BIT0460,%d6
 522         bne     Lspata68040
 523 
 524 /* Mapping of the last 16M of virtual address space to the first 16M
 525    for efficient addressing of hardware registers */
 526         movel   #0x40000,%d1
 527         movel   #63,%d2
 528         movel   %d3,%d0
 529         addl    #PAGEDESC,%d0
 530 1:      movel   %d0,%a0@+
 531         addl    %d1,%d0
 532         dbra    %d2,1b
 533         moveq   #0x40,%d0       /* make non-cachable */
 534         addl    %d0,%a5@(1020)  /* 0xFFFC0000-0xFFFFFFFF (I/O space) */
 535 /* GK: 0xFFF00000-0xFFF3FFFF (IDE-bus) has to be non-cachable too */
 536         addl    %d0,%a5@(1008)
 537 
 538         bra     Lmapphys
 539 
 540 Lspata68040:
 541         /* allocate 4 page tables */
 542         movel   %a6,%a3
 543         addw    #(4*PAGESIZE),%a6
 544 
 545 /* Initialize the upper half of the pointer table (a0 is still valid) */
 546         movel   %a3,%a1
 547         addql   #TABLEDESC,%a1
 548         movel   #256,%d2
 549         moveq   #63,%d1
 550 1:      movel   %a1,%a0@+
 551         addl    %d2,%a1
 552         dbra    %d1,1b
 553 
 554         /* Initialize the page tables as noncacheable/serialized! */
 555         movel   %a3,%a0
 556         movel   %d3,%a1
 557         addw    #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
 558         movel   #PAGESIZE,%d2
 559         movew   #(PAGESIZE-1),%d1
 560 1:      movel   %a1,%a0@+
 561         addl    %d2,%a1
 562         dbra    %d1,1b
 563 
 564         /*
 565          * Finally, since we just allocated 4 page tables, make sure that
 566          * the virtual mapping of the 4 page tables indicates
 567          * noncachable or write-through.
 568          */
 569         movel   %a3,%d0         /* page table start address */
 570         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
 571         subl    %a0,%d0         /* determine offset of root table page */
 572         moveq   #PAGE_INDEX_SHIFT,%d1 /* determine offset into 
 573                                          kernel page table */
 574         lsrl    %d1,%d0
 575         movel   %pc@(SYMBOL_NAME(kpt)),%a0
 576         moveq   #3,%d2
 577 1:      lea     %a0@(%d0:l:4),%a1
 578         movel   %a1@,%d1
 579         andl    #CM_MASK,%d1
 580         orw     %d6,%d1
 581         movel   %d1,%a1@
 582         addql   #1,%d0
 583         dbra    %d2,1b
 584 
 585 Lnotatari:
 586 
 587 /*
 588  * Setup a transparent mapping of the physical memory we are executing in.
 589  *
 590  * Only do this if the physical memory is not in the first 16M Meg, or not on
 591  * an Amiga since the first 16M is already identity mapped on the Amiga.
 592  */
 593 Lmapphys:
 594         moveq   #'J',%d7
 595         jbsr    Lserial_putc
 596 
 597         clrl    %d5             /* indicate that no cleanup is required */
 598 
 599         cmpl    #MACH_AMIGA,%d4
 600         bne     Lmapphysnotamiga        /* other machines will probably have
 601                                          * to put in code and jump to it here
 602                                          */
 603 
 604 /*
 605  * The virtual address of the start of the kernel is 0x1000.  On ALL
 606  * Amigas, there is CHIP RAM in this area.  Hence we will copy the MMU
 607  * enabling code to CHIP RAM (to the same physical address as the kernel
 608  * virtual address) and jump to it.  When the MMU is enabled, we will be
 609  * running from the code in the kernel virtual space, rather than the
 610  * physical space.
 611  */
 612 
 613 /*
 614  * Setup Supervisor Root Pointer register to point to page directory,
 615  * setup translation register contents and enable translation.
 616  */
 617         btst    #BIT0460,%d6
 618         bne     Lamimmu68040
 619 
 620         moveq   #'K',%d7
 621         jbsr    Lserial_putc
 622 
 623         lea     %pc@(mmu),%a0
 624         movel   #0x80000002,%a0@   /* no limit, 4byte descriptors */
 625         movel   %a4,%a0@(4)
 626         pmove   %a0@,%srp
 627         pmove   %a0@,%crp
 628         /*
 629          * enable,super root enable,4096 byte pages,7 bit root index,
 630          * 7 bit pointer index, 6 bit page table index.
 631          */
 632         movel   #0x82c07760,%a0@
 633 
 634         /* setup registers for jumping MMU enabling code */
 635         lea     %pc@(Ldoit030ami),%a2
 636         lea     Ldoit030ami,%a1
 637 
 638         moveq   #CR,%d7
 639         jbsr    Lserial_putc
 640         moveq   #LF,%d7
 641         jbsr    Lserial_putc
 642         movel   %a2,%d7
 643         jbsr    Lserial_putnum
 644         moveq   #' ',%d7
 645         jbsr    Lserial_putc
 646         movel   %a1,%d7
 647         jbsr    Lserial_putnum
 648 
 649         bra     LdoitAmiga
 650 
 651 #ifdef __ELF__
 652         .align  16
 653 #else
 654         .align  4
 655 #endif
 656 Ldoit030ami:
 657         pmove   %a0@,%tc        /* enable the MMU */
 658         jra     LdoneMMUenable  /* branch to continuation of startup */
 659 
 660 Lamimmu68040:
 661         moveq   #'L',%d7
 662         jbsr    Lserial_putc
 663         
 664         .word   0xf4d8          /* CINVA I/D */
 665         .word   0xf518          /* pflusha      */
 666         .long   0x4e7bc807      /* movec a4,srp */
 667         .long   0x4e7bc806      /* movec a4,urp */
 668         movel   #(TC_ENABLE+TC_PAGE4K),%d0
 669 
 670         /* setup registers for jumping MMU enabling code */
 671         lea     Ldoit040ami,%a1
 672         lea     %pc@(Ldoit040ami),%a2
 673         bra     LdoitAmiga
 674 
 675 #ifdef __ELF__
 676         .align  16
 677 #else
 678         .align  4
 679 #endif
 680 Ldoit040ami:
 681         .long   0x4e7b0003      /* movec d0,tc  (enable the MMU) */
 682         jra     LdoneMMUenable  /* branch to continuation of startup */
 683 
 684 LdoitAmiga:
 685         /* copy the appropriate code (two longwords) to chipmem */
 686         movel   %a2@,%a1@
 687         movel   %a2@(4),%a1@(4)
 688 
 689         /*
 690          * save physaddr of phys mem in register a3
 691          */
 692         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
 693 
 694         /* jump to the physical address in chipmem */
 695         jmp     %a1@
 696 
 697 Lmapphysnotamiga:
 698 
 699         cmpl    #MACH_ATARI,%d4
 700         bne     Lmapphysnotatari
 701 
 702         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE),%a0
 703         tstl    %a0
 704         jeq     Lnophys2
 705 
 706         /* The kernel physical address is different from its virtual
 707            address.  Temporarily set up an identity mapping of the
 708            16MB chunk where the kernel is executing. */
 709   
 710         /* 680[46]0? */
 711         btst    #BIT0460,%d6
 712         jeq     1f
 713 
 714         /*
 715          * For the 68040, we will use the transparent translation
 716          * registers to identity map the 16M chunk that contains
 717          * the physical memory.
 718          */
 719         movel   %a0,%d2
 720         andl    #0xff000000,%d2         /* logical address base */
 721         orw     #0xc040,%d2             /* add in magic bits */
 722         .long   0x4e7b2004              /* movec d2,ittr0 */
 723         .long   0x4e7b2006              /* movec d2,dttr0 */
 724 
 725         /* d5 is kept 0 to do no cleanup. This didn't work in head.S, I don't
 726          * know why... The transparent translation is turned off in
 727          * atari/config.c instead.
 728          */
 729         jra     Lnophys2
 730 
 731         /* Transparent translation for the 68030 via transparent translation
 732            register */
 733 
 734 1:
 735         /* cleanup is needed; note it */
 736         moveq   #1,%d5
 737 
 738         /* tt0 doesn't work if physical and virtual address of kernel is in
 739          * the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
 740          */
 741         movel   %a0,%d2
 742         andl    #0xff000000,%d2         /* logical address base */
 743         jeq     1f
 744         orw     #0x8143,%d2             /* add in magic bits */
 745         lea     %pc@(mmu),%a0
 746         movel   %d2,%a0@
 747         pmove   %a0@,%tt0
 748         jra     Lnophys2
 749 1:
 750         /* Transparent translation through kernel pointer table
 751          * Requires that this code until after MMU enabling lies in
 752          * the 256K page around %a0
 753          */
 754         movel   %a0,%d2
 755         moveq   #ROOT_INDEX_SHIFT,%d1
 756         lsrl    %d1,%d2
 757         movel   %a4@(%d2:l:4),%d0
 758         andw    #0xfff0,%d0
 759         movel   %d0,%a1
 760         movel   %a0,%d2
 761         andl    #0x01ffffff,%d2
 762         moveq   #(ROOT_INDEX_SHIFT-7),%d1
 763         lsrl    %d1,%d2
 764         movel   %a0,%d0
 765         addql   #PAGEDESC,%d0
 766         movel   %a1@(%d2:l:4),%a2       /* save old_entry */
 767         movel   %d0,%a1@(%d2:l:4)
 768 
 769 Lnophys2:
 770         /*
 771          * save physaddr of phys mem in register a3
 772          */
 773         lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
 774 
 775         btst    #BIT0460,%d6
 776         jne     Latarimmu68040
 777 
 778         moveq   #'K',%d7
 779         jbsr    Lserial_putc
 780 
 781         lea     %pc@(mmu),%a0
 782         movel   #0x80000002,%a0@   /* no limit, 4byte descriptors */
 783         movel   %a4,%a0@(4)
 784         pmove   %a0@,%srp
 785         pmove   %a0@,%crp
 786         /*
 787          * enable,super root enable,4096 byte pages,7 bit root index,
 788          * 7 bit pointer index, 6 bit page table index.
 789          */
 790         movel   #0x82c07760,%a0@
 791         pmove   %a0@,%tc                /* enable the MMU */
 792 
 793         /* Jump to the virtual address of continuation of startup. */
 794         jmp     LdoneMMUenable
 795 
 796 Latarimmu68040:
 797         moveq   #'L',%d7
 798         jbsr    Lserial_putc
 799 
 800         .word   0xf4d8          /* CINVA I/D */
 801         .word   0xf518          /* pflusha      */
 802         .long   0x4e7bc807      /* movec a4,srp */
 803         .long   0x4e7bc806      /* movec a4,urp */
 804         movel   #(TC_ENABLE+TC_PAGE4K),%d0
 805         /* this value is also ok for the '060, we don't use the cache
 806          * mode/protection defaults */
 807         .long   0x4e7b0003      /* movec d0,tc  (enable the MMU) */
 808         jmp     LdoneMMUenable  /* jump to virtual address of
 809                                    continuation of startup */
 810 
 811 Lmapphysnotatari:
 812 
 813 
 814 LdoneMMUenable:
 815 
 816 /*
 817  * Fixup the addresses for the kernel pointer table and availmem.
 818  * Convert them from physical addresses to virtual addresses.
 819  */
 820 
 821         /*
 822          * fixup the Amiga custom register location before printing
 823          */
 824         addl    #0x80000000,Lcustom
 825 
 826         /* The same for the Atari */
 827         movel   #0xff000000,Liobase
 828 
 829         moveq   #'M',%d7
 830         jbsr    Lserial_putc
 831 
 832         /*
 833          * a3 contains physaddr of kernel start
 834          */
 835         movel   SYMBOL_NAME(kpt),%d1
 836         subl    %a3,%d1
 837         movel   %d1,SYMBOL_NAME(kpt)
 838 
 839         /*
 840          * do the same conversion on the first available memory
 841          * address (in a6).
 842          */
 843         subl    %a3,%a6
 844 
 845         /* Allocate a page to be used by get_kpointer_table.  */
 846         movel   %a6,SYMBOL_NAME(kernel_pmd_table)
 847         addl    #PAGESIZE,%a6
 848         movel   %a6,SYMBOL_NAME(availmem) /* first available memory address */
 849 
 850         moveq   #'N',%d7
 851         jbsr    Lserial_putc
 852 
 853         /*
 854          * Clean up the temporary physical mapping (if necessary)
 855          */
 856 
 857         tstl    %d5
 858         jeq     Lnoclean
 859 
 860         btst    #BIT0460,%d6
 861         jne     Loff040
 862 
 863         /* clean up physical identity mapping for 68020/68030 */
 864         /* Is this needed for the Amiga anymore? */
 865         /* it's not in 1.2.13pl6 - Jes */
 866         cmpl    #MACH_AMIGA,%d4
 867         jeq     Lclean030
 868         cmpl    #MACH_ATARI,%d4
 869         jne     Lnoclean
 870 
 871         movel   %a3,%d2
 872         andl    #0xff000000,%d2
 873         jeq     1f
 874         /* clear transparent translation register */
 875         lea     %pc@(mmu),%a0
 876         clrl    %a0@
 877         pmove   %a0@,%tt0
 878         jra     Lnoclean
 879 1:
 880         movel   %a3,%d2
 881         moveq   #ROOT_INDEX_SHIFT,%d1
 882         lsrl    %d1,%d2
 883         movel   %a4@(%d2:l:4),%d0
 884         andw    #0xfff0,%d0
 885         subl    %a3,%d0         /* to virtual address */
 886         movel   %d0,%a0
 887         movel   %a3,%d2
 888         andl    #0x01ffffff,%d2
 889         moveq   #(ROOT_INDEX_SHIFT-7),%d1
 890         lsrl    %d1,%d2
 891         movel   %a2,%a0@(%d2:l:4)       /* restore old entry */
 892         jra     Lnoclean
 893 
 894 Lclean030:
 895         movel   %a0,%d2         /* a0 contains physical start address */
 896         moveq   #25,%d3         /* find appropriate index in root table */
 897         lsrl    %d3,%d2
 898         moveq   #0,%d0
 899         movel   %d0,%a4@(%d2:l:4)  /* clear descriptor */
 900 
 901         jra     Lnoclean
 902 
 903 Loff040:
 904         /* turn off transparent translation registers for '0[46]0 */
 905         moveq   #0,%d0
 906         .long   0x4e7b0004      /* movec d0,ittr0 */
 907         .long   0x4e7b0006      /* movec d0,dttr0 */
 908 
 909 Lnoclean:
 910         moveq   #'O',%d7
 911         jbsr    Lserial_putc
 912 
 913 
 914 /*
 915  * Enable caches
 916  */
 917         btst    #BIT0460,%d6
 918         jne     Lcache680460
 919 
 920         movel   #0x00001919,%d0
 921         movec   %d0,%cacr
 922         jra     1f
 923 
 924 Lcache680460:
 925         btst    #BIT060,%d6
 926         jne     Lcache68060
 927 
 928         .word   0xf4d8       /* CINVA I/D */
 929         movel   #I_ENABLE+D_ENABLE,%d0
 930         /* MMU stuff works in copyback mode now, so enable the cache */
 931         movec   %d0,%cacr
 932         jra     1f
 933 
 934 Lcache68060:
 935         .word   0xf4d8       /* CINVA I/D */
 936         movel   #I_ENABLE+D_ENABLE+SB_ENABLE+PUSH_DPI+BC_ENABLE+BC_CLRA,%d0
 937         /* MMU stuff works in copyback mode now, so enable the cache */
 938         movec   %d0,%cacr
 939         /* enable superscalar dispatch in PCR */
 940         moveq   #1,%d0
 941         .long   0x4e7b0808      /* movec d0,pcr */
 942 
 943 1:
 944 
 945 /*
 946  * Setup initial stack pointer
 947  */
 948         lea     SYMBOL_NAME(init_user_stack)+PAGESIZE,%sp
 949 
 950 /* jump to the kernel start */
 951 
 952         jbsr    SYMBOL_NAME(start_kernel)
 953 
 954 #if 0
 955 tmp_fault_handler:
 956      lea       %pc@(tfh_1st_str),%a0
 957      jbsr       Lserial_puts
 958      move.l    %sp@(2),%d7                     /* PC */
 959      jbsr       Lserial_putnum
 960      move.w    %sp@(0xa),%d7
 961      swap      %d7
 962      move.w    %sp@(0x6),%d7
 963      jbsr       Lserial_putnum
 964      lea       %pc@(tfh_2nd_str),%a0
 965      jbsr       Lserial_puts
 966      move.l    %sp@(0x10),%d7                  /* Fault address */
 967      jbsr       Lserial_putnum
 968      moveq     #CR,%d7
 969      jbsr       Lserial_putc
 970      moveq     #LF,%d7
 971      jbsr       Lserial_putc
 972 1:   jra       1b
 973 
 974 tfh_1st_str:
 975      .byte     CR
 976      .byte     LF
 977      .ascii    "Access fault occurred. PC = "
 978      .byte     0
 979 
 980 tfh_2nd_str:
 981      .byte     CR
 982      .byte     LF
 983      .ascii    "FaultAddress = "
 984      .byte     0
 985 #endif
 986 
 987 /*
 988  * Serial port output support.
 989  */
 990 LSERPER      = 0xdff032
 991 LSERDAT      = 0xdff030
 992 LSERDATR     = 0xdff018
 993 LNTSC_PERIOD = 371
 994 LPAL_PERIOD  = 368/2        /* /2 for 19200 baud */
 995 LNTSC_ECLOCK = 7159090
 996 LSERIAL_CNTRL = 0xbfd000
 997 LSERIAL_DTR   = 7
 998 
 999 /*
1000  * Debug output support
1001  * Atarians have a choice between the parallel port, the serial port
1002  * from the MFP or a serial port of the SCC
1003  */
1004 
1005 /* #define USE_PRINTER */
1006 /* #define USE_SCC */
1007 #define USE_MFP
1008 
1009 #ifdef USE_PRINTER
1010 
1011 LPSG_SELECT     = 0xff8800
1012 LPSG_READ       = 0xff8800
1013 LPSG_WRITE      = 0xff8802
1014 LPSG_IO_A       = 14
1015 LPSG_IO_B       = 15
1016 LPSG_CONTROL    = 7
1017 LSTMFP_GPIP     = 0xfffa01
1018 LSTMFP_DDR      = 0xfffa05
1019 LSTMFP_IERB     = 0xfffa09
1020 
1021 #elif defined(USE_SCC)
1022  
1023 LSCC_CTRL_B     = 0xff8c85
1024 LSCC_DATA_B     = 0xff8c87
1025 
1026 /* Initialisation table for SCC */
1027 scc_initable:
1028         .byte   9,12            /* Reset */
1029         .byte   4,0x44          /* x16, 1 stopbit, no parity */
1030         .byte   3,0xc0          /* receiver: 8 bpc */
1031         .byte   5,0xe2          /* transmitter: 8 bpc, assert dtr/rts */
1032         .byte   9,0             /* no interrupts */
1033         .byte   10,0            /* NRZ */
1034         .byte   11,0x50         /* use baud rate generator */
1035         .byte   12,24,13,0      /* 9600 baud */
1036         .byte   14,2,14,3       /* use master clock for BRG, enable */
1037         .byte   3,0xc1          /* enable receiver */
1038         .byte   5,0xea          /* enable transmitter */
1039         .byte   -1
1040         .even
1041 
1042 #elif defined(USE_MFP)
1043 
1044 LMFP_UCR     = 0xfffa29
1045 LMFP_TDCDR   = 0xfffa1d
1046 LMFP_TDDR    = 0xfffa25
1047 LMFP_TSR     = 0xfffa2d
1048 LMFP_UDR     = 0xfffa2f
1049 
1050 #endif
1051 
1052 /*
1053  * Initialize serial port hardware for 9600/8/1
1054  * a0 thrashed
1055  * Atari d0 trashed (a1 in case of SCC)
1056  */
1057         .even
1058 Lserial_init:
1059         cmpil   #MACH_AMIGA,%d4
1060         jne     1f
1061         bclr    #LSERIAL_DTR,LSERIAL_CNTRL
1062         movew   #LNTSC_PERIOD,LSERPER
1063         cmpl    #LNTSC_ECLOCK,%a0@(BI_AMIGA_ECLK)
1064         jeq     9f
1065         movew   #LPAL_PERIOD,LSERPER
1066         jra     9f
1067 1:      cmpil   #MACH_ATARI,%d4
1068         jne     9f
1069 #ifdef USE_PRINTER
1070         bclr    #0,LSTMFP_IERB
1071         bclr    #0,LSTMFP_DDR
1072         moveb   #LPSG_CONTROL,LPSG_SELECT
1073         moveb   #0xff,LPSG_WRITE
1074         moveb   #LPSG_IO_B,LPSG_SELECT
1075         clrb    LPSG_WRITE
1076         moveb   #LPSG_IO_A,LPSG_SELECT
1077         moveb   LPSG_READ,%d0
1078         bset    #5,%d0
1079         moveb   %d0,LPSG_WRITE
1080 #elif defined(USE_SCC)
1081         lea     LSCC_CTRL_B,%a0
1082         lea     %pc@(scc_initable:w),%a1
1083 2:      moveb   %a1@+,%d0
1084         jmi     3f
1085         moveb   %d0,%a0@
1086         moveb   %a1@+,%a0@
1087         jra     2b
1088 3:      clrb    %a0@
1089 #elif defined(USE_MFP)
1090         bclr    #1,LMFP_TSR
1091         moveb   #0x88,LMFP_UCR
1092         andb    #0x70,LMFP_TDCDR
1093         moveb   #2,LMFP_TDDR
1094         orb     #1,LMFP_TDCDR
1095         bset    #1,LMFP_TSR
1096 #endif
1097 9:
1098         rts
1099 
1100 /*
1101  * Output character in d7 on serial port.
1102  * d7 thrashed.
1103  */
1104 Lserial_putc:
1105         moveml  %a0/%a1,%sp@-
1106         cmpil   #MACH_AMIGA,%d4
1107         jne     2f
1108         andw    #0x00ff,%d7
1109         oriw    #0x0100,%d7
1110         movel   %pc@(Lcustom),%a1
1111         movew   %d7,%a1@(LSERDAT)
1112 1:      movew   %a1@(LSERDATR),%d7
1113         andw    #0x2000,%d7
1114         jeq     1b
1115         jra     9f
1116 2:      cmpil   #MACH_ATARI,%d4
1117         jne     9f
1118         movel   %pc@(Liobase),%a1
1119 #ifdef USE_PRINTER
1120 3:      btst    #0,%a1@(LSTMFP_GPIP)
1121         jne     3b
1122         moveb   #LPSG_IO_B,%a1@(LPSG_SELECT)
1123         moveb   %d7,%a1@(LPSG_WRITE)
1124         moveb   #LPSG_IO_A,%a1@(LPSG_SELECT)
1125         moveb   %a1@(LPSG_READ),%d7
1126         bclr    #5,%d7
1127         moveb   %d7,%a1@(LPSG_WRITE)
1128         nop
1129         nop
1130         bset    #5,%d7
1131         moveb   %d7,%a1@(LPSG_WRITE)
1132 #elif defined(USE_SCC)
1133 3:      btst    #2,%a1@(LSCC_CTRL_B)
1134         jeq     3b
1135         moveb   %d7,%a1@(LSCC_DATA_B)
1136 #elif defined(USE_MFP)
1137 3:      btst    #7,%a1@(LMFP_TSR)
1138         jeq     3b
1139         moveb   %d7,%a1@(LMFP_UDR)
1140 #endif
1141 9:
1142         moveml  %sp@+,%a0/%a1
1143         rts
1144 
1145 /*
1146  * Output string pointed to by a0 to serial port.
1147  * a0 trashed.
1148  */
1149 Lserial_puts:
1150         movel   %d7,%sp@-
1151 1:      moveb   %a0@+,%d7
1152         jeq     2f
1153         jbsr    Lserial_putc
1154         jra     1b
1155 2:      movel   %sp@+,%d7
1156         rts
1157 
1158 /*
1159  * Output number in d7 in hex notation on serial port.
1160  * d0-d2 trashed.
1161  * d7 trashed.
1162  */
1163 
1164 Lserial_putnum:
1165         moveml  %d0-%d2/%d7,%sp@-
1166         movel   %d7,%d1
1167         moveq   #4,%d0
1168         moveq   #7,%d2
1169 L1:     roll    %d0,%d1
1170         moveb   %d1,%d7
1171         andb    #0x0f,%d7
1172         cmpb    #0x0a,%d7
1173         bccs    1f
1174         addb    #'0',%d7
1175         jra     2f
1176 1:      addb    #'A'-10,%d7
1177 2:      jbsr    Lserial_putc
1178         dbra    %d2,L1
1179         moveq   #32,%d7
1180         jbsr    Lserial_putc
1181         moveml  %sp@+,%d0-%d2/%d7
1182         rts
1183 #if 0
1184 .globl showtest
1185 showtest:
1186         moveml  %a1/%d7,%sp@-
1187         moveq   #'A',%d7
1188         jbsr    Lserial_putc
1189         moveq   #'=',%d7
1190         jbsr    Lserial_putc
1191         movel   %a0,%d7
1192         jbsr    Lserial_putnum
1193 
1194         ptestr  #5,%a0@,#7,%a1
1195 
1196         moveq   #'D',%d7
1197         jbsr    Lserial_putc
1198         moveq   #'A',%d7
1199         jbsr    Lserial_putc
1200         moveq   #'=',%d7
1201         jbsr    Lserial_putc
1202 
1203         movel   %a1,%d7
1204         jbsr    Lserial_putnum
1205 
1206         moveq   #'D',%d7
1207         jbsr    Lserial_putc
1208         moveq   #'=',%d7
1209         jbsr    Lserial_putc
1210         movel   %a1@,%d7
1211         jbsr    Lserial_putnum
1212 
1213         moveq   #'S',%d7
1214         jbsr    Lserial_putc
1215         moveq   #'=',%d7
1216         jbsr    Lserial_putc
1217 
1218         lea     %pc@(mmu),%a1
1219         pmove   %psr,%a1@
1220         clrl    %d7
1221         movew   %a1@,%d7
1222         jbsr    Lserial_putnum
1223 
1224         moveq   #CR,%d7
1225         jbsr    Lserial_putc
1226         moveq   #LF,%d7
1227         jbsr    Lserial_putc
1228 
1229         moveml  %sp@+,%a1/%d7
1230         rts
1231 #endif
1232 
1233 #ifdef __ELF__
1234         .align 512
1235 #else
1236         .align 9
1237 #endif                  /*
1238                          * MMU root-pointers need to be 512-byte
1239                          * aligned on the 680[46]0 - Jes
1240                          */
1241 
1242 SYMBOL_NAME_LABEL(swapper_pg_dir)
1243         .skip ROOT_TABLE_SIZE * 4
1244 SYMBOL_NAME_LABEL(kernel_pg_dir)
1245         .skip ROOT_TABLE_SIZE * 4
1246 
1247         .data
1248         .even
1249 Lcustom:
1250         .long 0
1251 Liobase:
1252         .long 0
1253 mmu:    .quad 0
1254 SYMBOL_NAME_LABEL(kernel_pmd_table)
1255         .long 0
1256 SYMBOL_NAME_LABEL(kpt)
1257         .long 0
1258 SYMBOL_NAME_LABEL(availmem)
1259         .long 0
1260 SYMBOL_NAME_LABEL(is_medusa)
1261         .long 0
1262 SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
1263         .long 0

/* [previous][next][first][last][top][bottom][index][help] */