root/sys/arch/mac68k/mac68k/macrom.c
/*      $NetBSD: macrom.c,v 1.77 2026/05/06 12:46:24 thorpej Exp $      */

/*-
 * Copyright (C) 1994   Bradley A. Grantham
 * All rights reserved.
 *
 * 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.
 */

/*
 * Mac ROM Glue
 *
 * This allows MacBSD to access (in a limited fashion) routines included
 * in the Mac ROMs, like ADBReInit.
 *
 * As a (fascinating) side effect, this glue allows ROM code (or any other
 * MacOS code) to call MacBSD kernel routines, like NewPtr.
 *
 * Uncleaned-up weirdness,
 *      This doesn't work on a lot of machines.  Perhaps the IIsi stuff
 * can be generalized somewhat for others.  It looks like most machines
 * are similar to the IIsi ("Universal ROMs"?).
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: macrom.c,v 1.77 2026/05/06 12:46:24 thorpej Exp $");

#include "opt_adb.h"
#include "opt_ddb.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/cpu.h>
#include <sys/intr.h>

#include <uvm/uvm_extern.h>

#include <machine/frame.h>
#include <machine/viareg.h>

#include <mac68k/mac68k/macrom.h>
#include <mac68k/dev/adbvar.h>

        /* trap modifiers (put it macrom.h) */
#define TRAP_TOOLBOX(a) ((a) & 0x800)
#define TRAP_PASSA0(a)  ((a) & 0x100)
#define TRAP_NUM(a)     (TRAP_TOOLBOX(a) ? (a) & 0x3ff : (a) & 0xff)
#define TRAP_SYS(a)     ((a) & 0x400)
#define TRAP_CLEAR(a)   ((a) & 0x200)


        /* Mac Rom Glue global variables */
/*
 * ADB Storage.  Is 512 bytes enough?  Too much?
 */
u_char mrg_adbstore[512];
u_char mrg_adbstore2[512];
u_char mrg_adbstore3[512];
u_char mrg_ExpandMem[512];                      /* 0x1ea Bytes minimum */
u_char mrg_adbstore4[32];                       /* 0x16 bytes was the largest I found yet */
u_char mrg_adbstore5[80];                       /* 0x46 bytes minimum */

/*
 * InitEgret in the AV ROMs requires a low memory global at 0x2010 to be
 * pointed at this jump table, which can be found at 0x40803280. It's
 * included here so we can do mrg_fixupROMBase on it.
 */

u_int32_t mrg_AVInitEgretJT[] = {
        0x408055D0, 0x4083985A, 0x40839AB6, 0x4080F180,
        0x4080C0B6, 0x4080C30A, 0x4080C380, 0x4080C482,
        0x4080C496, 0x4080C82E, 0x4080C9FE, 0x4080CA16,
        0x4081D1D6, 0x4085CDDE, 0x4080DF28, 0x4080DFC6,
        0x4080E292, 0x4080E2C0, 0x4080E348, 0x4080E600,
        0x4080E632, 0x4080E6B8, 0x4080E6E4, 0x4080E750,
        0x4080E776, 0x4080E7B4, 0x408B90E0, 0x40852490,
        0x40852280, 0x40852410, 0x4080E8F0, 0x4080E940,
        0x4080E960, 0x4080E9B0, 0x4080E9E0, 0x4080EA50,
        0x4080EA70, 0x4080EB14, 0x4080EBC0, 0x4081D1D6,
        0x40810AB0, 0x40810BDA, 0x40810CCA, 0x40810FF2,
        0x4080FF8C, 0x40810292, 0x40812CE2, 0x40813AAE,
        0x40813AE0, 0x408113DE, 0x40811EB0, 0x40811FA0,
        0x40811DD0, 0x4083B720, 0x408412E0, 0x40841300,
        0x40841380, 0x4083A390, 0x408411F0
};

void *  mrg_romadbintr = (void *)0;     /* ROM ADB interrupt */
void *  mrg_rompmintr = 0;              /* ROM PM (?) interrupt */
const char *mrg_romident = NULL;                /* ident string for ROMs */
void *  mrg_ADBAlternateInit = 0;
void *  mrg_InitEgret = 0;
void *  mrg_ADBIntrPtr = (void *)0x0;   /* ADB interrupt taken from MacOS vector table*/
void *  ROMResourceMap = 0;
extern romvec_t *mrg_MacOSROMVectors;
#if defined(MRG_TEST) || defined(MRG_DEBUG)
void *  ResHndls[] = {
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0
};
#else
void *  ResHndls[] = {
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0
};
#endif

void *dtmgr_softintr_cookie;

/*
 * Last straw functions; we didn't set them up, so freak out!
 * When someone sees these called, we can finally go back and
 * bother to implement them.
 */

int
mrg_Delay(void)
{
#define TICK_DURATION 16625
        u_int32_t ticks;

        __asm volatile ("movl   %%a0,%0"        /* get arguments */
                : "=g" (ticks)
                :
                : "a0");

#if defined(MRG_DEBUG)
        printf("mrg: mrg_Delay(%d) = %d ms\n", ticks, ticks * 60);
#endif
        delay(ticks * TICK_DURATION);

        /*
         * The number of ticks since startup should be
         * returned here. Until someone finds a need for
         * this, we just return the requested number
         * of ticks
         */
        return (ticks);
}

/*
 * Handle the Deferred Task manager here
 *
 */
static void *   mrg_DTList = NULL;

void
mrg_DTInstall(void)
{
        void *ptr, *prev;
        void **cptr, **cprev;

        __asm volatile ("movl %%a0,%0" : "=g" (ptr));

        prev = (void *)&mrg_DTList;
        while (*(void **)prev != NULL) 
                prev = *(void **)prev;
        cptr = (void **)ptr;
        cprev = (void **)prev;
        *cptr = NULL;
        *cprev = ptr;
        softint_schedule(dtmgr_softintr_cookie);

        __asm volatile ("clrl %%d0" : : : "d0");
}

