MoreIsBetterBits/MoreInterfaceLib.c

/*
    File:       MoreInterfaceLib.c
 
    Contains:   Compatibility shim for routines not in InterfaceLib.
 
    Written by: Quinn
 
    Copyright:  Copyright © 1999 by Apple Computer, Inc., all rights reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
 
        <11>    18/10/99    Quinn   Convert MoreAssert's to, more correct, MoreAssertQ's.
        <10>     16/9/99    Quinn   Add FSM FCB accessors.
         <9>     16/8/99    Quinn   Added comment about nasty restriction with MorePBRemoteAccess.
         <8>     22/7/99    Quinn   Use correct ProcInfo in MoreAddDrive.
         <7>     15/6/99    Quinn   Added MoreBlockZero.
         <6>     15/6/99    Quinn   Fixed Gestalt Value glue for pre-8.5 systems.  Added Extended
                                    Disk Init Package routines.
         <5>     22/4/99    Quinn   Added PBRemoteAccess.
         <4>     20/4/99    Quinn   Added Gestalt Value routines.
         <3>     16/3/99    Quinn   Added MoreUTFindDrive and MoreAddDrive.  Also fixed some mixups
                                    about which traps are toolbox traps and which aren't.
         <2>      1/3/99    Quinn   Added MoreFlushCodeCacheRange.  Also some general tidy up.
         <1>     25/2/99    Quinn   First checked in.
*/
 
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
 
#include "MoreSetup.h"
 
/////////////////////////////////////////////////////////////////
// Mac OS Interfaces
 
#include <CodeFragments.h>
#include <LowMem.h>
#include <Traps.h>
#include <FSM.h>
#include <Gestalt.h>
#include <DiskInit.h>
 
/////////////////////////////////////////////////////////////////
// Our Prototypes
 
#include "MoreInterfaceLib.h"
 
/////////////////////////////////////////////////////////////////
 
// This file contains implementations of various Mac OS API routines
// that were rolled in to InterfaceLib as of Mac OS 8.5.  They are
// in the InterfaceLib stub library as of Universal Interfaces 3.2.
// This code does the magic to decide whether the routine is available
// via InterfaceLib, or whether we have to synthesise our own MixedMode
// glue (or, in some cases, implementation).
 
// If you use any of the routines in this library, you must either:
//
// a) continue to hard link to InterfaceLib, in which case you won't
//    launch on pre-8.5 systems (with a cryptic error message), or
// b) weak link to InterfaceLib, in which case you must check that you're
//    on 8.5 or later before calling any of these routine lest
//    you die by trying to call nil.
 
// You can change the definition of the following compiler variable,
// which causes these routine to always use the InterfaceLib variant.
// You'd better make sure they're available, as described above.
 
#ifndef MORE_MAC_OS_8_5_OR_LATER
    #define MORE_MAC_OS_8_5_OR_LATER 0
#endif
 
// Also, Universal Interfaces 3.2 defines macros for some missing
// low memory accessors.  For CFM code, these macros override
// the external procedure definition.  So you can no longer
// call the real accessors, even if you do depend on Mac OS 8.5
// or greater.  This hack fixes the problem.  [Radar ID 2308604]
 
