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.
Load PCI Driver.c
/* |
File: Load PCI Driver.c |
Contains: Load PCI Driver Sample,This Code loads Wayne Flansburg PCI 'ndrv' |
so you can see it load without having to have a PCI card installed. |
This requires the PCI interfaces and libraries from ETO. |
Written by: Matthew Xavier Mora |
Copyright: Copyright © 1996-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): |
8/3/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
06/11/97 mxm Fixed the error -2538 by passing nil for the regID. |
04/15/97 mxm Cleaned it up for the Dev CD |
03/28/97 mxm Took out the MyFindSpaceInUnitTable routine. I wasn't using the |
InstallDriverFromFile correctly. HighestUnitNumber wasn't the problem. |
That's what I get for trying to program without the Documentation. |
Added Drag Manger and ODoOC support so you can drag a driver |
into the window or on the application and it will load it. |
Display more info from the driver. |
03/25/97 mxm Moved to a real app |
Fixed the can't load the library a second time bug. |
I was using HighestUnitNumber to get the unit number to load. |
I thought this call found the last used unit number. It |
actually expanded the unit table to the max number of |
entries! I put in MyFindSpaceInUnitTable routine and use it instead. |
Fix crashing Malph by moving it into an application shell. I don't |
know why it would cause Malph to crash. |
02/01/96 mxm I wrote the first version in the "Writing PCI drivers" class. Got it to load |
the sample driver I was writing. No real user interface |
to speak of. |
*/ |
//------------------------------------------------------------------ |
#pragma mark Includes |
//------------------------------------------------------------------ |
#include <Devices.h> |
#include <NameRegistry.h> |
#include <StandardFile.h> |
#include <LowMem.h> |
#include <Dialogs.h> |
#include "SimpleApp.h" |
#include <stdio.h> |
#include <string.h> |
#include <TextUtils.h> |
#include <CodeFragments.h> |
//------------------------------------------------------------------ |
#pragma mark Prototypes |
//------------------------------------------------------------------ |
pascal OSErr FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath); |
//------------------------------------------------------------------ |
#pragma mark Globals |
//------------------------------------------------------------------ |
short gDrvrRefNum = 0; /* global variable for storing my driver reference number */ |
long gLoadButton; |
long gUnloadButton; |
short gVert; |
short gLineHeight; |
NMRec gAlertNMRec; |
Str255 gAlertStr = "\pAn error occurred. Please bring Matt's PCI Loader to the front."; |
short gError = 0; |
//------------------------------------------------------------------ |
#pragma mark Defines |
//------------------------------------------------------------------ |
#pragma mark - |
//------------------------------------------------------------------ |
static void AlertUser(short err) |
//------------------------------------------------------------------ |
{ |
// in this case just set the global and the idle routine will display the error |
gError = err; |
} |
/* |
// I grabbed this code from somewhere |
//------------------------------------------------------------------ |
static short MyFindSpaceInUnitTable(void) |
//------------------------------------------------------------------ |
{ |
Ptr curUTableBase, newUTableBase; |
short curUTableEntries, newUTableEntries; |
short refNum, unitNum; |
// get current unit table values from low memory globals |
curUTableEntries = LMGetUnitTableEntryCount(); |
curUTableBase = LMGetUTableBase(); |
// search for empty space in the current unit table |
for ( unitNum = curUTableEntries - 1; |
unitNum >= 48; // lowest available unit number |
unitNum-- ) |
{ |
refNum = ~(unitNum); |
if (GetDCtlEntry(refNum) == nil) |
return(unitNum); // found a space |
} |
// no space in the current table, so make a new one |
// increase the size of the table by 16 (an arbitrary value) |
newUTableEntries = curUTableEntries + 16; |
// allocate space for the new table |
newUTableBase = NewPtrSysClear((long)newUTableEntries * sizeof(Handle)); |
if (newUTableBase == nil) { |
return(MemError()); |
} |
// copy the old table to the new table |
BlockMoveData(curUTableBase, newUTableBase, (long)curUTableEntries * sizeof(Handle)); |
// set the new unit table values in low memory |
LMSetUTableBase(newUTableBase); |
LMSetUnitTableEntryCount( newUTableEntries); |
unitNum = newUTableEntries - 1; |
// unitNum = 0; //uh bad thing man. |
return(unitNum); |
} |
*/ |
//------------------------------------------------------------------ |
static void ForceUpdate(void) |
//------------------------------------------------------------------ |
{ |
if (gSACurrentWindow) { |
SetPort(gSACurrentWindow); |
InvalRect(&gSACurrentWindow->portRect); |
} |
} |
//------------------------------------------------------------------ |
static void UnloadDriver(void) |
//------------------------------------------------------------------ |
{ |
short err; |
if (gDrvrRefNum) { |
err = RemoveDriver(gDrvrRefNum, true); |
gDrvrRefNum = 0; |
} |
} |
//------------------------------------------------------------------ |
static short InstallDriver(FSSpecPtr spec) |
//------------------------------------------------------------------ |
{ |
RegEntryID device={0,0}; |
short lowUnitNumber,hiUnitNumber ; |
short err = -1; |
if (gDrvrRefNum) { |
UnloadDriver(); |
} |
lowUnitNumber = 48 ; // MyFindSpaceInUnitTable(); |
hiUnitNumber = HighestUnitNumber(); |
if (lowUnitNumber > 0) { |
err = InstallDriverFromFile(spec,nil,lowUnitNumber ,hiUnitNumber,&gDrvrRefNum); |
if (err != noErr) { |
AlertUser(err); // we can be called from inside a drag handler so just set a flag |
SAEnableObject(gLoadButton); |
SADisableObject(gUnloadButton); |
} else { |
SAEnableObject(gUnloadButton); |
SADisableObject(gLoadButton); |
} |
} |
ForceUpdate(); |
return err; |
} |
// Load a driver via StandardFile |
//------------------------------------------------------------------ |
static short LoadDriver(void) |
//------------------------------------------------------------------ |
{ |
short err = -1; |
OSType typeList[4]; |
OSType * typeListPtr = typeList; |
StandardFileReply reply; |
typeList[0] = 'ndrv'; |
StandardGetFile(nil,1,typeList,&reply); |
if (reply.sfGood) { |
err = InstallDriver(&reply.sfFile); |
} |
return err; |
} |
// ODOC handler |
//------------------------------------------------------------------ |
static pascal OSErr MyOpenFileProc(FSSpecPtr myFSSPtr) |
//------------------------------------------------------------------ |
{ |
short err; |
err = InstallDriver(myFSSPtr) ; |
return noErr; |
} |
//------------------------------------------------------------------ |
static pascal short DoIdle(EventRecord *evt) |
//------------------------------------------------------------------ |
{ |
Str255 tempStr; |
short err; |
#pragma unused (evt) |
// in case we want to do something at idle time |
if (gError) { |
gAlertNMRec.qType = nmType; |
gAlertNMRec.nmFlags = 0; |
gAlertNMRec.nmPrivate = 0; |
gAlertNMRec.nmReserved = 0; |
gAlertNMRec.nmResp = nil; |
gAlertNMRec.nmStr = gAlertStr; |
gAlertNMRec.nmSound = nil; |
gAlertNMRec.nmMark = 1; |
gAlertNMRec.nmIcon = nil; |
err = AEInteractWithUser(kAEDefaultTimeout,&gAlertNMRec,nil); |
NumToString(gError,tempStr); |
ParamText(tempStr,"\p","\p","\p"); |
Alert(1002,nil); |
gError = 0; |
} |
return noErr; |
} |
//------------------------------------------------------------------ |
static pascal short DoLoadDriver(ButtonItemRef me,long refCon) |
//------------------------------------------------------------------ |
{ |
#pragma unused (me,refCon) |
short err; |
err = LoadDriver(); |
if (err == noErr ) { |
SADisableMe(); |
SAEnableObject(gUnloadButton); |
ForceUpdate(); |
} |
return noErr; |
} |
//------------------------------------------------------------------ |
static pascal short DoUnloadDriver(ButtonItemRef me,long refCon) |
//------------------------------------------------------------------ |
{ |
#pragma unused (me,refCon) |
UnloadDriver(); |
SADisableMe(); |
SAEnableObject(gLoadButton); |
ForceUpdate(); |
return noErr; |
} |
//------------------------------------------------------------------ |
static GetLineHeight(void) |
//------------------------------------------------------------------ |
{ |
FontInfo info; |
GetFontInfo(&info); |
return (info.ascent + info.descent + info.leading); |
} |
//------------------------------------------------------------------ |
static void DrawItem(StringPtr label,StringPtr text) |
//------------------------------------------------------------------ |
{ |
DrawString (label); |
DrawString (text); |
MoveTo(5,gVert); |
gVert += gLineHeight; |
} |
//------------------------------------------------------------------ |
static void DrawHex(StringPtr label,long n) |
//------------------------------------------------------------------ |
{ |
char s[256]; |
sprintf(s,"%0X",n); |
DrawString (label); |
DrawText(s,0,strlen(s)); |
MoveTo(5,gVert); |
gVert += gLineHeight; |
} |
//------------------------------------------------------------------ |
static void DrawHandle(StringPtr label,Handle text) |
//------------------------------------------------------------------ |
{ |
DrawString (label); |
if (text) { |
DrawText (*text,0,GetHandleSize(text)); |
} |
MoveTo(5,gVert); |
gVert += gLineHeight; |
} |
//------------------------------------------------------------------ |
static void DrawNumber(StringPtr label,long n) |
//------------------------------------------------------------------ |
{ |
Str255 tempStr; |
NumToString(n,tempStr); |
DrawString (label); |
DrawString (tempStr); |
MoveTo(5,gVert); |
gVert += gLineHeight; |
} |
//------------------------------------------------------------------ |
static pascal short MyUpdate(long refCon) |
//------------------------------------------------------------------ |
{ |
#pragma unused (refCon) |
Str255 tempStr; |
UnitNumber unitNum; |
DriverFlags flags; |
DriverOpenCount count; |
RegEntryID device; |
CFragSystem7Locator driverLoadLocation; |
CFragConnectionID fragmentConnID; |
DriverEntryPointPtr fragmentMain; |
DriverDescription driverDesc; |
FSSpec fileSpec; |
Handle fullPath = nil; |
short err = 0; |
short fullPathLength; |
gLineHeight = GetLineHeight(); |
gVert = 120; |
MoveTo(5,gVert); |
gVert += gLineHeight; |
if (gDrvrRefNum) { |
DrawString("\pThe driver is loaded. refNum = ("); |
NumToString(gDrvrRefNum,tempStr); |
DrawString (tempStr); |
DrawString("\p)"); |
MoveTo(5,gVert); |
gVert += gLineHeight; |
driverLoadLocation.u.onDisk.fileSpec = &fileSpec; |
err = GetDriverInformation(gDrvrRefNum, |
&unitNum, |
&flags, |
&count, |
tempStr, |
&device, |
&driverLoadLocation, |
&fragmentConnID, |
&fragmentMain, |
&driverDesc); |
DrawItem("\pName: ",tempStr); |
DrawNumber("\pUnitNumber: ",unitNum); |
DrawNumber("\pCount: ",count); |
DrawHex("\pflags: ",flags); |
err = FSpGetFullPath(&fileSpec,&fullPathLength, &fullPath); |
if (fullPath) { |
DrawHandle("\pPath: ",fullPath); |
DisposeHandle(fullPath); |
} |
DrawHex("\pFragment Main: 0x",(long)fragmentMain); |
} else { |
DrawString("\pNo Driver Loaded. "); |
} |
return noErr; |
} |
//--------------------------------------------------------------------------------------- |
static pascal OSErr MyPutData (ObjectItemRef orh,OSType kind,Ptr data,long len,long flags) |
//--------------------------------------------------------------------------------------- |
{ |
#pragma unused (orh,len,flags) |
HFSFlavor * theFile; |
if (kind == flavorTypeHFS) { |
theFile = (HFSFlavor *)data; |
if (theFile->fileType == 'cfrg' ) { |
InstallDriver(&theFile->fileSpec); |
} |
} |
return noErr; |
} |
// The drag receive handler |
//------------------------------------------------------------------ |
static pascal short MyReceive(ObjectItemRef orh,DragReference theDrag) |
//------------------------------------------------------------------ |
{ |
#pragma unused(orh) |
ItemReference itemRef; |
Size dataSize; |
HFSFlavor theHFSFlavor; |
OSErr retCode; |
// There is only one item, so get its reference number. |
retCode = GetDragItemReferenceNumber(theDrag, 1, &itemRef); |
if (retCode == noErr) { |
dataSize = sizeof(HFSFlavor); |
retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &theHFSFlavor, &dataSize, 0); |
if (retCode == noErr) { |
InstallDriver(&theHFSFlavor.fileSpec) ; |
} |
} |
return retCode; |
} |
//------------------------------------------------------------------ |
void main(void) |
//------------------------------------------------------------------ |
{ |
long buttonID = 1; |
long textID = 2; |
long dragID = 3; |
Str255 tempStr; |
Rect r ; |
long gMyWindowID; |
short err; |
InitSimpleApp(2,kUseStandardMenu); // Simple App Sets up the Tool Box For us |
gMyWindowID = GetDocumentWindow (128); // Get our stored window |
SetOpenFileProc (MyOpenFileProc); // set open file proc. This is called on an ODOC event |
SetWTitle(gSACurrentWindow,"\pMatt's PCI Driver Loader"); |
InstallIdleProc(DoIdle); |
SetWindowUpdateProc(gSACurrentWindow,MyUpdate ); //gSACurrentWindow for now, its a Kludge |
GetIndString(tempStr,kStaticStrings,kButtonName); // Get button name |
SetRectDimensions(&r, 180, 20); // This Sets its size without changing it position |
SetRectLocation(&r, 10, 30); // This Sets a rects anchor point |
(void)InstallPushButton(&buttonID,gSACurrentWindow,tempStr,&r,0,DoLoadDriver,nil); |
gLoadButton = buttonID; |
OffsetRect(&r,200,0); |
GetIndString(tempStr,kStaticStrings,3); // Get button name |
(void)InstallPushButton(&buttonID,gSACurrentWindow,tempStr,&r,0,DoUnloadDriver,nil); |
gUnloadButton = buttonID; |
SADisableMe(); |
SetRect(&r,4,55,gSACurrentWindow->portRect.right - 4,110); |
GetIndString(tempStr,kStaticStrings,kAboutText); // Get about this snippet text |
(void)InstallStaticText(&textID,gSACurrentWindow,tempStr,&r); |
// lets add drag and drop support for our window |
err = InstallDragObject(&dragID,gSACurrentWindow,"\p",&gSACurrentWindow->portRect, nil, nil, MyReceive, 0); |
err = SAInstallStandardDragHandlers(gSACurrentWindow); // enable dragging |
err = SAAddWindowDragDataTypes(gSACurrentWindow,flavorTypeHFS); // we accept flavorTypeHFS |
Run(); //Let SimpleApp handle the rest |
// lets check and see if the driver is still loaded and ask the |
// user what to do if it is loaded |
if (gDrvrRefNum) { |
short itemHit; |
itemHit = Alert(1001,nil); |
if (itemHit == 1 ) { |
UnloadDriver(); |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14