Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
RamINIT.c
#define __DebugVersion 1 |
/* |
** Apple Macintosh Developer Technical Support |
** |
** RAMInit.c: An INIT which installs DRVR for RamDisk |
** |
** by Gordon Sheridan and Jim Luther |
** modified incessantly by Brian Bechtel |
** and even more so by Quinn "The Eskimo!" |
** |
** File: RamINIT.c |
** |
** Copyright © 1992-1996 Apple Computer, Inc. |
** All rights reserved. |
** |
** You may incorporate this sample code into your applications without |
** restriction, though the sample code has been provided "AS IS" and the |
** responsibility for its operation is 100% yours. However, what you are |
** not permitted to do is to redistribute the source as "DTS Sample 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 Code, but that you've made changes. |
** |
** Change History (most recent first): |
** |
** <1.4> 19970207 Quinn Reworked to use new file layout and bring generally |
** up-to-date. |
** <1.4> 19970207 Quinn Rewrote to use TradDriverLoaderLib |
** Junked some unused prototypes |
** Renamed RemoveDrive to RemoveDriveFromQueue |
** <1.3> 08/23/96 BL¡B Change dcePtr to dceHandle. Thanks to |
** Tim Fredenburg for pointing out the error. |
** <1.3> 06/20/96 BL¡B Changes to new routine names |
** <1.2> 07/03/95 BL¡B Many changes for Universal Header 2.0 |
** compliance. Changed how we install driver. |
** Other bug fixes. See "Changes in 1.2" for |
** details. |
** <7> 06/10/94 BL¡B Explicitly set zone to system zone before |
** getting the DRVR resource. Symantec 7.0 |
** doesn't set the System attribute on the DRVR |
** resource. This can be hard to track down. |
** <6> 05/19/94 BL¡B Modified debugger macros to avoid use of ANSI |
** routines, and weird c-string dependencies. |
** <5> 10/15/93 JML Added code to resize unit table if needed. |
** <4> 10/14/93 JML Implement AddDebuggerLabels routine for MacsBug. |
** Added Panic debug macros. |
** <3> 6/29/93 gs Change AddDriveToQueue to start with drive number 5. |
** <2> 6/28/93 gs Change _DebugVersion to __DebugVersion |
** <1> 6/13/93 gs Implement AddDebuggerLabels routine for TMON. |
** <0> 4/17/92 gs Clean up for Sample Code release. |
**/ |
#ifdef __MWERKS__ |
#include <A4Stuff.h> |
#endif |
#ifdef THINK_C |
#include <SetupA4.h> |
#endif |
#include <string.h> |
#include <TextUtils.h> |
#include <QuickDraw.h> |
#include <Traps.h> |
#include <Gestalt.h> |
#include <Memory.h> |
#include <Resources.h> |
#include <DiskInit.h> |
#include "RamDiskCommon.h" |
#include "TradDriverLoaderLib.h" |
#include "ShowInitIcon.h" |
/////////////////////////////////////////////////////////////////////////// |
#define kDriverName "\p.RamDRVR" |
enum { |
kMinUnitNum = 48 /* the lowest unit number we can use */ |
}; |
/////////////////////////////////////////////////////////////////////////// |
// |
// Custom drive queue element. Normally you might to extend this to have |
// extra drive-specific variables, but in this case we have no extra |
// variables. Still, we define our own structure rather than use |
// the one in <Files.h> because our structure has the magic "flags" |
// field at the front. |
struct MyDrvQEl |
{ |
long flags; |
QElemPtr qLink; |
short qType; |
short dQDrive; |
short dQRefNum; |
short dQFSID; |
unsigned short dQDrvSz; |
unsigned short dQDrvSz2; |
}; |
typedef struct MyDrvQEl MyDrvQEl; |
typedef MyDrvQEl *MyDrvQElPtr; |
/////////////////////////////////////////////////////////////////////////// |
enum { |
// ICN# |
rLoadOKIcon = -4064, /* same as cdev icon */ |
rLoadBadIcon = -4033, |
rPhysicalIcon = -4034, |
rMediaIcon = -4035 |
}; |
/////////////////////////////////////////////////////////////////////////// |
static OSErr InitializeGlobals (DrvrGlobals *driverGlobals) |
// Initialize the globals using data read from resources. |
{ |
OSErr result = -1; |
Handle physicalIconHandle; |
Handle mediaIconHandle; |
VersRecHndl versionHandle; |
ConfigRecHandle configHandle; |
long length; |
driverGlobals->ramDisk = nil; /* RAM disk memory isn't allocated yet */ |
/* Get the user configuration, icons, and the "where" string */ |
configHandle = (ConfigRecHandle)Get1Resource ('RDcf', rConfiguration); |
physicalIconHandle = Get1Resource('ICN#', rPhysicalIcon); |
mediaIconHandle = Get1Resource('ICN#', rMediaIcon); |
versionHandle = (VersRecHndl) Get1Resource('vers', 1); |
if (configHandle && physicalIconHandle && mediaIconHandle && versionHandle) |
{ |
/* See if we are supposed to install */ |
if ((**configHandle).install) |
{ |
/* Copy the user's preferred volume name to the driver globals. */ |
length = (**configHandle).volumeName[0]+1; |
BlockMoveData((**configHandle).volumeName, driverGlobals->volumeName, length); |
/* Copy ICN# to driver globals so it has a physical location icon for volumes. */ |
BlockMoveData( &(**physicalIconHandle), (Ptr)(driverGlobals->physicalIcon), kLargeIconSize); |
/* Copy ICN# to driver globals so it has a default media icon for volumes. */ |
BlockMoveData( &(**mediaIconHandle), (Ptr)(driverGlobals->mediaIcon), kLargeIconSize); |
/* Put the drive location string into the driver globals. */ |
GetIndString(driverGlobals->locationStr, rStringList, strLocationStr); |
if (ResError() != noErr) |
BlockMoveData("\pIn RAM", driverGlobals->locationStr, 7); |
driverGlobals->ramSize = (**configHandle).size * 1024; |
driverGlobals->driverVersion = (**versionHandle).numericVersion; |
result = noErr; |
} |
} |
if (configHandle) |
ReleaseResource((Handle)configHandle); |
else |
Panic("\pYou forgot to turn settings on in control panel"); |
if (physicalIconHandle) |
ReleaseResource(physicalIconHandle); |
if (mediaIconHandle) |
ReleaseResource(mediaIconHandle); |
return (result); |
} |
/////////////////////////////////////////////////////////////////////////// |
static OSErr AddDriveToQueue (long size, short drvrRef, short *driveNum) |
// Find the first unused drive number greater than 4, allocate and initialize |
// a drive queue element (including the drive flags), and add the drive queue |
// element to the drive queue. |
{ |
OSErr result = noErr; |
QHdrPtr driveQHdr; |
DrvQEl *drivePtr; |
MyDrvQElPtr newDrivePtr; |
Boolean driveNumFound = false; |
driveQHdr = GetDrvQHdr(); |
/* find first free drive number */ |
*driveNum = 5; /* drive numbers 1-4 are reserved */ |
while (! driveNumFound) |
{ |
drivePtr = (DrvQEl *)driveQHdr->qHead; /* get first drive */ |
while (drivePtr && *driveNum != drivePtr->dQDrive) /* order of tests important! */ |
drivePtr = (DrvQEl *)drivePtr->qLink; /* get next drive */ |
if (drivePtr == nil) |
driveNumFound = true; |
else |
++(*driveNum); |
} |
if (*driveNum > 0) /* must be a positive short */ |
{ |
/* allocate new drive queue element */ |
newDrivePtr = (MyDrvQElPtr)NewPtrSysClear(sizeof(MyDrvQEl)); |
if (newDrivePtr != nil) |
{ |
newDrivePtr->flags = 0x00080000; /* non-ejectable, disk not locked */ |
newDrivePtr->qType = 1; /* see IM vol.4 p.181 */ |
newDrivePtr->dQDrive = *driveNum; /* ¥¥ dQDrive and dQRefNum are filled */ |
newDrivePtr->dQRefNum = drvrRef; /* ¥¥ in by AddDrive */ |
newDrivePtr->dQFSID = 0; /* HFS */ |
newDrivePtr->dQDrvSz = size & 0x0000FFFF; /* dQDrvSz = LoWord of size */ |
newDrivePtr->dQDrvSz2 = size >> 16; /* dQDrvSz2 = HiWord of size */ |
AddDrive (drvrRef, *driveNum, (DrvQEl *)&newDrivePtr->qLink); |
} |
else |
result = memFullErr; |
} |
else |
/* more than 32768 drives!?! */ |
result = nsDrvErr; |
return (result); |
} |
/////////////////////////////////////////////////////////////////////////// |
static OSErr RemoveDriveFromQueue (short driveNum, DrvQElPtr *drivePtr) |
// Find the drive queue element for driveNum in the drive queue and Dequeue it. |
// Return pointer to the drive queue element removed in *drivePtr. |
{ |
QHdrPtr driveQHdr; |
driveQHdr = GetDrvQHdr(); |
*drivePtr = (DrvQEl *)driveQHdr->qHead; /* get first drive */ |
while (*drivePtr && (driveNum != (*drivePtr)->dQDrive)) /* order of tests important! */ |
*drivePtr = (DrvQEl *)(*drivePtr)->qLink; /* get next drive */ |
if (*drivePtr != nil) |
return (Dequeue((QElemPtr)*drivePtr, driveQHdr)); |
else |
return (nsDrvErr); |
} |
/////////////////////////////////////////////////////////////////////////// |
static short NumToolboxTraps (void) |
{ |
if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap) ) |
return (0x200); |
else |
return (0x400); |
} |
/////////////////////////////////////////////////////////////////////////// |
static TrapType GetTrapType (short theTrap) |
{ |
if (theTrap & 0x0800) |
return (ToolTrap); |
else |
return (OSTrap); |
} |
/////////////////////////////////////////////////////////////////////////// |
static Boolean TrapAvailable (short theTrap) |
{ |
TrapType tType; |
tType = GetTrapType(theTrap); |
if (tType == ToolTrap) |
{ |
theTrap = theTrap & 0x7FF; |
if (theTrap >= NumToolboxTraps() ) |
theTrap = _Unimplemented; |
} |
return (NGetTrapAddress(theTrap, tType) != |
NGetTrapAddress(_Unimplemented, ToolTrap) ); |
} |
/////////////////////////////////////////////////////////////////////////// |
#define kMacsbugMacroStr "\p;MC RamDisk 'DM #" |
#define kMacsbugMacroStr2 "\p';g" |
#define kTMONMacroStr "\pªAddLabel RamDisk,." |
#define kTMONMacroStr2 "\p,." |
#define AddString(src, dst) { BlockMoveData(&src[1], dst+i, src[0]); i += src[0]; } |
static void AddDebuggerLabels (DrvrGlobals driverGlobals) |
// Add TMON or MacsBug debugger macros for easy viewing of RamDisk |
{ |
Str255 strbuf = "\p"; |
Str31 numstr; |
long tmonVal; |
short err; |
Boolean done = false; |
SignedByte debugFlags; |
short i; |
if (TrapAvailable(_Gestalt)) /* check for TMON */ |
{ |
err = Gestalt('TMON',&tmonVal); |
if (err == 0) |
{ |
/* Add TMON label */ |
i = 1; |
AddString(kTMONMacroStr, strbuf); |
NumToString((long)driverGlobals.ramDisk,numstr); |
AddString(numstr, strbuf); |
AddString(kTMONMacroStr2, strbuf); |
NumToString(driverGlobals.ramSize,numstr); |
AddString(numstr, strbuf); |
strbuf[0] = i - 1; |
DebugStr(strbuf); |
done = true; |
} |
} |
if (!done) /* If TMON isn't installed, define a macro for MacsBug */ |
{ |
debugFlags = *(SignedByte *) 0x0BFF; // MacJmpFlag |
if (debugFlags == -1) |
debugFlags = *(SignedByte *) 0x0120; // MacJmp |
if (debugFlags & 0x20) |
{ |
/* Define MacsBug macro */ |
i = 1; |
AddString(kMacsbugMacroStr, strbuf); |
NumToString((long)driverGlobals.ramDisk, numstr); |
AddString(numstr, strbuf); |
AddString(kMacsbugMacroStr2, strbuf); |
strbuf[0] = i - 1; |
DebugStr(strbuf); |
} |
} |
} |
/////////////////////////////////////////////////////////////////////////// |
void main (void) |
{ |
DrvrGlobals driverGlobals; |
short csParam[11]; |
short drvrRefNum = 0; |
short driveNum = 0; |
DrvQElPtr driveQElPtr; |
OSErr result; |
DCtlHandle dceHandle; |
Boolean driverInstalled = false; |
#ifdef THINK_C |
RememberA0(); |
SetUpA4(); |
#endif |
#ifdef __MWERKS__ |
long oldA4 = SetCurrentA4(); |
#endif |
Panic("\pStarting RAMDisk"); |
ShowInitIcon(rLoadOKIcon,false); /* show OK icon to indicate we're executing */ |
result = InitializeGlobals(&driverGlobals); |
if (result != noErr) |
{ |
Panic("\pCould not initialize globals"); |
goto Done; |
} |
driverGlobals.ramDisk = NewPtrSysClear(driverGlobals.ramSize); |
if (driverGlobals.ramDisk == nil) |
{ |
Panic("\pNewSysPtr = nil"); |
result = memFullErr; |
goto Done; |
} |
#if __DebugVersion |
AddDebuggerLabels(driverGlobals); |
#endif __DebugVersion |
// <1.4> |
result = TradInstallDriverFromResource(0, kDriverName, |
kMinUnitNum, |
TradHighestUnitNumber() + 1, |
&drvrRefNum); |
if (result == noErr || result == dupFNErr) { |
driverInstalled = (result == noErr); |
result = TradOpenInstalledDriver(drvrRefNum, fsRdWrPerm); |
} else { |
Panic("\pTradInstallDriverFromResource failed!"); |
goto Done; |
} |
if (result != noErr) |
{ |
Panic("\pTradOpenInstalledDriver failed"); |
goto Done; |
} |
/* put in drive queue */ |
result = AddDriveToQueue (driverGlobals.ramSize / 512, drvrRefNum, &driveNum); |
if (result != noErr) |
{ |
Panic("\pAddMyDrive returned negative driveNum!"); |
goto Done; |
} |
/* driveNum now = drive number */ |
/* Save driveNum in our globals so driver code can verify drive number in |
Prime, Status and Control calls (if need be). The driver also checks |
driveNum in the driver globals for a non-zero value before accepting |
regular prime, control and status calls. |
*/ |
driverGlobals.driveNumber = driveNum; |
/* set drivers globals */ |
*(Ptr *)csParam = (Ptr)&driverGlobals; |
result = Control(drvrRefNum, setGlobalsCC, (Ptr)csParam); |
if (result != noErr) |
{ |
Panic("\pControl returned err"); |
goto Done; |
} |
/* check to see if it got them */ |
result = Status(drvrRefNum, getGlobalsSC, (Ptr)csParam); |
if ((result != noErr) || (driverGlobals.ramSize != *(long *)csParam)) |
{ |
Panic("\pStatus returned err"); |
goto Done; |
} |
/* zero & mount */ |
result = DIZero(driveNum, driverGlobals.volumeName); |
if (result != noErr) |
{ |
Panic("\pDIZero returned err"); |
goto Done; |
} |
Done: |
if (result == noErr) |
ShowInitIcon(rLoadOKIcon,true); /* draw OK icon and move pen */ |
else |
{ |
dceHandle = GetDCtlEntry(drvrRefNum); |
if (dceHandle != nil) |
if ((**dceHandle).dCtlFlags & dOpenedMask) |
{ |
/* Driver is open - close it */ |
result = CloseDriver(drvrRefNum); |
if (result == noErr) |
/* If driver was closed, ramDisk memory was released! */ |
driverGlobals.ramDisk = nil; |
} |
if (driveNum != 0) |
{ |
result = RemoveDriveFromQueue(driveNum, &driveQElPtr); /* ignore errors */ |
if (result == noErr) |
/* Dispose of the DrvQEl. Since it was allocated as a |
MyDrvQEl record, we have to subract 4 from the address */ |
DisposePtr((Ptr)((Ptr)(driveQElPtr) - 4)); |
} |
// <1.4> |
if (driverInstalled) { |
(void) TradRemoveDriver(drvrRefNum, false); |
} |
if (driverGlobals.ramDisk != nil) |
DisposePtr(driverGlobals.ramDisk); |
#if __DebugVersion |
/* ¥¥¥ Need to add routine to remove TMON/MacsBug debugging macros */ |
#endif __DebugVersion |
ShowInitIcon(rLoadBadIcon,true); /* draw bad load icon and move pen */ |
} |
#ifdef THINK_C |
RestoreA4(); |
#endif |
#ifdef __MWERKS__ |
SetA4(oldA4); |
#endif |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14