#undef LMGetUnitTableEntryCount
#undef LMSetUnitTableEntryCount
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
extern pascal SInt16 MoreLMGetUnitTableEntryCount(void)
{
    if (MORE_MAC_OS_8_5_OR_LATER || (LMGetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
        return LMGetUnitTableEntryCount();
    } else {
        return *((SInt16 *) 0x01d2);
    }
}
 
extern pascal void   MoreLMSetUnitTableEntryCount(SInt16 value)
{
    if (MORE_MAC_OS_8_5_OR_LATER || (LMSetUnitTableEntryCount != (void *) kUnresolvedCFragSymbolAddress)) {
        LMSetUnitTableEntryCount(value);
    } else {
        *((SInt16 *) 0x01d2) = value;
    }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
// Mixed Mode ProcInfo Helper
 
// Bit Numbers
//
//  3         2         1         0
// 10987654321098765432109876543210
 
// Stack Based Layout
//
//                             cccc <- calling convention = kPascalStackBased (0), kCStackBased (1), kThinkCStackBased (5)
//                           ss     <- result size
//                         ss       <- stack parameter 1 size
//                       ss         <- stack parameter 2 size
//                     ss           <- stack parameter 3 size
//                   ss             <- stack parameter 4 size
//                 ss               <- stack parameter 5 size
//               ss                 <- stack parameter 6 size
//             ss                   <- stack parameter 7 size
//           ss                     <- stack parameter 8 size
//         ss                       <- stack parameter 9 size
//       ss                         <- stack parameter 10 size
//     ss                           <- stack parameter 11 size
//   ss                             <- stack parameter 12 size
 
// Register Based Layout
//
//                             cccc <- calling convention = kRegisterBased (2)
//                      rrrss       <- register result location and size
//                 rrrss            <- register parameter 1 location and size
//            rrrss                 <- register parameter 1 location and size
//       rrrss                      <- register parameter 1 location and size
//  rrrss                           <- register parameter 1 location and size
 
// Dispatched Stack Based Layout
//
//                             cccc <- calling convention = kD0DispatchedPascalStackBased (8), kD1DispatchedPascalStackBased (12), kD0DispatchedCStackBased (9), kStackDispatchedPascalStackBased (14)
//                           ss     <- result size
//                         ss       <- selector size
//                       ss         <- stack parameter 1 size
//                     ss           <- stack parameter 2 size
//                   ss             <- stack parameter 3 size
//                 ss               <- stack parameter 4 size
//               ss                 <- stack parameter 5 size
//             ss                   <- stack parameter 6 size
//           ss                     <- stack parameter 7 size
//         ss                       <- stack parameter 8 size
//       ss                         <- stack parameter 9 size
//     ss                           <- stack parameter 10 size
//   ss                             <- stack parameter 11 size
 
// Special Case Layout
//
//                             cccc <- calling convention = kSpecialCase (15)
//                       xxxxxx     <- special case selector (see "MixedMode.h")
 
// Values for "ss":
//
// 00 = kNoByteCode
// 01 = kOneByteCode
// 10 = kTwoByteCode
// 11 = kFourByteCode
 
// Values for "rrr":
//
//
// 000 = kRegisterD0
// 001 = kRegisterD1
// 010 = kRegisterD2
// 011 = kRegisterD3
// 100 = kRegisterA0
// 101 = kRegisterA1
// 110 = kRegisterA2
// 111 = kRegisterA3
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
// DriverInstallReserveMem is a bit trickier to implement than the
// previous two routines.  Basically we have get the address of the
// _DriverInstall ($A03D) trap and then call it using
// CallOSTrapUniversalProc.  There are a number of important things
// to note here:
//   a) We can just get the trap address and treat it as a UPP.
//      The trap tables are defined to contain UPPs, either pointers
//      to real 68K code, or pointers to a routine descriptor (if
//      the trap is native or fat).
//   b) We must use CallOSTrapUniversalProc, not CallUniversalProc.
//      CallOSTrapUniversalProc automatically does a number of things 
//      that are very critical for call OS traps.  See "IM:PowerPC
//      System Software", p2-42 for a full description.
//   c) When calling OS traps from PPC, it's important to get the
//      ProcInfo right.  Specifically, all OS traps assume an
//      implicit parameter of D1 as the first parameter.  After
//      that, the parameters should be defined in the order that
//      they are declared in the prototype.  If you fail to get
//      the order right, or to put D1 first, your code will work,
//      up until it encounters someone who has patched the OS trap
//      with a native or fat patch.  Then strange things will happen,
//      and you'll spend hours in MacsBug trying to figure it out.
 
// The trap number and ProcInfo description for DriverInstallReserveMem.
 
enum {
    _DriverInstallReserveMem = 0x0A43D
};
 
enum {
    uppDriverInstallProcInfo = kRegisterBased
        | REGISTER_RESULT_LOCATION(kRegisterD0)
        | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
        | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))
        | REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DRVRHeaderPtr)))
        | REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(short)))
};
 
// IMPORTANT: Previous versions of TradDriverLoaderLib defined parameter 1
// as sizeof(short), not sizeof(long).  I fixed this based on information
// I extracted from the official Apple version of this glue, in the 
// InterfaceLib implementation on Mac OS 8.5.
 
