bootdisk.c 4.19 KB
/*
 * Copyright 1996, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 *
 * UNPUBLISHED -- Rights reserved under the copyright laws of the United
 * States.   Use of a copyright notice is precautionary only and does not
 * imply publication or disclosure.
 *
 * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to restrictions
 * as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or
 * in similar or successor clauses in the FAR, or the DOD or NASA FAR
 * Supplement.  Contractor/manufacturer is Silicon Graphics, Inc.,
 * 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311.
 *
 * THE CONTENT OF THIS WORK CONTAINS CONFIDENTIAL AND PROPRIETARY
 * INFORMATION OF SILICON GRAPHICS, INC. ANY DUPLICATION, MODIFICATION,
 * DISTRIBUTION, OR DISCLOSURE IN ANY FORM, IN WHOLE, OR IN PART, IS STRICTLY
 * PROHIBITED WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SILICON
 * GRAPHICS, INC.
 *
 */

#include <ultra64.h>
#include <os_internal.h>
#include "ipl4.h"


/*
 * IPL4 bootstrap loader code
 *
 * This is the code that will bootstrap into running the game that
 * has been read off of disk. The game has already been successfully read
 * off of the disk and is in the correct spot in RDRAM. The goal is to 
 * reinitialize the system and begin running the game. Some of the IP1,
 * IP2, and IP3 initializations will be done again.
 *
 * ASSUMPTIONS on call:
 *   - Graphics and Audio have just been stopped. The RSP and RDP are unused
 *   - No outstanding PI DMAs are in progress (includes disk)
 *   - New game has been loaded off of the disk and is awaiting execution
 *     in RDRAM
 *
 * Reinitialize the system to the same state as at the end of IPL3:
 *
 * Final intialization and jump to preamble code in game by calling 
 * assembly routine
 *
 */

void
BootDiskImage(IPLHeader *bh)
{
    int i;
    vu32 *memp;

    /* put the system in the same state as after IPL1, IPL2 and IPL3 */
    __osSetSR(SR_CU1|SR_CU0);		/* disable interrupts (IPL1) */

    /* no need to set C0_CONFIG */

    /* make sure RSP is halted (IPL1) */
    while (!IO_READ(SP_STATUS_REG) & SP_STATUS_HALT)
	;

    IO_WRITE(SP_STATUS_REG, SP_SET_HALT|SP_CLR_INTR);

    while (IO_READ(SP_DMA_BUSY_REG) & 0x1)
	;

    /* reset PI (IPL1) */
    IO_WRITE(PI_STATUS_REG, PI_STATUS_RESET|PI_STATUS_CLR_INTR);

    /* blank the video */
    /* Spin until we are in the pre-blank stage */
    while (IO_READ(VI_CURRENT_REG) > 10)
	;

    /* Zero out control register so that reset to LAN1 is safe */
//  IO_WRITE(VI_CONTROL_REG,    0);     /* Turn off video, reset counters */
    IO_WRITE(VI_V_INTR_REG, 0x3ff);
    IO_WRITE(VI_H_START_REG, 0);
    IO_WRITE(VI_V_CURRENT_LINE_REG, 0);

    /* stop audio */
    IO_WRITE(AI_BASE_REG, 0);
    IO_WRITE(AI_LEN_REG, 0);

    /* IPL2 work */
    /* no need to get info from pif on video, reset, rom */
    /* no need to set PI rom speed */

    /* on to IPL3 work */
    __osSetCause(0);
    __osSetCount(0);
    __osSetCompare(0);

    /* no need to initialize RD-RAM */

    /* section 19  - Clear RCP status ?? */
    /* should I do the checking if PC is 0? */
    IO_WRITE(SP_STATUS_REG, SP_SET_HALT|SP_CLR_BROKE|SP_CLR_INTR| \
		SP_CLR_SSTEP|SP_CLR_SIG0|SP_CLR_SIG1|SP_CLR_SIG2| \
		SP_CLR_SIG3|SP_CLR_SIG4|SP_CLR_SIG5|SP_CLR_SIG6|  \
		SP_CLR_SIG7|SP_CLR_INTR_BREAK);


    /* clear interrupt mask */
    IO_WRITE(MI_INTR_MASK_REG, 0);

    /* rest of RCP interrupts (already did SP, PI and VI) */
    IO_WRITE(SI_STATUS_REG, 0);
    IO_WRITE(AI_STATUS_REG, 0);
    IO_WRITE(MI_MODE_REG, MI_CLR_DP_INTR);
    IO_WRITE(PI_STATUS_REG, PI_STATUS_CLR_INTR);

    /*
     * The os variables in locore should already be valid.
     * These are osTvType, osRomType, osResetType, osVersion
     */

    /* clear IMEM and DMEM */
    memp = (vu32 *)PHYS_TO_K1(SP_IMEM_START);
    for (i=0; i<256; i++)
	*memp++ = 0;

    memp = (vu32 *)PHYS_TO_K1(SP_DMEM_START);
    for (i=0; i<256; i++)
	*memp++ = 0;

    /*
     * now call the assembly language routine to flush/invalidate
     * caches, and jump to game
     */
     FinalBoot(bh->entry);

}
/* details to work out:  NMI vs cold reset, global variables, ... */