www.pudn.com > cdx.zip > IOCTL.CPP


/*C4*/ 
//**************************************************************** 
//	Author:	Jethro Wright, III 			TS :  1/18/1994 12:06 
//	Date:	01/01/1994 
// 
//			ioctl.cpp :  ioctl-oriented cmd interface to mscdex 
//			primarily used to control audio cds 
// 
//	History: 
//		01/01/1994  jw3	also sprach zarathustra.... 
//****************************************************************/ 
 
 
#include		 
#include		 
#include		 
#include		 
 
#include		"types.h" 
#include		"device.h" 
#include		"ioctl.hpp" 
 
 
			//	device driver/ioctl command codes 
 
#define		IOCTL_READ		(3) 
#define 	IOCTL_WRITE		(12) 
#define		PLAY_AUDIO		(132) 
#define		STOP_AUDIO		(133) 
#define		RESUME_AUDIO	(136) 
 
 
			//	ioctl_read sub-commands 
 
enum { 
	GET_DVC_STATUS = 6, 
	GET_DISK_INFO = 10, 
	GET_TRACK_INFO, 
	GET_QCHNL_INFO, 
	GET_SUBCNHL_DATA, 
	GET_UPC = 14, 
	GET_PLAY_STATUS, 
} ; 
 
 
			//	ioctl_write sub-commands 
 
enum { 
	EJECT_DISK, 
	LOCK_DOOR, 
	RESET_DISK, 
	AUDIO_CONTROL, 
	CLOSE_TRAY = 5 
} ; 
 
 
//******************************************************** 
// 
//		IOCTL::IOCTL  :- 
// 
//		initialize the cmd interface for this cdrom, by 
//		storing the device's unit and sub-unit nbr and 
//		the device's strategy and interrupt fn ptrs, for 
//		future reference. 
// 
//********************************************************/ 
 
