home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / sparc / kernel / head.S < prev    next >
Encoding:
Text File  |  1995-03-06  |  39.1 KB  |  1,046 lines

  1. /* boot.S: The initial boot code for the Sparc port of Linux.
  2.  
  3.    Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  4.  
  5.            This file has to serve three purposes.
  6.  
  7.        1) determine the prom-version and cpu/architecture
  8.        2) print enough useful info before we start to execute
  9.           c-code that I can possibly begin to debug things
  10.        3) Hold the vector of trap entry points
  11.  
  12.    The Sparc offers many challenges to kernel design. Here I will
  13.    document those I have come across thus far. Upon bootup the boot
  14.    prom loads your a.out image into memory. This memory the prom has
  15.    already mapped for you in two places, however as far as I can tell
  16.    the virtual address cache is not turned on although the MMU is
  17.    translating things. You get loaded at 0x4000 exactly and you are
  18.    aliased to 0xf8004000 with the appropriate mmu entries. So, when
  19.    you link a boot-loadable object you want to do something like:
  20.  
  21.         ld -e start -Ttext 4000 -o mykernel myobj1.o myobj2.o ....
  22.  
  23.    to produce a proper image.
  24.  
  25.    At boot time you are given (as far as I can tell at this time)
  26.    one key to figure out what machine you are one and what devices
  27.    are available. The prom when it loads you leaves a pointer to
  28.    the 'rom vector' in register %o0 right before it jumps to your
  29.    starting address. This is a pointer to a struct that is full of
  30.    pointer to functions (ie. printf, halt, reboot), pointers to
  31.    linked lists (ie. memory mappings), and pointer to empirical
  32.    constants (ie. stdin and stdout magic cookies + rom version).
  33.    Starting with this piece of information you can figure out 
  34.    just about anything you want about the machine you are on.
  35.  
  36.    Although I don't use it now, if you are on a Multiprocessor and
  37.    therefore a v3 or above prom, register %o2 at boot contains a
  38.    function pointer you must call before you proceed to invoke the
  39.    other cpu's on the machine. I have no idea what kind of magic this
  40.    is, give me time.
  41. */
  42.  
  43. #include <asm/cprefix.h>
  44. #include <asm/head.h>
  45. #include <asm/version.h>
  46. #include <asm/asi.h>
  47. #include <asm/contregs.h>
  48. #include <asm/psr.h>
  49. #include <asm/page.h>
  50.  
  51.     .data
  52.  
  53. /* First thing to go in the data segment is the interrupt stack. */
  54.  
  55.         .globl  C_LABEL(intstack)
  56.         .globl  C_LABEL(eintstack)
  57. C_LABEL(intstack):
  58.         .skip   4 * PAGE_SIZE                ! 16k = 128 128-byte stack frames
  59. C_LABEL(eintstack):
  60.  
  61.  
  62.  
  63. /* 
  64.    The following are used with the prom_vector node-ops to figure out
  65.    the cpu-type 
  66. */
  67.  
  68.         .globl  C_LABEL(cputyp)
  69.  
  70. C_LABEL(cputyp):
  71.         .word   1
  72.  
  73. C_LABEL(cputypval):
  74.     .asciz "sun4c"
  75.     .ascii "     "
  76.  
  77.     .align 4
  78. /*
  79.  * Sun people can't spell worth damn. "compatability" indeed.
  80.  * At least we *know* we can't spell, and use a spell-checker.
  81.  */
  82.  
  83. /* Uh, actually Linus it is I who cannot spell. Too much murky
  84.  * Sparc assembly will do this to ya.
  85.  */
  86. C_LABEL(cputypvar):
  87.     .asciz "compatability"
  88.  
  89. C_LABEL(cputypvallen) = C_LABEL(cputypvar) - C_LABEL(cputypval)
  90.  
  91. /* This hold the prom-interface-version number for either v0 or v2. */
  92.  
  93.     .align 4
  94.     .globl     C_LABEL(prom_iface_vers)
  95.  
  96. C_LABEL(prom_iface_vers):    .skip 4
  97.  
  98. /* WARNING: evil messages follow */
  99.  
  100.     .align 4
  101.  
  102. sun4_notsup:
  103.     .asciz  "Sparc-Linux: sun4 support not implemented yet\n\n"
  104.     .align 4
  105.  
  106. sun4m_notsup:
  107.         .asciz  "Sparc-Linux: sun4m support does not exist\n\n"
  108.     .align 4
  109.  
  110. sun4d_notsup:
  111.         .asciz  "Sparc-Linux: sun4d support does not exist\n\n"
  112.     .align 4
  113.  
  114. you_lose:
  115.     .asciz    "You lose..... Thanks for playing...\n"
  116.     .align 4
  117.  
  118.  
  119.     .globl boot_msg
  120.  
  121. /* memory descriptor property strings, v2 = yuk yuk yuk  */
  122. /* XXX how to figure out vm mapped by prom? May have to scan magic addresses */
  123.  
  124. mem_prop_physavail:    .asciz "available"
  125.     
  126.             .align 4
  127. mem_prop_phystot:    .asciz "reg"
  128.  
  129. /* v2_memory descriptor struct kludged here for assembly, if it ain't broke */
  130.  
  131.         .align 4
  132. v2_mem_struct:     .skip 0xff
  133.  
  134.             .align 4
  135. v2_printf_physavail:    .asciz "Physical Memory Available: 0x%x bytes"
  136.     
  137.             .align 4
  138. v2_printf_phystot:    .asciz "Physical Memory: 0x%x bytes"
  139.  
  140. /* A place to store property strings returned from the prom 'node' funcs */
  141.  
  142.             .align 4
  143. prop_string_buf:    .skip 32
  144.  
  145.         .align 4
  146. prop_name:    .asciz "name"
  147.     
  148.         .align 4
  149. current_node:    .skip 4
  150.  
  151.  
  152. /* nice little boot message */
  153.  
  154.         .align 4
  155. boot_msg:    
  156.     .ascii "Booting Sparc-Linux V0.00PRE-ALPHA "
  157.     .ascii WHO_COMPILED_ME 
  158.     .ascii "\r\n"
  159.     .align 4
  160.  
  161.     .globl boot_msg2
  162.  
  163. boot_msg2:
  164.     .asciz "Booting Sparclinux V0.00 PRE-ALPHA on a (SUN4C)\r\n\n"
  165.  
  166.     .align 4
  167.  
  168. pstring1:
  169.     .asciz "Prom Magic Cookie: 0x%x  \n"
  170.     .align 4
  171.  
  172. pstring2:
  173.     .asciz "Interface Version: v%d\n"
  174.     .align 4
  175.  
  176. pstring3:
  177.     .asciz "Prom Revision: V%d\n\n"
  178.     .align 4
  179.  
  180. pstring4:
  181.     .ascii "Total Physical Memory: %d bytes\nVM mapped by Prom: %d bytes\n"
  182.     .asciz "Available Physical Memory: %d bytes\n"
  183.     .align 4
  184.  
  185.  
  186.     .text
  187.  
  188.         .globl  C_LABEL(msgbuf)
  189. msgbufsize = PAGE_SIZE                       ! 1 page for msg buffer
  190. C_LABEL(msgbuf) =  PAGE_SIZE
  191.  
  192.  
  193. IE_reg_addr = C_LABEL(msgbuf) + msgbufsize   ! this page not used; points to IEreg
  194.  
  195.     
  196. /* Ok, things start to get interesting. We get linked such that 'start'
  197.    is the entry symbol. However, it is real low in kernel address space
  198.    and as such a nifty place to place the trap table. We achieve this goal
  199.    by just jumping to 'gokernel' for the first trap's entry as the sparc
  200.    never receives the zero trap as it is real special (hw reset).
  201.  
  202.    Each trap entry point is the size of 4 sparc instructions (or 4 bytes
  203.    * 4 insns = 16 bytes). There are 128 hardware traps (some undefined
  204.    or unimplemented) and 128 software traps (sys-calls, etc.).
  205.  
  206.    One of the instructions must be a branch. More often than not this
  207.    will be to a trap handler entry point because it is completely
  208.    impossible to handle any trap in 4 insns. I welcome anyone to 
  209.    challenge this theory. :-)
  210.  
  211.    On entry into this table the hardware has loaded the program counter
  212.    at which the trap occurred into register %l1 and the next program
  213.    counter into %l2, this way we can return from the trap with a simple
  214.  
  215.            jmp %l1; rett %l2  ! poof...
  216.  
  217.    after properly servicing the trap. It wouldn't be a bad idea to load
  218.    some more information into the local regs since we have technically
  219.    2 or 3 instructions to play with besides the jmp to the 'real' trap
  220.    handler (one can even go in the delay slot). For now I am going to put
  221.    the %psr (processor status register) and the trap-type value in %l0
  222.    and %l3 respectively. Also, for IRQ's I'll put the level in %l4.
  223.  
  224. */
  225.  
  226.     .globl    start
  227.     .globl     _start  /* warning, solaris hack */
  228.     .globl  C_LABEL(trapbase)
  229. _start:   /* danger danger */
  230. start:
  231. C_LABEL(trapbase):
  232.     b gokernel; nop; nop; nop;    ! we never get trap #0 it is special 
  233.  
  234.     TRAP_ENTRY(0x1, my_trap_handler) /* Instruction Access Exception */
  235.     TRAP_ENTRY(0x2, my_trap_handler) /* Illegal Instruction */
  236.     TRAP_ENTRY(0x3, my_trap_handler) /* Privileged Instruction */
  237.     TRAP_ENTRY(0x4, my_trap_handler) /* Floating Point Disabled */
  238.     TRAP_ENTRY(0x5, spill_window_entry)   /* Window Overflow */
  239.     TRAP_ENTRY(0x6, fill_window_entry)  /* Window Underflow */
  240.     TRAP_ENTRY(0x7, my_trap_handler) /* Memory Address Not Aligned */
  241.     TRAP_ENTRY(0x8, my_trap_handler) /* Floating Point Exception */
  242.     TRAP_ENTRY(0x9, my_trap_handler) /* Data Miss Exception */
  243.     TRAP_ENTRY(0xa, my_trap_handler) /* Tagged Instruction Overflow */
  244.     TRAP_ENTRY(0xb, my_trap_handler) /* Watchpoint Detected */
  245.     TRAP_ENTRY(0xc, my_trap_handler) /* Undefined... */
  246.     TRAP_ENTRY(0xd, my_trap_handler) /* Undefined... */
  247.     TRAP_ENTRY(0xe, my_trap_handler) /* Undefined... */
  248.     TRAP_ENTRY(0xf, my_trap_handler) /* Undefined... */
  249.     TRAP_ENTRY(0x10, my_trap_handler) /* Undefined... */
  250.  
  251. /* Level'd interrupt entry points, see macro defs above */
  252.  
  253.         TRAP_ENTRY_INTERRUPT_SOFT(1, 0x101) /* IRQ Software/SBUS Level 1  */
  254.         TRAP_ENTRY_INTERRUPT(2)             /* IRQ SBUS Level 2           */
  255.         TRAP_ENTRY_INTERRUPT(3)             /* IRQ SCSI/DMA/SBUS Level 3  */
  256.         TRAP_ENTRY_INTERRUPT_SOFT(4, 0x104) /* IRQ Software Level 4       */
  257.         TRAP_ENTRY_INTERRUPT(5)             /* IRQ SBUS/Ethernet Level 5  */
  258.         TRAP_ENTRY_INTERRUPT_SOFT(6, 0x106) /* IRQ Software Level 6       */
  259.         TRAP_ENTRY_INTERRUPT(7)             /* IRQ Video/SBUS Level 5     */
  260.         TRAP_ENTRY_INTERRUPT(8)             /* IRQ SBUS Level 6           */
  261.         TRAP_ENTRY_INTERRUPT(9)             /* IRQ SBUS Level 7           */
  262.         TRAP_ENTRY_INTERRUPT(10)            /* IRQ Timer #1               */
  263.         TRAP_ENTRY_INTERRUPT(11)            /* IRQ Floppy Intr.           */
  264.         TRAP_ENTRY_INTERRUPT(12)            /* IRQ Zilog serial chip      */
  265.         TRAP_ENTRY_INTERRUPT(13)            /* IRQ Audio Intr.            */
  266.         TRAP_ENTRY_TIMER                    /* IRQ Timer #2 (one we use)  */
  267.         TRAP_ENTRY_INTERRUPT_NMI(15, linux_trap_nmi) /* Level 15 (nmi) */
  268.  
  269.     TRAP_ENTRY(0x20, my_trap_handler)   /* General Register Access Error */
  270.     TRAP_ENTRY(0x21, my_trap_handler)   /* Instruction Access Error      */
  271.     TRAP_ENTRY(0x22, my_trap_handler)   /* Undefined...                  */
  272.     TRAP_ENTRY(0x23, my_trap_handler)   /* Undefined...                  */
  273.     TRAP_ENTRY(0x24, my_trap_handler)   /* Co-Processor Disabled         */
  274.     TRAP_ENTRY(0x25, my_trap_handler)   /* Unimplemented FLUSH inst.     */
  275.     TRAP_ENTRY(0x26, my_trap_handler)   /* Undefined...                  */
  276.     TRAP_ENTRY(0x27, my_trap_handler)   /* Undefined...                  */
  277.     TRAP_ENTRY(0x28, my_trap_handler)   /* Co-Processor Exception        */
  278.     TRAP_ENTRY(0x29, my_trap_handler)   /* Data Access Error             */
  279.     TRAP_ENTRY(0x2a, my_trap_handler)   /* Division by zero, you lose... */
  280.     TRAP_ENTRY(0x2b, my_trap_handler)   /* Data Store Error              */
  281.     TRAP_ENTRY(0x2c, my_trap_handler)   /* Data Access MMU-Miss          */
  282.     TRAP_ENTRY(0x2d, my_trap_handler)   /* Undefined...                  */
  283.     TRAP_ENTRY(0x2e, my_trap_handler)   /* Undefined...                  */
  284.     TRAP_ENTRY(0x2f, my_trap_handler)   /* Undefined...                  */
  285.     TRAP_ENTRY(0x30, my_trap_handler)   /* Undefined...                  */
  286.     TRAP_ENTRY(0x31, my_trap_handler)   /* Undefined...                  */
  287.     TRAP_ENTRY(0x32, my_trap_handler)   /* Undefined...                  */
  288.     TRAP_ENTRY(0x33, my_trap_handler)   /* Undefined...                  */
  289.     TRAP_ENTRY(0x34, my_trap_handler)   /* Undefined...                  */
  290.     TRAP_ENTRY(0x35, my_trap_handler)   /* Undefined...                  */
  291.     TRAP_ENTRY(0x36, my_trap_handler)   /* Undefined...                  */
  292.     TRAP_ENTRY(0x37, my_trap_handler)   /* Undefined...                  */
  293.     TRAP_ENTRY(0x38, my_trap_handler)   /* Undefined...                  */
  294.     TRAP_ENTRY(0x39, my_trap_handler)   /* Undefined...                  */
  295.     TRAP_ENTRY(0x3a, my_trap_handler)   /* Undefined...                  */
  296.     TRAP_ENTRY(0x3b, my_trap_handler)   /* Undefined...                  */
  297.     TRAP_ENTRY(0x3c, my_trap_handler)   /* Instruction Access MMU-Miss   */
  298.     TRAP_ENTRY(0x3d, my_trap_handler)   /* Undefined...                  */
  299.     TRAP_ENTRY(0x3e, my_trap_handler)   /* Undefined...                  */
  300.     TRAP_ENTRY(0x3f, my_trap_handler)   /* Undefined...                  */
  301.     TRAP_ENTRY(0x40, my_trap_handler)   /* Undefined...                  */
  302.     TRAP_ENTRY(0x41, my_trap_handler)   /* Undefined...                  */
  303.     TRAP_ENTRY(0x42, my_trap_handler)   /* Undefined...                  */
  304.     TRAP_ENTRY(0x43, my_trap_handler)   /* Undefined...                  */
  305.     TRAP_ENTRY(0x44, my_trap_handler)   /* Undefined...                  */
  306.     TRAP_ENTRY(0x45, my_trap_handler)   /* Undefined...                  */
  307.     TRAP_ENTRY(0x46, my_trap_handler)   /* Undefined...                  */
  308.     TRAP_ENTRY(0x47, my_trap_handler)   /* Undefined...                  */
  309.     TRAP_ENTRY(0x48, my_trap_handler)   /* Undefined...                  */
  310.     TRAP_ENTRY(0x49, my_trap_handler)   /* Undefined...                  */
  311.     TRAP_ENTRY(0x4a, my_trap_handler)   /* Undefined...                  */
  312.     TRAP_ENTRY(0x4b, my_trap_handler)   /* Undefined...                  */
  313.     TRAP_ENTRY(0x4c, my_trap_handler)   /* Undefined...                  */
  314.     TRAP_ENTRY(0x4d, my_trap_handler)   /* Undefined...                  */
  315.     TRAP_ENTRY(0x4e, my_trap_handler)   /* Undefined...                  */
  316.     TRAP_ENTRY(0x4f, my_trap_handler)   /* Undefined...                  */
  317.     TRAP_ENTRY(0x50, my_trap_handler)   /* Undefined...                  */
  318.     TRAP_ENTRY(0x51, my_trap_handler)   /* Undefined...                  */
  319.     TRAP_ENTRY(0x52, my_trap_handler)   /* Undefined...                  */
  320.     TRAP_ENTRY(0x53, my_trap_handler)   /* Undefined...                  */
  321.     TRAP_ENTRY(0x54, my_trap_handler)   /* Undefined...                  */
  322.     TRAP_ENTRY(0x55, my_trap_handler)   /* Undefined...                  */
  323.     TRAP_ENTRY(0x56, my_trap_handler)   /* Undefined...                  */
  324.     TRAP_ENTRY(0x57, my_trap_handler)   /* Undefined...                  */
  325.     TRAP_ENTRY(0x58, my_trap_handler)   /* Undefined...                  */
  326.     TRAP_ENTRY(0x59, my_trap_handler)   /* Undefined...                  */
  327.     TRAP_ENTRY(0x5a, my_trap_handler)   /* Undefined...                  */
  328.     TRAP_ENTRY(0x5b, my_trap_handler)   /* Undefined...                  */
  329.     TRAP_ENTRY(0x5c, my_trap_handler)   /* Undefined...                  */
  330.     TRAP_ENTRY(0x5d, my_trap_handler)   /* Undefined...                  */
  331.     TRAP_ENTRY(0x5e, my_trap_handler)   /* Undefined...                  */
  332.     TRAP_ENTRY(0x5f, my_trap_handler)   /* Undefined...                  */
  333.     TRAP_ENTRY(0x60, my_trap_handler)   /* Impl-Dep Exception            */
  334.     TRAP_ENTRY(0x61, my_trap_handler)   /* Impl-Dep Exception            */
  335.     TRAP_ENTRY(0x62, my_trap_handler)   /* Impl-Dep Exception            */
  336.     TRAP_ENTRY(0x63, my_trap_handler)   /* Impl-Dep Exception            */
  337.     TRAP_ENTRY(0x64, my_trap_handler)   /* Impl-Dep Exception            */
  338.     TRAP_ENTRY(0x65, my_trap_handler)   /* Impl-Dep Exception            */
  339.     TRAP_ENTRY(0x66, my_trap_handler)   /* Impl-Dep Exception            */
  340.     TRAP_ENTRY(0x67, my_trap_handler)   /* Impl-Dep Exception            */
  341.     TRAP_ENTRY(0x68, my_trap_handler)   /* Impl-Dep Exception            */
  342.     TRAP_ENTRY(0x69, my_trap_handler)   /* Impl-Dep Exception            */
  343.     TRAP_ENTRY(0x6a, my_trap_handler)   /* Impl-Dep Exception            */
  344.     TRAP_ENTRY(0x6b, my_trap_handler)   /* Impl-Dep Exception            */
  345.     TRAP_ENTRY(0x6c, my_trap_handler)   /* Impl-Dep Exception            */
  346.     TRAP_ENTRY(0x6d, my_trap_handler)   /* Impl-Dep Exception            */
  347.     TRAP_ENTRY(0x6e, my_trap_handler)   /* Impl-Dep Exception            */
  348.     TRAP_ENTRY(0x6f, my_trap_handler)   /* Impl-Dep Exception            */
  349.     TRAP_ENTRY(0x70, my_trap_handler)   /* Impl-Dep Exception            */
  350.     TRAP_ENTRY(0x71, my_trap_handler)   /* Impl-Dep Exception            */
  351.     TRAP_ENTRY(0x72, my_trap_handler)   /* Impl-Dep Exception            */
  352.     TRAP_ENTRY(0x73, my_trap_handler)   /* Impl-Dep Exception            */
  353.     TRAP_ENTRY(0x74, my_trap_handler)   /* Impl-Dep Exception            */
  354.     TRAP_ENTRY(0x75, my_trap_handler)   /* Impl-Dep Exception            */
  355.     TRAP_ENTRY(0x76, my_trap_handler)   /* Impl-Dep Exception            */
  356.     TRAP_ENTRY(0x77, my_trap_handler)   /* Impl-Dep Exception            */
  357.     TRAP_ENTRY(0x78, my_trap_handler)   /* Impl-Dep Exception            */
  358.     TRAP_ENTRY(0x79, my_trap_handler)   /* Impl-Dep Exception            */
  359.     TRAP_ENTRY(0x7a, my_trap_handler)   /* Impl-Dep Exception            */
  360.     TRAP_ENTRY(0x7b, my_trap_handler)   /* Impl-Dep Exception            */
  361.     TRAP_ENTRY(0x7c, my_trap_handler)   /* Impl-Dep Exception            */
  362.     TRAP_ENTRY(0x7d, my_trap_handler)   /* Impl-Dep Exception            */
  363.     TRAP_ENTRY(0x7e, my_trap_handler)   /* Impl-Dep Exception            */
  364.     TRAP_ENTRY(0x7f, my_trap_handler)   /* Impl-Dep Exception            */
  365.     TRAP_ENTRY(0x80, my_trap_handler)   /* SunOS System Call             */
  366.     TRAP_ENTRY(0x81, my_trap_handler)   /* Software Trap                 */
  367.     TRAP_ENTRY(0x82, my_trap_handler)   /* Divide by zero trap XXX       */
  368.     TRAP_ENTRY(0x83, my_trap_handler)   /* Flush Windows Trap XXX        */
  369.     TRAP_ENTRY(0x84, my_trap_handler)   /* Clean Windows Trap XXX        */
  370.     TRAP_ENTRY(0x85, my_trap_handler)   /* Software Trap                 */
  371.     TRAP_ENTRY(0x86, my_trap_handler)   /* Fix Unaligned Access Trap XXX */
  372.     TRAP_ENTRY(0x87, my_trap_handler)   /* Integer Overflow Trap XXX     */
  373.     TRAP_ENTRY(0x88, my_trap_handler)   /* Slowaris System Call          */
  374.     TRAP_ENTRY(0x89, my_trap_handler)   /* NetBSD System Call            */
  375.     TRAP_ENTRY(0x8a, my_trap_handler)   /* Software Trap                 */
  376.     TRAP_ENTRY(0x8b, my_trap_handler)   /* Software Trap                 */
  377.     TRAP_ENTRY(0x8c, my_trap_handler)   /* Software Trap                 */
  378.     TRAP_ENTRY(0x8d, my_trap_handler)   /* Software Trap                 */
  379.     TRAP_ENTRY(0x8e, my_trap_handler)   /* Software Trap                 */
  380.     TRAP_ENTRY(0x8f, my_trap_handler)   /* Software Trap                 */
  381.     TRAP_ENTRY(0x90, my_trap_handler)   /* SparcLinux System Call        */
  382.     TRAP_ENTRY(0x91, my_trap_handler)   /* Software Trap                 */
  383.     TRAP_ENTRY(0x92, my_trap_handler)   /* Software Trap                 */
  384.     TRAP_ENTRY(0x93, my_trap_handler)   /* Software Trap                 */
  385.     TRAP_ENTRY(0x94, my_trap_handler)   /* Software Trap                 */
  386.     TRAP_ENTRY(0x95, my_trap_handler)   /* Software Trap                 */
  387.     TRAP_ENTRY(0x96, my_trap_handler)   /* Software Trap                 */
  388.     TRAP_ENTRY(0x97, my_trap_handler)   /* Software Trap                 */
  389.     TRAP_ENTRY(0x98, my_trap_handler)   /* Software Trap                 */
  390.     TRAP_ENTRY(0x99, my_trap_handler)   /* Software Trap                 */
  391.     TRAP_ENTRY(0x9a, my_trap_handler)   /* Software Trap                 */
  392.     TRAP_ENTRY(0x9b, my_trap_handler)   /* Software Trap                 */
  393.     TRAP_ENTRY(0x9c, my_trap_handler)   /* Software Trap                 */
  394.     TRAP_ENTRY(0x9d, my_trap_handler)   /* Software Trap                 */
  395.     TRAP_ENTRY(0x9e, my_trap_handler)   /* Software Trap                 */
  396.     TRAP_ENTRY(0x9f, my_trap_handler)   /* Software Trap                 */
  397.     TRAP_ENTRY(0xa0, my_trap_handler)   /* Software Trap                 */
  398.     TRAP_ENTRY(0xa1, my_trap_handler)   /* Software Trap                 */
  399.     TRAP_ENTRY(0xa2, my_trap_handler)   /* Software Trap                 */
  400.     TRAP_ENTRY(0xa3, my_trap_handler)   /* Software Trap                 */
  401.     TRAP_ENTRY(0xa4, my_trap_handler)   /* Software Trap                 */
  402.     TRAP_ENTRY(0xa5, my_trap_handler)   /* Software Trap                 */
  403.     TRAP_ENTRY(0xa6, my_trap_handler)   /* Software Trap                 */
  404.     TRAP_ENTRY(0xa7, my_trap_handler)   /* Software Trap                 */
  405.     TRAP_ENTRY(0xa8, my_trap_handler)   /* Software Trap                 */
  406.     TRAP_ENTRY(0xa9, my_trap_handler)   /* Software Trap                 */
  407.     TRAP_ENTRY(0xaa, my_trap_handler)   /* Software Trap                 */
  408.     TRAP_ENTRY(0xab, my_trap_handler)   /* Software Trap                 */
  409.     TRAP_ENTRY(0xac, my_trap_handler)   /* Software Trap                 */
  410.     TRAP_ENTRY(0xad, my_trap_handler)   /* Software Trap                 */
  411.     TRAP_ENTRY(0xae, my_trap_handler)   /* Software Trap                 */
  412.     TRAP_ENTRY(0xaf, my_trap_handler)   /* Software Trap                 */
  413.     TRAP_ENTRY(0xb0, my_trap_handler)   /* Software Trap                 */
  414.     TRAP_ENTRY(0xb1, my_trap_handler)   /* Software Trap                 */
  415.     TRAP_ENTRY(0xb2, my_trap_handler)   /* Software Trap                 */
  416.     TRAP_ENTRY(0xb3, my_trap_handler)   /* Software Trap                 */
  417.     TRAP_ENTRY(0xb4, my_trap_handler)   /* Software Trap                 */
  418.     TRAP_ENTRY(0xb5, my_trap_handler)   /* Software Trap                 */
  419.     TRAP_ENTRY(0xb6, my_trap_handler)   /* Software Trap                 */
  420.     TRAP_ENTRY(0xb7, my_trap_handler)   /* Software Trap                 */
  421.     TRAP_ENTRY(0xb8, my_trap_handler)   /* Software Trap                 */
  422.     TRAP_ENTRY(0xb9, my_trap_handler)   /* Software Trap                 */
  423.     TRAP_ENTRY(0xba, my_trap_handler)   /* Software Trap                 */
  424.     TRAP_ENTRY(0xbb, my_trap_handler)   /* Software Trap                 */
  425.     TRAP_ENTRY(0xbc, my_trap_handler)   /* Software Trap                 */
  426.     TRAP_ENTRY(0xbd, my_trap_handler)   /* Software Trap                 */
  427.     TRAP_ENTRY(0xbe, my_trap_handler)   /* Software Trap                 */
  428.     TRAP_ENTRY(0xbf, my_trap_handler)   /* Software Trap                 */
  429.     TRAP_ENTRY(0xc0, my_trap_handler)   /* Software Trap                 */
  430.     TRAP_ENTRY(0xc1, my_trap_handler)   /* Software Trap                 */
  431.     TRAP_ENTRY(0xc2, my_trap_handler)   /* Software Trap                 */
  432.     TRAP_ENTRY(0xc3, my_trap_handler)   /* Software Trap                 */
  433.     TRAP_ENTRY(0xc4, my_trap_handler)   /* Software Trap                 */
  434.     TRAP_ENTRY(0xc5, my_trap_handler)   /* Software Trap                 */
  435.     TRAP_ENTRY(0xc6, my_trap_handler)   /* Software Trap                 */
  436.     TRAP_ENTRY(0xc7, my_trap_handler)   /* Software Trap                 */
  437.     TRAP_ENTRY(0xc8, my_trap_handler)   /* Software Trap                 */
  438.     TRAP_ENTRY(0xc9, my_trap_handler)   /* Software Trap                 */
  439.     TRAP_ENTRY(0xca, my_trap_handler)   /* Software Trap                 */
  440.     TRAP_ENTRY(0xcb, my_trap_handler)   /* Software Trap                 */
  441.     TRAP_ENTRY(0xcc, my_trap_handler)   /* Software Trap                 */
  442.     TRAP_ENTRY(0xcd, my_trap_handler)   /* Software Trap                 */
  443.     TRAP_ENTRY(0xce, my_trap_handler)   /* Software Trap                 */
  444.     TRAP_ENTRY(0xcf, my_trap_handler)   /* Software Trap                 */
  445.     TRAP_ENTRY(0xd0, my_trap_handler)   /* Software Trap                 */
  446.     TRAP_ENTRY(0xd1, my_trap_handler)   /* Software Trap                 */
  447.     TRAP_ENTRY(0xd2, my_trap_handler)   /* Software Trap                 */
  448.     TRAP_ENTRY(0xd3, my_trap_handler)   /* Software Trap                 */
  449.     TRAP_ENTRY(0xd4, my_trap_handler)   /* Software Trap                 */
  450.     TRAP_ENTRY(0xd5, my_trap_handler)   /* Software Trap                 */
  451.     TRAP_ENTRY(0xd6, my_trap_handler)   /* Software Trap                 */
  452.     TRAP_ENTRY(0xd7, my_trap_handler)   /* Software Trap                 */
  453.     TRAP_ENTRY(0xd8, my_trap_handler)   /* Software Trap                 */
  454.     TRAP_ENTRY(0xd9, my_trap_handler)   /* Software Trap                 */
  455.     TRAP_ENTRY(0xda, my_trap_handler)   /* Software Trap                 */
  456.     TRAP_ENTRY(0xdb, my_trap_handler)   /* Software Trap                 */
  457.     TRAP_ENTRY(0xdc, my_trap_handler)   /* Software Trap                 */
  458.     TRAP_ENTRY(0xdd, my_trap_handler)   /* Software Trap                 */
  459.     TRAP_ENTRY(0xde, my_trap_handler)   /* Software Trap                 */
  460.     TRAP_ENTRY(0xdf, my_trap_handler)   /* Software Trap                 */
  461.     TRAP_ENTRY(0xe0, my_trap_handler)   /* Software Trap                 */
  462.     TRAP_ENTRY(0xe1, my_trap_handler)   /* Software Trap                 */
  463.     TRAP_ENTRY(0xe2, my_trap_handler)   /* Software Trap                 */
  464.     TRAP_ENTRY(0xe3, my_trap_handler)   /* Software Trap                 */
  465.     TRAP_ENTRY(0xe4, my_trap_handler)   /* Software Trap                 */
  466.     TRAP_ENTRY(0xe5, my_trap_handler)   /* Software Trap                 */
  467.     TRAP_ENTRY(0xe6, my_trap_handler)   /* Software Trap                 */
  468.     TRAP_ENTRY(0xe7, my_trap_handler)   /* Software Trap                 */
  469.     TRAP_ENTRY(0xe8, my_trap_handler)   /* Software Trap                 */
  470.     TRAP_ENTRY(0xe9, my_trap_handler)   /* Software Trap                 */
  471.     TRAP_ENTRY(0xea, my_trap_handler)   /* Software Trap                 */
  472.     TRAP_ENTRY(0xeb, my_trap_handler)   /* Software Trap                 */
  473.     TRAP_ENTRY(0xec, my_trap_handler)   /* Software Trap                 */
  474.     TRAP_ENTRY(0xed, my_trap_handler)   /* Software Trap                 */
  475.     TRAP_ENTRY(0xee, my_trap_handler)   /* Software Trap                 */
  476.     TRAP_ENTRY(0xef, my_trap_handler)   /* Software Trap                 */
  477.     TRAP_ENTRY(0xf0, my_trap_handler)   /* Software Trap                 */
  478.     TRAP_ENTRY(0xf1, my_trap_handler)   /* Software Trap                 */
  479.     TRAP_ENTRY(0xf2, my_trap_handler)   /* Software Trap                 */
  480.     TRAP_ENTRY(0xf3, my_trap_handler)   /* Software Trap                 */
  481.     TRAP_ENTRY(0xf4, my_trap_handler)   /* Software Trap                 */
  482.     TRAP_ENTRY(0xf5, my_trap_handler)   /* Software Trap                 */
  483.     TRAP_ENTRY(0xf6, my_trap_handler)   /* Software Trap                 */
  484.     TRAP_ENTRY(0xf7, my_trap_handler)   /* Software Trap                 */
  485.     TRAP_ENTRY(0xf8, my_trap_handler)   /* Software Trap                 */
  486.     TRAP_ENTRY(0xf9, my_trap_handler)   /* Software Trap                 */
  487.     TRAP_ENTRY(0xfa, my_trap_handler)   /* Software Trap                 */
  488.     TRAP_ENTRY(0xfb, my_trap_handler)   /* Software Trap                 */
  489.     TRAP_ENTRY(0xfc, my_trap_handler)   /* Software Trap                 */
  490.     TRAP_ENTRY(0xfd, my_trap_handler)   /* Software Trap                 */
  491.     TRAP_ENTRY(0xfe, my_trap_handler)   /* Software Trap                 */
  492.     TRAP_ENTRY(0xff, my_trap_handler)   /* Software Trap                 */    
  493.  
  494.     .skip 4096
  495.  
  496. C_LABEL(msgbufmapped):
  497.         .word   1
  498.  
  499.  
  500.  
  501. /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
  502.    %g7 and at _prom_vector_p. And also quickly check whether we are on
  503.    a v0 or v2 prom.
  504. */
  505.  
  506. gokernel:    or    %g0, %o0, %g7
  507.         sethi    %hi( C_LABEL(prom_vector_p) ), %g1
  508.         st    %o0, [%g1 + %lo( C_LABEL(prom_vector_p) )]   ! we will need it later
  509.         rd    %psr, %l2
  510.         rd    %wim, %l3
  511.         rd    %tbr, %l4
  512.         or    %g0, %o2, %l5        ! could be prom magic value...
  513.     
  514. #if 0 /* You think I'm nutz? */
  515.         subcc    %l5, 0x0, %g0        ! check for magic SMP pointer
  516.         bne    nosmp    
  517.         nop
  518.         call    %o2            ! call smp prom setup 
  519.         nop
  520. #endif /* I will be soon... */
  521.  
  522. /* Acquire boot time privileged register values, this will help debugging.
  523.  * I figure out and store nwindows later on.
  524.  */
  525.  
  526. nosmp:        sethi    %hi( C_LABEL(boot_psr) ), %l1
  527.         st    %l2, [%l1 + %lo( C_LABEL(boot_psr) )]
  528.         sethi    %hi( C_LABEL(boot_wim) ), %l1
  529.         st    %l3, [%l1 + %lo( C_LABEL(boot_wim) )]
  530.         sethi    %hi( C_LABEL(boot_tbr) ), %l1
  531.         st    %l4, [%l1 + %lo( C_LABEL(boot_tbr) )]
  532.         sethi    %hi( C_LABEL(boot_smp_ptr) ), %l1
  533.         st    %l5, [%l1 + %lo( C_LABEL(boot_smp_ptr) )]
  534.  
  535.         or    %g0, %o0, %g7
  536.         sethi    %hi( C_LABEL(prom_vector_p) ), %g5
  537.         st    %o0, [%g5 + %lo( C_LABEL(prom_vector_p) )]   ! we will need it later
  538.  
  539.         ld    [%g7 + 0x4], %o3
  540.         subcc    %o3, 0x2, %g0            ! a v2 prom?
  541.         be    found_v2
  542.         nop
  543.  
  544.         /* paul@sfe.com.au */
  545.         subcc    %o3, 0x3, %g0            ! a v3 prom?
  546.         or    %g0, 0x3, %o5
  547.         sethi    %hi(C_LABEL(prom_iface_vers) ), %g1
  548.         st    %o5, [%g1 + %lo( C_LABEL(prom_iface_vers) )]
  549.         be    not_v2
  550.         nop
  551.  
  552.  
  553. /* Old sun4's pass our load address into %o0 instead of the prom
  554.    pointer. On sun4's you have to hard code the romvec pointer into
  555.    your code. Sun probably still does that because they don't even
  556.    trust their own "OpenBoot" specifications.
  557. */
  558.  
  559.         sethi    %hi(LOAD_ADDR), %g6
  560.         subcc    %o0, %g6, %g0        ! an old sun4?
  561.         be    no_sun4_here
  562.         nop
  563.  
  564.         sethi    %hi( C_LABEL(prom_iface_vers) ), %g1
  565.         st    %g0, [%g1 + %lo( C_LABEL(prom_iface_vers) )]
  566.         b    not_v2
  567.         nop
  568.  
  569. found_v2:
  570.         or    %g0, 0x2, %o5
  571.         sethi    %hi( C_LABEL(prom_iface_vers) ), %g1
  572.         st    %o5, [%g1 + %lo( C_LABEL(prom_iface_vers) )]
  573.  
  574. not_v2:
  575.  
  576. /* Get the machine type via the mysterious romvec node operations.
  577.  * Here we can find out whether we are on a sun4 sun4c, sun4m, or
  578.  * a sun4m. The "nodes" are set up as a bunch of n-ary trees which
  579.  * you can traverse to get information about devices and such. The
  580.  * information acquisition happens via the node-ops which are defined
  581.  * in the linux_openprom.h header file. Of particular interest is the
  582.  * 'nextnode(int node)' function as it does the smart thing when
  583.  * presented with a value of '0', it gives you the first node in the
  584.  * tree. These node integers probably offset into some internal prom
  585.  * pointer table the openboot has. It's completely undocumented, so
  586.  * I'm not about to go sifting through the prom address space, but may
  587.  * do so if I get suspicious enough. :-)
  588.  */
  589.  
  590.         or    %g0, %g7, %l1
  591.         add    %l1, 0x1c, %l1        
  592.         ld    [%l1], %l0
  593.         ld    [%l0], %l0
  594.         call     %l0
  595.         or    %g0, %g0, %o0        ! next_node(0) = first_node
  596.  
  597.         sethi    %hi( C_LABEL(cputypvar) ), %o1    ! first node has cpu-arch
  598.         or    %o1, %lo( C_LABEL(cputypvar) ), %o1
  599.         sethi    %hi( C_LABEL(cputypval) ), %o2    ! information, the string
  600.         or    %o2, %lo( C_LABEL(cputypval) ), %o2
  601.         ld    [%l1], %l0        ! 'compatibility' tells
  602.         ld    [%l0 + 0xc], %l0    ! that we want 'sun4x' where
  603.         call    %l0            ! x is one of '', 'c', 'm',
  604.         nop                ! 'd' or 'e'. %o2 holds pointer
  605.                         ! to a buf where above string
  606.                         ! will get stored by the prom.
  607.  
  608.         sethi    %hi( C_LABEL(cputypval) ), %o2    ! better safe than sorry
  609.         or    %o2, %lo( C_LABEL(cputypval) ), %o2
  610.         ldub    [%o2 + 0x4], %o0
  611.         subcc    %o0, 'c', %g0        ! we already know we are not
  612.         be    is_sun4c        ! on a plain sun4 because of
  613.         nop                ! the check for 0x4000 in %o0
  614.         subcc    %o0, 'm', %g0        ! at start:
  615.         be    is_sun4m
  616.         nop
  617.         b    no_sun4d_here        ! god bless the person who
  618.         nop                ! tried to run this on sun4d
  619.  
  620. is_sun4m:
  621. is_sun4c:                    ! OK, this is a sun4c, yippie
  622.         or     %g0, %g7, %g6        ! load up the promvec offsets
  623.         sethi    %hi(prom_magic), %g5       ! magic mushroom :>
  624.         st    %g6, [%g5 + %lo(prom_magic)]
  625.         add    %g7, 0x4, %g6
  626.         sethi    %hi(prom_rom_vers), %g5
  627.         st    %g6, [%g5 + %lo(prom_rom_vers)]
  628.         add    %g7, 0x8, %g6
  629.         sethi    %hi(prom_pluginvers), %g5
  630.         st    %g6, [%g5 + %lo(prom_pluginvers)]
  631.         add    %g7, 0xc, %g6
  632.         sethi    %hi(prom_revision), %g5
  633.         st    %g6, [%g5 + %lo(prom_revision)]
  634.         add    %g7, 0x10, %g6
  635.         sethi    %hi(prom_v0mem_desc), %g5
  636.         st    %g6, [%g5 + %lo(prom_v0mem_desc)]
  637.         add    %g7, 0x1c, %g6
  638.         sethi    %hi(prom_nodefuncs), %g5
  639.         st    %g6, [%g5 + %lo(prom_nodefuncs)]
  640.         add    %g7, 0x68, %g6
  641.         sethi    %hi(prom_printf), %g5
  642.         st    %g6, [%g5 + %lo(prom_printf)]
  643.         add    %g7, 0x6c, %g6
  644.         sethi    %hi(prom_abort), %g5
  645.         st    %g6, [%g5 + %lo(prom_abort)]
  646.         add    %g7, 0x74, %g6
  647.         sethi    %hi(prom_halt), %g5
  648.         st    %g6, [%g5 + %lo(prom_halt)]
  649.         add    %g7, 0x78, %g6
  650.         sethi    %hi(prom_sync), %g5
  651.         st    %g6, [%g5 + %lo(prom_sync)]
  652.         add    %g7, 0x7c, %g6
  653.         sethi    %hi(prom_eval), %g5
  654.         st    %g6, [%g5 + %lo(prom_eval)]
  655.         add    %g7, 0x80, %g6
  656.         sethi    %hi(prom_v0bootline), %g6
  657.         st    %g6, [%g5 + %lo(prom_v0bootline)]
  658.  
  659.  
  660. /* That was easy, now lets try to print some message on the screen.
  661.  * We don't have to worry about bad address translations when the prom
  662.  * addresses our pointers because our pointers are at 0x0-kern_size
  663.  * as the prom expects.
  664.  */
  665.  
  666. /* paul@sfe.com.au */
  667. /* V3 doesn't have printf.. And I don't really feel like doing the formatting
  668.  * myself.. So we miss out on some messages (for now).
  669.  */
  670.         ld    [%g7 + 0x4], %o0
  671.         subcc    %o3, 0x3, %g0
  672.         be    v3_bootmsg
  673.         nop
  674.  
  675.         sethi    %hi(boot_msg), %o0    
  676.         or    %o0, %lo(boot_msg), %o0
  677.         sethi    %hi(prom_printf), %o1
  678.         ld    [%o1 + %lo(prom_printf)], %o1
  679.         ld    [%o1], %o1
  680.         call    %o1              ! print boot message #1
  681.         nop
  682.  
  683.         sethi    %hi(pstring1), %o0
  684.         or    %o0, %lo(pstring1), %o0
  685.         sethi    %hi(prom_printf), %o2
  686.         ld    [%o2 + %lo(prom_printf)], %o2
  687.         ld    [%o2], %o2
  688.         sethi    %hi(prom_magic), %o1
  689.         ld    [%o1 + %lo(prom_magic)], %o1
  690.         ld    [%o1], %o1
  691.         call    %o2
  692.         nop
  693.  
  694.         sethi    %hi(pstring2), %o0
  695.         or    %o0, %lo(pstring2), %o0
  696.         sethi    %hi(prom_printf), %o2
  697.         ld    [%o2 + %lo(prom_printf)], %o2
  698.         ld    [%o2], %o2
  699.         sethi    %hi( C_LABEL(prom_iface_vers) ), %o1
  700.         ld    [%o1 + %lo( C_LABEL(prom_iface_vers) )], %o1
  701.         ld    [%o1], %o1
  702.         call     %o2
  703.         nop
  704.  
  705.         b    rest_of_boot
  706.         nop
  707.  
  708. v3_bootmsg:
  709.         ld    [%g7 + 0x94], %o0
  710.         ld    [%o0], %o0
  711.         sethi    %hi(boot_msg), %o1
  712.         or    %o1, %lo(boot_msg), %o1
  713.         mov    BOOT_MSG_LEN, %o2
  714.         ld    [%g7 + 0xb8], %o4
  715.         call    %o4
  716.         nop
  717.  
  718.         ld    [%g7 + 0x94], %o0
  719.         ld    [%o0], %o0
  720.         sethi    %hi(boot_msg2), %o1
  721.         or    %o1, %lo(boot_msg2), %o1
  722.         mov    BOOT_MSG2_LEN, %o2
  723.         ld    [%g7 + 0xb8], %o4
  724.         call    %o4
  725.         nop
  726.         b    rest_of_boot
  727.         nop
  728.  
  729.  
  730. no_sun4_here:
  731.         ld    [%g7 + 0x68], %o1
  732.         set    sun4_notsup, %o0
  733.         call    %o1
  734.         nop
  735.  
  736. rest_of_boot:
  737.         or    %g0, PAGE_SHIFT, %g5
  738.  
  739.         sethi    %hi(AC_CONTEXT), %g1    ! kernel context, safe now
  740.                         ! the only valid context
  741.                         ! until we call paging_init()
  742.         stba    %g0, [%g1] ASI_CONTROL
  743.  
  744.  
  745. /* I make the kernel image sit in memory relative to 0x0 with the text 
  746.  * starting at 0x4000. Now it looks like the way memory is set in Linux
  747.  * on an ix86.
  748.  */
  749.  
  750. /* Uh, oh, interrupt time. This crap is real confusing. What I want to do is
  751.  * clear all interrupts, map the interrupt enable register which in effect
  752.  * enables non-maskable interrupts (or NMI's). Actually we take no interrupts
  753.  * until we frob with the %tbr (trap base register) which the prom has set 
  754.  * to all its routines which allows some sanity during bootup.
  755.  */
  756.  
  757.         sethi    %hi(IE_reg_addr), %l0
  758.         or    %l0, %lo(IE_reg_addr), %l0
  759.  
  760.         set    0xf4000000, %l3
  761.         sethi    %hi(INT_ENABLE_REG_PHYSADR), %l2
  762.         or    %l2, %lo(INT_ENABLE_REG_PHYSADR), %l2
  763.         srl    %l2, %g5, %l2
  764.         or    %l2, %l3, %l1        
  765.  
  766. #ifndef CONFIG_SRMMU
  767.         sta    %l1, [%l0] ASI_PTE
  768. #endif
  769.     
  770.         or    %g0, 0x1, %l1
  771.         stb    %l1, [%l0]
  772.     
  773.  
  774. /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's
  775.  * show-time!
  776.  */
  777.  
  778.         sethi    %hi(1f), %g1
  779.         or    %g1, %lo(1f), %g1
  780.         jmp    %g1
  781.         nop
  782.  
  783.         .align 4
  784. 1:        sethi    %hi( C_LABEL(cputyp) ), %o0
  785.         st    %g4, [%o0 + %lo( C_LABEL(cputyp) )]
  786.  
  787.         sethi    %hi( C_LABEL(pgshift) ), %o0
  788.         st    %g5, [%o0 + %lo( C_LABEL(pgshift) )]
  789.  
  790.         mov    1, %o0
  791.         sll    %o0, %g5, %g5
  792.         sethi    %hi( C_LABEL(nbpg) ), %o0
  793.         st    %g5, [%o0 + %lo( C_LABEL(nbpg) )]
  794.  
  795.         sub    %g5, 1, %g5
  796.         sethi    %hi( C_LABEL(pgofset) ), %o0
  797.         st    %g5, [%o0 + %lo( C_LABEL(pgofset) )]
  798.  
  799.  
  800.         rd    %psr, %g3
  801.         andn    %g3, PSR_ET, %g3
  802.         wr    %g3, 0x0, %psr        ! make sure traps are off
  803.                         ! before we play around
  804.         WRITE_PAUSE            ! no guarantees until 3 insns
  805.  
  806.  
  807.         wr    %g0, 0x0, %wim        ! magical invalid window reg
  808.         WRITE_PAUSE            ! see above
  809.  
  810. /* I keep the timer interrupt on so that BogoMIPS works and the prom
  811.  * keeps updating its "jiffies" counter. 100HZ clock on sparcstations.
  812.  */    
  813.  
  814. /* If gas wasn't so dumb, I could use or'd macros in this next
  815.  * write. ;-( like this (PSR_PS | PSR_S | PSR_PIL)...
  816.  */
  817.  
  818.         sethi    %hi(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
  819.         or    %g2, %lo(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
  820.         wr    %g2, 0x0, %psr
  821.         WRITE_PAUSE
  822.  
  823.         wr    %g0, 0x2, %wim        ! window 1 invalid
  824.         WRITE_PAUSE
  825.  
  826.         or    %g0, 0x1, %g1
  827.         sethi    %hi( C_LABEL(current) + THREAD_WIM), %g2
  828.         st    %g1, [%g2 + %lo( C_LABEL(current) + THREAD_WIM)]
  829.  
  830. /* I want a kernel stack NOW! */
  831.  
  832.         set    ( C_LABEL(init_user_stack) + 4092 - 96 - 80), %fp    
  833.         set    ( C_LABEL(init_user_stack) + 4092), %sp
  834.  
  835. /* now out stack is set up similarly to the way it is on the i386 */
  836.  
  837.         rd    %psr, %l0
  838.         wr    %l0, PSR_ET, %psr
  839.         WRITE_PAUSE
  840.  
  841. /*
  842.  * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
  843.  * don't know, do you?
  844.  */
  845.  
  846.         set    C_LABEL(edata) , %o0
  847.         set    C_LABEL(end) , %o1
  848.         sub    %o1, %o0, %g2
  849.         sethi    %hi( C_LABEL(kernel_bss_len) ), %g3
  850.         st    %g2, [%g3 + %lo( C_LABEL(kernel_bss_len) )]
  851.         sethi    %hi( C_LABEL(trapbase) ), %g3
  852.         or    %g3, %lo( C_LABEL(trapbase) ), %g3
  853.         sethi    %hi( C_LABEL(etext) ), %g4
  854.         or    %g4, %lo( C_LABEL(etext) ), %g4            
  855.         sub    %g4, %g3, %g2
  856.         sethi    %hi( C_LABEL(kernel_text_len) ), %g3
  857.         st    %g2, [%g3 + %lo( C_LABEL(kernel_text_len) )]
  858.         sethi    %hi( C_LABEL(etext) ), %g4
  859.         or    %g4, %lo( C_LABEL(etext) ), %g4
  860.         sethi    %hi( C_LABEL(edata) ), %g3
  861.         or    %g3, %lo( C_LABEL(edata) ), %g3
  862.         sub    %g3, %g4, %g2
  863.         sethi    %hi( C_LABEL(kernel_data_len) ), %g3
  864.         st    %g2, [%g3 + %lo( C_LABEL(kernel_data_len) )]
  865.         or    %g0, %g0, %g1
  866.  
  867. 1:    
  868.         st    %g0, [%o0]
  869.         add    %o0, 0x4, %o0
  870.         subcc    %o0, %o1, %g0
  871.         bl    1b
  872.         nop
  873.  
  874. /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
  875.  * in the V8 manual. Ok, this method seems to work, sparc is cool...
  876.  */
  877.  
  878.         sethi    %hi(0xffffffff), %g1
  879.         rd    %wim, %g2            ! save current value
  880.         or    %g1, %lo(0xffffffff), %g1
  881.         wr    %g1, 0x0, %wim
  882.         rd    %wim, %g1            ! get remaining mask
  883.         wr    %g2, 0x0, %wim            ! restore old value
  884.         WRITE_PAUSE
  885.  
  886.         or    %g0, 0x0, %g3
  887.  
  888. 1:        srl    %g1, 0x1, %g1            ! shift until highest
  889.         subcc    %g1, 0x0, %g0            ! bit set
  890.         bne    1b
  891.         add    %g3, 0x1, %g3
  892.         sethi    %hi( C_LABEL(nwindows) ), %g4
  893.         st    %g3, [%g4 + %lo( C_LABEL(nwindows) )]    ! store final value
  894.         sub    %g3, 0x1, %g3
  895.         sethi    %hi( C_LABEL(nwindowsm1) ), %g4
  896.         st    %g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
  897.  
  898.  
  899. /* Here we go */
  900.  
  901. #ifndef CONFIG_SUN4M
  902.         /* paul@sfe.com.au */
  903.         /* Look into traps later :( */
  904.         set    C_LABEL(trapbase), %g3
  905.         wr    %g3, 0x0, %tbr
  906.         WRITE_PAUSE
  907. #endif
  908.  
  909.  
  910. /* First we call init_prom() to set up romvec, then off to start_kernel() */
  911. /* XXX put this in arch_init() */
  912.  
  913.         sethi    %hi( C_LABEL(prom_vector_p) ), %g5
  914.         call    C_LABEL(init_prom)
  915.         ld    [%g5 + %lo( C_LABEL(prom_vector_p) )], %o0   /* delay slot */
  916.  
  917.         call     C_LABEL(start_kernel)
  918.         nop
  919.     
  920.         call    halt_me
  921.         nop
  922.  
  923. /* There, happy now adrian? */
  924.  
  925. no_sun4d_here:
  926.         ld    [%g7 + 0x68], %o1
  927.         set    sun4d_notsup, %o0
  928.         call    %o1
  929.         nop
  930.         b    halt_me
  931.         nop
  932.  
  933. halt_me:
  934.         ld    [%g7 + 0x74], %o0
  935.         call    %o0            ! get us out of here...
  936.         nop                ! apparently solaris is better
  937.  
  938.     .data
  939.     .align 4
  940.  
  941. /*
  942.  * Fill up the prom vector, note in particular the kind first element,
  943.  * no joke. I don't need all of them in here as the entire prom vector
  944.  * gets initialized in c-code so all routines can use it.
  945.  */
  946.  
  947.             .globl C_LABEL(prom_vector_p)
  948.  
  949. C_LABEL(prom_vector_p):    .skip 4
  950. prom_magic:          .skip 4            ! magic mushroom, beware...
  951. prom_rom_vers:         .skip 4            ! interface version (v0 or v2)
  952. prom_pluginvers:    .skip 4            ! XXX help help help ???
  953. prom_revision:        .skip 4            ! PROM revision (ie. 1.4)
  954. prom_halt:        .skip 4            ! void halt(void)  solaris friend
  955. prom_eval:        .skip 4            ! void eval(int len, char* string)
  956. prom_v0bootline:    .skip 4            ! boot command line
  957. prom_v0mem_desc:    .skip 4            ! V0 memory descriptor list ptr.
  958. prom_nodefuncs:        .skip 4            ! Magical Node functions
  959. prom_printf:        .skip 4            ! minimal printf()
  960.  
  961. /* The prom_abort pointer MUST be mapped in all contexts, because if you
  962.  * don't then if a user process is running when you press the abort key
  963.  * sequence, all sorts of bad things can happen
  964.  */
  965.  
  966. prom_abort:        .skip 4        ! L1-A magic cookie
  967.                     ! must be mapped in ALL contexts
  968.  
  969. /* prom_sync is a place where the kernel should place a pointer to a kernel
  970.  * function that when called will sync all pending information to the drives
  971.  * and then promptly return. If the kernel gets aborted with 'L1-A' one can
  972.  * give the 'sync' command to the boot prompt and this magic cookie gets
  973.  * executed. Nice feature eh?
  974.  */
  975.  
  976. prom_sync:        .skip 4            ! hook in prom for sync func
  977.  
  978.     .align 4
  979.  
  980. /* We calculate the following at boot time, window fills/spills and trap entry
  981.  * code uses these to keep track of the register windows.
  982.  */
  983.  
  984.     .globl C_LABEL(nwindows)
  985.     .globl C_LABEL(nwindowsm1)
  986. C_LABEL(nwindows):    .skip 4
  987. C_LABEL(nwindowsm1):    .skip 4
  988.  
  989.     .align 4
  990. /* Boot time privileged register values, plus magic %o2 value */
  991.  
  992.     .globl C_LABEL(boot_wim)
  993.     .globl C_LABEL(boot_psr)
  994.     .globl C_LABEL(boot_tbr)
  995.     .globl C_LABEL(boot_smp_ptr)
  996. C_LABEL(boot_wim):        .skip 4
  997. C_LABEL(boot_psr):        .skip 4
  998. C_LABEL(boot_tbr):        .skip 4
  999. C_LABEL(boot_smp_ptr):        .skip 4
  1000.  
  1001.  
  1002.     .align 4
  1003. /* Miscellaneous pieces of information saved at kernel startup. */
  1004.     .globl C_LABEL(kernel_text_len)
  1005.     .globl C_LABEL(kernel_data_len)
  1006.     .globl C_LABEL(kernel_bss_len)
  1007. C_LABEL(kernel_text_len):    .word 0
  1008. C_LABEL(kernel_data_len):    .word 0
  1009. C_LABEL(kernel_bss_len):    .word 0
  1010.  
  1011. /* These are for page alignment/offset information as they change from
  1012.    machine to machine.
  1013. */
  1014.  
  1015.         .globl  C_LABEL(pgshift)
  1016.     .globl     C_LABEL(nbpg)
  1017.     .globl    C_LABEL(pgofset)
  1018.  
  1019.     .align 4
  1020. C_LABEL(pgshift):
  1021.         .word   1
  1022. C_LABEL(nbpg):
  1023.         .word   1
  1024. C_LABEL(pgofset):
  1025.         .word   1
  1026.  
  1027. /* Just to get the kernel through the compiler for now */
  1028.     .globl C_LABEL(swapper_pg_dir), C_LABEL(pg0)
  1029.     .globl C_LABEL(empty_bad_page)
  1030.     .globl C_LABEL(empty_bad_page_table)
  1031.     .globl C_LABEL(empty_zero_page)
  1032.     .globl C_LABEL(floppy_track_buffer)
  1033. C_LABEL(floppy_track_buffer):
  1034.     .fill 512*2*36,1,0
  1035.  
  1036.     .align 4
  1037. C_LABEL(swapper_pg_dir):        .skip 0x1000
  1038. C_LABEL(pg0):                .skip 0x1000
  1039. C_LABEL(empty_bad_page):        .skip 0x1000
  1040. C_LABEL(empty_bad_page_table):        .skip 0x1000
  1041. C_LABEL(empty_zero_page):        .skip 0x1000
  1042.  
  1043.         .align 4
  1044. diagstr:    .asciz    "DIAG\n"
  1045.         .align 4
  1046.