/*      $NetBSD: start.S,v 1.7 2020/04/06 01:43:26 snj Exp $ */
/*
* Copyright (c) 1995 Ludd, University of Lule}, Sweden.
* All rights reserved.
*
* This code is derived from software contributed to Ludd by
* Bertram Barth.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* All bugs are subject to removal without further notice */


#define _LOCORE

#define __HAVE_OLD_DISKLABEL    /* not automatically added due to _LOCORE */
#define OMIT_DKTYPENUMS
#define OMIT_FSTYPENUMS
#include "sys/disklabel.h"

#include "../include/mtpr.h"
#include "../include/asm.h"

_C_LABEL(_start):
_C_LABEL(start):
       .globl _C_LABEL(start)  # this is the symbolic name for the start
       .globl _C_LABEL(_start) # of code to be relocated. We can use this
                               # to get the actual/real address (pc-rel)
                               # or to get the relocated address (abs).

org     0x00                    # uVAX booted from TK50 starts here
       brb     from_0x00       # continue behind dispatch-block

# At offset 0x02 we have a dual used area: VMB.EXE starts execution here,
# and uVAX-ROM looks for a pointer to a parameter block. We arrange for
# the parameter block offset to disassemble as a CASEL instructions which
# falls through to 0x08.
org     0x02                    # information used by uVAX-ROM
       .byte   0xcf            # offset in words to identification area
       .byte   1               # this byte must be 1
       .word   0               # logical block number (word swapped)
       .word   0               # of the secondary image

org     0x08                    #
       brb     from_0x08       # skip ...

org     0x0C                    # 11/750  & 8200 starts here
       movzbl  $1,_C_LABEL(from)# We booted from "old" rom.
       brw     cont_750


from_0x00:                      # uVAX from TK50
       brw     start_uvax      # all uVAXen continue there

from_0x08:                      # Any machine from VMB
       movzbl  $4,_C_LABEL(from)               # Booted from full VMB
       /*
        * Read in block 1-15.
        */
       movl    52(%r11), %r7   # load iovec/bqo into %r7
       addl3   (%r7), %r7, %r6 # load qio into %r6
       pushl   %r11            # base of rpb
       pushl   $0              # virtual-flag
       pushl   $33             # read-logical-block
       pushl   $1              # lbn to start reading
       pushl   $7680           # number of bytes to read
       pushab  start_uvax      # buffer-address
       calls   $6, (%r6)       # call the qio-routine
       brw     start_uvax

# the complete area reserved for label
# must be empty (i.e. filled with zeroes).
# disklabel(8) checks that before installing
# the bootblocks over existing label.

org     LABELOFFSET
       .globl  _C_LABEL(romlabel)
_C_LABEL(romlabel):
       .long   0

org     LABELOFFSET + d_end_
# Make sure the parameter block is past the disklabel.
# If not, the next .org would try to move backwards.

/*
* Parameter block for uVAX boot.
*/
#define VOLINFO         0       /* 1=single-sided  81=double-sided volumes */
#define SISIZE          16      /* size in blocks of secondary image */
#define SILOAD          0       /* load offset (usually 0) from the default */
#define SIOFF           0x200   /* byte offset into secondary image */

org     0x19e   # do not move, see comment earlier about CASEL
       .byte   0x18            # must be 0x18
       .byte   0x00            # must be 0x00 (MBZ)
       .byte   0x00            # any value
       .byte   0xFF - (0x18 + 0x00 + 0x00)
               /* 4th byte holds 1s' complement of sum of previous 3 bytes */

       .byte   0x00            # must be 0x00 (MBZ)
       .byte   VOLINFO
       .byte   0x00            # any value
       .byte   0x00            # any value

       .long   SISIZE          # size in blocks of secondary image
       .long   SILOAD          # load offset (usually 0)
       .long   SIOFF           # byte offset into secondary image
       .long   (SISIZE + SILOAD + SIOFF)       # sum of previous 3


       .align  2
       .globl  _C_LABEL(from)
_C_LABEL(from):
       .long   0