IOCTL::IOCTL( int cdUnitNbr, int cdSubUnitNbr, VFP cdDevStrategyFn, 
			  VFP cdDevIntrFn ) 
{ 
 
	memset( &theRequest, 0, sizeof( theRequest ) ) ; 
	unitNbr = cdUnitNbr ; subUnitNbr = cdSubUnitNbr ; 
	devStrategy = cdDevStrategyFn ; devInterrupt = cdDevIntrFn ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::~IOCTL  :- 
// 
//		don't know that we'll need a dstor, but it's here 
//		anyway.... 
// 
//********************************************************/ 
 
IOCTL::~IOCTL() 
{ 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetDeviceStatus  :- 
// 
//		get the most up-to-date status from the cdrom's 
//		device driver.... 
// 
//********************************************************/ 
 
WORD	IOCTL::GetDeviceStatus( DWORD far * cdStatus ) 
{ 
 
	DeviceStatusCmd	devStatus ; 
 
	devStatus.command = GET_DVC_STATUS ; 
	Setup( IOCTL_READ, ( VFP ) &devStatus, sizeof( DeviceStatusCmd ) ) ; 
	DoCmd() ;							// perform, i say ! 
 
	//	return the desired data back to the caller.... 
	*cdStatus = devStatus.deviceStatus ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::LockDoor  :- 
// 
//		lock the drive door depending on the flag word 
//		specified by the consumer.... 
// 
//********************************************************/ 
 
WORD	IOCTL::LockDoor( Boolean fLock ) 
{ 
 
	DoorLockCmd	lockCmd ; 
 
	lockCmd.command = LOCK_DOOR ; 
	lockCmd.lockCode = fLock ; 
	Setup( IOCTL_WRITE, ( VFP ) &lockCmd, sizeof( DoorLockCmd ) ) ; 
	DoCmd() ;							// perform, i say ! 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::CloseTray  :- 
// 
//		this is one of a series of functions that is 
//		not always supported on all cdrom drives, but is 
//		provided anyway and will close the motorized tray 
//		of a cdrom drive, if drive is capable of doing so.... 
// 
//********************************************************/ 
 
WORD	IOCTL::CloseTray( void ) 
{ 
 
	CloseTrayCmd	closeCmd ; 
 
	closeCmd.command = CLOSE_TRAY ; 
	Setup( IOCTL_WRITE, ( VFP ) &closeCmd, sizeof( CloseTrayCmd ) ) ; 
	DoCmd() ;							// nike it ! 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::EjectDisk  :- 
// 
//		eject the disk from the drive, if supported by the 
//		device.... 
// 
//********************************************************/ 
 
WORD	IOCTL::EjectDisk( void ) 
{ 
 
	EjectCommand	ejectCmd ; 
 
	ejectCmd.command = EJECT_DISK ; 
	Setup( IOCTL_WRITE, ( VFP ) &ejectCmd, sizeof( EjectCommand ) ) ; 
	DoCmd() ;							// nike it ! 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::ResetDisk  :- 
// 
//		reset the cdrom and (presumably) the device driver 
//		as well.... 
// 
//********************************************************/ 
 
WORD	IOCTL::ResetDisk( void ) 
{ 
 
	ResetCommand	resetCmd ; 
 
	resetCmd.command = RESET_DISK ; 
	Setup( IOCTL_WRITE, ( VFP ) &resetCmd, sizeof( ResetCommand ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetDiskInfo  :- 
// 
//		get the disk's pertinent info (starting & ending 
//		track nbrs and the address of the lead-out track) 
// 
//********************************************************/ 
 
WORD	IOCTL::GetDiskInfo( struct DiskInfoCmd far * dskInfo ) 
{ 
 
	dskInfo->command = GET_DISK_INFO ; 
	Setup( IOCTL_READ, ( VFP ) dskInfo, sizeof( DiskInfoCmd ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetTrackInfo  :- 
// 
//		get the information corresponding to a particular 
//		track.... 
// 
//********************************************************/ 
 
WORD	IOCTL::GetTrackInfo( struct TrackInfoCmd far * trackInfo ) 
{ 
 
	trackInfo->command = GET_TRACK_INFO ; 
	Setup( IOCTL_READ, ( VFP ) trackInfo, sizeof( TrackInfoCmd ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetQInfo  :- 
// 
//		retrieve the current q-channel info for the disk 
//		(track nbr, pos into the track and disk, etc) 
// 
//********************************************************/ 
 
WORD	IOCTL::GetQInfo( struct QChannelInfoCmd far * qInfo ) 
{ 
 
	qInfo->command = GET_QCHNL_INFO ; 
	Setup( IOCTL_READ, ( VFP ) qInfo, sizeof( QChannelInfoCmd ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::Play  :- 
// 
//		play a span of audio usg the specified addressing 
//		mode.  the play audio fn reqs a different procedure 
//		from the rest of the other operations bec it uses 
//		a different layout for the ioctl cmd packet, so 
//		we can't use the Setup() mbr fn.... 
// 
//********************************************************/ 
 
WORD	IOCTL::Play( DWORD stAddr, DWORD nSects, BYTE addrMode ) 
{ 
 
	PlayCommand	* playCmd = ( PlayCommand * ) ( ( void * ) &theRequest ) ; 
 
	playCmd->rqh.len = sizeof( PlayCommand ) ; 
	playCmd->rqh.unit = subUnitNbr ; 
	playCmd->rqh.status = 0 ; 
	playCmd->rqh.command = PLAY_AUDIO ; 
	playCmd->startAddr = stAddr ; 
	playCmd->nbrSects = nSects ; 
	playCmd->addressMode = addrMode ; 
	DoCmd() ; 
	return playCmd->rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::Stop  :- 
// 
//		stop/resume the audio pgm based on the incoming 
//		flag.... 
// 
//********************************************************/ 
 
WORD	IOCTL::Stop( Boolean fStop ) 
{ 
 
	WORD	cmd ; 
 
	if ( fStop ) 
		cmd = STOP_AUDIO ; 
	else cmd = RESUME_AUDIO ; 
 
	Setup( cmd, ( VFP ) NULL, 0 ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetUPC  :- 
// 
//		get the upc code from the disk.... 
// 
//********************************************************/ 
 
WORD	IOCTL::GetUPC( struct UPCCommand far * upcData ) 
{ 
 
	upcData->command = GET_UPC ; 
	Setup( IOCTL_READ, ( VFP ) upcData, sizeof( UPCCommand ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
//******************************************************** 
// 
//		IOCTL::GetPlayStatus  :- 
// 
//		get the current play status from the disk (is the 
//		disk pgm paused & starting/ending addresses of the 
//		curr audio pgm).... 
// 
//********************************************************/ 
 
WORD	IOCTL::GetPlayStatus( struct PlayStatusCmd far * playStatus ) 
{ 
 
	playStatus->command = GET_PLAY_STATUS ; 
	playStatus->startAddress = playStatus->endAddress = 0L ; 
	Setup( IOCTL_READ, ( VFP ) playStatus, sizeof( PlayStatusCmd ) ) ; 
	DoCmd() ; 
	return theRequest.rqh.status ; 
 
} 
 
 
/***************************************************************** 
 
	IOCTL private mbr fns 
 
*****************************************************************/ 
 
 
//******************************************************** 
// 
//		IOCTL::DoCmd  :- 
// 
//		execute the device driver command specified in 
//		theRequest, by calling the device driver's 
//		strategy fn, then following it up w/ a call to 
//		the interrupt fn. 
// 
//********************************************************/ 
 
void	IOCTL::DoCmd( void ) 
{ 
 
	VFP			rqh = ( VFP ) &theRequest ; 
	VFP			devStrat = devStrategy, devIntr = devInterrupt ; 
 
	_asm { 
		mov		es, word ptr rqh+2 
		mov		bx, word ptr rqh 
		call	dword ptr devStrat		// setup the desired operation 
		call	dword ptr devIntr		// now do it ! 
	} 
	return ; 
 
}