/*
	File:		MoreDisks.h

	Contains:	General disk driver utility routines.

	Written by:	Quinn

	Copyright:	Copyright © 1999 by Apple Computer, Inc., all rights reserved.

				You may incorporate this Apple sample source code into your program(s) without
				restriction. This Apple sample source code has been provided "AS IS" and the
				responsibility for its operation is yours. You are not permitted to redistribute
				this Apple sample source code as "Apple sample source 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 source
				code, but that you've made changes.

	Change History (most recent first):

         <6>    18/10/99    Quinn   Added target mode csCodes.
         <5>     15/6/99    Quinn   Include "DriverGestalt.h" in here so that our clients don't have
                                    to.
         <4>      8/6/99    Quinn   Added some csCode that are reserved for the HDI driver.
         <3>      7/5/99    Quinn   Added MoreIsDriveCDROM.
         <2>      9/4/99    Quinn   Added more reserved _Control and _Status codes from the latest
                                    Apple CD/DVD ERS.
         <1>     16/3/99    Quinn   First checked in.
*/

#pragma once

/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup

#include "MoreSetup.h"

// Mac OS Interfaces

#include <Types.h>
#include <Devices.h>
#include <DriverGestalt.h>

#ifdef __cplusplus
extern "C" {
#endif

/////////////////////////////////////////////////////////////////
#pragma mark ----- Disk Driver Control/Status Codes -----

// Key to References:
// 
// o IM:Devices -- "Inside Macintosh: Devices"
// o DV 17 -- DTS Technote DV 17 "What Your .Sony Driver Can Do For You"
// o PCI C&Ds -- "Designing PCI Cards and Drivers for Power Macintosh Computers"
// o TN1xxx -- Technote 1xxx "Disk Drivers, 1984 to 1999"
// o "DriverGestalt.h" -- Documented (barely) in the "DriverGestalt.h" header file in Universal Interfaces.
// o LPX-40 -- "Apple Logic Board Design LPX-40 Developer Note" (Tanzania),
//             "MFM Floppy Disk Device Drive" chapter
//             <http://developer.apple.com/techpubs/hardware/hardware2.html>
// Entries that are commented out are already defined in Universal Interfaces.

enum {

//	Identifier					Value		Reference
//	----------					-----		---------

//	***** Control *****

//	goodbye						= -1,		// IM:Devices
//	killCode					= 1,		// IM:Devices
//	kVerify						= 5,		// DV 17
//	kFormat						= 6,		// DV 17
//	kEject						= 7,		// DV 17
//	kSetTagBuffer				= 8,		// DV 17
//	kTrackCache					= 9,		// DV 17
	kPhysicalIOCode				= 17,		// TN1xxx, target mode
	kGetIconID					= 20,		// reserved (.Sony), do not use
//	kDriveIcon					= 21,		// DV 17
//	kMediaIcon					= 22,		// DV 17
//	kDriveInfo					= 23,		// DV 17
	kHDIReserved1				= 24,		// reserved (HDI Driver - External Reference Specification), do not use
	kHDIReserved2				= 25,		// reserved (HDI Driver - External Reference Specification), do not use
//	kDriverConfigureCode		= 43,		// PCI C&Ds
	kSetStartupPartition		= 44,		// TN1xxx
	kSetStartupMount			= 45,		// TN1xxx
	kLockPartition				= 46,		// TN1xxx
	kClearPartitionMount		= 48,		// TN1xxx
	kUnlockPartition			= 49,		// TN1xxx
//	kRegisterPartition			= 50,		// TN1xxx
//	kGetADrive					= 51,		// TN1xxx
//	kProhibitMounting			= 52,		// TN1xxx
//	kIsContainerMounted			= 53,		// DriverGestalt.h
//	kMountVolumeImg				= 54,		// DriverGestalt.h
	kMountVolume				= 60,		// TN1xxx
//	accRun						= 65,		// IM:Devices
	kSetPowerMode				= 70,		// PCI C&Ds
	kModifyPostEvent			= 76,		// DV 22
	kRawSCSICommand				= 77,		// reserved (.AppleCD), deprecated, not to be documented
	kChooseIOStyle				= 78,		// reserved (.AppleCD), deprecated, not to be documented
	kChangeBlockSize			= 79,		// DV 22
	kSetUserEject				= 80,		// DV 22
	kSetPollFrequency			= 81,		// DV 22
	kReadTOC					= 100,		// DV 22
	kReadTheQSubcode			= 101,		// DV 22
	kReadHeader					= 102,		// DV 22
	kAudioTrackSearch			= 103,		// DV 22
	kAudioPlay					= 104,		// DV 22
	kAudioPause					= 105,		// DV 22
	kAudioStop					= 106,		// DV 22
	kAudioStatus				= 107,		// DV 22
	kAudioScan					= 108,		// DV 22
	kAudioControl				= 109,		// DV 22
	kReadMCN					= 110,		// DV 22
	kReadISRC					= 111,		// DV 22
	kReadAudioVolume			= 112,		// DV 22
	kGetSpindleSpeed			= 113,		// DV 22
	kSetSpindleSpeed			= 114,		// DV 22
	kReadAudio					= 115,		// DV 22
	kReadAllSubcodes			= 116,		// DV 22
	kSetTrackList				= 122,		// DV 22
	kGetTrackList				= 123,		// DV 22
	kGetTrackIndex				= 124,		// DV 22
	kSetPlayMode				= 125,		// DV 22
	kGetPlayMode				= 126,		// DV 22
	kRawRead					= 127,		// reserved (.AppleCD), do not use
	kDiagnostics				= 127,		// reserved (.ATADisk), do not use
	kSetQuiescentMode			= 1079,		// DV 22 (a future update will document this)
	kEnableClose				= 16971,	// LPX-40 (Tanzania) Developer Note
	kRetries					= 17232,	// reserved (.Sony), do not use
//	kRawTrack					= 18244		// DV 17
	kFormatCopy					= 21315,	// LPX-40 (Tanzania) Developer Note
	kAppleCDReserved1			= -130,		// reserved (Apple CD/DVD Driver ERS), do not use
	kAppleCDReserved2			= -132,		// reserved (Apple CD/DVD Driver ERS), do not use
	kAppleCDReserved5			= -301,		// reserved (Apple CD/DVD Driver ERS), do not use

//	***** Status *****

//	kReturnFormatList			= 6,		// DV 17
//	kDriveStatus				= 8,		// DV 17
//	kMFMStatus					= 10,		// LPX-40 (Tanzania) Developer Note
//	kDriverGestaltCode			= 43,		// PCI C&Ds
	kGetStartupStatus			= 44,		// TN1xxx
	kGetMountStatus				= 45,		// TN1xxx
	kGetLockStatus				= 46,		// TN1xxx
//	kGetPartitionStatus			= 50,		// TN1xxx
//	kGetPartInfo				= 51,		// TN1xxx
//	kGetContainerAlias			= 52,		// DriverGestalt.h
	kGetPowerMode				= 70,		// PCI C&Ds
	kGet2KOffset				= 95,		// DV 22
	kGetDriveType				= 96,		// DV 22
	kResponsibleFor				= 97,		// DV 22
	kGetBlockSize				= 98,		// DV 22
	kGetSenseCode				= 99,		// reserved (.AppleCD), do not use
	kReturnDeviceIdent			= 120,		// DV 22
	kGetCDFeatures				= 121,		// DV 22
	kGetErrorInfo				= 123,		// TN1xxx, target mode
	kGetDriveInfo				= 124,		// TN1xxx, target mode
	kGetDriveCapacity			= 125,		// TN1xxx, target mode
	kLastErrorCode				= 127,		// reserved (.ATADisk), do not use
	kGetQuiescentMode			= 1079,		// DV 22 (a future update will document this)
	kSpeedCheck					= 17232,	// reserved (.Sony), do not use
	kDuplicatorVersionSupport	= 17494,	// LPX-40 (Tanzania) Developer Note
	kLastFormByte				= 21315,	// LPX-40 (Tanzania) Developer Note
	kAppleCDReserved3			= -129,		// reserved (Apple CD/DVD Driver ERS), do not use
	kAppleCDReserved4			= -131,		// reserved (Apple CD/DVD Driver ERS), do not use
	kAppleCDReserved6			= -300		// reserved (Apple CD/DVD Driver ERS), do not use
};

/////////////////////////////////////////////////////////////////
#pragma mark ----- Basic Disk Drive Utilities -----

#if PRAGMA_STRUCT_ALIGN
	#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
	#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
	#pragma pack(2)
#endif

// This structure mirrors the 4 bytes of flags before the drive queue
// element in memory.  The fields are documented in "Inside Macintosh:
// Files":
//
//   <http://developer.apple.com/techpubs/mac/Files/Files-112.html>
//
// The comments here are a precis for your reference.

struct DriveFlags {
	SInt8	writeProt;			// bit 7 set => write protected
	SInt8	diskInPlace;		// 0 => no disk, 1 & 2 => ejectable disk, 8 => non-ejectable disk, $48 => non-ejectable disk but driver wants call, < 0 => disk in process of being ejected
	SInt8	installed;			// "used internally during system startup"
	SInt8	sides;				// bit 7 set => disk is single sided
};
typedef struct DriveFlags DriveFlags, *DriveFlagsPtr;

#if PRAGMA_STRUCT_ALIGN
	#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
	#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
	#pragma pack()
#endif

extern pascal DriveFlagsPtr MoreGetDriveFlags(DrvQElPtr drvQEl);
	// Returns the flags for a given drive queue element.  Note
	// that this is a pointer to the real flags, not a copy.
	// The pointer is valid only so long as the drive queue is
	// valid.  Also, if you access the flags via this pointer,
	// the flags will continually reflect the changes made
	// by the driver.
	//
	// This routine is safe to call from all interrupt contexts.

extern pascal OSErr MoreUTFindDriveQ(SInt16 drive, DrvQElPtr *foundDrvQEl);
	// A version of UTFindDrive that doesn't return extFSErr on
	// non-HFS drive queue elements.  It also works regardless of
	// whether FSM is installed or not.
	//
	// This really belongs in "MoreFSM.h", but it seems pointless
	// to create that file just for this program.
	//
	// This routine is safe to call from all interrupt contexts.

extern pascal DrvQElPtr MoreGetIndDrive(SInt16 index);
	// Returns the drive queue element of the index'th drive
	// on the system, with index 1 being the first drive,
	// or nil if there is no such drive.
	//
	// This routine is safe to call from all interrupt contexts.

extern pascal SInt16 MoreFindFreeDriveNumber(SInt16 firstDrive);
	// Returns the first free drive number, starting
	// from drive number firstDrive.  Drive numbers 
	// below 5 are reserved, so you shoud pass 5 or
	// more for firstDrive.  Typically hard disk drive
	// numbers start from 8, although this is not required.
	//
	// This routine must be called at system task time,
	// not because it is interrupt unsafe but because
	// if you call it at interrupt time you might interrupt
	// some other code that's allocating drive numbers
	// and you might both get the same drive number!
	
extern pascal OSErr MoreRemoveDrive(DrvQElPtr drvQEl);
	// This routine removes a drive queue element from the drive
	// queue.  It's an adjunct to the system routine AddDrive;
	// someone forgot to supply a to remove drive queue elements
	// from the system.
	//
	// This routine returns volOnLinErr if there is a volume
	// mounted on the drive.
	//
	// This routine must be called at system task time.
	// Removing drive queue elements at interrupt time is
	// unsafe because some non-interrupt code might be
	// in the process of walking the drive queue.

extern pascal DriverRefNum MoreGetDriveRefNum(SInt16 drive);
    // Walks the drive queue looking for the given drive
    // and returns the driver reference number of the driver
    // controlling the drive, or 0 if it wasn't found.
    //
	// This routine is safe to call from all interrupt contexts.

extern pascal Boolean MoreDriveSupportsDriverGestalt(SInt16 drive);
    // Returns true if the driver controlling the
    // specified drive supports Driver Gestalt.
    //
	// This routine must be called at system task time.
	// It calls into TradDriverLoaderLib, which is not
	// guaranteed to be interrupt safe.

extern pascal Boolean MoreDriveSupportFileExchange(SInt16 drive);
	// Returns true if the driver controlling the specified
	// drive support the File Exchange control call interface.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

extern pascal OSErr MoreGetDriveSize(SInt16 drive, UInt32 *sizeInBlocks);
	// Returns the size, in blocks, of the specified drive.
	//
	// Except for packaging and some cosmetic stuff, this
	// is pretty much the same code as "GetDiskBlocks" from
	// MoreFiles.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

extern pascal SInt16 MoreVolumeMountedOnDrive(SInt16 drive, Boolean ejectedIsMounted);
	// Returns the vRefNum of the volume mounted on the drive,
	// or 0 if there are no volumes mounted on the drive.
	//
	// The ejectedIsMounted flag controls whether this routine
	// considers an offline volume that was ejected from
	// drive is still mounted on drive.  Typically you pass
	// false to this parameter.  If you pass true, the routine
	// will return the first offline volume that was ejected from
	// drive.  There may be more than one.
	//
	// This routine walks the drive and VCB queues directly,
	// so it's safe to call at interrupt time and when the
	// the File System is busy.
	//
	// This routine is safe to call from all interrupt contexts.

extern pascal SInt16 MoreFirstDriveWithoutVolume(DriverRefNum refNum);
	// Returns the drive number of the first drive in the drive
	// queue which is controlled by refNum and which doesn't have
	// a volume mounted on it, or 0 if there are no such drives.
	//
	// This routine is safe to call from all interrupt contexts.

typedef UInt32 MoreDisksCDROMResponse;
enum {
	kMoreDriveUnableToDetermineCDROM = 0,
	kMoreDriveIsCDROM = 1,
	kMoreDriveIsNotCDROM = 2
};

extern pascal void MoreIsDriveCDROM(SInt16 drive, MoreDisksCDROMResponse *response);
	// Sets *response to one of the constants shown above to indicate
	// whether the drive is a CD-ROM drive.

/////////////////////////////////////////////////////////////////
#pragma mark ----- File Exchange Control Call Interface -----

extern pascal OSErr MoreCreateNewDriveQueueElement(SInt16 driveToClone,
						UInt32 firstBlock, UInt32 sizeInBlocks,
						SInt16 *newDrive);
	// Creates a new drive queue element controlled by the driver
	// which is controlling driveToClone.  The firstBlock and sizeInBlocks
	// parameters dictate where on the disk the drive queue element will
	// access.  The drive number of the new drive queue element is returned
	// in newDrive.
	//
	// driveToClone must support the File Exchange control call interface.
	// If it doesn't, this routine will return an error.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

extern pascal OSErr MoreSetDrivePartition(SInt16 drive, UInt32 firstBlock, UInt32 sizeInBlocks);
	// Sets the partition on the disk which drive accesses.  This
	// allows you to retarget drive to point to any range of blocks
	// on the disk.  A high-level wrapper for the kRegisterPartition
	// control call.
	//
	// drive must support the File Exchange control call interface.
	// If it doesn't, this routine will return an error.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

extern pascal OSErr MoreGetDrivePartition(SInt16 drive, UInt32 *firstBlock, UInt32 *sizeInBlocks);
	// Returns the partition on the disk which the drive access.
	//
	// drive must support the File Exchange control call interface.
	// If it doesn't, this routine will return an error.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

#ifndef partInfoRec
//	typedef void partInfoRec;
#endif

extern pascal OSErr MoreGetPartitionInfo(SInt16 drive, partInfoRec *partInfo);
	// Returns the File Exchange partInfoRec for the specified drive.
	// A high-level wrapper for the kGetPartInfo status call.
	//
	// drive must support the File Exchange control call interface.
	// If it doesn't, this routine will return an error.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.

extern pascal OSErr MoreGetPartitionVolume(DriverRefNum refNum, const partInfoRec *partInfo, SInt16 *vRefNum);
	// Returns in vRefNum the volume which is mounted on the partition
	// specified by partInfoRec.
	//
	// IMPORTANT: refNum is the driver reference number of the driver,
	// *not* a drive number.  If you have a drive number, you can
	// call MoreGetDriveRefNum to get the correct value.
	//
	// refNum must support the File Exchange control call interface.
	// If it doesn't, this routine will return an error.
	//
	// This routine must be called at system task time.
	// It makes synchronous Device Manager calls.
	
#ifdef __cplusplus
}
#endif
