home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cdrom.zip
/
DDK
/
BASE
/
SRC
/
DEV
/
DASD
/
CDROM
/
OS2CDROM
/
cdioc81.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-18
|
29KB
|
1,003 lines
/**************************************************************************
*
* SOURCE FILE NAME = CDIOC81.C
*
* DESCRIPTIVE NAME = IOCTL handling routines for OS/2 CD-ROM Device Mgr
*
* Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
* LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
* REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
* RESTRICTED MATERIALS OF IBM
* IBM CONFIDENTIAL
*
* VERSION = V2.0
*
* DATE
*
* DESCRIPTION
*
*
* FUNCTIONS
*
* ENTRY POINTS:
*
* DEPENDENCIES:
*
* NOTES
*
*
* STRUCTURES
*
* EXTERNAL REFERENCES
*
* EXTERNAL FUNCTIONS
*
* CHANGE ACTIVITY =
* DATE FLAG APAR CHANGE DESCRIPTION
* -------- ---------- ----- --------------------------------------
* 09/08/95 @V135221 Sam Detweiler - CD-ROM changer support
*
****************************************************************************/
#include "cdh.h"
/****************************************************************************
*
* FUNCTION NAME = CD_AudioChannelCtrl
*
* DESCRIPTION = Audio Channel Control.
*
* Provides playback control of audio information on the disk. This
* includes assigning input channels to output channels and controlling
* the volume of each output channel.
*
* USHORT CD_ChannelControl (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioChannelCtrl (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
BOOL playing;
NPIORB_CDB pIORB;
struct AudioChannelControl_Data FAR *pDataPkt;
struct Channel *channel;
struct Audio *audio;
struct Status *audio_status;
union AddressType start_red, end_red;
pDataPkt = (struct AudioChannelControl_Data FAR *) pRP->DataPacket;
audio = &pUnitCB->DeviceInfo.Audio;
channel = &audio->channel;
audio_status = &audio->status;
/*
** Copy the data to the UnitCB for channels 0 and 1
*/
channel->input_0 = pDataPkt->input_0;
channel->volume_0 = pDataPkt->volume_0;
channel->input_1 = pDataPkt->input_1;
channel->volume_1 = pDataPkt->volume_1;
/*
** Only 2 channels supported at this time, so check to make sure
** channels above 1 are not specified.
*/
if (channel->input_0 > 1 || channel->input_1 > 1)
{
channel->input_0 = 0;
channel->input_1 = 1;
channel->volume_0 = 0xFF;
channel->volume_1 = 0xFF;
return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
}
/*
** Set volume setting for both channels the same.
*/
/*
** if (channel->volume_0 && channel->volume_1)
** {
** if (channel->volume_0 > channel->volume_1)
** channel->volume_1 = channel->volume_0;
** else
** channel->volume_0 = channel->volume_1;
** }
*/
/*
** If the drive doesn't support receiving an audio control command
** while it's playing, then pause the audio, issue the audio control
** command and resume the audio.
*/
rc = GetPlayStatus (pUnitCB, &playing);
if (rc == STDON && playing &&
(audio->capabilities & DCAPS_NO_AUDIO_CTRL_DURING_PLAY))
{
/*
** Pause the play operation
*/
rc = CD_Stop (pRP, pUnitCB);
/*
** Issue the audio control command
*/
BuildCDB_AudioControl(pUnitCB, (NPIORB_CDB FAR *) &pIORB);
pIORB->filter_workspace[0] = (UCHAR) playing;
rc = SubmitIORB_Wait (pUnitCB, pIORB);
FreeIORB (pUnitCB, pIORB);
/*
** Resume playing
*/
rc = CD_Resume (pRP, pUnitCB);
}
else
{
/*
** Issue Mode Select to set Audio Control Page info
*/
BuildCDB_AudioControl(pUnitCB, (NPIORB_CDB FAR *) &pIORB);
pIORB->filter_workspace[0] = (UCHAR) playing;
rc = SubmitIORB_Wait (pUnitCB, pIORB);
FreeIORB (pUnitCB, pIORB);
}
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = CD_Play
*
* DESCRIPTION = Play
*
* Play the selected audio tracks until the selection is done
* or until a stop command is issued.
*
* USHORT CD_Play (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_Play (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
BOOL playing;
NPIORB_CDB pIORB;
union AddressType start_red, start_hsg, end_red, end_hsg, last_sector;
struct PlayAudio FAR *pParmPkt;
struct Audio *audio;
struct Status *audio_status;
pParmPkt = (struct PlayAudio FAR *) pRP->ParmPacket;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
return (STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
if ( (rc = GetPlayStatus (pUnitCB, &playing)) & STERR)
return(rc);
if (playing)
return (STDON + STERR + ERROR_I24_DEVICE_IN_USE);
switch(pParmPkt->address_mode)
{
case CDROM_HSG_MODE:
start_hsg.dword = pParmPkt->start_sector;
end_hsg.dword = pParmPkt->end_sector;
start_red.dword = HSGtoRedBook (start_hsg.dword);
end_red.dword = HSGtoRedBook (end_hsg.dword);
break;
case CDROM_REDBOOK_MODE:
start_red.dword = pParmPkt->start_sector;
end_red.dword = pParmPkt->end_sector;
start_hsg.dword = RedBooktoHSG (start_red.dword);
end_hsg.dword = RedBooktoHSG (end_red.dword);
break;
default:
return(STDON + STERR + ERROR_I24_INVALID_PARAMETER);
}
if ( (pUnitCB->DeviceInfo.leadout.dword == end_red.dword) &&
(end_red.dword != 0) )
{
if (end_red.ul_redbook.frame != 0)
end_red.ul_redbook.frame --;
else if (end_red.ul_redbook.sec != 0)
{
end_red.ul_redbook.sec --;
end_red.ul_redbook.frame = 74;
}
else
{
end_red.ul_redbook.min--;
end_red.ul_redbook.sec = 59;
end_red.ul_redbook.frame = 74;
}
}
if ( (ULONG) start_hsg.dword < 0L )
return (STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND);
audio = &pUnitCB->DeviceInfo.Audio;
audio_status = &audio->status;
/*
** Issue Play command
*/
BuildCDB_PlayAudio_MSF (pUnitCB, start_red, end_red,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
FreeIORB (pUnitCB, pIORB);
if (rc == STDON)
{
pUnitCB->DeviceInfo.playing = TRUE;
if(pUnitCB->pParentUnitCB) /*SD135221*/
{ /*SD135221*/
pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying = TRUE; /*SD135221*/
} /* endif */ /*SD135221*/
audio_status->paused = FALSE;
audio_status->last_start_location.min = start_red.ul_redbook.min;
audio_status->last_start_location.sec = start_red.ul_redbook.sec;
audio_status->last_start_location.frame = start_red.ul_redbook.frame;
audio_status->last_end_location.min = end_red.ul_redbook.min;
audio_status->last_end_location.sec = end_red.ul_redbook.sec;
audio_status->last_end_location.frame = end_red.ul_redbook.frame;
}
else if (rc == STDON + STERR + ERROR_I24_BAD_COMMAND)
{
rc = STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND;
}
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = CD_Stop
*
* DESCRIPTION = Stop play
*
* Cancel any active play request. It is not an error if the
* drive is not currently playing. The ending location is
* saved for a subsequent resume operation.
*
* USHORT CD_Stop (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_Stop (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
BOOL playing;
NPIORB_CDB pIORB;
struct Status *audio_status;
struct SubChannel_Position NEAR *pCDBData;
audio_status = &pUnitCB->DeviceInfo.Audio.status;
/*
** Simply return without error if not currently playing
*/
rc = GetPlayStatus (pUnitCB, &playing);
if ( ! playing)
return (STDON);
/*
** Issue SCSI Pause Command to cancel play operation.
*/
BuildCDB_PauseResume (pUnitCB, CDBF_PAUSE, (NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
FreeIORB (pUnitCB, pIORB);
if (rc & STERR)
return(rc);
/*
** Issue SCSI Read SubChannel - Current Position Command
*/
BuildCDB_ReadSubChannel(pUnitCB, RSC_CURRENT_POSITION,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait(pUnitCB, pIORB);
if (rc == STDON)
{
pCDBData = (struct SubChannel_Position FAR *) pIORB->CDB_data;
if (pUnitCB->DeviceInfo.product_id_code == NEC_260_17B)
{
audio_status->last_start_location.frame
= BCDtoBinary(pCDBData->abs_address.redbook.frame);
audio_status->last_start_location.sec
= BCDtoBinary(pCDBData->abs_address.redbook.sec);
audio_status->last_start_location.min
= BCDtoBinary(pCDBData->abs_address.redbook.min);
}
else
{
audio_status->last_start_location.frame
= pCDBData->abs_address.redbook.frame;
audio_status->last_start_location.sec
= pCDBData->abs_address.redbook.sec;
audio_status->last_start_location.min
= pCDBData->abs_address.redbook.min;
}
audio_status->paused = TRUE;
pUnitCB->DeviceInfo.playing = FALSE;
if(pUnitCB->pParentUnitCB) /*SD135221*/
{ /*SD135221*/
pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying = FALSE; /*SD135221*/
} /* endif */ /*SD135221*/
}
FreeIORB (pUnitCB, pIORB);
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = CD_Resume
*
* DESCRIPTION = Resume Play
*
* Resume playing audio tracks after play has been interrupted
* with the Stop Audio command. An error is returned if there
* was no previous Stop command. The Resume is converted to a
* Play command from the last play address when paused.
*
* USHORT CD_Resume (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_Resume (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
NPIORB_CDB pIORB;
struct Status *audio_status;
struct Audio *audio;
union AddressType start_red, end_red;
audio = &pUnitCB->DeviceInfo.Audio;
audio_status = &audio->status;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
return(STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
if ( ! audio_status->paused )
return (STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND);
/*
** Resume is simply a play from the last address when paused to the
** last ending play address.
*/
start_red.ul_redbook.min = audio_status->last_start_location.min;
start_red.ul_redbook.sec = audio_status->last_start_location.sec;
start_red.ul_redbook.frame = audio_status->last_start_location.frame;
start_red.ul_redbook.zero = 0;
end_red.ul_redbook.min = audio_status->last_end_location.min;
end_red.ul_redbook.sec = audio_status->last_end_location.sec;
end_red.ul_redbook.frame = audio_status->last_end_location.frame;
end_red.ul_redbook.zero = 0;
BuildCDB_PlayAudio_MSF (pUnitCB, start_red, end_red,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
FreeIORB (pUnitCB, pIORB);
if ( (rc == STDON) || (rc == STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA) )
audio_status->paused = FALSE;
pUnitCB->DeviceInfo.playing = TRUE;
if(pUnitCB->pParentUnitCB) /*SD135221*/
{ /*SD135221*/
pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying = TRUE; /*SD135221*/
} /* endif */ /*SD135221*/
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioChannelInfo
*
* DESCRIPTION = Return audio channel information
*
* Return the current settings of the audio channel controls. These
* are either the default settings or those set with the Audio Channel
* control IOCTL.
*
* USHORT CD_AudioChannelInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioChannelInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
struct Channel *channel;
channel = &pUnitCB->DeviceInfo.Audio.channel;
* (struct AudioChannelControl_Data FAR *)pRP->DataPacket =
* (struct AudioChannelControl_Data NEAR *) channel;
return(STDON);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioDiskInfo
*
* DESCRIPTION = Return audio disk information.
*
* Returns the first and last track numbers and the Red Book address
* for the lead-out track. This information is read from the TOC info
* on the Q-channel on the lead-in track. The first and last number are
* binary values and not BCD.
*
* USHORT CD_AudioDiskInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioDiskInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
NPIORB_CDB pIORB;
struct AudioDiskInfo_Data FAR *pDataPkt;
struct ReadTOC_Data FAR *pCDBData;
pDataPkt = (struct AudioDiskInfo_Data FAR *) pRP->DataPacket;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
return (STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
/*
** Issue a SCSI Read TOC command to retrieve the information.
*/
BuildCDB_ReadTOC (pUnitCB,LEAD_OUT_TRACK_NUMBER,1,(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
if (rc & STERR)
{
if (ReadTOC_Leadout (pUnitCB, pIORB) & STERR)
{
FreeIORB (pUnitCB, pIORB);
return(rc);
}
}
/*
** Copy the data from the CDB data area to the IOCTL data packet
*/
pCDBData = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
pDataPkt->lowest_track = pCDBData->toc_hdr.first_track;
pDataPkt->highest_track = pCDBData->toc_hdr.last_track;
pDataPkt->frame = pCDBData->toc_descriptor[0].abs_address.redbook.frame;
pDataPkt->sec = pCDBData->toc_descriptor[0].abs_address.redbook.sec;
pDataPkt->min = pCDBData->toc_descriptor[0].abs_address.redbook.min;
pDataPkt->zero = 0;
pUnitCB->DeviceInfo.leadout.ul_redbook.min = pDataPkt->min;
pUnitCB->DeviceInfo.leadout.ul_redbook.sec = pDataPkt->sec;
pUnitCB->DeviceInfo.leadout.ul_redbook.frame = pDataPkt->frame;
if (pUnitCB->DeviceInfo.product_id_code == NEC_260_17B)
{
pDataPkt->frame = BCDtoBinary(pDataPkt->frame);
pDataPkt->sec = BCDtoBinary(pDataPkt->sec);
pDataPkt->min = BCDtoBinary(pDataPkt->min);
}
FreeIORB (pUnitCB, pIORB);
/*
** Some early ATAPI devices with OAK firmware return LEAD_OUT_TRACK_NUMBER
** as the first track instead of the true first track. If we issue the
** ReadTOC with a starting track of 0, the correct first track will be
** in the data returned.
*/
if ((pDataPkt->lowest_track == LEAD_OUT_TRACK_NUMBER) &&
(pUnitCB->DeviceInfo.interface_type == INTERFACE_ATAPI))
{
/*
** Issue a SCSI Read TOC command to retrieve the information.
*/
BuildCDB_ReadTOC (pUnitCB,0,1,(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
if (!(rc & STERR) )
{
pCDBData = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
pDataPkt->lowest_track = pCDBData->toc_hdr.first_track;
}
FreeIORB (pUnitCB, pIORB);
}
return(STDON);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioTrackInfo
*
* DESCRIPTION = Return audio track information.
*
* Given a track number, return the Red Book address for the starting
* point of the track, and the track control information for that track.
*
* USHORT CD_AudioTrackInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioTrackInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
NPIORB_CDB pIORB;
struct AudioTrackInfo_Data FAR *pDataPkt;
struct ReadTOC_Data FAR *pCDBData;
pDataPkt = (struct AudioTrackInfo_Data FAR *) pRP->DataPacket;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
return (STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
/*
** Issue a SCSI Read TOC command to retrieve the information.
*/
BuildCDB_ReadTOC (pUnitCB,
((struct AudioTrackInfo FAR *)pRP->ParmPacket)->track_number,
1,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
/*
** If there's an error reading the TOC for the leadout track, then
** re-read 2 TOC entries starting with the last valid track number.
*/
if ( (rc & STERR) &&
( ((struct AudioTrackInfo FAR *)pRP->ParmPacket)->track_number
== LEAD_OUT_TRACK_NUMBER) )
{
rc = ReadTOC_Leadout (pUnitCB, pIORB);
}
/*
** Copy the data from the CDB data area to the IOCTL data packet
*/
if (rc == STDON)
{
pCDBData = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
pDataPkt->frame = pCDBData->toc_descriptor[0].abs_address.redbook.frame;
pDataPkt->sec = pCDBData->toc_descriptor[0].abs_address.redbook.sec;
pDataPkt->min = pCDBData->toc_descriptor[0].abs_address.redbook.min;
pDataPkt->zero = 0;
if (pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_NO_ADR_RETURNED)
pCDBData->toc_descriptor[0].ADR = ADR_CURRENT_POSITION;
pDataPkt->control = pCDBData->toc_descriptor[0].ADR |
(pCDBData->toc_descriptor[0].control << 4);
if (pUnitCB->DeviceInfo.product_id_code == NEC_260_17B)
{
pDataPkt->frame = BCDtoBinary(pDataPkt->frame);
pDataPkt->sec = BCDtoBinary(pDataPkt->sec);
pDataPkt->min = BCDtoBinary(pDataPkt->min);
}
}
FreeIORB (pUnitCB, pIORB);
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = ReadTOC_Leadout
*
* DESCRIPTION = Read the TOC for the leadout track;
*
* The Hitachi 3750 returns a check condition if a ReadTOC command is
* issued for track_num = 0xAA, the leadout track. Reading the TOC for
* the leadout track is valid under SCSI-II. The workaround is to issue
* the ReadTOC command for 2 TOC entries, starting with the last valid
* track_num before the lead out track. The last entry is the leadout track.
*
* USHORT RetryTOCRead (NPUNITCB pUnitCB, NPIORB pIORB)
*
* INPUT = pUnitCB - Pointer to UnitCB
* pIORB - Pointer to IORB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT ReadTOC_Leadout (pUnitCB, pIORB)
NPUNITCB pUnitCB;
NPIORB_CDB pIORB;
{
NPIORB_CDB pIORB2;
struct ReadTOC_Data FAR *pCDBData1;
struct ReadTOC_Data FAR *pCDBData2;
USHORT rc = STDON + STERR;
if ( (pIORB->status_block.Flags & STATUS_SENSEDATA_VALID) &&
((pIORB->sense_data.error_code == 0x70) ||
(pIORB->sense_data.error_code == 0x71)) &&
pIORB->sense_data.sense_key == SCSI_SK_ILLEGALREQ)
/* && pIORB->sense_data.additional_sense_code == ASC_INVALID_FIELD) */
{
BuildCDB_ReadTOC (pUnitCB, 1, 1, (NPIORB_CDB FAR *) &pIORB2);
rc = SubmitIORB_Wait (pUnitCB, pIORB2);
if (rc == STDON)
{
pCDBData1 = (struct ReadTOC_Data FAR *) pIORB->CDB_data;
pCDBData2 = (struct ReadTOC_Data FAR *) pIORB2->CDB_data;
FreeIORB(pUnitCB, pIORB2);
BuildCDB_ReadTOC (pUnitCB,
pCDBData2->toc_hdr.last_track,
2,
(NPIORB_CDB FAR *) &pIORB2);
rc = SubmitIORB_Wait (pUnitCB, pIORB2);
if (rc == STDON)
{
pCDBData1->toc_hdr = pCDBData2->toc_hdr;
pCDBData1->toc_descriptor[0] = pCDBData2->toc_descriptor[1];
}
}
FreeIORB(pUnitCB, pIORB2);
}
return(rc);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioQChannelInfo
*
* DESCRIPTION = Return audio Q-channel information.
*
* Reads and returns the most current address information from the
* Q-channel. This command does not interrupt the present status
* of the drive as one of its intended purposes is to monitor the
* location of the read head while playing audio tracks.
*
* USHORT CD_QChannelInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioQChannelInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
NPIORB_CDB pIORB;
struct AudioQChannelInfo_Data FAR *pDataPkt;
struct SubChannel_Position FAR *pCDBData;
pDataPkt = (struct AudioQChannelInfo_Data FAR *) pRP->DataPacket;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
return (STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
if ( (rc = ClearCheckCondition (pUnitCB)) & STERR)
return(rc);
/*
** Issue a SCSI Read TOC command to retrieve the information.
*/
BuildCDB_ReadSubChannel(pUnitCB, RSC_CURRENT_POSITION,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
if (rc & STERR)
{
FreeIORB (pUnitCB, pIORB);
return(rc);
}
/*
** Copy the data from the CDB data area to the IOCTL data packet
*/
pCDBData = (struct SubChannel_Position FAR *) pIORB->CDB_data;
if (pUnitCB->DeviceInfo.product_id_code == NEC_260_17B)
{
pDataPkt->min = BCDtoBinary(pCDBData->rel_address.redbook.min);
pDataPkt->sec = BCDtoBinary(pCDBData->rel_address.redbook.sec);
pDataPkt->frame = BCDtoBinary(pCDBData->rel_address.redbook.frame);
pDataPkt->amin = BCDtoBinary(pCDBData->abs_address.redbook.min);
pDataPkt->asec = BCDtoBinary(pCDBData->abs_address.redbook.sec);
pDataPkt->aframe = BCDtoBinary(pCDBData->abs_address.redbook.frame);
}
else
{
pDataPkt->min = pCDBData->rel_address.redbook.min;
pDataPkt->sec = pCDBData->rel_address.redbook.sec;
pDataPkt->frame = pCDBData->rel_address.redbook.frame;
pDataPkt->amin = pCDBData->abs_address.redbook.min;
pDataPkt->asec = pCDBData->abs_address.redbook.sec;
pDataPkt->aframe = pCDBData->abs_address.redbook.frame;
}
pDataPkt->zero = 0;
if (pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_NO_ADR_RETURNED)
pCDBData->ADR = ADR_CURRENT_POSITION;
pDataPkt->control = pCDBData->ADR | (pCDBData->control << 4);
pDataPkt->tno = BinaryToBCD (pCDBData->track_number);
pDataPkt->point = BinaryToBCD (pCDBData->index_number);
FreeIORB (pUnitCB, pIORB);
return(STDON);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioSubChannelInfo
*
* DESCRIPTION = Return subchannel information
*
* Return subchannel information.
*
* USHORT CD_AudioSubChannelInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioSubChannelInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
return(STDON + STERR + ERROR_I24_BAD_COMMAND);
}
/****************************************************************************
*
* FUNCTION NAME = CD_AudioStatusInfo
*
* DESCRIPTION = Return audio status information.
*
* Returns the Audio Paused bit and the starting and ending locations
* of the last play or the next resume.
*
* USHORT CD_AudioStatusInfo (PRP_GENIOCTL pRP, NPUNITCB pUnitCB)
*
* INPUT = pRP - Request Packet
* pUnitCB - Pointer to UnitCB
*
* OUTPUT = USHORT - Packet Status word
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT CD_AudioStatusInfo (pRP, pUnitCB)
PRP_GENIOCTL pRP;
NPUNITCB pUnitCB;
{
USHORT rc;
NPIORB_CDB pIORB;
struct AudioStatusInfo_Data FAR *pDataPkt;
struct SubChannel_Position FAR *pCDBData;
struct Status *audio_status;
struct Audio *audio;
struct ul_RedBookAddress start, end;
pDataPkt = (struct AudioStatusInfo_Data FAR *) pRP->DataPacket;
audio = &pUnitCB->DeviceInfo.Audio;
audio_status = &audio->status;
/*
** Issue a SCSI Read SubChannel command to retrieve the information.
*/
BuildCDB_ReadSubChannel(pUnitCB, RSC_CURRENT_POSITION,
(NPIORB_CDB FAR *) &pIORB);
rc = SubmitIORB_Wait (pUnitCB, pIORB);
if (rc == STDON)
{
/*
** Copy the data to the IOCTL data packet
*/
pCDBData = (struct SubChannel_Position FAR *) pIORB->CDB_data;
start.frame = audio_status->last_start_location.frame;
start.sec = audio_status->last_start_location.sec;
start.min = audio_status->last_start_location.min;
start.zero = 0;
end.frame = audio_status->last_end_location.frame;
end.sec = audio_status->last_end_location.sec;
end.min = audio_status->last_end_location.min;
end.zero = 0;
pDataPkt->audio_status = *(USHORT *) audio_status;
pDataPkt->last_start_location = *(ULONG FAR *) &start;
pDataPkt->last_end_location = *(ULONG FAR *) &end;
if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
rc = STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA;
}
FreeIORB (pUnitCB, pIORB);
return(rc);
}