extern pascal OSErr  MoreDriverInstallReserveMem(DRVRHeaderPtr drvrPtr, DriverRefNum refNum)
{
    if (MORE_MAC_OS_8_5_OR_LATER || (DriverInstallReserveMem != (void *) kUnresolvedCFragSymbolAddress)) {
        return DriverInstallReserveMem(drvrPtr, refNum);
    } else {
        UniversalProcPtr trapAddress;
        
        // Check that I've got the ProcInfo correct.  This magic value
        // was extracted from InterfaceLib on Mac OS 8.5.
 
        MoreAssertQ(uppDriverInstallProcInfo == 0x00533822);
        
        trapAddress = GetOSTrapAddress(_DriverInstallReserveMem);
        return CallOSTrapUniversalProc(trapAddress, uppDriverInstallProcInfo, _DriverInstallReserveMem, drvrPtr, refNum);
    }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
enum {
    uppFlushCodeCacheRangeProcInfo = kRegisterBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            REGISTER_RESULT_LOCATION(kRegisterD0) |
            REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(long))) |
            REGISTER_ROUTINE_PARAMETER(2, kRegisterD1, SIZE_CODE(sizeof(long))) |
            REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(void *))) |
            REGISTER_ROUTINE_PARAMETER(4, kRegisterA1, SIZE_CODE(sizeof(unsigned long)))
};
 
extern pascal OSErr  MoreFlushCodeCacheRange(void *address, unsigned long count)
{
    if (MORE_MAC_OS_8_5_OR_LATER || (FlushCodeCacheRange != (void *) kUnresolvedCFragSymbolAddress)) {
        return FlushCodeCacheRange(address, count);
    } else {
        UniversalProcPtr trapAddress;
        
        // Check that I've got the ProcInfo correct.  This magic value
        // was extracted from InterfaceLib on Mac OS 8.5.
 
        MoreAssertQ(uppFlushCodeCacheRangeProcInfo == 0x5e671822);
        
        trapAddress = GetOSTrapAddress(_HWPriv);
        return CallOSTrapUniversalProc(trapAddress, uppFlushCodeCacheRangeProcInfo, 9, _HWPriv, address, count);
    }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
enum {
    uppUTFindDriveProcInfo = kD0DispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(long))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SInt16))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(DrvQElPtr *))),
    uppUTLocateFCBProcInfo = kD0DispatchedPascalStackBased
             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
             | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(VCBPtr)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(StringPtr)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(short*)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(FCBRecPtr*))),
    uppUTLocateNextFCBProcInfo = kD0DispatchedPascalStackBased
             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
             | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(VCBPtr)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(StringPtr)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(short*)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(FCBRecPtr*))),
    uppUTIndexFCBProcInfo = kD0DispatchedPascalStackBased
             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
             | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(VCBPtr)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(short*)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(FCBRecPtr*))),
    uppUTResolveFCBProcInfo = kD0DispatchedPascalStackBased
             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
             | DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kFourByteCode)
             | DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
             | DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(FCBRecPtr*)))
};
 
extern pascal OSErr MoreUTFindDrive(SInt16 driveNum, DrvQElPtr *driveQElementPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (UTFindDrive != (void *) kUnresolvedCFragSymbolAddress)) {
            return UTFindDrive(driveNum, driveQElementPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppUTFindDriveProcInfo == 0x0EE8);
            
            trapAddress = GetToolTrapAddress(_HFSUtilDispatch);
            return CallUniversalProc(trapAddress, uppUTFindDriveProcInfo, 15, driveNum, driveQElementPtr);
        }
}
 
extern pascal OSErr MoreUTLocateFCB(VCBPtr              volCtrlBlockPtr,
                                 unsigned long          fileNum,
                                 StringPtr              namePtr,
                                 short *                fileRefNum,
                                 FCBRecPtr *            fileCtrlBlockPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (UTLocateFCB != (void *) kUnresolvedCFragSymbolAddress)) {
            return UTLocateFCB(volCtrlBlockPtr, fileNum, namePtr, fileRefNum, fileCtrlBlockPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppUTLocateFCBProcInfo == 0x03FFE8);
            
            trapAddress = GetToolTrapAddress(_HFSUtilDispatch);
            return CallUniversalProc(trapAddress, uppUTLocateFCBProcInfo, 2, volCtrlBlockPtr, fileNum, namePtr, fileRefNum, fileCtrlBlockPtr);
        }
}
 
