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.
Src/DoListSCSIDevices.c
/* DoListSCSIDevices.c */ |
/* |
* DoListSCSIDevices.c |
* Copyright © 1992-94 Apple Computer Inc. All Rights Reserved. |
* |
* Find all SCSI devices. The alogrithm first asks the SCSI Manager for the |
* number of busses, then loops through each bus for each device and LUN. |
* old SCSI Manager. This is made complex by the flexible SCSI Manager 4.3 |
* architecture: it is possible for the asynchronous SCSI Manager to only |
* be available on a third-party bus interface, for example. Because of this, |
* we must always scan the bus using the original SCSI Manager even if the |
* asynchronous manager is present. |
*/ |
#include "SCSISimpleSample.h" |
void |
DoListSCSIDevices(void) |
{ |
OSErr status; |
unsigned short lastHostBus; |
unsigned short initiatorID; |
unsigned short bus; |
unsigned short targetID; |
unsigned short LUN; |
DeviceIdent scsiDevice; |
SCSIGetVirtualIDInfoPB scsiGetVirtualIDInfo; |
short deviceCount; |
unsigned short maxTarget; |
Boolean useAsynchManager; |
Str255 work; |
LOG("\pList all SCSI Devices"); |
deviceCount = 0; |
/* |
* If we have the asynchronous SCSI Manager, find out how many busses |
* are present on this system. If not, force a "single bus" scan, since |
* DoSCSICommandWithSense ignores the hostBus information if it is |
* forced into "old-style" calls. |
*/ |
if (gEnableNewSCSIManager) |
status = SCSIGetHighHostBusAdaptor(&lastHostBus); |
else { |
status = noErr; |
lastHostBus = 0; /* Force one bus only */ |
} |
if (status == noErr) { |
for (bus = 0; bus <= lastHostBus; bus++) { |
/* |
* Look at this SCSI bus. This would be a good place to allocate |
* the SCSIExecIO command block. In this sample, however, it's |
* allocated on each call to AsyncSCSI, though this is inefficient. |
* Note that it is possible to have busses with no devices. This |
* is true for Apple Macintosh models with two busses (such as |
* the Quadra 950 and PowerMac 8100). Also, if you install a |
* third-party bus adaptor that supports the asynchronous SCSI |
* Manager on a machine with two busses, it would be assigned |
* bus 2 (with busses 0 and 1 referencing the internal system |
* busses). In this case, a system could have no devices on bus |
* 0 or 1. |
*/ |
*((long *) &scsiDevice) = 0; |
scsiDevice.bus = bus; |
/* |
* Check whether we can access this scsi device. SCSIBusAPI will |
* return an error status if this bus is inaccessable (i.e. no bus |
* or other trouble). If it returns noErr, useAsyncManager will |
* be TRUE if the asynchronous SCSI Manager is supported for this |
* bus, and FALSE if it can only be accessed through the original |
* SCSI Manager. This would indicate that a third-party bus |
* interface patched the original SCSI Manager traps (i.e., |
* patched SCSIGet, SCSISelect, etc). |
*/ |
status = SCSIBusAPI(scsiDevice, &useAsynchManager); |
if (status == noErr) { |
if (useAsynchManager) |
status = SCSIGetInitiatorID(scsiDevice, &initiatorID); |
else { |
initiatorID = 7; /* Asynch manager is disabled */ |
} |
} |
if (status != noErr) |
continue; |
/* |
* SCSIGetInitiatorID returned the bus ID of the Macintosh. This |
* is almost always seven, but only the SCSI Manager knows for |
* sure. Note that, by getting the Macintosh bus ID dynamically, |
* we prepare the code for a future system that permitted more |
* than one Macintosh on the same SCSI bus. |
*/ |
status = SCSIGetMaxTargetID(scsiDevice, &maxTarget); |
for (targetID = 0; targetID <= maxTarget; targetID++) { |
if (targetID != initiatorID) { |
scsiDevice.targetID = targetID; |
for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) { |
/* |
* Try to send a command to this LUN. If it fails, |
* don't try for higher-valued LUNs. |
* SCSICheckForDevicePresent looks, carefully, at the |
* returned error to distinguish between missing |
* devices and devices that are present, but unable to |
* respond, such as CD-ROM players with no disk |
* inserted. This call to SCSICheckForDevicePresent |
* will use the asynchronous SCSI Manager if it can. |
* |
* Note that, if the asynchronous manager is not |
* available, we can still check for non-zero LUNs by |
* using the old method of stuffing the LUN into the |
* command block, however this is not supported in |
* this example. |
*/ |
scsiDevice.LUN = LUN; |
if (SCSICheckForDevicePresent( |
scsiDevice, useAsynchManager) == FALSE) |
break; /* Don't look for LUNs */ |
else { |
++deviceCount; /* Found a device */ |
DoGetDriveInfo(scsiDevice, TRUE, useAsynchManager); |
} /* Check status */ |
} /* LUN loop */ |
} /* Not the initiator id */ |
} /* Target loop */ |
} /* Bus loop */ |
/* |
* Now, we need to look at the hard-wired SCSI drive addresses and |
* check whether a third-party hardware interface that does not use |
* the asynchronous SCSI Manager recognizes this address. If |
* gEnableNewSCSIManager is FALSE, the above loop called the original |
* SCSI Manager, so we don't have to try it again. In this sequence, |
* we hard-wire the initiator ID to seven, as there is no supported |
* way to determine it from the SCSI Manager or operating system. |
*/ |
if (gEnableNewSCSIManager) { |
scsiDevice.bus = 0; |
for (targetID = 0; targetID <= 6; targetID++) { |
CLEAR(scsiGetVirtualIDInfo); |
scsiGetVirtualIDInfo.scsiPBLength = sizeof scsiGetVirtualIDInfo; |
scsiGetVirtualIDInfo.scsiOldCallID = targetID; |
status = SCSIAction((SCSI_PB *) &scsiGetVirtualIDInfo); |
if (status != noErr) { |
/* |
* The asynchronous SCSI Manager does not know about this |
* target ID. Check whether it exists (forcing the request |
* to use the original SCSI Manager). |
*/ |
scsiDevice.targetID = targetID; |
for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) { |
scsiDevice.LUN = LUN; |
if (SCSICheckForDevicePresent(scsiDevice, FALSE) == FALSE) |
break; /* Don't look for LUNs */ |
else { |
++deviceCount; /* Found a device */ |
DoGetDriveInfo(scsiDevice, TRUE, FALSE); |
} /* Check status */ |
} |
} |
} |
} |
} /* Found a host adaptor */ |
NumToString(deviceCount, work); |
AppendPascalString(work, "\p SCSI Devices"); |
LOG(work); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14