sys7.1-doc-wip/OS/SCSIMgr4pt3/XPT.c
2019-07-27 22:37:48 +08:00

1450 lines
43 KiB
C

/*
File: XPT.c
Contains: routines that implement the CAM Transport layer
Entry points:
OSErr SCSITrap (short scsiSelector, SCSI_PB *pbPtr )
Single entry point (Jerry's _NewSCSI trap). Uses scsiSelector to choose a routine
from those shown below.
Client Calls
void SCSIAction (SCSI_PB *, Boolean syncCall, void (*callback)())
SCSI_PB *NewSCSI_PB (void)
void DisposeSCSI_PB (SCSI_PB *)
OS Module Calls
OSErr InitSCSIMgr ()
long SCSIRegisterBus (SIMinitInfo * SIMinfo)
Called to register a SCSI bus for use with the XPT.
Several characteristics of the Bus are specified as well as the software
entry points and the number of bytes required for a static data space
(for global variables). The XPT returns a BusID that will be used for
that Bus as well as a pointer to the allocated static space.
SIMinitInfo is defined as shown:
typedef struct { // directions are for SCSIRegisterBus call ( -> parm, <- result)
long staticSize; // -> num bytes SIM needs for static vars
void (*SIMinit)(); // -> pointer to the SIM init routine
void (*SIMaction)(); // -> pointer to the SIM action routine
Boolean oldCallCapable; // -> T if this SIM can handle old-API calls
ushort busID; // <- bus number for the registered bus
char * SIMstaticPtr; // <- alloc. ptr to the SIM's static vars
} SIMinitInfo;
OSErr SCSIDeregisterBus (ushort busID)
void SCSIAsyncEvent (long what,
ushort busID,
ushort targetID,
ushort lun,
long dataBfr,
long dataCnt)
Written by: Paul Wolf
Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<SM33> 2/1/94 DCB Making sure our busy patch version gets set.
<SM32> 1/31/94 DCB Fixed a bug in the way I checked the version number for the SCSI
Busy patch.
<SM31> 1/25/94 DCB Getting rid of compiler warning.
<SM30> 1/25/94 DCB Don't block interrupts when polling since this screws up
interrupt latency and besides we have the file system patches
now.
<ML4> 1/9/94 pdw Added check for SCSIBusyPatch version number so that init can
run and only patch when necessary.
<ML3> 1/5/94 pdw Converted SCSIGlobal uses to new format and rolled in new
SCSIBusy Patch.
<ML2> 12/15/93 pdw Checking in for the build.
<SM28> 12/19/93 DCB Poll at all interrupt levels now since we might have a deferred
task pending but not an interrupt. Also block interrupts at
level 2 if not already blocked so we don't get re-entered when
we don't expect it. This won't crash the SCSI Manager but could
lead to calling a completion routine when syncUnsafe is non-zero
which causes file system headaches until SCSI Busy gets fixed.
<SM27> 11/22/93 pdw Rolling in from <MCxx>.
<MC7> 11/11/93 pdw Added support back in for forceSyncAlways debugging.
<MC6> 11/10/93 pdw Added forceSync functionality which is used only when inDebugger
and interrupts are blocked. This fixes the hang using Macsbug
log which was caused by the FSCallAsync-always change to the
File System.
<MC5> 11/5/93 pdw Series of attempts and re-attempts to fix various VM/FileShare
problems.
<SM26> 10/29/93 DCB <MC> roll-in.
<MC4> 10/28/93 pdw Added fix: we didn't use to return the result in D0 in
synchronous requests like we were supposed to. Now we do.
<SM25> 10/14/93 pdw <MC> roll-in.
<MC3> 10/12/93 pdw Added support for Synchronous data transfers, rewrote State
Machine, message handling etc.
<MC2> 9/26/93 pdw Had to add a header file because of changes elsewhere.
<SM24> 9/12/93 pdw Removed SIMRegisterHAL support. Check for nonzero staticSize
before allocating globals for SIM. Fixed up the reregister stuff
a bit - moved common register/reregister stuff into sepearate
routine. Added ability to alloc new SIM globals in Reregister.
<SM23> 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug
stuff.
<SM22> 8/13/93 pdw Added check for nonZeroStatus to see if CallComp should do a
virtual ID mapping.
<SM21> 7/17/93 pdw Lots of little things.
<SM20> 7/8/93 pdw Adding record events around Inquiry, GetVirtualID and Create
Xref calls.
<SM19> 7/1/93 pdw Fixed RemoveRefNum bug where it would always return an error.
We now "return" after setting up the noErr return value.
<SM18> 6/29/93 pdw Massive checkins: Change asynchronicity mechanism to CallMachine
stack switching mechanism. Adding support for Cold Fusion.
Rearranging HW/SW Init code. Some code optimizations.
<SM17> 5/29/93 PW Adding SCSIDebug.h to includes.
<SM16> 5/25/93 DCB Rollin from Ludwig. (The next item below)
<LW15> 5/20/93 DCB Added call to ciDebuggerPatch. This is a patch to _DebugUtil
which prevents deferred completion routines from occuring when
we are in a debugger.
<SM15> 5/5/93 PW Converted names to meanies-friendly names. Updated with latest
from Ludwig stuff.
<LW14> 5/1/93 PW Added check for non-zero QLink to allow clients to see if we
support pre-linked requests. Changed one last name:
SCSI_RegisterWithNewXPT.
<LW13> 4/30/93 DCB Remove InitXPTRecorder if recording is turned off.
<LW11> 4/14/93 DCB Added ReRegisterAll Sims and fixed several bugs in the
re-register SIM call. This allows us to install a new XPT at a
later date.
<LW10> 4/13/93 MB (Really DCB) Fixing sign extension problem in GetRefNum.
<LW9> 3/26/93 PW Rolling in SuperMario changes. Removing useless RejectMsg stuff.
Changed refNumXref stuff to use -1 in bus field instead of -1 in
whole device ident as magic value.
<SM13> 3/20/93 PW Removing EnableUserCode/DisableUserCode calls from
CallCompRoutine, SIMAction… - leaving it up to the SIM to do
these calls instead (if necessary for that SIM).
<LW8> 3/1/93 DCB Changed parameters to CallCompRoutine to make life easier for
developers.
<LW7> 2/17/93 PW Adding forceSyncAlways stuff (from PDM) because it will be
useful for running benchmarks.
<SM12> 2/4/93 PW Enabled BusInquiry on PDM. Fixed forceSync stuff by making
callback from XPTAction.
<SM11> 1/31/93 PW Update from the latest of Ludwig. Also changes required for PDM
(will update Ludwig with these as needed myself).
<LW6> 1/30/93 PW Added glue code for calling completion routines (saving
registers that were getting trashed by File Manager).
<LW5> 1/27/93 PW Added clear of diReserved in GetRefNum.
<LW4> 1/27/93 PW Removed "fix" for 'double completion on autosense" bug. Fixed it
a much better way in CompAutoSense (a way that works).
<LW3> 1/12/93 DCB Added enable and disable user code calls around calls to
completion routines to allow page faults in the completion
routines.
<LW2> 1/8/93 PW Adding Disable/Enable user code calls around call to completion
routine to fix async comp -> old-API deadlock bug. Added ISRs 8
through 0x0F to complete the set. Removed explicit Quadra int
support from DispatchISR.
<SM10> 12/9/92 PW Got rid of selective DoVirtualMap stuff. Now we always do the
mapping.
<SM9> 12/5/92 PW Handle returned fail from CallSIMaction. Added SetAsyncCallback
partial support. Changed RefNum function names. Added
InterleaveFactor support. Added check for invalid bus num in
CallSIMaction.
<SM8> 11/20/92 PW Added some Includes that were removed from headers. Changed
InitXPT & XPTregBus to reflect change from linked list of
BusInfos to array. Removed DItoBus macro. Added maxbuses (16)
restriction to XPTregBus. Added error checking. Added init of
new fn ptrs to SIMinfo. Made Abort,Term,Reset async callbacks
work. Changed sync from scSync flag to scComp=0. Removed
EngineInq, Setup & DecodeDI. Removed calling of CompFn on XPT
errs. Filled out XPT_ISR2 & 3.
<SM7> 11/1/92 DCB Fixed finalStatus length bug in CallCompRoutine that was
stripping off the top byte of the scsiResult.
<SM6> 10/30/92 DCB Changed over to multiple ISR routines for improved efficiency
<SM5> 10/8/92 PW Added variable-sized SCSI_IO support. Lots of trivial name
changes.
<SM4> 9/17/92 PW Added check for function code not supported.
<SM3> 9/14/92 DCB Added some Parameter Block validation.
<SM2> 8/1/92 PW Added comments.
*/
#include <Types.h>
#include <Memory.h>
#include <OSUtils.h>
#include <Errors.h>
#include <SCSIStandard.h>
#include <SCSI.h>
#include <Slots.h>
#include <Start.h>
#include "CUtils.h"
#include "ACAM.h"
#include "SCSIDebug.h"
#include "SCSIGlue.h"
#include "BootItt.h" // for IsItt
#include "XPT.h"
#include "XPTpriv.h"
#include "Recorder.h"
#ifdef TESTGLOBALS
extern short testGlobal3;
extern short testGlobal2;
extern short testGlobal1;
#endif
#define GetVBLQHdr() ((QHdrPtr) 0x0160)
#define inVBL 6
// ************ Internal-only Function Prototypes **************
void SetRefNum( SCSI_Driver_PB *, XPTglobals * );
void GetRefNum( SCSI_Driver_PB *, XPTglobals * );
void RemoveRefNum( SCSI_Driver_PB *, XPTglobals * );
OSErr ReRegisterAllSIMs( XPTglobals *);
OSErr XPTRegisterBus( SIMinitInfo * SIMinfo, XPTglobals *XPTg );
OSErr XPTDeregisterBus( ushort busID, XPTglobals *XPTg );
OSErr XPTReregisterBus( SIMinitInfo * SIMinfoPtr, XPTglobals *XPTg);
void XPTRegisterCommon( SIMinitInfo * SIMinfoPtr);
OSErr XPTKillXPT( XPTglobals *XPTg);
void SyncWait( SCSI_PB *pbPtr, XPTglobals *XPTg );
void TryToRecover ( XPTglobals *XPTg);
OSErr XPTAction( SCSI_PB *pbPtr, XPTglobals *XPTg );
Boolean OldSCSIExists( void);
void InitXPTRecorder( long sizeOfTape );
void XPT_ISR0(void);
void XPT_ISR1(void);
void XPT_ISR2(void);
void XPT_ISR3(void);
void XPT_ISR4(void);
void XPT_ISR5(void);
void XPT_ISR6(void);
void XPT_ISR7(void);
void XPT_ISR8(void);
void XPT_ISR9(void);
void XPT_ISRa(void);
void XPT_ISRb(void);
void XPT_ISRc(void);
void XPT_ISRd(void);
void XPT_ISRe(void);
void XPT_ISRf(void);
/*********************************************************************************
InitXPT - Initialize XPT Globals and stuff
*********************************************************************************/
OSErr
InitXPT( void )
{
XPTglobals *XPTg;
#ifdef TESTGLOBALS
short testG;
testG = testGlobal3;
testG = testGlobal1;
#endif
InitRecorder();
// This gets a bit complicated if there is already a XPT installed. If there is
// then we need to manage the transition from the old one to the new one. This
// is accomplished by the routine ReRegisterAllSIMs:
//
// Allocate room for XPT globals and store XPTg ptr in magic spot in SCSIGlobals
XPTg = (XPTglobals *) NewPtrSysClear( sizeof(XPTglobals)); //&&&& NewPtrSysClear
if (XPTg == nil)
return (memFullErr);
// Build Driver List (for RefNum to DeviceIdent cross-ref)
XPTg->Drivers = (DrvrList *) NewPtrSysClear( sizeof(DrvrList));
if ( XPTg->Drivers == nil ) {
DisposPtr( (Ptr)XPTg);
return (memFullErr);
}
XPTg->Drivers->DrvrCnt = 0;
// Initialize static fields in the completionDT
XPTg->completionDT.qType = dtQType;
XPTg->completionDT.dtAddr = DeferredCall;
if ( ISITT() ) {
// Let the old instantiation of KillXPT know what version of busyPatch we currently use.
// It will compare this against its own linked in value and remove its patch if they
// aren't the same.
SCSIGlobals->newBusyPatchVers = kbusyPatchVers;
if( ReRegisterAllSIMs(XPTg) )
return(memFullErr);
}
else if ( OldSCSIExists() ) {
XlateOldSCSIGlobals( XPTg ); // if New is replacing Old SCSI Mgr, xlate old's globals
}
Init_SCSIXlate();
InitXPTAsm();
if( (XPTg->debugPatch = ciDebuggerPatch( (Ptr) NGetTrapAddress( _DebugUtil, OSTrap ))) != nil )
NSetTrapAddress( (long) XPTg->debugPatch, _DebugUtil, OSTrap );
if (SCSIGlobals->busyPatchVers != kbusyPatchVers) {
if( (SCSIGlobals->busyPatch = ciBusyPatch( (Ptr) NGetTrapAddress( _SCSIDispatch, ToolTrap ))) != nil ) {
NSetTrapAddress( (long) SCSIGlobals->busyPatch, _SCSIDispatch, ToolTrap );
SCSIGlobals->busyPatchVers = kbusyPatchVers;
}
}
SetXPTg( XPTg);
InitSyncWait( XPTg );
// Setup the A089 Trap
NSetTrapAddress ( (long)SCSIAtomic, 0x89, OSTrap );
return (0);
}
/*————————————————————————————————————————————————————————————————————————
OldSCSIExists -
————————————————————————————————————————————————————————————————————————*/
Boolean OldSCSIExists( void)
{
return( NGetTrapAddress(0xA815, ToolTrap) !=
NGetTrapAddress(UNIMPTRAP, ToolTrap) );
}
/*********************************************************************************
GetXPTg, SetXPTg - store and retrieve the XPT globals pointer
*********************************************************************************/
#if 0
XPTglobals *
GetXPTg( void )
{
return(*(XPTglobals **)(*((Ptr *)0xC0C) + 0x1B4) );
}
#endif
void
SetXPTg( XPTglobals *XPTg )
{
*(XPTglobals **)(*((Ptr *)0xC0C) + 0x1B4) = XPTg;
SCSIGlobals->tempXPTGInUse = 0; // Remember that we are using the real globals
}
void
SetTempXPTg( XPTglobals *XPTg )
{
SCSIGlobals->tempXPTGGlobals = XPTg; // Save the globals in a temporary spot
SCSIGlobals->tempXPTGInUse = tempXPT; // Remember that we did this
}
/*********************************************************************************
SCSITrap - This is our NewSCSI trap entry point
*********************************************************************************/
OSErr
SCSITrap( short scsiSelector, void * pbPtr )
{
XPTglobals *XPTg;
ushort busID;
XPTg = GetXPTg();
if (scsiSelector == xptSCSIAction) { // Do a SCSI_PB action
return (XPTAction( (SCSI_PB *)pbPtr, XPTg));
}
switch (scsiSelector) {
case xptSCSIRegisterBus:
return (XPTRegisterBus( (SIMinitInfo *)pbPtr, XPTg));
break;
case xptSCSIDeregisterBus:
busID = ((SCSI_PB *)pbPtr)->scsiDevice.bus;
return ( XPTDeregisterBus( busID, XPTg) );
break;
case xptSCSIReregisterBus:
return (XPTReregisterBus( (SIMinitInfo *)pbPtr, XPTg));
break;
case xptSCSIKillXPT:
return ( XPTKillXPT( XPTg) );
break;
default:
return (scsiFunctionNotAvailable);
break;
}
}
/*********************************************************************************
XPTRegisterBus - Register new SIM/HBA with Xpt
*********************************************************************************/
OSErr
XPTRegisterBus (SIMinitInfo * SIMinfoPtr, XPTglobals *XPTg)
{
ushort busID;
uchar * busG;
BusInfo *thisBusInfoPtr;
// Get next bus number and see if this one would be one too many
if (XPTg->numBuses == kMaxBuses) {
return( scsiTooManyBuses);
}
if (XPTg->numBuses > kMaxBuses) {
IfDebugStr("\pWay too many bus registrations");
return( scsiTooManyBuses);
}
// Allocate memory for SIM's static vars
if (SIMinfoPtr->staticSize) { // if SIM wants some statics
busG = (uchar *) NewPtrSysClear((Size)SIMinfoPtr->staticSize);
if (busG == 0) {
IfDebugStr("\pCouldn't allocate bus statics");
return( memFullErr);
}
}
// Get a BusInfo structure for this Bus's info
// there are some BusInfos that are allocated in the XPT's globals already so
// we try there first, if no room then we NewPtrSysClear another BusInfo spot.
if (XPTg->numBuses < kNumBusInfos) {
thisBusInfoPtr = &(XPTg->TopBusInfos[ XPTg->numBuses]);
}
else {
thisBusInfoPtr = (BusInfo *)NewPtrSysClear(sizeof(BusInfo));
if (thisBusInfoPtr == 0) {
return( memFullErr);
}
}
// At this point, we've got everything a registration needs so we can consider
// it a done deal. We will now increment the number of buses.
// and find an empty bus number for this SIM.
XPTg->numBuses+=1;
for( busID = 0; busID < XPTg->numBuses; busID+=1 ) {
if( XPTg->BusInfoPtr[busID] == nil )
break;
}
// We must put this pointer in XPT's BusInfoPtrs
XPTg->BusInfoPtr[busID] = thisBusInfoPtr;
// Set up the return values in the SIMinitInfo
SIMinfoPtr->busID = busID; // -> bus number for the registered bus
SIMinfoPtr->SIMstaticPtr = busG; // -> alloc. ptr to the SIM's static vars
// Do all the common stuff - sticking our values in the SIM's init pb
XPTRegisterCommon( SIMinfoPtr);
// Set up the XPT's BusInfo with what's known about the HBA so far
thisBusInfoPtr->initInfo = *SIMinfoPtr;
// If we need to, allocate a new SCSI_IO for old API emulation.
if ((SIMinfoPtr->ioPBSize > XPTg->xptIOpbSize) && SIMinfoPtr->oldCallCapable)
{
if (XPTg->xptIOpbSize) // if not first time thru, dispose old one
DisposPtr( (char *)(XPTg->xptIOptr));
if (NewXPTioPB( SIMinfoPtr->ioPBSize, XPTg))
return (memFullErr);
}
// If we need to, adjust the maxIOpbSize field
if (SIMinfoPtr->ioPBSize > XPTg->maxIOpbSize)
XPTg->maxIOpbSize = SIMinfoPtr->ioPBSize;
// If we got this far, call the SIMinit routine and return it's result as our result
return ( (SIMinfoPtr->SIMinit) (SIMinfoPtr) );
}
/*********************************************************************************
XPTReregisterBus - Re-Register existing SIM/HBA with XPT
*********************************************************************************/
OSErr
XPTReregisterBus (SIMinitInfo * SIMinfoPtr, XPTglobals *XPTg)
{
ushort busID;
BusInfo *thisBusInfoPtr;
// If we are in the transition from one XPT to another then use the
// temporary XPT globals
if( SCSIGlobals->tempXPTGInUse == tempXPT )
XPTg = SCSIGlobals->tempXPTGGlobals;
// Allocate memory for SIM's static vars
if (SIMinfoPtr->SIMstaticPtr == 0) { // if the SIM wants new globals
if (SIMinfoPtr->staticSize) { // and if SIM wants more than 0
SIMinfoPtr->SIMstaticPtr = (uchar *) NewPtrSysClear((Size)SIMinfoPtr->staticSize);
if (SIMinfoPtr->SIMstaticPtr == 0) {
IfDebugStr("\pCouldn't allocate bus statics");
return( memFullErr);
}
}
}
// Get the bus ID
busID = SIMinfoPtr->busID;
// Do all the common stuff - sticking our values in the SIM's init pb
XPTRegisterCommon( SIMinfoPtr);
// If we don't have a BusInfo structure for this Bus's info then go get one
// there are some BusInfos that are allocated in the XPT's globals already so
// we try there first, if no room then we NewPtrSysClear another BusInfo spot.
if( XPTg->BusInfoPtr[busID] == nil ) {
if (XPTg->numBuses < kNumBusInfos) {
thisBusInfoPtr = &(XPTg->TopBusInfos[XPTg->numBuses]);
}
else {
thisBusInfoPtr = (BusInfo *)NewPtrSysClear(sizeof(BusInfo));
if (thisBusInfoPtr == 0) {
return( memFullErr);
}
}
XPTg->numBuses+=1;
XPTg->BusInfoPtr[busID] = thisBusInfoPtr;
}
// Copy SIMinitInfo data into XPT's BusInfoPtr
XPTg->BusInfoPtr[busID]->initInfo = *SIMinfoPtr;
// If we need to, allocate a new SCSI_IO for old API emulation.
if ((SIMinfoPtr->ioPBSize > XPTg->xptIOpbSize) && SIMinfoPtr->oldCallCapable)
{
if (XPTg->xptIOptr) // if not first time thru, dispose old one
DisposPtr( (char *)(XPTg->xptIOptr));
if (NewXPTioPB( SIMinfoPtr->ioPBSize, XPTg))
return (memFullErr);
}
// If we need to, adjust the maxIOpbSize field
if (SIMinfoPtr->ioPBSize > XPTg->maxIOpbSize)
XPTg->maxIOpbSize = SIMinfoPtr->ioPBSize;
// We do not call the SIM's Initialization routine on reregister. Instead,
// the SIM will get the data out upon return
return ( noErr);
}
/*********************************************************************************
XPTRegisterCommon - Common between Register and Reregister code
*********************************************************************************/
void
XPTRegisterCommon( SIMinitInfo * SIMinfoPtr)
{
// Set up the return values in the SIMinitInfo
SIMinfoPtr->MakeCallback = XPTCallCompRoutine;
SIMinfoPtr->EnteringSIM = VMDisableUserCode;
SIMinfoPtr->ExitingSIM = VMEnableUserCode;
switch ( SIMinfoPtr->busID)
{
case 0:
SIMinfoPtr->XPT_ISR = XPT_ISR0; // -> ptr to the XPT's ISR (so SIM can install it)
break;
case 1:
SIMinfoPtr->XPT_ISR = XPT_ISR1;
break;
case 2:
SIMinfoPtr->XPT_ISR = XPT_ISR2;
break;
case 3:
SIMinfoPtr->XPT_ISR = XPT_ISR3;
break;
case 4:
SIMinfoPtr->XPT_ISR = XPT_ISR4;
break;
case 5:
SIMinfoPtr->XPT_ISR = XPT_ISR5;
break;
case 6:
SIMinfoPtr->XPT_ISR = XPT_ISR6;
break;
case 7:
SIMinfoPtr->XPT_ISR = XPT_ISR7;
break;
case 8:
SIMinfoPtr->XPT_ISR = XPT_ISR8;
break;
case 9:
SIMinfoPtr->XPT_ISR = XPT_ISR9;
break;
case 0x0a:
SIMinfoPtr->XPT_ISR = XPT_ISRa;
break;
case 0x0b:
SIMinfoPtr->XPT_ISR = XPT_ISRb;
break;
case 0x0c:
SIMinfoPtr->XPT_ISR = XPT_ISRc;
break;
case 0x0d:
SIMinfoPtr->XPT_ISR = XPT_ISRd;
break;
case 0x0e:
SIMinfoPtr->XPT_ISR = XPT_ISRe;
break;
case 0x0f:
SIMinfoPtr->XPT_ISR = XPT_ISRf;
break;
}
}
/*********************************************************************************
XPTDeregisterBus - Remove registration of SIM/HBA
*********************************************************************************/
OSErr
XPTDeregisterBus (ushort busID, XPTglobals *XPTg)
{
#pragma unused (busID)
#pragma unused (XPTg)
return (scsiFunctionNotAvailable);
}
/*********************************************************************************
XPTKillXPT - Render XPT and its stuff inoperative (might be used for patching)
*********************************************************************************/
OSErr
XPTKillXPT ( XPTglobals *XPTg)
{
ulong * oldPatch;
RemoveSyncWait(XPTg); // Get rid of our patch to syncWait
// Disable patch by changing the enabled variable in the patch
// this variable is embedded in the code 4 bytes before the
// actual beginning of the code.
oldPatch = (ulong *)(XPTg->debugPatch);
*(--oldPatch) = 0; // disable the patch
// Ditto for the SCSIBusy Patch if it changed.
if( SCSIGlobals->newBusyPatchVers != kbusyPatchVers ) {
// Let the new XPT know that there isn't a SCSI Busy patch.
SCSIGlobals->busyPatchVers = 0;
oldPatch = (ulong *)(SCSIGlobals->busyPatch);
*(--oldPatch) = 0; // disable the patch
}
DisposPtr( (char *)(XPTg->xptIOptr));
DisposPtr((Ptr)XPTg); // Get rid of our globals
// Anything else I missed? !!!
return (noErr);
}
#if 0
/*********************************************************************************
XPTAsyncEvent - notifies clients of event that they had registered for
*********************************************************************************/
OSErr
XPTAsyncEvent (SCSI_PB *pbPtr, XPTglobals *XPTg)
{
/*SCSIAsyncEvent (long what,
ushort busID,
ushort targetID,
ushort lun,
long dataBfr,
long dataCnt)*/
return (scsiFunctionNotAvailable);
}
#endif
/*********************************************************************************
XPTAction - perform an Action (either XPT or pass it to SIM)
*********************************************************************************/
OSErr
XPTAction (SCSI_PB *pbPtr, XPTglobals *XPTg)
{
Boolean needSyncWait = false; // assume that the call won't need syncWait
OSErr result = noErr; // error returned synchronously (result in D0)
BusInfo *busInfoPtr;
Boolean forceSync = false;
pascal void (*oldCompletion)(SCSI_IO *);
if (pbPtr->qLink) { // <LW14> pdw Fß TOP
pbPtr->scsiResult = scsiQLinkInvalid;
return ( pbPtr->scsiResult);
} // <LW14> pdw Fß BOT
// We have to see if the Function code is handled by the XPT or by the SIM
switch (pbPtr->scsiFunctionCode) {
case SCSIExecIO: // SIM
case SCSIResetBus: // SIM // <SM8> pdw
case SCSIResetDevice: // SIM // <SM8> pdw
case SCSIReleaseQ: // SIM // <SM8> pdw
case SCSIAbortCommand: // SIM // <SM8> pdw
case SCSITerminateIO: // SIM // <SM8> pdw
#if forceSyncAlways // will poll always (not just when int level high)
{
#else
if (SCSIGlobals->inDebugger && InterruptLevel() >1 ) {
#endif
forceSync = true;
oldCompletion = pbPtr->scsiCompletion;
pbPtr->scsiCompletion = 0;
}
((SCSI_IO *)pbPtr)->savedA5 = getCurrentA5();
if( pbPtr->scsiCompletion == 0) // <SM8> pdw
needSyncWait = true;
if( needSyncWait && XPTg->syncUnsafeCount ) {
pbPtr->scsiResult = scsiBusy;
return ( pbPtr->scsiResult);
}
if ( (((SCSI_PB *)pbPtr)->scsiDevice).bus >= XPTg->numBuses) {
pbPtr->scsiResult = scsiBusInvalid;
return ( pbPtr->scsiResult);
}
busInfoPtr = XPTg->BusInfoPtr[ (((SCSI_PB *)pbPtr)->scsiDevice).bus];
if( busInfoPtr )
(busInfoPtr->initInfo.SIMaction) (pbPtr, (busInfoPtr->initInfo).SIMstaticPtr);
else{
pbPtr->scsiResult = scsiBusInvalid;
return ( pbPtr->scsiResult);
}
if ( needSyncWait) {
SyncWait( pbPtr, XPTg);
if (forceSync) {
if (oldCompletion!=0) {
pbPtr->scsiCompletion = oldCompletion;
XPTCallCompRoutine( (SCSI_IO *)pbPtr );
return (noErr);
}
}
return (pbPtr->scsiResult); // return the error! (unlike Cyclone)
}
break;
case SCSIBusInquiry: // SIM
IfRecordEvent( *(long *)&pbPtr->scsiDevice, (long)'Inq-');
pbPtr->scsiResult = noErr;
if ( pbPtr->scsiPBLength < sizeof(SCSIBusInquiryPB)) {
pbPtr->scsiResult = scsiPBLengthError;
}
else if ( pbPtr->scsiDevice.bus == 0xff) {
((SCSIBusInquiryPB *)pbPtr)->scsiIOpbSize = sizeof(SCSI_IO);
((SCSIBusInquiryPB *)pbPtr)->scsiMaxIOpbSize = XPTg->maxIOpbSize;
((SCSIBusInquiryPB *)pbPtr)->scsiHiBusID = XPTg->numBuses - 1;
BlockMove("Apple Computer \0",((SCSIBusInquiryPB *)pbPtr)->scsiSIMVendor,16);
}
else if ( pbPtr->scsiDevice.bus >= XPTg->numBuses) {
pbPtr->scsiResult = scsiBusInvalid;
}
else {
((SCSIBusInquiryPB *)pbPtr)->scsiIOpbSize = sizeof(SCSI_IO);
((SCSIBusInquiryPB *)pbPtr)->scsiMaxIOpbSize = XPTg->maxIOpbSize;
((SCSIBusInquiryPB *)pbPtr)->scsiHiBusID = XPTg->numBuses - 1;
pbPtr->scsiResult = CallSIMaction( pbPtr, XPTg);
}
IfRecordEvent( (long)(pbPtr->scsiResult), (long)'-Inq');
return ( pbPtr->scsiResult);
break;
case SCSISetAsyncCallback: // XPT & SIM
result = CallSIMaction( pbPtr, XPTg);
break;
case SCSIGetVirtualIDInfo: // XPT
IfRecordEvent( *(long *)(&(((SCSIGetVirtualIDInfoPB *)pbPtr)->scsiOldCallID)), (long)'Vid-');
GetVirtualIDInfo( (SCSIGetVirtualIDInfoPB *) pbPtr, XPTg);
IfRecordEvent( *(long *)(&(((SCSIGetVirtualIDInfoPB *)pbPtr)->scsiOldCallID)), *(long *)&(pbPtr->scsiDevice));
break;
case SCSICreateRefNumXref: // XPT
IfRecordEvent( *(long *)(&(((SCSI_Driver_PB *)pbPtr)->scsiDevice)), (long)'Xrf-');
SetRefNum( (SCSI_Driver_PB *) pbPtr, XPTg);
IfRecordEvent( *(long *)(&(((SCSI_Driver_PB *)pbPtr)->scsiDriver)), (long)(pbPtr->scsiResult));
break;
case SCSILookupRefNumXref: // XPT
GetRefNum( (SCSI_Driver_PB *) pbPtr, XPTg);
break;
case SCSIRemoveRefNumXref: // XPT
RemoveRefNum( (SCSI_Driver_PB *) pbPtr, XPTg);
break;
case SCSIGenerateInterleaveID: // XPT
((SCSIGenerateInterleaveIDPB *) pbPtr)->scsiInterleaveID = XPTg->nextInterleave++;
break;
case SCSINop: // XPT
break;
default:
result = CallSIMaction( pbPtr, XPTg);
break;
}
return (result);
}
/*********************************************************************************
CallSIMaction - perform an Action (either Xpt or pass it to SIM)
*********************************************************************************/
OSErr
CallSIMaction( void * pbPtr, XPTglobals * XPTg)
{
BusInfo *busInfoPtr;
if ( (((SCSI_PB *)pbPtr)->scsiDevice).bus >= XPTg->numBuses)
return (scsiBusInvalid);
busInfoPtr = XPTg->BusInfoPtr[ (((SCSI_PB *)pbPtr)->scsiDevice).bus];
if( busInfoPtr ) {
(busInfoPtr->initInfo.SIMaction) (pbPtr, (busInfoPtr->initInfo).SIMstaticPtr);
return ( noErr);
}
return(scsiBusInvalid);
}
/*********************************************************************************
SyncWait - wait for a synchronous request to be completed
*********************************************************************************/
void
SyncWait( SCSI_PB *pbPtr, XPTglobals *XPTg)
{
IfRecordEvent( (long)(pbPtr), (long)'Xsyw');
do {
CheckInterrupts( XPTg);
} while (pbPtr->scsiResult == scsiRequestInProgress);
}
/*********************************************************************************
CheckInterrupts -
*********************************************************************************/
void
CheckInterrupts (XPTglobals * XPTg)
{
#if forceSyncAlways // will poll always (not just when int level high)
DispatchISR();
#else
// GROSS Hack Alert!
//
// In theory the private DT Queue is a SIM private since it is only used by the
// pseudo DMA machines. However if I actually poll all SIMs at all interrupt
// levels the overhead is such that basic operations that depend on syncwait start
// to slow down. To get around this I only poll when I _have_ to which means if
// there is something in our private deferred task queue or if it is busy (we are
// working on soemthing and hadn't blocked ints at the VIA yet.)
if (InterruptLevel() > 1 || SCSIGlobals->privDTQueue.qHead || SCSIGlobals->privDTQueue.qFlags )
{
if (bset(inVBL, (char *)&((GetVBLQHdr()->qFlags)))) // make VBL busy: was it already?
DispatchISR(); // yes: check interrupt sources
else {
DispatchISR(); // no: check interrupt sources
bclr(inVBL, (char *)&((GetVBLQHdr()->qFlags))); // and clr busy bit (return to prev value)
}
}
#endif
if ( bclr( kbResetFromSync, &XPTg->flags ))
TryToRecover( XPTg);
}
/*********************************************************************************
TryToRecover -
*********************************************************************************/
void
TryToRecover ( XPTglobals *XPTg)
{
#pragma unused (XPTg)
SCSIResetBusPB rstPB;
Clear( &rstPB, sizeof(rstPB));
rstPB.scsiDevice.bus = 0;
SCSIAction( (SCSI_PB *)&rstPB);
rstPB.scsiDevice.bus = 1;
SCSIAction( (SCSI_PB *)&rstPB);
}
/*********************************************************************************
DispatchISR -
*********************************************************************************/
void
DispatchISR ( void)
{
short i;
XPTglobals * XPTg;
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
XPTg = GetXPTg();
for (i=0; i< XPTg->numBuses; i+=1)
{
busInfoPtr = XPTg->BusInfoPtr[i];
((busInfoPtr->initInfo).SIMInterruptPoll) ( (busInfoPtr->initInfo).SIMstaticPtr);
}
VMEnableUserCode(); // enable user code (allow page faults)
}
/*********************************************************************************
SetRefNum, GetNextRefNum, RemoveRefNum -
*********************************************************************************/
void
SetRefNum( SCSI_Driver_PB * pbPtr, XPTglobals * XPTg)
{
ulong index;
Ptr temp;
ulong size;
pbPtr->scsiDevice.diReserved = 0;
for ( index = 0; index < XPTg->Drivers->DrvrCnt; index+=1 ) {
if ( pbPtr->scsiDevice == XPTg->Drivers->Drvr[index].DevID ) {
pbPtr->scsiResult = scsiDeviceConflict;
return;
}
}
size = sizeof(DrvrList) + sizeof(RefInfo) * (index + 1);
temp = NewPtrSysClear(size);
if ( temp ) {
BlockMove(XPTg->Drivers,temp,size - sizeof(RefInfo));
DisposPtr((Ptr)XPTg->Drivers);
XPTg->Drivers = (DrvrList *)temp;
}
else {
pbPtr->scsiResult = memFullErr;
return;
}
XPTg->Drivers->DrvrCnt+=1;
XPTg->Drivers->Drvr[index].DevID = pbPtr->scsiDevice;
XPTg->Drivers->Drvr[index].DRefNum = pbPtr->scsiDriver;
pbPtr->scsiResult = noErr;
}
void
GetRefNum( SCSI_Driver_PB * pbPtr, XPTglobals * XPTg)
{
ulong index;
pbPtr->scsiResult = noErr; /* Can't Fail */
if ( pbPtr->scsiDevice.bus == 0xFF ) { /* Marker for Give me the first in the list */
pbPtr->scsiDriver = 0; /* Not a driver */
if ( XPTg->Drivers->DrvrCnt )
pbPtr->scsiNextDevice = XPTg->Drivers->Drvr[0].DevID; /* First one in the list */
else
pbPtr->scsiNextDevice.bus = 0xFF ; /* Nobody home */
return;
}
pbPtr->scsiDevice.diReserved = 0; /* Get rid of "unused" byte which might have
(like the installer's setting of the high
bit) extraneaous stuff in it! */
for ( index = 0; index < XPTg->Drivers->DrvrCnt; index+=1 ) {
if ( pbPtr->scsiDevice == XPTg->Drivers->Drvr[index].DevID ) {
pbPtr->scsiDriver = XPTg->Drivers->Drvr[index].DRefNum;
if ( index + 1 == XPTg->Drivers->DrvrCnt )
pbPtr->scsiNextDevice.bus = 0xFF ; /* Nobody home */
else
pbPtr->scsiNextDevice = XPTg->Drivers->Drvr[index + 1].DevID;
return;
}
}
pbPtr->scsiDriver = 0; /* Not a driver */
pbPtr->scsiNextDevice.bus = 0xFF ; /* Nobody home */
}
void
RemoveRefNum( SCSI_Driver_PB * pbPtr, XPTglobals * XPTg)
{
ulong index,remainder;
pbPtr->scsiDevice.diReserved = 0;
for ( index = 0; index < XPTg->Drivers->DrvrCnt; index+=1 ) {
if ( pbPtr->scsiDevice == XPTg->Drivers->Drvr[index].DevID ) {
for ( remainder = index; remainder < XPTg->Drivers->DrvrCnt - 1; remainder+=1 )
XPTg->Drivers->Drvr[remainder] = XPTg->Drivers->Drvr[remainder + 1];
XPTg->Drivers->DrvrCnt -= 1;
pbPtr->scsiResult = noErr; /* Removed it */
return; //<SM19>pdw
}
}
pbPtr->scsiResult = scsiNoSuchXref;
}
/*********************************************************************************
XPTCallCompRoutine - Called by the SIM's CompleteIO
*********************************************************************************/
void
XPTCallCompRoutine( SCSI_IO * ioPtr ) // <SM7>
{
pascal void (*fn)(SCSI_IO *);
// Ptr oldA5;
XPTglobals * XPTg;
//--- If we need to do virtual ID mapping, and result==noErr then do it // <SM10> pdw
XPTg = GetXPTg();
if (XPTg->oldIDBusNumber[ioPtr->scsiDevice.targetID]<0) {
if ( ioPtr->scsiFunctionCode == SCSIExecIO) // <LW14> pdw Fß
if ( ioPtr->scsiResult==noErr || ioPtr->scsiResult==scsiNonZeroStatus || ioPtr->scsiResult==scsiDataRunError )
if( XPTg->BusInfoPtr[ioPtr->scsiDevice.bus]->initInfo.oldCallCapable)
XPTg->oldIDBusNumber[ioPtr->scsiDevice.targetID] = ioPtr->scsiDevice.bus;
}
ioPtr->qLink = 0; // set qLink back to NIL in case pb is reused // <LW14> pdw Fß
//--- Call the completion routine (with proper A5) as long as routine ptr isn't NIL
// scsiCompletion was moved into the header - therefore we can call it for any pb <SM8>
if( (fn=ioPtr->scsiCompletion) != nil ) {
// oldA5 = getCurrentA5(); now it's done in CallCompRoutineGlue
IfRecordEvent( (long)(ioPtr), (long)'xcC-');
CallCompRoutineGlue( ioPtr, &(XPTg->completionDT)); // MAKE CALLBACK
IfRecordEvent( (long)(fn), (long)'-xcC');
}
}
/*********************************************************************************
ReRegisterAllSIMs -
*********************************************************************************/
OSErr
ReRegisterAllSIMs( XPTglobals *XPTg )
{
long OldXPT;
Boolean *oldSIMs;
ulong id;
SCSIGetVirtualIDInfoPB dIdent;
SCSI_Driver_PB drvrPB;
SCSIBusInquiryPB scPB;
uchar busID;
uchar highBusID;
SCSI_PB reRegister;
// Setup our globals in a temporary spot so we don't step on any existing globals
// Use GetVirtualID to build up a list of virtual IDs
// Use BusInquiry to build up a list of existing SIMs
// SetTrapAddress to the new XPT and remember the address of the old one.
// Use the old XPT to send a ReRegisterSIM call to each SIM
// Call KillXPT to get rid of the old XPT (Note Kill XPT can't call SetTrapAddress!!!)
// Put our Globals in the normal spot
// Install any patches (such as vSyncWait) that we will use (this MUST be done AFTER KillXPT)
// If the normal internal SIMs didn't already exist then tell InitItt to install them
SetTempXPTg( XPTg);
// Use the old XPT to find all of the virtual IDs
Clear((char *)&dIdent,sizeof(dIdent));
for( id = 0; id < 7; id+=1 ) {
dIdent.scsiOldCallID = id;
dIdent.scsiFunctionCode = SCSIGetVirtualIDInfo;
dIdent.scsiCompletion = nil;
dIdent.scsiPBLength = sizeof(SCSIGetVirtualIDInfoPB);
SCSIAction((SCSI_PB *) &dIdent);
if( dIdent.scsiExists )
XPTg->oldIDBusNumber[id] = dIdent.scsiDevice.bus;
else
XPTg->oldIDBusNumber[id] = -1;
}
// Now go get all of the existing Drivers which have been registered
Clear((char *)&drvrPB,sizeof(drvrPB));
/* Get the devIdent of the first driver registered with Itt */
drvrPB.scsiDevice.bus = 0xff; /* Give us the first one in the list */
drvrPB.scsiPBLength = sizeof(drvrPB);
drvrPB.scsiFunctionCode = SCSILookupRefNumXref;
SCSIAction( (SCSI_PB *) &drvrPB );
drvrPB.scsiDevice = drvrPB.scsiNextDevice; /* Get The first one in the list */
while( drvrPB.scsiDevice.bus != 0xff ) {
SCSIAction( (SCSI_PB *) &drvrPB );
SetRefNum(&drvrPB,XPTg); /* Register with the new set of globals */
drvrPB.scsiDevice = drvrPB.scsiNextDevice; /* Get The next one in the list */
}
// Look for existing SIMs
Clear((char *)&scPB,sizeof(scPB));
*(long *)&(scPB.scsiDevice) = 0xff; // XPT Inquiry
scPB.scsiFunctionCode = SCSIBusInquiry;
scPB.scsiPBLength = sizeof(SCSIBusInquiryPB);
SCSIAction( (SCSI_PB *) &scPB ); // Get info for the XPT
highBusID = scPB.scsiHiBusID;
if( (oldSIMs = (Boolean *)NewPtrSysClear(sizeof(Boolean) * (highBusID + 1))) == 0 ) {
IfDebugStr("\pNot enough memory to switch XPTs"); // Yikes, this would be really bad...
return(memFullErr);
}
for( busID = 0; busID <= highBusID; busID+=1 ) {
scPB.scsiDevice.bus = busID;
scPB.scsiFunctionCode = SCSIBusInquiry;
scPB.scsiPBLength = sizeof(SCSIBusInquiryPB);
if( SCSIAction( (SCSI_PB *) &scPB ) == noErr)
oldSIMs[busID] = true;
}
// Remember the old TrapAddress and setup the new one
OldXPT = NGetTrapAddress(SCSIATOM, OSTrap);
NSetTrapAddress ( (long)SCSIAtomic, 0x89, OSTrap );
// And... Re-Register all existing SIMs
Clear((char *)&reRegister,sizeof(reRegister));
for( busID = 0; busID <= highBusID; busID+=1 ) {
if( oldSIMs[busID] ) {
reRegister.scsiPBLength = sizeof(reRegister);
reRegister.scsiDevice.bus = busID;
reRegister.scsiFunctionCode = SCSIRegisterWithNewXPT;
CallOldXPT( &reRegister,xptSCSIAction,OldXPT );
}
}
// Get rid of the old XPT and get out of here
CallOldXPT(0, xptSCSIKillXPT, OldXPT);
SetXPTg(XPTg); // Put the real XPT Globals in place
DisposPtr((Ptr)oldSIMs);
}
/*********************************************************************************
XPT_ISR0 -
*********************************************************************************/
#if 0
void
XPT_ISR0 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0];
((busInfoPtr->initInfo).SIM_ISR)( (busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR1 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[1];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
#endif
void
XPT_ISR2 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[2];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR3 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[3];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR4 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[4];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR5 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[5];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR6 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[6];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR7 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[7];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR8 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[8];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISR9 (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[9];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRa (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0a];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRb (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0b];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRc (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0c];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRd (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0d];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRe (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0e];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}
void
XPT_ISRf (void)
{
BusInfo * busInfoPtr;
VMDisableUserCode(); // disable user code (so page faults won't happen)
// vv
busInfoPtr = GetXPTg()->BusInfoPtr[0x0f];
((busInfoPtr->initInfo).SIM_ISR)((busInfoPtr->initInfo).SIMstaticPtr);
VMEnableUserCode(); // enable user code (allow page faults)
}