void
mrg_execute_deferred(void)
{
        void *ptr;
        int s;

        while (mrg_DTList != NULL) {
                s = splhigh();
                ptr = *(void **)mrg_DTList;
                mrg_DTList = *(void **)ptr;
                splx(s);

                __asm volatile (
                "       moveml %%a0-%%a6/%%d1-%%d7,%%sp@-       \n"
                "       movl %0,%%a0            \n"
                "       movl %%a0@(8),%%a2      \n"
                "       movl %%a0@(12),%%a1     \n"
                "       jsr %%a2@               \n"
                "       moveml %%sp@+,%%a0-%%a6/%%d1-%%d7" : : "g" (ptr));
        }
}

void
mrg_VBLQueue(void)
{
#define qLink 0
#define qType 4
#define vblAddr 6
#define vblCount 10
#define vblPhase 12
        char *vbltask;
        char *last_vbltask;
        
        last_vbltask = (char *)&VBLQueue_head;
        vbltask = VBLQueue_head;
        while (0 != vbltask) {
                if (0 != *((u_int16_t *)(vbltask + vblPhase)))
                        *((u_int16_t *)(vbltask + vblPhase)) -= 1;
                else if (0 != *((u_int16_t *)(vbltask + vblCount)))
                        *((u_int16_t *)(vbltask + vblCount)) -= 1;
                else {
#if defined(MRG_DEBUG)
                        printf("mrg: mrg_VBLQueue: calling VBL task at 0x%x with VBLTask block at %p\n",
                            *((u_int32_t *)(vbltask + vblAddr)), vbltask);
#endif
                        __asm volatile(
                        "       movml   #0xfffe,%%sp@-  \n"
                        "       movl    %0,%%a0         \n"
                        "       movl    %1,%%a1         \n"
                        "       jbsr    %%a1@           \n"
                        "       movml   %%sp@+,#0x7fff"
                                : : "g" (vbltask),
                                    "g" (*((char *)(vbltask + vblAddr)))
                                : "a0","a1");
#if defined(MRG_DEBUG)
                        printf("mrg: mrg_VBLQueue: back from VBL task\n");
#endif
                        if (0 == *((u_int16_t *)(vbltask + vblCount))) {
#if defined(MRG_DEBUG)
                                printf("mrg: mrg_VBLQueue: removing VBLTask block at %p\n",
                                    vbltask);
#endif
                                *((u_int32_t *)(last_vbltask + qLink)) =
                                    *((u_int32_t *)(vbltask + qLink));
                                /*
                                 * can't free memory from VBLTask block as
                                 * we don't know where it came from
                                 */
                                if (vbltask == VBLQueue_tail)
                                        VBLQueue_tail = last_vbltask;
                        }
                }
                last_vbltask = vbltask;
                vbltask = (void *) *((u_int32_t *)(vbltask + qLink));
        }
}

void
mrg_init_stub_1(void)
{
        __asm volatile ("movml #0xffff,%sp@-");
        printf("mrg: hit mrg_init_stub_1\n");
        __asm volatile ("movml %sp@+, #0xffff");
}

void
mrg_init_stub_2(void)
{
        panic("mrg: hit mrg_init_stub_2");
}

short
Count_Resources(u_int32_t rsrc_type)
{
        rsrc_t *rsrc = (rsrc_t *)ROMResourceMap;
        short count = 0;

#if defined(MRG_DEBUG)
        printf("Count_Resources looking for 0x%08lx at 0x%08lx\n",
            (long)rsrc_type, (long)rsrc);
#endif
        /*
         * Return a Count of all the ROM Resources of the requested type.
         */
        if (ROMResourceMap == 0)
                panic("Oops! Need ROM Resource Map ListHead address!");

        while (rsrc != 0) {
#if defined(MRG_DEBUG)
                if (rsrc_type == 0)
                        printf("0x%08lx: %04x %04x %04x %04x %08x %08x %08x %04x\n",
                            (long)rsrc, rsrc->unknown[0], rsrc->unknown[1],
                            rsrc->unknown[2], rsrc->unknown[3], rsrc->next,
                            rsrc->body, rsrc->name, rsrc->index);
#endif
                if (rsrc_type == 0 || (rsrc_type == rsrc->name))
                        count++;
                rsrc = rsrc->next == 0 ? 0 : (rsrc_t *)(rsrc->next + (char *)ROMBase);
        }

#if defined(MRG_DEBUG)
        printf("Count_Resources found %d\n", count);
#endif
        return count;
}

void **
Get_Ind_Resource(u_int32_t rsrc_type, u_int16_t rsrc_ind)
{
        rsrc_t *rsrc = (rsrc_t *)ROMResourceMap;
        short i = 0;

        /*
         * This routine return the "Handle" to a ROM Resource.  Since few
         * ROM Resources are called for in NetBSD we keep a small table
         * for the Handles we return. (Can't reuse the Handle without
         * defeating the purpose for a Handle in the first place!)  If
         * we get more requests than we have space for, we panic.
         */
        if (ROMResourceMap == 0)
                panic("Oops! Need ROM Resource Map ListHead address!");

        while (rsrc != 0) {
                if (rsrc_type == rsrc->name) {
                        rsrc_ind--;
                        if (rsrc_ind == 0) {
                                for (i = 0;
                                    i < sizeof(ResHndls) / sizeof(void *); i++)
                                        if ((ResHndls[i] == 0) ||
                                            (ResHndls[i] == (void *)(rsrc->next + (char *)ROMBase))) {
                                                ResHndls[i] = (void *)(rsrc->body + (char *)ROMBase);
                                                return (void **)&ResHndls[i];
                                        }
                                panic("ResHndls table too small!");
                        }
                }
                rsrc = rsrc->next == 0 ? 0 : (rsrc_t *)(rsrc->next + (char *)ROMBase);
        }
        return (void **)0;
}

void
mrg_FixDiv(void)
{
        panic("Oops! Need ROM address of _FixDiv for this system!");
}

void
mrg_FixMul(void)
{
        panic("Oops! Need ROM address of _FixMul for this system!");
}

