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.
Relevant replacement documents include:
- Sample Code Project CDROMSample
CDROMDetection.c
/* |
File: CDROMDetection.c |
Description:The sample shows how to determine whether a drive is a CD-ROM drive. |
Author: BB |
Copyright: Copyright: © 1998,1999 by Apple Computer, Inc. |
all rights reserved. |
Disclaimer: 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. |
Change History (most recent first): |
6/23/99 Updated for Metrowerks Codwarrior Pro 2.1(KG) |
*/ |
#include <TextUtils.h> |
#include <LowMem.h> |
#include <DriverGestalt.h> |
#include <Files.h> |
#include <Devices.h> |
#include <SCSI.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <SIOUX.h> // Metrowerks only |
// Be sure and put the #pragma options align=mac68k statement |
// around any structure definitions which require a particular |
// structure alignment; otherwise the compiler tries to word |
// align the definitions, and nothing works on the PowerPC side. |
#if PRAGMA_ALIGN_SUPPORTED |
#pragma options align=mac68k |
#endif |
struct DeviceIdentParam { |
QElemPtr qLink; |
short qType; |
short ioTrap; |
Ptr ioCmdAddr; |
IOCompletionUPP ioCompletion; |
OSErr ioResult; |
StringPtr ioNamePtr; |
short ioVRefNum; |
short ioCRefNum; |
short csCode; |
DeviceIdent deviceIdentification; |
short csParam[9]; |
}; |
typedef struct DeviceIdentParam DeviceIdentParam, *DeviceIdentParamPtr; |
#if PRAGMA_ALIGN_SUPPORTED |
#pragma options align=reset |
#endif |
// This declares in C a type called "CallForEveryDriveQueueElement" |
// which can then be declared as a variable in some other routine. |
// That routine can initialize the variable to the address of some |
// routine to call, and pass that as a parameter to CruiseDriveQueue. |
typedef pascal OSErr (*CallForEveryDriveQueueElement)(DrvQElPtr dqPtr); |
// to use the above declaration, you would have code such as this: |
// CallForEveryDriveQueueElement someCall = YourRoutineName; |
// CruiseDriveQueue(someCall); |
// where "YourRoutineName" is replaced by the name of a routine |
// which has been declared as follows: |
// pascal OSErr YourRoutineName(DrvQElPtr dqPtr); |
// |
// This is the declaration of the routine which cruises the drive |
// queue, calling the input parameter (a procedure) with each drive |
// queue element in the drive queue. It looks complicated, but |
// it winds up being much easier to use. |
pascal OSErr CruiseDriveQueue(CallForEveryDriveQueueElement theCall); |
void DetectCD(void); |
OSErr DeviceIdentification( |
StringPtr drvrNamePtr, |
DrvQElPtr dqPtr, |
DeviceIdent *d); |
pascal OSErr PrintDriverInformation(DrvQElPtr dqPtr); |
StringPtr DrvrRefToName(short refNum); |
OSErr DetermineUsingDriverGestalt( |
short driverRefNum, |
short driveNumber, |
OSType *deviceType); |
//----------------------------------------------------------------- |
// The main routine. Start here. We turn off the annoying |
// "Do you want to save this window?" option of Metrowerks |
// Standard Libraries |
// |
void main(void) |
{ |
SIOUXSettings.asktosaveonclose = false; // Metrowerks only |
printf ("Sample showing how to detect CD-ROM drives\n\n"); |
DetectCD(); |
} |
//----------------------------------------------------------------- |
// This is the declaration of the routine which cruises the drive |
// queue, calling the input parameter (a procedure) with each drive |
// queue element in the drive queue. It looks complicated, but it |
// winds up being easy to use. |
// |
pascal OSErr CruiseDriveQueue(CallForEveryDriveQueueElement theCall) |
{ |
register DrvQElPtr dqPtr; |
OSErr err; |
dqPtr = (DrvQElPtr) GetDrvQHdr()->qHead; |
while (dqPtr != NULL) |
{ |
err = theCall(dqPtr); |
if (err) |
break; |
dqPtr = (DrvQEl *) dqPtr->qLink; |
} |
return (err); |
} |
//----------------------------------------------------------------- |
// This routine returns the device identification as documented |
// in Designing PCI Cards and Drivers |
// |
OSErr DeviceIdentification( StringPtr drvrNamePtr, |
DrvQElPtr dqPtr, |
DeviceIdent *d) |
{ |
DeviceIdentParam pb = {0}; |
OSErr err; |
pb.ioCompletion = nil; |
pb.ioNamePtr = drvrNamePtr; |
err = PBOpenSync((ParmBlkPtr)&pb); |
if (!err) |
{ |
pb.ioVRefNum = dqPtr -> dQDrive; |
pb.ioCRefNum = dqPtr -> dQRefNum; |
pb.csCode = 120; |
err = PBStatusSync((ParmBlkPtr)&pb); |
} |
*d = pb.deviceIdentification; |
return err; |
} |
//----------------------------------------------------------------- |
// This routine just sets up a variable with the name of a routine |
// to call for every drive queue element, and then calls our |
// generic "scan the drive queue" routine. This will call the |
// routine we passed in for every drive queue element. |
// We tell the "CruiseDriveQueue" routine to call our |
// PrintDriverInformation routine for each entry in the drive queue. |
void DetectCD(void) |
{ |
CallForEveryDriveQueueElement someCall = PrintDriverInformation; |
CruiseDriveQueue(someCall); |
} |
//----------------------------------------------------------------- |
// PrintDriverInformation prints information about the driver for |
// each Drive Queue Element we pass it. If the drive in question |
// passes tests to see if it's a CD-ROM drive, we print additional |
// information |
// |
pascal OSErr PrintDriverInformation(DrvQElPtr dqPtr) |
{ |
StringPtr drvrNamePtr; |
OSType theDriveType; |
DeviceIdent d; |
OSErr err; |
// dqPtr->dQRefNum contains the driver reference number. |
// In order to display something to the user, we will get |
// the driver name by looking in the unit table (an array) |
// to find the driver name. |
drvrNamePtr = DrvrRefToName(dqPtr->dQRefNum); |
printf("DriverName: %.*s ", drvrNamePtr[0], &drvrNamePtr[1]); |
if ( EqualString(drvrNamePtr, "\p.AppleCD", false, true) ) |
printf("(This is a CD-ROM drive.) "); |
err = DetermineUsingDriverGestalt(dqPtr->dQRefNum, dqPtr->dQDrive, &theDriveType); |
if (!err) |
{ |
char c[5]; |
BlockMoveData(&theDriveType, c, 4); |
c[4] = 0; |
printf("Driver Gestalt returned '%s'", c); |
} |
err = DeviceIdentification(drvrNamePtr, dqPtr, &d); |
if (!err) |
{ |
printf("\nDevice reports that it is bus type %d, bus %d, target %d, partition/LUN %d.", |
d.diReserved, d.bus, d.targetID, d.LUN); |
} |
printf("\n"); |
return noErr; |
} |
//----------------------------------------------------------------- |
// Lookup driver name from the unit table. The driver name starts |
// at 18 bytes into the driver itself. From the Unit Table entry |
// for this driver, get the name, but take into account whether it |
// is a handle based driver or a pointer based driver. |
// |
StringPtr DrvrRefToName(short refNum) |
{ |
AuxDCEHandle* UTable = (AuxDCEHandle*) LMGetUTableBase(); |
DCtlPtr dctl; |
Ptr p; |
static StringPtr driverName; |
if ( refNum == 0 ) |
{ |
driverName = "\p<none>"; |
} |
else |
{ |
dctl = (DCtlPtr) *UTable[~refNum]; |
p = dctl->dCtlDriver; |
// a RAMbased driver is handle based, a ROMbased driver |
// is pointer based. If it's a handle based driver, we |
// need one more level of indirection. The following |
// test provides that indirection if necessary. |
if( dctl->dCtlFlags & dRAMBasedMask) |
p = (void*) *p; |
if ( p != nil ) |
driverName = (void *)(p+18); |
else |
driverName = "\p-Purged-"; |
} |
return ( driverName); |
} |
//----------------------------------------------------------------- |
// Call the driver using the DriverGestalt status code. The result |
// tells us if this driver is a CD-ROM |
// |
OSErr DetermineUsingDriverGestalt(short driverRefNum, |
short driveNumber, |
OSType *deviceType) |
{ |
DriverGestaltParam pb; |
OSErr err; |
pb.ioVRefNum = driveNumber; |
pb.ioCRefNum = driverRefNum; |
pb.csCode = kDriverGestaltCode; |
pb.driverGestaltSelector = kdgDeviceType; |
err = PBStatusSync((ParmBlkPtr) &pb); |
if (!err) |
{ |
*deviceType = pb.driverGestaltResponse; |
} |
return (err); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14