TradDriverLoaderLib/TradDriverLoaderLib.h

/*
    File:       TradDriverLoaderLib.h
 
    Contains:   C interface for the pseudo-DriverLoaderLib for 'DRVR's.
 
    Written by: Quinn "The Eskimo!"
 
    Copyright:  © 1996 by Apple Computer, Inc., all rights reserved.
 
    Change History (most recent first):
 
    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 "DSC 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.
*/
 
#include <Types.h>
#include <Devices.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
///////////////////////////////////////////////////////////////////////////
 
// The following routines are implemented with semantics virtually identical
//  to those found in DriverLoaderLib.  You should look in
//  "Designing PCI Cards and Drivers for Power Macintosh Computers" for
//  documentation.  You can FTP an electronic copy from:
/*  <ftp://ftpdev.info.apple.com//Developer_Services/
     Technical_Documentation/PCI_Information/Designing_PCI_Cards_-_Driv.sit.>
*/
 
extern pascal SInt16 TradHigherDriverVersion(NumVersion *dv1, NumVersion *dv2);
 
extern pascal UnitNumber TradHighestUnitNumber(void);
 
extern pascal OSErr TradDriverGestaltOn(DriverRefNum refNum);
 
extern pascal OSErr TradDriverGestaltOff(DriverRefNum refNum);
 
extern pascal Boolean TradDriverGestaltIsOn(DriverFlags flags);
 
extern pascal OSErr TradLookupDrivers(UnitNumber beginningUnit,
                                        UnitNumber endingUnit,
                                        Boolean emptyUnits,
                                        ItemCount *returnedRefNums, 
                                        DriverRefNum *refNums);
 
///////////////////////////////////////////////////////////////////////////
 
// The following routines are similar to the corresponding routines in
//  DriverLoaderLib, but their interface differs because of the
//  inherent differences between 'DRVR's and 'ndrv's.  The comments
//  cover the differences for each routine.  If there's a difference
//  that's not commented, it's most probably a bug and you should let
//  me know.
 
extern pascal OSErr TradInstallDriverFromPtr(DRVRHeaderPtr driver,
                                                UnitNumber beginningUnit,
                                                UnitNumber endingUnit,
                                                DriverRefNum *refNum);
    // This routine is similar to InstallDriverFromMemory except
    //  that you pass a pointer to the 'DRVR', rather than a base pointer
    //  and length.  This pointer is copied verbatim into the dCtlDriver
    //  field of the DCE, so you have to make sure that it's in
    //  the system heap if the driver is going to hang around longer than
    //  your application.
    // One other deviation from InstallDriverFromMemory is that this
    //  call won't replace an existing driver.  This is because 'DRVR's
    //  don't have infrastructure to support this.  If there's already
    //  a driver of the same name in the unit table, the call will fail
    //  with a dupFNErr, and *refNum will be set to the refnum of the
    //  existing driver.
    // The semantics of the endingUnit match those of DriverLoaderLib,
    //  ie the call will not grow the unit table unless endingUnit is
    //  greater than TradHighestUnitNumber.  The simplest way to work
    //  this is to pass TradHighestUnitNumber() + 1 to endingUnit.
    // If the call fails, it's your responsibility to dispose of the
    //  the driver pointer.  If it succeeds, the system has a copy
    //  of the pointer, which can be disposed by calling TradRemoveDriver.
 
extern pascal OSErr TradInstallDriverFromHandle(DRVRHeaderHandle driver,
                                                UnitNumber beginningUnit,
                                                UnitNumber endingUnit,
                                                DriverRefNum *refNum);
    // This routine is similar to InstallDriverFromMemory except
    //  that you pass a handle to the 'DRVR', rather than a base pointer
    //  and length.  This is generally more convenient in the traditional
    //  'DRVR' world.
    // In most other respects, this routine works like TradInstallDriverFromPtr.
    //  The routine simply creates a pointer in the system heap and copies
    //  your driver into it, then calls TradInstallDriverFromPtr.  Because
    //  a copy is made, you do not have to ensure that the handle you
    //  pass in is in the system heap.
    // Regardless of whether call succeeds or fails, it's your responsibility
    //  to dispose of the driver handle.
    
extern pascal OSErr TradInstallDriverFromResource(SInt16 rsrcID, StringPtr rsrcName,
                                                UnitNumber beginningUnit,
                                                UnitNumber endingUnit,
                                                DriverRefNum *refNum);
    // This call offers functionality like InstallDriverFromFile.
    //  It differs from InstallDriverFromFile in that the driver is expected
    //  to be in a resource in the current resource file.  If rsrcName is nil,
    //  the call uses Get1Resource('DRVR', rsrcID) to get the driver.  If
    //  rsrcName is not nil, it uses Get1NamedResource('DRVR', rsrcName)
    //  to get the driver.
    // In most other respects, this routine works like TradInstallDriverFromPtr.
    // If the call fails, the routine will clean up after itself.  If the
    //  call succeeds, the driver code is left as a memory block in the system
    //  heap, which can be cleaned up by calling TradRemoveDriver.
 