void
mrg_1sec_timer_tick(void)
{       
        /* The timer tick from the Egret chip triggers this routine via
         * Lvl1DT[0] (addr 0x192) once every second.
         */
}
  
void
mrg_lvl1dtpanic(void)           /* Lvl1DT stopper */
{
        printf("Agh!  I was called from Lvl1DT!!!\n");
#ifdef DDB
        Debugger();
#endif
}

void
mrg_lvl2dtpanic(void)           /* Lvl2DT stopper */
{
        panic("Agh!  I was called from Lvl2DT!!!");
}

void
mrg_jadbprocpanic(void) /* JADBProc stopper */
{
        panic("Agh!  Called JADBProc!");
}

void
mrg_jswapmmupanic(void) /* jSwapMMU stopper */
{
        panic("Agh!  Called jSwapMMU!");
}

void
mrg_jkybdtaskpanic(void)        /* JKybdTask stopper */
{
        panic("Agh!  Called JKybdTask!");
}

#ifdef MRG_ADB
/*
 * mrg_adbintr() and mrg_pmintr() are defined in adb_direct.c if we
 * not using the MRG method of accessing the ADB/PRAM/RTC.
 */

long
mrg_adbintr(void)       /* Call ROM ADB Interrupt */
{
        if (mrg_romadbintr != NULL) {
#if defined(MRG_TRACE)
                tron();
#endif

                /* Gotta load a1 with VIA address. */
                /* ADB int expects it from Mac intr routine. */
                __asm volatile (
                "       movml   #0xffff,%%sp@-  \n"
                "       movl    %0,%%a0         \n"
                "       movl    " ___STRING(_C_LABEL(VIA)) ",%%a1 \n"
                "       jbsr    %%a0@           \n"
                "       movml   %%sp@+,#0xffff"
                        :
                        : "g" (mrg_romadbintr)
                        : "a0","a1");

#if defined(MRG_TRACE)
                troff();
#endif

        }
        return (1);
}

long
mrg_pmintr(void)        /* Call ROM PM Interrupt */
{
        if (mrg_rompmintr != NULL) {
#if defined(MRG_TRACE)
                tron();
#endif

                /* Gotta load a1 with VIA address. */
                /* ADB int expects it from Mac intr routine. */
                __asm volatile (
                "       movml   #0xffff,%%sp@-  \n"
                "       movl    %0,%%a0         \n"
                "       movl    " ___STRING(_C_LABEL(VIA)) ",%%a1 \n"
                "       jbsr    %%a0@           \n"
                "       movml   %%sp@+,#0xffff"
                        :
                        : "g" (mrg_rompmintr)
                        : "a0","a1");

#if defined(MRG_TRACE)
                troff();
#endif
        }
        return (1);
}
#endif  /* MRG_ADB */


void
mrg_notrap(void)
{
        printf("Aigh!\n");
        panic("mrg_notrap: We're doomed!");
}

int
myowntrap(void)
{
        printf("Oooo!  My Own Trap Routine!\n");
        return (50);
}

int
mrg_NewPtr(void)
{
        int result = noErr;
        u_int numbytes;
/*      u_int32_t trapword; */
        char *ptr;

        __asm volatile ("movl   %%d0,%0" : "=g" (numbytes) : : "d0");

#if defined(MRG_SHOWTRAPS)
        printf("mrg: NewPtr(%d bytes, ? clear, ? sys)", numbytes);
#endif

                /* plus 4 for size */
        ptr = malloc(numbytes + 4 , M_DEVBUF, M_NOWAIT); /* ?? */
                /* We ignore "Sys;" where else would it come from? */
                /* plus, (I think), malloc clears block for us */

        if (ptr == NULL) {
                result = memFullErr;
#if defined(MRG_SHOWTRAPS)
                printf(" failed.\n");
#endif
        }else{
#if defined(MRG_SHOWTRAPS)
                printf(" succeded = %p.\n", ptr);
#endif
                *(u_int32_t *)ptr = numbytes;
                ptr += 4;
                memset(ptr, 0, numbytes); /* NewPtr, 0, Clear ! */
        }

        __asm volatile("movl    %0,%%a0" :  : "g" (ptr) : "a0");
        return (result);
}

int
mrg_DisposPtr(void)
{
        int result = noErr;
        char *ptr;

        __asm volatile("movl    %%a0,%0" : "=g" (ptr) : : "a0");

#if defined(MRG_SHOWTRAPS)
        printf("mrg: DisposPtr(%p)\n", ptr);
#endif

        if (ptr == 0)
                result = memWZErr;
        else
                free(ptr - 4, M_DEVBUF);

        return (result);
}

int
mrg_GetPtrSize(void)
{
        char *ptr;

        __asm volatile("movl    %%a0,%0" : "=g" (ptr) : : "a0");

#if defined(MRG_SHOWTRAPS)
        printf("mrg: GetPtrSize(%p)\n", ptr);
#endif

        if (ptr == 0)
                return (memWZErr);
        else
                return (*(int *)(ptr - 4));
}

int
mrg_SetPtrSize(void)
{
        void *ptr;
        int newbytes;

        __asm volatile(
        "       movl    %%a0,%0 \n"
        "       movl    %%d0,%1"
                : "=g" (ptr), "=g" (newbytes) : : "d0","a0");

#if defined(MRG_SHOWTRAPS)
        printf("mrg: SetPtrSize(%p, %d) failed\n", ptr, newbytes);
#endif

        return (memFullErr);    /* How would I handle this, anyway? */
}

int
mrg_PostEvent(void)
{
        return 0;
}

void
mrg_StripAddress(void)
{
}

int
mrg_SetTrapAddress(void)
{
        extern void *mrg_OStraps[];
        void *ptr;
        int trap_num;

        __asm volatile(
        "       movl %%a0,%0    \n"
        "       movl %%d0,%1"
                : "=g" (ptr), "=g" (trap_num) : : "d0","a0");

#if defined(MRG_DEBUG)
        printf("mrg: trap 0x%x set to 0x%lx\n", trap_num, (long)ptr);
#endif
        mrg_OStraps[trap_num] = ptr;
/*
 * If the Trap for Egret was changed, we'd better remember it!
 */
        if (trap_num == 0x92) {
#if defined(MRG_DEBUG)
                printf("mrg: reconfigured Egret address from 0x%lx to 0x%lx\n",
                    (long)jEgret, (long)ptr);
#endif
                jEgret = (void (*))ptr;
        }
        return 0;
}