extern pascal OSErr MoreUTLocateNextFCB(VCBPtr          volCtrlBlockPtr,
                                 unsigned long          fileNum,
                                 StringPtr              namePtr,
                                 short *                fileRefNum,
                                 FCBRecPtr *            fileCtrlBlockPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (UTLocateNextFCB != (void *) kUnresolvedCFragSymbolAddress)) {
            return UTLocateNextFCB(volCtrlBlockPtr, fileNum, namePtr, fileRefNum, fileCtrlBlockPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppUTLocateNextFCBProcInfo == 0x03FFE8);
            
            trapAddress = GetToolTrapAddress(_HFSUtilDispatch);
            return CallUniversalProc(trapAddress, uppUTLocateNextFCBProcInfo, 3, volCtrlBlockPtr, fileNum, namePtr, fileRefNum, fileCtrlBlockPtr);
        }
}
 
extern pascal OSErr MoreUTIndexFCB(VCBPtr               volCtrlBlockPtr,
                                 short *                fileRefNum,
                                 FCBRecPtr *            fileCtrlBlockPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (UTIndexFCB != (void *) kUnresolvedCFragSymbolAddress)) {
            return UTIndexFCB(volCtrlBlockPtr, fileRefNum, fileCtrlBlockPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppUTIndexFCBProcInfo == 0x03FE8);
            
            trapAddress = GetToolTrapAddress(_HFSUtilDispatch);
            return CallUniversalProc(trapAddress, uppUTIndexFCBProcInfo, 4, volCtrlBlockPtr, fileRefNum, fileCtrlBlockPtr);
        }
}
 
extern pascal OSErr MoreUTResolveFCB(short              fileRefNum,
                                 FCBRecPtr *            fileCtrlBlockPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (UTResolveFCB != (void *) kUnresolvedCFragSymbolAddress)) {
            return UTResolveFCB(fileRefNum, fileCtrlBlockPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppUTResolveFCBProcInfo == 0x0EE8);
            
            trapAddress = GetToolTrapAddress(_HFSUtilDispatch);
            return CallUniversalProc(trapAddress, uppUTResolveFCBProcInfo, 5, fileRefNum, fileCtrlBlockPtr);
        }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
enum {
    uppAddDriveProcInfo = kRegisterBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            REGISTER_RESULT_LOCATION(kRegisterD0) |
            REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(short))) |
            REGISTER_ROUTINE_PARAMETER(2, kRegisterA0, SIZE_CODE(sizeof(DrvQElPtr))) |
            REGISTER_ROUTINE_PARAMETER(3, kRegisterD0, SIZE_CODE(sizeof(long)))
};
 
// Some comments about the ProcInfo value:
//
// o It's set to return a result even though the high-level glue doesn't.
//   This is because the trap returns a result in D0.  We can safely ignored
//   it from the C code.
//
// o The D1 parameter is listed as sizeof(short), not sizeof(long) which is
//   the size used by most other OS traps.  The reason: I'm not sure.
//   Come to think of it, sizeof(short) makes more sense to me because
//   that's what trap words are.  Anyway, I'm just parroting what
//   InterfaceLib 8.5 does; my specific goal is to make CFM patches to
//   AddDrive work properly, which requires that we all use identical
//   ProcInfo's.
//
// o Register D0 contains the drvrRefNum and drvNum parameters combined,
//   with drvNum in the high word and drvrRefNum in the low word.
//   Oh, those wacky 68K calling conventions (-:
 
extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
{
    UInt32 response;
    
    if ( MORE_MAC_OS_8_5_OR_LATER || ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x0850))) {
        AddDrive(drvrRefNum, drvNum, qEl);
    } else {
        UniversalProcPtr trapAddress;
 
        // Prior to Mac OS 8.5, the InterfaceLib glue for AddDrive was
        // messed up, so we have to roll our own.
        
        // Check that I've got the ProcInfo correct.  This magic value
        // was extracted from InterfaceLib on Mac OS 8.5.
 
        MoreAssertQ(uppAddDriveProcInfo == 0x0733022);
        
        trapAddress = GetOSTrapAddress(_AddDrive);
        (void) CallOSTrapUniversalProc(trapAddress, uppAddDriveProcInfo, _AddDrive, qEl, ( ((UInt32) drvNum) << 16) | (UInt16) drvrRefNum);
    }
}
 
#else
 
