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.
ATA Demo.c
/* |
File: ATA Demo.c |
Description:ATADemo is a CodeWarrior C sample that will call the ATA |
Manager and scan the ATA bus and list the various device |
configuration data. |
This sample has been updated to properly work with the .AppleCD |
driver installed. |
The sample also has been updated to attempt to read sector 0 of |
each ATA or ATAPI device and display the contents. |
Copyright: © Copyright 1996-2001 Apple Computer, Inc. All rights reserved. |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
("Apple") in consideration of your agreement to the following terms, and your |
use, installation, modification or redistribution of this Apple software |
constitutes acceptance of these terms. If you do not agree with these terms, |
please do not use, install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and subject |
to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs |
copyrights in this original Apple software (the "Apple Software"), to use, |
reproduce, modify and redistribute the Apple Software, with or without |
modifications, in source and/or binary forms; provided that if you redistribute |
the Apple Software in its entirety and without modifications, you must retain |
this notice and the following text and disclaimers in all such redistributions of |
the Apple Software. Neither the name, trademarks, service marks or logos of |
Apple Computer, Inc. may be used to endorse or promote products derived from the |
Apple Software without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or implied, |
are granted by Apple herein, including but not limited to any patent rights that |
may be infringed by your derivative works or by other works in which the Apple |
Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Change History (most recent first): |
04/04/01 Converted to CW Pro 6 |
Added file ATAExecIO.c to demonstrate sending ATA and ATAPI commands |
Read and display sector 0 of each device <JAS> |
06/23/99 Reformatted and Recompiled on CW Pro 2.1(KG) |
03/15/99 Updated to CW 4 and it's headers. |
Added code to set the standard .AppleCD driver |
into a quiescent state and thus allow us to |
query the ATA bus without disturbing the .AppleCD driver.(VM) |
06/25/98 Buffer was still the incorrect size in |
DisplayATADriveIdentity routine. |
Buffer needs to be 256 words (for 512 bytes long). |
Drive identify just assumes you have allocated a |
512 byte buffer and writes it accordingly. In |
this case it overwrites the end of the array. |
Modified to CW Pro 3 and its headers(VM) |
10/05/97 Buffer was incorrect size in |
DisplayATADriveIdentity routine. |
Modified to CW Pro 1 and its headers |
Added Metrowerks SIOUX specific stuff |
Created Fat application |
Realized that the words come back swapped; |
adjusted for this in the DumpFormatedBuffer routine.(BLoB) |
*/ |
//------------------------------------------------------------------------------------ |
#pragma mark Includes |
//------------------------------------------------------------------------------------ |
#include <stdio.h> |
#include <stdlib.h> |
#include <LowMem.h> |
#include <Patches.h> |
#include <Traps.h> |
#include <Devices.h> |
#include <ATA.h> |
#ifdef __MWERKS__ |
#include <SIOUX.h> |
#endif |
#include "ATA Demo.h" |
//------------------------------------------------------------------------------------ |
#pragma mark Globals |
//------------------------------------------------------------------------------------ |
UInt8 gATAMgrPBVers; // used to hold current version of PB from ataMgrInquiry |
FormatTable kIdentFormat[] = { |
{ 0, 0, kHex, "Configuration word" }, |
{ 1, 1, kDecimal, "Cylinders" }, |
{ 3, 3, kDecimal, "Heads" }, |
{ 4, 4, kDecimal, "Bytes/Track" }, |
{ 5, 5, kDecimal, "Bytes/Sector (0 = 512 bytes)" }, |
{ 5, 5, kDecimal, "Sectors/Track" }, /* 35 */ |
{ 7, 9, kHex, "Vendor Unique (word 7..9)" }, |
{ 10, 19, kRightJust, "Serial Number" }, |
{ 20, 20, kHex, "Buffer Type" }, |
{ 21, 21, kDecimal, "Buffer size in 512 byte increments" }, |
{ 22, 22, kDecimal, "Number of ECC bytes available" }, |
{ 23, 26, kLeftJust, "Firmware Revision" }, |
{ 27, 46, kLeftJust, "Model Number" }, |
{ 47, 53, kHex, "Capability Flags (word 47..53)" }, |
{ 54, 54, kDecimal, "Cylinders (current mode)" }, |
{ 55, 55, kDecimal, "Heads (current mode)" }, |
{ 56, 56, kDecimal, "Sectors/Track (current mode)" }, |
{ 57, 58, kDecimal, "Current Capacity in Sectors" }, |
{ 59, 59, kHex, "Multiple Sector Capability Flag" }, |
{ 60, 61, kDecimal, "Current User-addressable Sectors" }, |
{ 62, 62, kHex, "Single Word DMA Transfer Mode Flags" }, |
{ 63, 63, kHex, "Multiword DMT Transfer Mode Flags" }, |
{ 0, 0, kEndOfTable,"" } |
}; |
//------------------------------------------------------------------------------------ |
#pragma mark - |
//------------------------------------------------------------------------------------ |
// --------------------------------------------------------------------------- |
void main (void) |
// --------------------------------------------------------------------------- |
{ |
OSErr status; |
SInt16 drvrRefNum = 0; |
#ifdef __MWERKS__ |
SIOUXSettings.asktosaveonclose = false; |
SIOUXSettings.columns = 88; |
#endif |
printf("Macintosh ATA Manager Sample\n\n"); |
// Check for ATA Hardware |
// you should do this before calling the ATAManager, since some early ROMS |
// could indicate an ATA manager without the proper HW, thus casing a crash. |
if (ATAHardwarePresent() == false) { |
printf("ATA Hardware is not present on this system\n"); |
exit(EXIT_FAILURE); |
} |
// Check for ATA Manager |
if (ATAManagerPresent() == false) { |
printf("ATA Manager is not present on this system\n"); |
exit(EXIT_FAILURE); |
} |
// Display ATA Manager Info |
status = DisplayATAManagerInquiryInfo(); |
if (status != noErr) { |
printf("Cannot access ATA Manager: %d\n", (int) status); |
exit(EXIT_FAILURE); |
} |
// Disable the CD driver |
status = OpenDriver("\p.AppleCD", &drvrRefNum); |
if (status == noErr) { |
printf("Found .AppleCD driver, preparing to disable it\n"); |
status = DisableCDDriver(drvrRefNum); |
} |
// Display ATA Device Info |
status = ScanATABusses(); |
if (status != noErr) { |
printf("Cannot access ATA Manager: %d\n", (int) status); |
exit(EXIT_FAILURE); |
} |
// Renable the CD driver |
if(drvrRefNum != 0) |
{ |
printf("Re-enabling the .AppleCD driver \n"); |
status = EnableCDDriver(drvrRefNum); |
} |
} |
// --------------------------------------------------------------------------- |
OSErr DisplayATAManagerInquiryInfo (void) |
// --------------------------------------------------------------------------- |
// |
// Display information about the ATA Manager |
// |
{ |
ataMgrInquiry pb; |
OSErr status; |
CLEAR(pb); |
pb.ataPBFunctionCode = kATAMgrManagerInquiry; |
pb.ataPBVers = kATAPBVers1; |
status = ataManager((ataPB*) &pb ); |
IF_ERROR(status, "ATA Manager Inquiry failed\n") |
printf("ATA Manager inquiry:\n"); |
PrintNumVersion("\tATA Manager Version:", pb.ataMgrVersion); |
printf("\tBusses:\t\t%d\n\tDevices:\t%d\n", |
pb.ataBusCnt, pb.ataDevCnt); |
printf("\tPIO Modes:\t%x\n\tDMA Modes:\t%d\n\tMulti DMA Modes:%x\n", |
pb.ataPioModes, pb.ataSingleDMAModes, pb.ataMultiDMAModes); |
printf("-----------------------------------------\n\n"); |
gATAMgrPBVers = pb.ataMgrPBVers; // remember current PB version |
return (status); |
} |
// --------------------------------------------------------------------------- |
OSErr ScanATABusses (void) |
// --------------------------------------------------------------------------- |
// |
// Display information about the ATA Busses |
// |
{ |
ataDrvrRegister pb; |
OSErr status; |
// Get first device ID (yes you have to do this once) |
CLEAR(pb); |
pb.ataPBFunctionCode = kATAMgrFindDriverRefnum; |
pb.ataPBVers = kATAPBVers1; |
pb.ataPBDeviceID = (UInt32)0x0000ffff; |
status = ataManager((ataPB*) &pb ); |
// loop through devices |
for (pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID; |
pb.ataPBDeviceID != 0xff; |
pb.ataPBDeviceID = (UInt32) pb.ataDeviceNextID) |
{ |
status = ataManager((ataPB*) &pb ); |
IF_ERROR(status, "ATA Find Driver failed\n") |
printf("\nDevice %d %#s\n", pb.ataPBDeviceID, DrvrRefToName(pb.ataDrvrRefNum) ); |
DisplayATADriveIdentity(pb.ataPBDeviceID); |
printf("-----------------------------------------\n"); |
}; |
printf("\n"); |
return (status); |
} |
// --------------------------------------------------------------------------- |
OSErr DisplayATADriveIdentity (UInt32 deviceID) |
// --------------------------------------------------------------------------- |
// |
// Display information about the ATA Identify Info |
// |
{ |
ataIdentify pb; |
ataDevConfiguration pb1; |
UInt8 devType; |
UInt16 buffer[256]; |
OSErr status; |
UInt8 dataBuffer[4096]; |
// Get Driver Configuration |
CLEAR(pb1); |
pb1.ataPBFunctionCode = kATAMgrGetDrvConfiguration; |
pb1.ataPBVers = kATAPBVers2; |
pb1.ataPBDeviceID = deviceID; |
status = ataManager((ataPB*) &pb1 ); |
IF_ERROR(status, "ATA GetDrvConfiguration failed\n") |
// Setup Identify block; |
CLEAR(pb); |
pb.ataPBFunctionCode = kATAMgrDriveIdentify; |
pb.ataPBVers = kATAPBVers1; |
pb.ataPBDeviceID = deviceID; |
pb.ataPBFlags = mATAFlagIORead + mATAFlagByteSwap ; |
if(pb1.ataDeviceType == kDevATAPI) pb.ataPBFlags += mATAFlagProtocol1; |
pb.ataPBTimeOut = 100; |
pb.ataPBBuffer = (void*) buffer; |
status = ataManager((ataPB*) &pb ); |
IF_ERROR(status, "ATA DriveIdentify failed\n") |
printf("Configuration: ("); |
switch(pb1.ataDeviceType){ |
case kDevUnknown: |
printf("Unknown protocol"); |
devType = 0; |
break; |
case kDevATA: |
printf("ATA"); |
devType = kDevATA; |
break; |
case kDevATAPI: |
printf("ATAPI"); |
devType = kDevATAPI; |
break; |
case kDevPCMCIA: |
printf("PCMCIA"); |
devType = kDevATA; |
break; |
} |
switch(pb1.ataSocketType){ |
case kSocketUnknown: |
printf(", Unknown Socket"); |
break; |
case kSocketInternal: |
printf(", Internal"); |
break; |
case kSocketMediaBay: |
printf(", Media Bay"); |
break; |
case kkSocketPCMCIA: |
printf(", PCMCIA, Vcc=%d, Vpp1=%d, Vpp2=%d", |
pb1.atapcVcc, pb1.atapcVpp1,pb1.atapcVpp2); |
break; |
} |
printf(")\n"); |
DumpFormatedBuffer(buffer, kIdentFormat); |
// read and display sector 0 |
if( (devType == kDevATA) ) |
{ |
status = ATARead( pb1.ataPBDeviceID, dataBuffer ); |
if( status == noErr ) |
{ |
printf( "\n*********************************** Sector 0 ***********************************\n\n" ); |
DumpRawBuffer( dataBuffer, 512 ); |
} |
else |
printf( "\nATA read failed: %d\n", status ); |
} |
else if( devType == kDevATAPI ) |
{ |
status = ATAPIRead( pb1.ataPBDeviceID, dataBuffer ); |
if( status == noErr ) |
{ |
printf( "\n*********************************** Sector 0 ***********************************\n\n" ); |
DumpRawBuffer( dataBuffer, 2048 ); |
} |
else |
printf( "\nATAPI read failed: %d\n", status ); |
} |
return status; |
} |
// --------------------------------------------------------------------------- |
OSErr DisableCDDriver (SInt16 refNum) |
// --------------------------------------------------------------------------- |
// |
// Disable the CD driver |
// |
{ OSErr status; |
printf("- Disable the CD Driver \n"); |
// wake up drive |
status = WakeUpCDDrive (refNum); |
if (status != noErr) |
{ |
return status; |
} |
// move driver to quiescent mode |
status = SetQuiescence (refNum, quiescenceON); |
if (status != noErr) |
{ |
return status; |
} |
return noErr; |
} |
// --------------------------------------------------------------------------- |
OSErr EnableCDDriver (SInt16 refNum) |
// --------------------------------------------------------------------------- |
// |
// Re-enable the CD driver |
// |
{ OSErr status; |
printf("- Enable the CD Driver \n"); |
// move driver to quiescent mode |
status = SetQuiescence (refNum, quiescenceOFF); |
if (status != noErr) |
{ |
return status; |
} |
return noErr; |
} |
// --------------------------------------------------------------------------- |
OSErr WakeUpCDDrive (SInt16 refNum) |
// --------------------------------------------------------------------------- |
// |
// Re-enable the CD driver |
// |
{ CntrlParam pb; |
OSErr status; |
printf("-- Wake up the CD Driver \n"); |
CLEAR(pb); |
pb.ioCRefNum = refNum; |
pb.csCode = csSetPowerMode; |
*(UInt8 *) &pb.csParam[0] = pmActive; |
// send command to the CD/DVD driver |
status = PBControlImmed ((ParmBlkPtr) &pb); |
return status; |
} |
// --------------------------------------------------------------------------- |
OSErr SetQuiescence (SInt16 refNum, UInt16 mode) |
// --------------------------------------------------------------------------- |
// |
// Re-enable the CD driver |
// |
{ |
CntrlParam pb; |
OSErr status; |
printf("-- Set the CD Driver Quiescence mode to %s\n", |
(mode ==quiescenceOFF)? "Off":"On"); |
CLEAR(pb); |
pb.ioCRefNum = refNum; |
pb.csCode = csQuiescence; |
pb.csParam[0] = mode; |
// send command to the CD/DVD driver |
status = PBControlImmed ((ParmBlkPtr) &pb); |
return status; |
} |
// --------------------------------------------------------------------------- |
Boolean ATAManagerPresent (void) |
// --------------------------------------------------------------------------- |
// |
// returns true if this machine has the ata manager |
// |
{ |
return (TrapAvailable(kATATrap)); |
} |
// --------------------------------------------------------------------------- |
Boolean ATAHardwarePresent (void) |
// --------------------------------------------------------------------------- |
// |
// returns true if this machine has ata hardware |
// |
{ |
UInt16 configFlags; |
// Hardware configuration flags |
configFlags = LMGetHWCfgFlags(); |
return (configFlags & 0x0080); |
} |
//------------------------------------------------------------------------------------ |
#pragma mark - |
#define NumToolboxTraps() ( \ |
(NGetTrapAddress(_InitGraf, ToolTrap) \ |
== NGetTrapAddress(0xAA6E, ToolTrap)) \ |
? 0x200 : 0x400 \ |
) |
#define GetTrapType(theTrap) ( \ |
(((theTrap) & 0x800) != 0) ? ToolTrap : OSTrap \ |
) |
// --------------------------------------------------------------------------- |
Boolean TrapAvailable (short theTrap) |
// --------------------------------------------------------------------------- |
// (see Inside Mac VI 3-8) |
{ |
TrapType trapType; |
trapType = GetTrapType(theTrap); |
if (trapType == ToolTrap) { |
theTrap &= 0x07FF; |
if (theTrap >= NumToolboxTraps()) |
theTrap = _Unimplemented; |
} |
return ( |
NGetTrapAddress(theTrap, trapType) |
!= NGetTrapAddress(_Unimplemented, ToolTrap) |
); |
} |
// --------------------------------------------------------------------------- |
void PrintNumVersion (char *label, NumVersion version ) |
// --------------------------------------------------------------------------- |
// |
// Decode version number info |
// |
{ |
char *stage; |
switch (version.stage) { |
case developStage: stage = "d"; break; |
case alphaStage: stage = "a"; break; |
case betaStage: stage = "b"; break; |
case finalStage: stage = ""; break; |
default: stage = "?"; break; |
} |
printf("%s %d.%d.%d", |
label, |
version.majorRev, |
(version.minorAndBugRev>>4), (version.minorAndBugRev & 0xf), |
stage); |
if(version.stage != finalStage) printf(".%d",version.nonRelRev); |
printf(" (hex %08lx)\n", (* ((unsigned long *) &version))); |
} |
// --------------------------------------------------------------------------- |
void DumpFormatedBuffer (void* p, const FormatTablePtr format) |
// --------------------------------------------------------------------------- |
// |
// Dump formatted buffer |
// |
{ |
unsigned short *idInfo = p; |
register char *charField; |
register short fieldLength; |
register short i; |
register long value; |
register FormatTablePtr formatPtr; |
#define FORMAT (*formatPtr) |
for (formatPtr = format; FORMAT.format != kEndOfTable; formatPtr++) { |
printf("%35s", FORMAT.label); |
switch (FORMAT.format) { |
// Decimal values come as two words with the words swapped. |
case kDecimal: |
value = 0; |
for (i = FORMAT.lastWord; i >= FORMAT.firstWord; i--) { |
value <<= 16; |
value += idInfo[i]; |
} |
printf(" %lu", value); // was %lu |
break; |
case kHex: |
for (i = FORMAT.lastWord; i >= FORMAT.firstWord; i--) { |
value = idInfo[i]; |
printf(" 0x%04X", value); |
} |
break; |
case kLeftJust: |
charField = (char *) &idInfo[FORMAT.firstWord]; |
fieldLength = (FORMAT.lastWord - FORMAT.firstWord + 1) |
* sizeof (unsigned short); |
/* |
* First scan for an unspecified field. |
*/ |
for (i = 0; i <= fieldLength; i++) { |
if (charField[i] != '\0') |
goto gotLeftJustField; |
} |
printf(" <not specified>"); |
break; |
gotLeftJustField: |
for (i = fieldLength; i > 0; --i) { |
if (charField[i - 1] != ' ') |
break; |
} |
printf(" \"%.*s\"", (int) i, charField); |
break; |
case kRightJust: |
charField = (char *) &idInfo[FORMAT.firstWord]; |
fieldLength = (FORMAT.lastWord - FORMAT.firstWord + 1) |
* sizeof (unsigned short); |
/* |
* First scan for an unspecified field. |
*/ |
for (i = 0; i <= fieldLength; i++) { |
if (charField[i] != '\0') |
goto gotRightJustField; |
} |
printf(" <not specified>"); |
break; |
gotRightJustField: |
for (i = 0; i < fieldLength; i++) { |
if (charField[i] != ' ') |
break; |
} |
printf(" \"%.*s\"", (int) (fieldLength - i), &charField[i]); |
break; |
} |
printf("\n"); |
} |
// DumpRawBuffer( p,512); |
} |
// --------------------------------------------------------------------------- |
void DumpRawBuffer ( UInt8 *bufferPtr, int length ) |
// --------------------------------------------------------------------------- |
// |
// Dump buffer |
// |
{ |
register int i; |
int lineStart; |
int lineLength; |
short c; |
#define kLineSize 16 |
for (lineStart = 0; lineStart < length; lineStart += lineLength) { |
lineLength = kLineSize; |
if (lineStart + lineLength > length) |
lineLength = length - lineStart; |
printf("%03x %3d:", lineStart, lineStart); |
for (i = 0; i < lineLength; i++) |
printf(" %02x", bufferPtr[lineStart + i] & 0xFF); |
for (; i < kLineSize; i++) |
printf(" "); |
printf(" "); |
for (i = 0; i < lineLength; i++) { |
c = bufferPtr[lineStart + i] & 0xFF; |
if (c > ' ' && c < '~') |
printf("%c", c); |
else { |
printf("."); |
} |
} |
printf("\n"); |
} |
} |
// --------------------------------------------------------------------------- |
char* DrvrRefToName(short refNum) |
// --------------------------------------------------------------------------- |
// |
// lookup driver name in table |
// |
{ |
AuxDCEHandle* UTable = (AuxDCEHandle*) LMGetUTableBase(); |
DCtlPtr dctl; |
Ptr p; |
if(!refNum) return ((char*) "\p<none>"); |
dctl = (DCtlPtr) *UTable[~refNum]; |
p = dctl->dCtlDriver; |
if( dctl->dCtlFlags & 0x0040) p = (void*) *p; |
return ( p?(char*) (p+18):(char*)"\p-Purged-"); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14