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 ; }