/*
* After bootblock (LBN0) has been loaded into the first page
* of good memory by 11/750's ROM-code (transfer address
* of bootblock-code is: base of good memory + 0x0C) registers
* are initialized as:
*      R0:     type of boot-device
*                      0:      Massbus device
*                      1:      RK06/RK07
*                      2:      RL02
*                      17:     UDA50
*                      35:     TK50
*                      64:     TU58
*      R1:     (UBA) address of UNIBUS I/O-page
*              (MBA) address of boot device's adapter
*      R2:     (UBA) address of the boot device's CSR
*              (MBA) controller number of boot device
*      R6:     address of driver subroutine in ROM
*
* cont_750 reads in LBN1-15 for further execution.
*/
cont_750:
       movl    $_C_LABEL(start), %sp   # move stack to avoid clobbering the code
       pushr   $0x131          # save clobbered registers
       clrl    %r4             # %r4 == # of blocks transferred
       movab   _C_LABEL(start),%r5     # %r5 have base address for next transfer
       pushl   %r5             # ...on stack also (Why?)
1:      incl    %r4             # increment block count
       movl    %r4,%r8         # LBN is in %r8 for rom routine
       addl2   $0x200,%r5      # Increase address for next read
       cmpl    $16,%r4         # read 15 blocks?
       beql    2f              # Yep
       movl    %r5,(%sp)               # move address to stack also
       jsb     (%r6)           # read 512 bytes
       blbs    %r0,1b          # jump if read succeeded
       halt                    # otherwise die...
2:      tstl    (%sp)+          # remove boring arg from stack
       popr    $0x131          # restore clobbered registers
       brw     start_all       # Ok, continue...

/* uVAX main entry is at the start of the second disk block.  This is
* needed for multi-arch CD booting where multiple architecture need
* to shove stuff in boot block 0.
*/
       .org    0x200           # uVAX booted from disk starts here

start_uvax:
       movzbl  $2,_C_LABEL(from)       # Booted from subset-VMB
       brb     start_all

/*
* start_all: stack already at RELOC, we save registers, move ourself
* to RELOC and loads boot.
*/
start_all:
       movl    $_C_LABEL(start), %sp   # move stack to a better
       pushr   $0x1fff                 # save all regs, used later.

       subl3   $_C_LABEL(start), $_C_LABEL(edata), %r0
                                       # get size of text+data (w/o bss)
       moval   _C_LABEL(start), %r1    # get actual base-address of code
       subl3   $_C_LABEL(start), $_C_LABEL(end), %r2
                                       # get complete size (incl. bss)
       movl    $_C_LABEL(start), %r3   # get relocated base-address of code
       movc5   %r0, (%r1), $0, %r2, (%r3)      # copy code to new location

       movpsl  -(%sp)
       movl    $relocated, -(%sp)      # return-address on top of stack
       rei                             # can be replaced with new address
relocated:                              # now relocation is done !!!
       movl    %sp, _C_LABEL(bootregs)
       calls   $0, _C_LABEL(Xmain)     # call Xmain (gcc workaround)which is
       halt                            # not intended to return ...

/*
* hoppabort() is called when jumping to the newly loaded program.
*/
ENTRY(hoppabort, 0)
       movl    4(%ap),%r6
       movl    _C_LABEL(rpb),%r11
       mnegl   $1,%ap          # Hack to figure out boot device.
       movpsl  -(%sp)
       pushab  2(%r6)
       mnegl   $1,_C_LABEL(vax_load_failure)
       rei
#       calls   $0,(%r6)
       halt

ENTRY(unit_init, R6|R7|R8|R9|R10|R11)
       mfpr    $17,%r7                 # Wanted bu KDB
       movl    4(%ap),%r0              # init routine address
       movl    8(%ap),%r9              # RPB in %r9
       movl    12(%ap),%r1             # VMB argument list
       callg   (%r1),(%r0)
       ret

# A bunch of functions unwanted in boot blocks.
ENTRY(getchar, 0)
       halt

#ifndef USE_PRINTF
ENTRY(putchar, 0)
       ret

ENTRY(printf, 0)
       ret
#endif

ENTRY(panic, 0)
       halt