extern pascal OSErr TradGetDriverInformation(DriverRefNum refNum,
                                                UnitNumber *thisUnit,
                                                DriverFlags *flags,
                                                StringPtr name,
                                                DRVRHeaderPtr *driverHeader
                                                );
    // This routine is like GetDriverInformation except that it only
    //  returns information that's pertinant to the traditional 'DRVR'
    //  world.  driverHeader comes back as a pointer to the beginning
    //  of the 'DRVR' header.
    // Note that this routine works for both drivers installed by
    //  this library and other drivers, however for drivers not installed
    //  by this library (ie 'RAM'-based drivers), driverHeader may be a 
    //  half dereferenced handle, locked or unlocked.  You have been warned.
    // Also, driverHeader can come back set to nil, if the driver
    //  is installed but its code has been purged, for example a DA.
    //  You must check for this before deferencing it.  If driverHeader
    //  is set to nil, name will be set to the empty string.
 
extern pascal OSErr TradOpenInstalledDriver(DriverRefNum refNum, SInt8 ioPermission);
    // This routine has the same semantics as OpenInstalledDriver
    //  except that the ioPermission parameter must be fsRdWrPerm.  This is
    //  because we call through to the Device Manager's OpenDriver routine,
    //  and that doesn't support passing in permissions.  I could switch the
    //  implementation to use PBOpen, but PBOpen is a trap fraught with much
    //  danger, so I'm avoiding it at the moment.
    // The danger associated with PBOpen is that it's highly overloaded,
    //  being used for FSOpen, PBOpen, PBHOpen, OpenSlot, OpenDriver,
    //  OpenDeskAcc, and so on.  If you get the glue wrong, you die in
    //  strange and evil ways.  So I'm bypassing the entire problem by
    //  ignoring ioPermission.  I may revisit this decision, but not soon.
 
extern pascal OSErr TradRemoveDriver(DriverRefNum refNum, Boolean immediate);
    // This routine implements similar semantics to RemoveDriver, except
    //  that the Immediate parameter must be false.  This is because
    //  we close the driver using PBCloseSync, which is a queued
    //  command, just like all the others.  We have no way to bypass
    //  this.
    // An important thing to note is that you should only call this on drivers
    //  you installed using this library's TradInstallDriverFromHandle
    //  and TradInstallDriverFromResource routine.  Don't call it on
    //  drivers installed by other people and be careful when calling it on
    //  drivers installed using TradInstallDriverFromPtr because you might
    //  be disposing the driver code even though a) it might not actually be a
    //  Memory Manager pointer block, or b) it might be still in use
    //  by another driver.
 
extern pascal OSErr TradRenameDriver(DriverRefNum refNum, ConstStr255Param newDriverName);
    // This routine is implemented with the caveat that you can't
    //  make the driver name longer.  This is because the 'DRVR'
    //  name is actually stored in the code resource which implements
    //  the driver, and making it longer would cause it to run into
    //  the code that immediately follows the name.
    // The reason why I implemented this routine at all is because
    //  it's useful for installing multiple copies of the same driver.
    //  For example, you can install ".Q_Out", then rename it to
    //  ".QAOut", and then install ".Q_Out" again, and rename that to
    //  ".QBOut".  This can be very useful when testing and debugging
    //  your driver (or TradDriverLoaderLib for that matter :).
    // You should take extreme care when calling this routine on drivers that
    //  weren't installed with this library.  Some of these drivers might
    //  not like being renamed in this way.
 
///////////////////////////////////////////////////////////////////////////
 
// The following routines from DriverLoaderLib were not implemented because
//  they make no sense at all in the world of 'DRVR's.
 
// VerifyFragmentAsDriver
// GetDriverMemoryFragment
// GetDriverDiskFragment
// InstallDriverFromFragment
// SetDriverClosureMemory
// -- If they've got fragment in the name, it's hard to map them into the
// 'DRVR' world.  Traditional 'DRVR's just aren't code fragments!
 
// InstallDriverFromFile -- This routine assumes that there's only
//  one driver in a file, which is not the case for traditional 'DRVR's
//  which are normally stored as resources.  The basic functionality has
//  been subsumed by TradInstallDriverFromResource.
 
// InstallDriverFromDisk
// FindDriversForDevice
// FindDriverCandidates
// ScanDriverCandidates
// GetDriverForDevice
// InstallDriverForDevice
// -- These routines all assume that there's some magic way of matching
//  drivers to their name register nodes.  In the traditional world, there
//  is no name registry and, even if there was, there's no way to match
//  devices against hardware.  So these routines are not sensible in the
//  traditional world. 
 
// ReplaceDriverWithFragment -- There's no good way to replace a traditional
//  device driver; the infrastructure just isn't there.
 
#ifdef __cplusplus
}
#endif