/*
 * trap jump address tables (different per machine?)
 * Can I just use the tables stored in the ROMs?
 * *Is* there a table stored in the ROMs?
 * We only initialize the A-Traps for the routines we have
 *  provided ourselves.  The routines we will be trying to
 *  use out of the MacROMs will be initialized at run-time.
 * I did this to make the code easier to follow and to keep
 *  from taking an unexpected side trip into the MacROMs on
 *  those systems we don't have fully decoded.
 */
void *mrg_OStraps[256] = {
#ifdef __GNUC__
                /* God, I love gcc.  see GCC2 manual, section 2.17, */
                /* "labeled elements in initializers." */
        [0x1e]  (void *)mrg_NewPtr,
                (void *)mrg_DisposPtr,
                (void *)mrg_SetPtrSize,
                (void *)mrg_GetPtrSize,
        [0x2f]  (void *)__UNCONST(mrg_PostEvent),       /* XXXGCC ? */
        [0x3b]  (void *)mrg_Delay,      
        [0x47]  (void *)mrg_SetTrapAddress,
        [0x55]  (void *)__UNCONST(mrg_StripAddress),    /* XXXGCC ? */
        [0x82]  (void *)mrg_DTInstall,
#else
#error "Using a GNU C extension."
#endif
};

void *mrg_ToolBoxtraps[1024] = {
        [0x19c] (void *)mrg_CountResources,
        [0x19d] (void *)mrg_GetIndResource,
        [0x1a0] (void *)mrg_GetResource,
        [0x1af] (void *)mrg_ResError,
};

/*
 * Handle a supervisor mode A-line trap.
 */
void
mrg_aline_super(struct frame *frame)
{
        void *trapaddr;
        u_short trapword;
        int isOStrap;
        int trapnum;
        int a0passback;
        u_int32_t a0bucket, d0bucket;
        int danprint=0; /* This shouldn't be necessary, but seems to be.  */

#if defined(MRG_DEBUG)
        printf("mrg: a super");
#endif

        trapword = *(u_short *)frame->f_pc;

        if (trapword == 0xa71e)
                danprint = 1;

#if defined(MRG_DEBUG)
        printf(" wd 0x%lx", (long)trapword);
#endif
        isOStrap = ! TRAP_TOOLBOX(trapword);
        trapnum = TRAP_NUM(trapword);

        if (danprint) {
                /*
                 * Without these print statements, ADBReInit fails on IIsi
                 * It is unclear why--perhaps a compiler bug?  delay()s do not
                 * work, nor does some assembly similar to the  printf calls.
                 * A printf(""); is sufficient, but gcc -Wall is noisy about
                 * it, so I figured backspace is harmless enough...
                 */
                printf(" "); printf("\010");
        }

#if defined(MRG_DEBUG)
        printf(" %s # 0x%x", isOStrap? "OS" :
                "ToolBox", trapnum);
#endif

        /*
         * Only OS Traps come to us; alinetrap() takes care of ToolBox
         * traps, which are a horrible Frankenstein-esque abomination.
         */

        trapaddr = mrg_OStraps[trapnum];
#if defined(MRG_DEBUG)
        printf(" addr 0x%lx\n", (long)trapaddr);
        printf("    got:    d0 = 0x%8x,  a0 = 0x%8x, called from: 0x%8x\n",
                frame->f_regs[0], frame->f_regs[8], frame->f_pc );
#endif
        if (trapaddr == NULL) {
                printf("unknown %s trap 0x%x, no trap address available\n",
                        isOStrap ? "OS" : "ToolBox", trapword);
                panic("mrg_aline_super()");
        }
        a0passback = TRAP_PASSA0(trapword);

#if defined(MRG_TRACE)
        tron();
#endif

/*      put a0 in a0 */
/*      put a1 in a1 */
/*      put d0 in d0 */
/*      put d1 in d1 */
/*      put trapaddr in a2 */
/* save a6 */
/*      call the damn routine */
/* restore a6 */
/*      store d0 in d0bucket */
/*      store a0 in d0bucket */
/* This will change a2,a1,d1,d0,a0 and possibly a6 */

        __asm volatile (
        "       movl    %2@,%%d0        \n"
        "       movl    %2@(4),%%d1     \n"
        "       movl    %2@(32),%%a0    \n"
        "       movl    %2@(36),%%a1    \n"
        "       movl    %3,%%a2         \n"
        "       jbsr    %%a2@           \n"
        "       movl    %%a0,%0         \n"
        "       movl    %%d0,%1"

                : "=g" (a0bucket), "=g" (d0bucket)

                : "a" (&frame->f_regs), "g" (trapaddr)

                : "d0","d1","a0","a1","a2"
);

#if defined(MRG_TRACE)
        troff();
#endif
#if defined(MRG_DEBUG)
        printf("    result: d0 = 0x%8x,  a0 = 0x%8x\n",
                d0bucket, a0bucket );
        printf(" bk");
#endif

        frame->f_regs[0] = d0bucket;
        if (a0passback)
                frame->f_regs[8] = a0bucket;

        frame->f_pc += 2;       /* skip offending instruction */

#if defined(MRG_DEBUG)
        printf(" exit\n");
#endif
}

extern u_int32_t traceloopstart[];
extern u_int32_t traceloopend;
extern u_int32_t *traceloopptr;

void
dumptrace(void)
{
#if defined(MRG_TRACE)
        u_int32_t *traceindex;

        printf("instruction trace:\n");
        traceindex = traceloopptr + 1;
        while (traceindex != traceloopptr) {
                printf("    %08x\n", *traceindex++);
                if (traceindex == &traceloopend)
                        traceindex = &traceloopstart[0];
        }
#else
        printf("mrg: no trace functionality enabled\n");
#endif
}

        /* To find out if we're okay calling ROM vectors */
