+ else
+ {
+
+ /*
+ * vcd device mode
+ */
+
+#if defined( __APPLE__ )
+ dk_cd_read_t cd_read;
+
+ memset( &cd_read, 0, sizeof(cd_read) );
+
+ cd_read.offset = i_sector * VCD_SECTOR_SIZE;
+ cd_read.sectorArea = kCDSectorAreaSync | kCDSectorAreaHeader |
+ kCDSectorAreaSubHeader | kCDSectorAreaUser |
+ kCDSectorAreaAuxiliary;
+ cd_read.sectorType = kCDSectorTypeUnknown;
+
+ cd_read.buffer = p_block;
+ cd_read.bufferLength = VCD_SECTOR_SIZE * i_nb;
+
+ if( ioctl( p_vcddev->i_device_handle, DKIOCCDREAD, &cd_read ) == -1 )
+ {
+ msg_Err( p_this, "could not read block %d", i_sector );
+ if( i_type == VCD_TYPE ) free( p_block );
+ return -1;
+ }
+
+#elif defined( WIN32 )
+ if( p_vcddev->hASPI )
+ {
+ HANDLE hEvent;
+ struct SRB_ExecSCSICmd ssc;
+
+ /* Create the transfer completion event */
+ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+ if( hEvent == NULL )
+ {
+ if( i_type == VCD_TYPE ) free( p_block );
+ return -1;
+ }
+
+ memset( &ssc, 0, sizeof( ssc ) );
+
+ ssc.SRB_Cmd = SC_EXEC_SCSI_CMD;
+ ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
+ ssc.SRB_HaId = LOBYTE( p_vcddev->i_sid );
+ ssc.SRB_Target = HIBYTE( p_vcddev->i_sid );
+ ssc.SRB_SenseLen = SENSE_LEN;
+
+ ssc.SRB_PostProc = (LPVOID) hEvent;
+ ssc.SRB_CDBLen = 12;
+
+ /* Operation code */
+ ssc.CDBByte[ 0 ] = READ_CD;
+
+ /* Sector type */
+ ssc.CDBByte[ 1 ] = i_type == VCD_TYPE ? SECTOR_TYPE_MODE2_FORM2 :
+ SECTOR_TYPE_CDDA;
+
+ /* Start of LBA */
+ ssc.CDBByte[ 2 ] = ( i_sector >> 24 ) & 0xff;
+ ssc.CDBByte[ 3 ] = ( i_sector >> 16 ) & 0xff;
+ ssc.CDBByte[ 4 ] = ( i_sector >> 8 ) & 0xff;
+ ssc.CDBByte[ 5 ] = ( i_sector ) & 0xff;
+
+ /* Transfer length */
+ ssc.CDBByte[ 6 ] = ( i_nb >> 16 ) & 0xff;
+ ssc.CDBByte[ 7 ] = ( i_nb >> 8 ) & 0xff;
+ ssc.CDBByte[ 8 ] = ( i_nb ) & 0xff;
+
+ /* Data selection */
+ ssc.CDBByte[ 9 ] = i_type == VCD_TYPE ? READ_CD_RAW_MODE2 :
+ READ_CD_USERDATA;
+
+ /* Result buffer */
+ ssc.SRB_BufPointer = p_block;
+ ssc.SRB_BufLen = VCD_SECTOR_SIZE * i_nb;
+
+ /* Initiate transfer */
+ ResetEvent( hEvent );
+ p_vcddev->lpSendCommand( (void*) &ssc );
+
+ /* If the command has still not been processed, wait until it's
+ * finished */
+ if( ssc.SRB_Status == SS_PENDING )
+ {
+ WaitForSingleObject( hEvent, INFINITE );
+ }
+ CloseHandle( hEvent );
+
+ /* check that the transfer went as planned */
+ if( ssc.SRB_Status != SS_COMP )
+ {
+ if( i_type == VCD_TYPE ) free( p_block );
+ return -1;
+ }
+ }
+ else
+ {
+ DWORD dwBytesReturned;
+ RAW_READ_INFO cdrom_raw;
+
+ /* Initialize CDROM_RAW_READ structure */
+ cdrom_raw.DiskOffset.QuadPart = CD_SECTOR_SIZE * i_sector;
+ cdrom_raw.SectorCount = i_nb;
+ cdrom_raw.TrackMode = i_type == VCD_TYPE ? XAForm2 : CDDA;
+
+ if( DeviceIoControl( p_vcddev->h_device_handle,
+ IOCTL_CDROM_RAW_READ, &cdrom_raw,
+ sizeof(RAW_READ_INFO), p_block,
+ VCD_SECTOR_SIZE * i_nb, &dwBytesReturned,
+ NULL ) == 0 )
+ {
+ if( i_type == VCD_TYPE )
+ {
+ /* Retry in YellowMode2 */
+ cdrom_raw.TrackMode = YellowMode2;
+ if( DeviceIoControl( p_vcddev->h_device_handle,
+ IOCTL_CDROM_RAW_READ, &cdrom_raw,
+ sizeof(RAW_READ_INFO), p_block,
+ VCD_SECTOR_SIZE * i_nb, &dwBytesReturned,
+ NULL ) == 0 )
+ {
+ free( p_block );
+ return -1;
+ }
+ }
+ else return -1;
+ }
+ }
+
+#elif defined( HAVE_SCSIREQ_IN_SYS_SCSIIO_H )
+ struct scsireq sc;
+ int i_ret;
+
+ memset( &sc, 0, sizeof(sc) );
+ sc.cmd[0] = 0xBE;
+ sc.cmd[1] = i_type == VCD_TYPE ? SECTOR_TYPE_MODE2_FORM2:
+ SECTOR_TYPE_CDDA;
+ sc.cmd[2] = (i_sector >> 24) & 0xff;
+ sc.cmd[3] = (i_sector >> 16) & 0xff;
+ sc.cmd[4] = (i_sector >> 8) & 0xff;
+ sc.cmd[5] = (i_sector >> 0) & 0xff;
+ sc.cmd[6] = (i_nb >> 16) & 0xff;
+ sc.cmd[7] = (i_nb >> 8) & 0xff;
+ sc.cmd[8] = (i_nb ) & 0xff;
+ sc.cmd[9] = i_type == VCD_TYPE ? READ_CD_RAW_MODE2 : READ_CD_USERDATA;
+ sc.cmd[10] = 0; /* sub channel */
+ sc.cmdlen = 12;
+ sc.databuf = (caddr_t)p_block;
+ sc.datalen = VCD_SECTOR_SIZE * i_nb;
+ sc.senselen = sizeof( sc.sense );
+ sc.flags = SCCMD_READ;
+ sc.timeout = 10000;
+
+ i_ret = ioctl( i_fd, SCIOCCOMMAND, &sc );
+ if( i_ret == -1 )
+ {
+ msg_Err( p_this, "SCIOCCOMMAND failed" );
+ if( i_type == VCD_TYPE ) free( p_block );
+ return -1;
+ }
+ if( sc.retsts || sc.error )
+ {
+ msg_Err( p_this, "SCSI command failed: status %d error %d\n",
+ sc.retsts, sc.error );
+ if( i_type == VCD_TYPE ) free( p_block );
+ return -1;
+ }