// Unlike most of these glue routines, the 68K version of AddDrive 
// is implemented as link-in glue.  Thus there are no inlines in the
// interface file.  We therefore have to implement this routine for
// classic 68K, as a simple call through to the real routine.
 
extern pascal void MoreAddDrive(DriverRefNum drvrRefNum, SInt16 drvNum, DrvQElPtr qEl)
{
    AddDrive(drvrRefNum, drvNum, qEl);
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
enum {
    _GestaltValue = 0xABF1
};
 
enum {
    uppNewGestaltValueProcInfo = kD0DispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
    uppReplaceGestaltValueProcInfo = kD0DispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
    uppSetGestaltValueProcInfo = kD0DispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))),
    uppDeleteGestaltValueProcInfo = kD0DispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(OSType)))
};
 
// The glue I use here is especially cheesy.  In general, I try
// to avoid using the pre-processor for generating bogus C syntax,
// ie I only use #if where I could syntactically use if().  However,
// in this case I've been forced to break my own rules.  The problem
// is that NewGestaltValue etc are not present in Universal Interface's
// 3.2 InterfaceLib for CFM-68K.  Why?  I don't know for sure, but it
// could be because they are only available in the real InterfaceLib for
// Mac OS 8.5 and higher, and that can't be run on 68K machines.  Anyway,
// given that they're not available in InterfaceLib, you can't reference
// the symbol in the CFM-68K build, which requires ugly preprocessor
// stuff.  There may be a better way of doing this, but I'm pushed for
// time right now.  I hope to revisit it eventually.
// -- Quinn, 20 Apr 1999
 
extern pascal OSErr MoreNewGestaltValue(OSType selector, long newValue)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (NewGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
            return NewGestaltValue(selector, newValue);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppNewGestaltValueProcInfo == 0x00000FA8);
            
            trapAddress = GetToolboxTrapAddress(_GestaltValue);
            return CallUniversalProc(trapAddress, uppNewGestaltValueProcInfo, 0x0401, selector, newValue);
        }
}
 
extern pascal OSErr MoreReplaceGestaltValue(OSType selector, long replacementValue)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (ReplaceGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
            return ReplaceGestaltValue(selector, replacementValue);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppReplaceGestaltValueProcInfo == 0x00000FA8);
            
            trapAddress = GetToolboxTrapAddress(_GestaltValue);
            return CallUniversalProc(trapAddress, uppReplaceGestaltValueProcInfo, 0x0402, selector, replacementValue);
        }
}
 
extern pascal OSErr MoreSetGestaltValue(OSType selector, long newValue)     
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (SetGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
            return SetGestaltValue(selector, newValue);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppSetGestaltValueProcInfo == 0x00000FA8);
            
            trapAddress = GetToolboxTrapAddress(_GestaltValue);
            return CallUniversalProc(trapAddress, uppSetGestaltValueProcInfo, 0x0404, selector, newValue);
        }
}
 
extern pascal OSErr MoreDeleteGestaltValue(OSType selector)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (DeleteGestaltValue != (void *) kUnresolvedCFragSymbolAddress)) {
            return DeleteGestaltValue(selector);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppDeleteGestaltValueProcInfo == 0x000003A8);
            
            trapAddress = GetToolboxTrapAddress(_GestaltValue);
            return CallUniversalProc(trapAddress, uppDeleteGestaltValueProcInfo, 0x0203, selector);
        }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
// Golly, this one is ugly.  In prior to ARA 3.0, this trap was
// implemented by 68K code that used D0 as a selector.  But
// with ARA 3.0, this trap is implemented by PowerPC code whose
// ProcInfo doesn't include the D0 selector.  So, you can either
// declare the ProcInfo to include the selector, and then you won't
// work with ARA 3.0 and higher, or you can declare it without
// the selector, in which case register D0 won't be set up
// and you won't work with ARA < 3.0.  Nasty.
//
// The long term solution is to check the version number of ARA
// and do the right thing for each version.  Alas, I don't have
// time to code and test that solution.  So I'm sticking with
// the ARA 3.x solution for the moment.
//
// Bletch!
//
// Quinn, 16 Aug 1999
 
enum {
    _RemoteAccess = 0xAA5B
};
 
enum {
    uppPBRemoteAccessProcInfo = kPascalStackBased
         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(TPRemoteAccessParamBlock)))
         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Boolean)))
};
 