int
mrg_romready(void)
{
        return (mrg_romident != NULL);
}

extern unsigned long    IOBase;
extern volatile u_char  *sccA;

        /* initialize Mac ROM Glue */
void
mrg_init(void)
{
        const char *findername = "MacBSD FakeFinder";
        int i;
#if defined(MRG_TEST)
        void *ptr;
        short rcnt;
        int sizeptr;
        extern short mrg_ResErr;
        void **handle;
#endif
        
        /*
         * Clear the VBLQueue.
         */
        VBLQueue = (u_int16_t) 0;
        VBLQueue_head = (void *) 0;
        VBLQueue_tail = (void *) 0;
                                         
#if defined(MRG_TEST)
        if (ROMResourceMap) {
                printf("mrg: testing CountResources\n");
                __asm volatile (
                "       clrl    %%sp@-  \n"
                "       clrl    %%sp@-  \n"
                "       .word   0xa99c  \n"
                "       movw    %%sp@+,%0"
                        : "=g" (rcnt));
                printf("mrg: found %d resources in ROM\n", rcnt);
                __asm volatile (
                "       clrl    %%sp@-  \n"
                "       movl    #0x44525652,%%sp@-      \n"
                "       .word   0xa99c  \n"
                "       movw    %%sp@+,%0"
                        : "=g" (rcnt));
                printf("mrg: %d are DRVR resources\n", rcnt);
                if (rcnt == 0)
                        panic("Oops! No DRVR Resources found in ROM");
        }
#endif
#if defined(MRG_TEST)
        if (ROMResourceMap) {
                printf("mrg: testing GetIndResource\n");
                __asm volatile (
                "       clrl    %%sp@-          \n"
                "       movl    #0x44525652,%%sp@-      \n"
                "       movw    #0x01,%%sp@-    \n"
                "       .word   0xa99d          \n"
                "       movl    %%sp@+,%0"
                        : "=g" (handle));
                printf("Handle to first DRVR resource is %p\n", handle);
                printf("DRVR: 0x%08lx -> 0x%08lx -> 0x%08lx\n",
                    (long)Get_Ind_Resource(0x44525652, 1),
                    (long)*Get_Ind_Resource(0x44525652, 1),
                    (long)*((u_int32_t *)*Get_Ind_Resource(0x44525652, 1)));
                __asm volatile (
                "       clrl    %%sp@-          \n"
                "       movl    #0x44525652,%%sp@-      \n"
                "       movw    #0x02,%%sp@-    \n"
                "       .word   0xa99d          \n"
                "       movl    %%sp@+,%0"
                        : "=g" (handle));
                printf("Handle to second DRVR resource is %p\n", handle);
                printf("DRVR: 0x%08lx -> 0x%08lx -> 0x%08lx\n",
                    (long)Get_Ind_Resource(0x44525652, 2),
                    (long)*Get_Ind_Resource(0x44525652, 2),
                    (long)*((u_int32_t *)*Get_Ind_Resource(0x44525652, 2)));
        }
#endif
        if (mrg_romready()) {
                printf("mrg: '%s' ROM glue", mrg_romident);

#if defined(MRG_TRACE)
#if defined(MRG_FOLLOW)
                printf(", tracing on (verbose)");
#else /* ! defined (MRG_FOLLOW) */
                printf(", tracing on (silent)");
#endif /* defined(MRG_FOLLOW) */
#else /* !defined(MRG_TRACE) */
                printf(", tracing off");
#endif  /* defined(MRG_TRACE) */

#if defined(MRG_DEBUG)
                printf(", debug on");
#else /* !defined(MRG_DEBUG) */
                printf(", debug off");
#endif /* defined(MRG_DEBUG) */

#if defined(MRG_SHOWTRAPS)
                printf(", verbose traps");
#else /* !defined(MRG_SHOWTRAPS) */
                printf(", silent traps");
#endif /* defined(MRG_SHOWTRAPS) */
        }else{
                printf("mrg: kernel has no ROM vectors for this machine!\n");
                return;
        }

        printf("\n");

#if defined(MRG_DEBUG)
        printf("mrg: start init\n");
#endif
                /* expected globals */
        ExpandMem = &mrg_ExpandMem[0];
        *((u_int16_t *)(mrg_ExpandMem + 0x00) ) = 0x0123;       /* magic (word) */
        *((u_int32_t *)(mrg_ExpandMem + 0x02) ) = 0x000001ea;   /* Length of table (long) */
        *((u_int32_t *)(mrg_ExpandMem + 0x1e0)) = (u_int32_t) &mrg_adbstore4[0];

        *((u_int32_t *)(mrg_adbstore4 + 0x8)) = (u_int32_t) mrg_init_stub_1;
        *((u_int32_t *)(mrg_adbstore4 + 0xc)) = (u_int32_t) mrg_init_stub_2;
        *((u_int32_t *)(mrg_adbstore4 + 0x4)) = (u_int32_t) &mrg_adbstore5[0];

        *((u_int32_t *)(mrg_adbstore5 + 0x08)) = (u_int32_t) 0x00100000;
        *((u_int32_t *)(mrg_adbstore5 + 0x0c)) = (u_int32_t) 0x00100000;
        *((u_int32_t *)(mrg_adbstore5 + 0x16)) = (u_int32_t) 0x00480000;

        ADBBase = &mrg_adbstore[0];
        ADBState = &mrg_adbstore2[0];
        ADBYMM = &mrg_adbstore3[0];
        MinusOne = 0xffffffff;
        Lo3Bytes = 0x00ffffff;
        VIA = (void *)__UNVOLATILE(Via1Base);
        MMU32Bit = 1; /* ?means MMU is in 32 bit mode? */
        if (TimeDBRA == 0)
                TimeDBRA = 0xa3b;               /* BARF default is Mac II */
        if (ROMBase == 0)
                panic("ROMBase not set in mrg_init()!");

        strcpy(&FinderName[1], findername);
        FinderName[0] = (u_char) strlen(findername);
#if defined(MRG_DEBUG)
        printf("After setting globals\n");
#endif

                /* Fake jump points */
        for (i = 0; i < 8; i++) /* Set up fake Lvl1DT */
                Lvl1DT[i] = mrg_lvl1dtpanic;
        for (i = 0; i < 8; i++) /* Set up fake Lvl2DT */
                Lvl2DT[i] = mrg_lvl2dtpanic;
        Lvl1DT[0] = (void (*)(void))mrg_1sec_timer_tick;
        Lvl1DT[2] = (void (*)(void))mrg_romadbintr;
        Lvl1DT[4] = (void (*)(void))mrg_rompmintr;
        JADBProc = mrg_jadbprocpanic;   /* Fake JADBProc for the time being */
        jSwapMMU = mrg_jswapmmupanic;   /* Fake jSwapMMU for the time being */
        JKybdTask = mrg_jkybdtaskpanic; /* Fake JKybdTask for the time being */

        /* probably very dangerous */
        jADBOp = (void (*)(void))mrg_OStraps[0x7c];

        mrg_VIA2 = (void *)((char *)__UNVOLATILE(Via1Base) + 
            VIA2 * 0x2000);     /* see via.h */
        SCCRd = (void *)__UNVOLATILE(sccA);/* ser.c ; we run before serinit */

        jDTInstall = (void *)mrg_DTInstall;
        dtmgr_softintr_cookie = softint_establish(SOFTINT_SERIAL,
            (void (*)(void *))mrg_execute_deferred, NULL);

        /* AV ROMs want this low memory vector to point to a jump table */
        InitEgretJTVec = (u_int32_t **)(void *)&mrg_AVInitEgretJT;

        switch (mach_cputype()) {
                case MACH_68020:        CPUFlag = 2;    break;
                case MACH_68030:        CPUFlag = 3;    break;
                case MACH_68040:        CPUFlag = 4;    break;
                default:
                        printf("mrg: unknown CPU type; cannot set CPUFlag\n");
                        break;
        }

#if defined(MRG_TEST)
        printf("Allocating a pointer...\n");
        ptr = (void *)NewPtr(1024);
        printf("Result is 0x%lx.\n", (long)ptr);
        sizeptr = GetPtrSize((Ptr)ptr);
        printf("Pointer size is %d\n", sizeptr);
        printf("Freeing the pointer...\n");
        DisposPtr((Ptr)ptr);
        printf("Free'd.\n");

        for (i = 0; i < 500000; i++)
                if ((i % 100000) == 0)printf(".");
        printf("\n");

        mrg_ResErr = 0xdead;    /* set an error we know */
        printf("Getting error code...\n");
        i = ResError();
        printf("Result code (0xdeadbaaf): %x\n", i);
        printf("Getting an ADBS Resource...\n");
        handle = GetResource(0x41244253, 2);
        printf("Handle result from GetResource: 0x%lx\n", (long)handle);
        printf("Getting error code...\n");
        i = ResError();
        printf("Result code (-192?) : %d\n", i);

        for (i = 0; i < 500000; i++)
                if ((i % 100000) == 0)printf(".");
        printf("\n");

#if defined(MRG_TRACE)
        printf("Turning on a trace\n");
        tron();
        printf("We are now tracing\n");
        troff();
        printf("Turning off trace\n");
        dumptrace();
#endif /* MRG_TRACE */

        for (i = 0; i < 500000; i++)
                if ((i % 100000) == 0)
                        printf(".");
        printf("\n");
#endif /* MRG_TEST */

#if defined(MRG_DEBUG)
        printf("after setting jump points\n");
        printf("mrg: end init\n");
#endif

#ifndef __HAVE_NEW_PMAP_68K
        /*
         * We don't need to do this in the new pmap case, because
         * we use machine_bootmap[] to map IOBase VA==PA.
         */
        if (1) {
                /*
                 * For the bloody Mac II ROMs, we have to map this space
                 * so that the PRam functions will work.
                 * Gee, Apple, is that a hard-coded hardware address in
                 * your code?  I think so! (_ReadXPRam + 0x0062 on the
                 * II)  We map the VIAs in here.  The C610 apparently
                 * needs it, too, which means that a bunch of 040s do, too.
                 * Once again, I regret the mapping changes I made...  -akb
                 */
#ifdef DIAGNOSTIC
                printf("mrg: I/O map kludge for ROMs that use hardware %s",
                        "addresses directly.\n");
#endif
                paddr_t addr = 0x50f00000;
                paddr_t end_addr = addr + 0x4000;
                while (addr < end_addr) {
                        pmap_enter(pmap_kernel(),
                            addr, addr, VM_PROT_READ|VM_PROT_WRITE, 0);
                        addr += PAGE_SIZE;
                }
                pmap_update(pmap_kernel());
        }
#endif /* ! __HAVE_NEW_PMAP_68K */
}

