ATAExecIO.c

/*
    File:       ATAExecIO.c
    
    Description:
                Sample code showing how to send ATA and ATAPI commands.
 
    Copyright:  © Copyright 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     <JAS>  Created and added to ATA Demo Sample
 
*/
 
 
#include <ATA.h>
#include "ATA Demo.h"
 
 
extern UInt8    gATAMgrPBVers;      // defined in ATA Demo.c
extern FormatTable kIdentFormat;    // defined in ATA Demo.c
 
 
OSErr   ATARead( UInt32 deviceID, UInt8* buffer )
{
    ataIOPB         ioPB;   // the parameter block
    OSErr           err;
    
    // init pb
    CLEAR(ioPB);    // this is the same macro used in ATA Demo
    
    // setup pb
    
    /*
        this is the version of the parameter block. you get this information when you make the
        kATAMgrManagerInquiry call. it is returned in the ataMgrPBVers field of the 
        ataMgrInquiry parameter block. see DisplayATAManagerInquiryInfo in ATA Demo.
    */
    ioPB.ataPBVers =            gATAMgrPBVers;  // pb version
    
    ioPB.ataPBFunctionCode =    kATAMgrExecIO;  // we are doing some I/O
    
    // these flags have different names in the documentation, which is somewhat confusing :(
    ioPB.ataPBFlags =           mATAFlagTFRead | mATAFlagIORead; // update regs, ATA read
 
    ioPB.ataPBDeviceID =        deviceID;   // device number and bus number 
    
    /*
        if possible you should ask a device what it's logical block size is
        since most (all?) ATA hard disks use a block size of 0x200, we use that in this example
    */
    ioPB.ataPBLogicalBlockSize = 0x200; // assume its 0x200 for now...
    
    /*
        this is a pointer to the buffer that will receive data if we're reading from an ATA
        device, or contain the data to send if we are writing.
    */
    ioPB.ataPBBuffer =  buffer;     // pointer to buffer
 
    /*
        this is the number of bytes to transfer. in this example we are only reading one
        sector so the byte count == 0x200
    */
    ioPB.ataPBByteCount = 0x200;    // number of bytes to transfer
    
    /*
        the fields in ataPBTaskFile are the values that are written to the registers on the
        device.
    */
    ioPB.ataPBTaskFile.ataTFCount = 1;          // read 1 sector
    
    // this example use LBA. remember to make sure the sector number fits into 28 bits
    ioPB.ataPBTaskFile.ataTFSector = 0;         // sector to read (bits 7:0)
    ioPB.ataPBTaskFile.ataTFCylinder = 0;       // sector to read (bits 23:8)
    ioPB.ataPBTaskFile.ataTFSDH = 0;            // sector to read (bits 27:24)
    
    ioPB.ataPBTaskFile.ataTFSDH |= 0x40;                    // set this bit to use LBA
    ioPB.ataPBTaskFile.ataTFSDH |= (deviceID & 0x0000FF00) >> 4;    // put in the DEV bit
    ioPB.ataPBTaskFile.ataTFCommand = kATAcmdRead;          // ATA read command
 
    err = ataManager((ataPB*) &ioPB );  // call the ATA Manager
    
    return( err );
}
 
/*============================================================================*/
 
 
OSErr   ATAPIRead( UInt32 deviceID, UInt8* buffer )
{
 
    ataIOPB         ioPB;       // the parameter block
    ATAPICmdPacket  atapiCmd;   // the ATAPI command to send
    OSErr           err;
    
    // init pb
    CLEAR(ioPB);    // this is the same macro used in ATA Demo
    
    // setup pb
    
        /*
        this is the version of the parameter block. you get this information when you make the
        kATAMgrManagerInquiry call. it is returned in the ataMgrPBVers field of the 
        ataMgrInquiry parameter block. see DisplayATAManagerInquiryInfo in ATA Demo.
    */
 
    ioPB.ataPBVers =            gATAMgrPBVers;  // pb version
    
    ioPB.ataPBFunctionCode =    kATAMgrExecIO;  // we are doing some I/O
    
    // these flags have different names in the documentation, which is somewhat confusing :(
    
    // update regs, read from device, use ATAPI protocol
    ioPB.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocolATAPI; 
 
    ioPB.ataPBDeviceID =        deviceID;   // device number and bus number
    
    /*
        if possible you should ask a device what it's logical block size is
        since most CD-ROMs use a block size of 0x800, we use that in this example
    */
    ioPB.ataPBLogicalBlockSize = 0x800; // assume its 0x800 for now...
 
    /*
        this is a pointer to the buffer that will receive data if we're reading or
        contain the data to send if we are writing.
    */
    ioPB.ataPBBuffer =  buffer;     // pointer to buffer
 
    /*
        this is the number of bytes to transfer. in this example we are only reading one
        sector so the byte count == 0x800
    */
    ioPB.ataPBByteCount = 0x800;
    
    /*
        the fields in ataPBTaskFile are the values that are written to the registers on the
        device.
    */
 
    // set the number of bytes to transfer per DRQ during PIO transfers
    // see the PACKET command in the ATA/ATAPI standard for details 
    ioPB.ataPBTaskFile.ataTFCylinder = 0x200;   // we read 0x200 bytes per DRQ
    
    ioPB.ataPBTaskFile.ataTFSDH |= 0x40;                    // set this bit to use LBA
    ioPB.ataPBTaskFile.ataTFSDH |= (deviceID & 0x0000FF00) >> 4;    // put in the DEV bit
    ioPB.ataPBTaskFile.ataTFCommand = 0xA0;                 // PACKET command
    
    ioPB.ataPBPacketPtr = &atapiCmd;                        // pointer to ATAPI command
 
    // set up ATAPI command packet
    atapiCmd.atapiPacketSize = 12;  // 12 byte command
    atapiCmd.atapiCommandByte[0] = 0x2800;      // Read(10) command
    atapiCmd.atapiCommandByte[1] = 0x0000;      // LBA (hi)
    atapiCmd.atapiCommandByte[2] = 0x0000;      // LBA (lo)
    atapiCmd.atapiCommandByte[3] = 0x0000;      // xfer length hi
    atapiCmd.atapiCommandByte[4] = 0x0100;      // xfer length lo
    atapiCmd.atapiCommandByte[5] = 0x0000;      // reserved
 
    err = ataManager((ataPB*) &ioPB );  // call the ATA Manager
 
    return( err );
}