extern pascal OSErr MorePBRemoteAccess(TPRemoteAccessParamBlock paramBlock, Boolean async)
    // There is still no InterfaceLib entry for PBRemoteAccess, so
    // we always do the CallUniversalProc thing.
{
    UniversalProcPtr trapAddress;
    
    trapAddress = GetToolboxTrapAddress(_RemoteAccess);
    return CallUniversalProc(trapAddress, uppPBRemoteAccessProcInfo, paramBlock, async);
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
#if TARGET_RT_MAC_CFM
 
enum {
    uppDIXFormatProcInfo = kStackDispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Boolean))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(unsigned long))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(unsigned long *))),
    uppDIXZeroProcInfo = kStackDispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ConstStr255Param))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(unsigned long))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(void *))),
    uppDIReformatProcInfo = kStackDispatchedPascalStackBased |
            RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
            DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(short))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(ConstStr255Param))) |
            DISPATCHED_STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(ConstStr255Param)))
};
 
// These routines use the same cheesy glue structure as the Gestalt Value
// routines, for much the same reasons.  See the comment above MoreNewGestaltValue
// for more details.
 
extern pascal OSErr MoreDIXFormat(   short                  drvNum,
                                     Boolean                fmtFlag,
                                     unsigned long          fmtArg,
                                     unsigned long *        actSize)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (DIXFormat != (void *) kUnresolvedCFragSymbolAddress)) {
            return DIXFormat(drvNum, fmtFlag, fmtArg, actSize);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppDIXFormatProcInfo == 0x0000F6AE);
            
            trapAddress = GetToolboxTrapAddress(_Pack2);
            return CallUniversalProc(trapAddress, uppDIXFormatProcInfo, 0x000C, drvNum, fmtFlag, fmtArg, actSize);
        }
}
 
extern pascal OSErr MoreDIXZero(     short                  drvNum,
                                     ConstStr255Param       volName,
                                     short                  fsid,
                                     short                  mediaStatus,
                                     short                  volTypeSelector,
                                     unsigned long          volSize,
                                     void *                 extendedInfoPtr)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (DIXZero != (void *) kUnresolvedCFragSymbolAddress)) {
            return DIXZero(drvNum, volName, fsid, mediaStatus, volTypeSelector, volSize, extendedInfoPtr);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppDIXZeroProcInfo == 0x003EAEAE);
            
            trapAddress = GetToolboxTrapAddress(_Pack2);
            return CallUniversalProc(trapAddress, uppDIXZeroProcInfo, 0x000E, drvNum, volName, fsid, mediaStatus, volTypeSelector, volSize, extendedInfoPtr);
        }
}
 
 
extern pascal OSErr MoreDIReformat(  short                  drvNum,
                                     short                  fsid,
                                     ConstStr255Param       volName,
                                     ConstStr255Param       msgText)
{
    #if !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (DIReformat != (void *) kUnresolvedCFragSymbolAddress)) {
            return DIReformat(drvNum, fsid, volName, msgText);
        } else
    #endif
        {
            UniversalProcPtr trapAddress;
            
            // Check that I've got the ProcInfo correct.  This magic value
            // was extracted from InterfaceLib on Mac OS 8.5.
 
            MoreAssertQ(uppDIReformatProcInfo == 0x0000FAAE);
            
            trapAddress = GetToolboxTrapAddress(_Pack2);
            return CallUniversalProc(trapAddress, uppDIReformatProcInfo, 0x0010, drvNum, fsid, volName, msgText);
        }
}
 
#endif
 
/////////////////////////////////////////////////////////////////
 
// the routine uses the same cheesy glue structure as the Gestalt Value
// routines, for much the same reasons.  See the comment above MoreNewGestaltValue
// for more details.
 
extern pascal void MoreBlockZero(void * destPtr, Size byteCount)
{
    #if TARGET_RT_MAC_CFM && !TARGET_CPU_68K
        if (MORE_MAC_OS_8_5_OR_LATER || (BlockZero != (void *) kUnresolvedCFragSymbolAddress)) {
            BlockZero(destPtr, byteCount);
        } else 
    #endif
        {
            UInt8 *cursor;
            
            cursor = (UInt8 *) destPtr;
            while (byteCount != 0) {
                *cursor = 0;
                cursor += 1;
                byteCount -= 1;
            }
        }
}
 
/////////////////////////////////////////////////////////////////