#ifdef MRG_ADB
static void     setup_egret(void);

static void
setup_egret(void)
{
        if (0 != mrg_InitEgret) {

        /* This initializes ADBState (mrg_ADBStore2) and
           enables interrupts */
                __asm volatile (
                "       movml   %%a0-%%a2,%%sp@-        \n"
                "       movl    %1,%%a0 \n"     /* ADBState, mrg_adbstore2 */
                "       movl    %0,%%a1 \n"
                "       jbsr    %%a1@   \n"
                "       movml   %%sp@+,%%a0-%%a2 "
                        :
                        : "g" (mrg_InitEgret), "g" (ADBState)
                        : "a0","a1");
                jEgret = (void (*)) mrg_OStraps[0x92]; /* may have been set in asm() */
        }
        else printf("Help ...  No vector for InitEgret!!\n");
        
#if defined(MRG_DEBUG)
        printf("mrg: ADBIntrVector: 0x%8lx,  mrg_ADBIntrVector: 0x%8lx\n",
                        (long) mrg_romadbintr,
                        *((long *) 0x19a));
        printf("mrg: EgretOSTrap: 0x%8lx\n",
                        (long) mrg_OStraps[0x92]);
#endif
}
#endif

void
mrg_initadbintr(void)
{
        if (mac68k_machine.do_graybars)
                printf("Got following HwCfgFlags: 0x%4x, 0x%8x, 0x%8x, 0x%8x\n",
                                HwCfgFlags, HwCfgFlags2, HwCfgFlags3, ADBReInit_JTBL);

        if ((HwCfgFlags == 0) && (HwCfgFlags2 == 0) && (HwCfgFlags3 == 0)) {
                printf("Caution: No HwCfgFlags from Booter, please "
                        "use at least booter version 1.8.\n");

                if (current_mac_model->class == MACH_CLASSIIsi) {
                        printf("     ...  Using defaults for IIsi.\n");

                        /* Egret and ADBReInit look into these HwCfgFlags */
                        HwCfgFlags = 0xfc00;    
                        HwCfgFlags2 = 0x0000773F;
                        HwCfgFlags3 = 0x000001a6;
                }

                printf("Using HwCfgFlags: 0x%4x, 0x%8x, 0x%8x\n",
                        HwCfgFlags, HwCfgFlags2, HwCfgFlags3);
        }

#ifdef MRG_ADB  
        /*
         * If we think there is an Egret in the machine, attempt to
         * set it up.  If not, just enable the interrupts (only on
         * some machines, others are already on from ADBReInit?).
         */
        if (   ((HwCfgFlags3 & 0x0e) == 0x06 )
            || ((HwCfgFlags3 & 0x70) == 0x20 )) {
                if (mac68k_machine.do_graybars)
                        printf("mrg: setup_egret:\n");

                setup_egret();

                if (mac68k_machine.do_graybars)
                        printf("mrg: setup_egret: done.\n");

        } else {

                if (mac68k_machine.do_graybars)
                        printf("mrg: Not setting up egret.\n");

                via_reg(VIA1, vIFR) = 0x4;
                via_reg(VIA1, vIER) = 0x84;

                if (mac68k_machine.do_graybars)
                        printf("mrg: ADB interrupts enabled.\n");
        }       
#else
        /* Extra Egret setup required only for MRG ADB functions. */
        printf("mrg: skipping egret setup\n");
#endif /* MRG_ADB */
}

/*
 * NOTE:  By eliminating the setvectors routine and moving its function
 *        to here we only have to deal with re-locating MacOS Addresses
 *        once and all in one place.
 */
void
mrg_fixupROMBase(void *obase, void *nbase)
{
        u_int32_t oldbase, newbase;
        romvec_t *rom;
        int i;

        oldbase = (u_int32_t) obase;
        newbase = (u_int32_t) nbase;

        /*
         * Grab the pointer to the Mac ROM Glue Vector table
         */ 
        rom = mrg_MacOSROMVectors;

        if (rom == NULL)
                return;         /* whoops!  ROM vectors not defined! */

        mrg_romident = rom->romident;

        if (0 != mrg_ADBIntrPtr) {
                mrg_romadbintr = mrg_ADBIntrPtr;
                printf("mrg_fixup: using ADBIntrPtr from booter: 0x%08lx\n",
                    (long)mrg_ADBIntrPtr);
        } else
                mrg_romadbintr = rom->adbintr == 0 ?
                    0 : (char *)rom->adbintr - oldbase + newbase;

        mrg_rompmintr = rom->pmintr == 0 ?
            0 : (char *)rom->pmintr - oldbase + newbase;
        mrg_ADBAlternateInit = rom->ADBAlternateInit == 0 ?
            0 : (char *)rom->ADBAlternateInit - oldbase + newbase;

        /*
         * mrg_adbstore becomes ADBBase
         */
        *((u_int32_t *)(mrg_adbstore + 0x130)) = rom->adb130intr == 0 ?
            0 : (u_int32_t) rom->adb130intr - oldbase + newbase;

        mrg_OStraps[0x77] = rom->CountADBs == 0 ?
            0 : (char *)rom->CountADBs - oldbase + newbase;
        mrg_OStraps[0x78] = rom->GetIndADB == 0 ?
            0 : (char *)rom->GetIndADB - oldbase + newbase;
        mrg_OStraps[0x79] = rom-> GetADBInfo == 0 ?
            0 : (char *)rom->GetADBInfo - oldbase + newbase;
        mrg_OStraps[0x7a] = rom->SetADBInfo == 0 ?
            0 : (char *)rom->SetADBInfo - oldbase + newbase;
        mrg_OStraps[0x7b] = rom->ADBReInit == 0 ?
            0 : (char *)rom->ADBReInit - oldbase + newbase;
        mrg_OStraps[0x7c] = rom->ADBOp == 0 ?
            0 : (char *)rom->ADBOp - oldbase + newbase;
        mrg_OStraps[0x85] = rom->PMgrOp == 0 ?
            0 : (char *)rom->PMgrOp - oldbase + newbase;
        mrg_OStraps[0x51] = rom->ReadXPRam == 0 ?
            0 : (char *)rom->ReadXPRam - oldbase + newbase;
        mrg_OStraps[0x38] = rom->WriteParam == 0 ?
            0 : (char *)rom->WriteParam - oldbase + newbase;/* WriteParam*/
        mrg_OStraps[0x3a] = rom->SetDateTime == 0 ?
            0 : (char *)rom->SetDateTime - oldbase + newbase;/*SetDateTime*/
        mrg_OStraps[0x3f] = rom->InitUtil == 0 ?
            0 : (char *)rom->InitUtil - oldbase + newbase;  /* InitUtil */
        mrg_OStraps[0x51] = rom->ReadXPRam == 0 ?
            0 : (char *)rom->ReadXPRam - oldbase + newbase; /* ReadXPRam */
        mrg_OStraps[0x52] = rom->WriteXPRam == 0 ?
            0 : (char *)rom->WriteXPRam - oldbase + newbase;/* WriteXPRam */

        if (rom->Egret == 0) {
                jEgret = 0;
                mrg_OStraps[0x92] = 0;
        } else {
                jEgret = (void (*))((char *)rom->Egret - oldbase + newbase);
                mrg_OStraps[0x92] = (char *)rom->Egret - oldbase + newbase;
        }
        mrg_InitEgret = rom->InitEgret == 0 ?
            0 : (char *)rom->InitEgret - oldbase + newbase;

        if (rom->jClkNoMem == 0) {
                printf("WARNING: don't have a value for jClkNoMem, ");
                printf("please contact:  walter@ghpc8.ihf.rwth-aachen.de\n");
                printf("Can't read RTC without it. Using MacOS boot time.\n");
                jClkNoMem = 0;
        } else
                jClkNoMem = (void (*))((char *)rom->jClkNoMem - oldbase + newbase);
        /*
         * Get the ToolBox Routines we may need.  These are
         * used in the ADB Initialization of some systems.
         * If we don't have the ROM addresses for these routines
         * we'll setup to catch the calls in our own dummy
         * routines. That way we can politely tell the user
         * what we'll need to complete initialization on the system.
         */
        mrg_ToolBoxtraps[0x04d] = rom->FixDiv == 0 ?
            (void *)mrg_FixDiv : (char *)rom->FixDiv - oldbase + newbase;
        mrg_ToolBoxtraps[0x068] = rom->FixMul == 0 ?
            (void *)mrg_FixMul : (char *)rom->FixMul - oldbase + newbase;

        /*
         * Some systems also require this to be setup for use in
         * ADB Initialization.  Use whatever address was provided
         * to us in the romvec table for this system. This may
         * cause a problem on some systems, and may need a better
         * Trap handler in the future.
         */
        ADBReInit_JTBL = rom->ADBReInit_JTBL == 0 ?
           0 : (u_int32_t)rom->ADBReInit_JTBL - oldbase + newbase;

        /*
         * Setup to trap unexpected access to ADBProc which is used in
         * ADB Initialization on some systems. If the correct entry
         * point in the ADBInit code is selected, this address is
         * re-configured by the ROM during initialization. This feature
         * is not currently used by NetBSD.
         */
        JADBProc = mrg_jadbprocpanic;

        /*
         * Get the address of the first (top) Resource in the ROM.
         * This will be the head of a linked list of all Resources
         * in the ROM which will be mapped in mrg_InitResources.
         */
        ROMResourceMap = rom->ROMResourceMap == 0 ?
            0 : (void (*))((char *)rom->ROMResourceMap - oldbase + newbase);

        for (i = 0; i < sizeof(mrg_AVInitEgretJT) / sizeof(mrg_AVInitEgretJT[0]); i++)
                mrg_AVInitEgretJT[i] = mrg_AVInitEgretJT[i] == 0 ?
                    0 : mrg_AVInitEgretJT[i] - oldbase + newbase;

#if defined(MRG_DEBUG)
        printf("mrg: ROM adbintr 0x%08lx -> 0x%08lx\n",
            (long)rom->adbintr, (long)mrg_romadbintr);
        printf("mrg: ROM pmintr 0x%08lx -> 0x%08lx\n",
            (long)rom->pmintr, (long)mrg_rompmintr);
        printf("mrg: OS trap 0x77 (CountADBs) = 0x%08lx -> 0x%08lx\n",
            (long)rom->CountADBs, (long)mrg_OStraps[0x77]);
        printf("mrg: OS trap 0x78 (GetIndADB) = 0x%08lx -> 0x%08lx\n",
            (long)rom->GetIndADB, (long)mrg_OStraps[0x78]);
        printf("mrg: OS trap 0x79 (GetADBInfo) = 0x%08lx -> 0x%08lx\n",
            (long)rom->GetADBInfo, (long)mrg_OStraps[0x79]);
        printf("mrg: OS trap 0x7a (SetADBInfo) = 0x%08lx -> 0x%08lx\n",
            (long)rom->SetADBInfo, (long)mrg_OStraps[0x7a]);
        printf("mrg: OS trap 0x7b (ADBReInit) = 0x%08lx -> 0x%08lx\n",
            (long)rom->ADBReInit, (long)mrg_OStraps[0x7b]);
        printf("mrg: OS trap 0x7c (ADBOp) = 0x%08lx -> 0x%08lx\n",
            (long)rom->ADBOp, (long)mrg_OStraps[0x7c]);
        printf("mrg: OS trap 0x85 (PMgrOp) = 0x%08lx -> 0x%08lx\n",
            (long)rom->PMgrOp, (long)mrg_OStraps[0x85]);
        printf("mrg: OS trap 0x92 (Egret) = 0x%08lx -> 0x%08lx\n",
            (long)rom->Egret, (long)mrg_OStraps[0x92]);
        printf("mrg: ROM ADBAltInit 0x%08lx -> 0x%08lx\n",
            (long)rom->ADBAlternateInit, (long)mrg_ADBAlternateInit);
        printf("mrg: ROM ADBReInit_JTBL 0x%08lx -> 0x%08lx\n",
            (long)rom->ADBReInit_JTBL, (long)ADBReInit_JTBL);
        printf("mrg: ROM InitEgret  0x%08lx -> 0x%08lx\n",
            (long)rom->InitEgret, (long)mrg_InitEgret);
        printf("mrg: ROM Resource list-head 0x%08lx -> 0x%08lx\n",
            (long)rom->ROMResourceMap, (long)ROMResourceMap);
#endif
}   

#ifdef MRG_ADB
void
ADBAlternateInit(void)
{
        if (0 == mrg_ADBAlternateInit) {
                ADBReInit();
        } else {
                __asm volatile (
                "       movml   %%a0-%%a6/%%d0-%%d7,%%sp@-      \n"
                "       movl    %0,%%a1         \n"
                "       movl    %1,%%a3         \n"
                "       jbsr    %%a1@           \n"
                "       movml   %%sp@+,%%a0-%%a6/%%d0-%%d7"
                        : 
                        : "g" (mrg_ADBAlternateInit), "g" (ADBBase)
                        : "a1","a3");
        }
}
#endif /* MRG_ADB */