2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2002-09-25 03:45:43 +04:00
|
|
|
// $Id: cdrom.cc,v 1.43 2002-09-24 23:45:43 cbothamy Exp $
|
2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2002-02-01 19:46:27 +03:00
|
|
|
// Copyright (C) 2002 MandrakeSoft S.A.
|
2001-04-10 05:04:59 +04:00
|
|
|
//
|
|
|
|
// MandrakeSoft S.A.
|
|
|
|
// 43, rue d'Aboukir
|
|
|
|
// 75002 Paris - France
|
|
|
|
// http://www.linux-mandrake.com/
|
|
|
|
// http://www.mandrakesoft.com/
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
|
|
|
|
|
|
// These are the low-level CDROM functions which are called
|
|
|
|
// from 'harddrv.cc'. They effect the OS specific functionality
|
|
|
|
// needed by the CDROM emulation in 'harddrv.cc'. Mostly, just
|
|
|
|
// ioctl() calls and such. Should be fairly easy to add support
|
|
|
|
// for your OS if it is not supported yet.
|
|
|
|
|
|
|
|
|
|
|
|
#include "bochs.h"
|
|
|
|
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
#define LOG_THIS /* no SMF tricks here, not needed */
|
|
|
|
|
2001-10-07 07:34:54 +04:00
|
|
|
extern "C" {
|
2001-10-06 21:32:58 +04:00
|
|
|
#include <errno.h>
|
2001-10-07 07:34:54 +04:00
|
|
|
}
|
2001-10-06 21:32:58 +04:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef __linux__
|
|
|
|
extern "C" {
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <linux/cdrom.h>
|
|
|
|
// I use the framesize in non OS specific code too
|
|
|
|
#define BX_CD_FRAMESIZE CD_FRAMESIZE
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-09-23 10:57:57 +04:00
|
|
|
#if defined(__GNU__) || (defined(__CYGWIN32__) && !defined(WIN32))
|
2002-05-31 13:56:58 +04:00
|
|
|
extern "C" {
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#define BX_CD_FRAMESIZE 2048
|
|
|
|
#define CD_FRAMESIZE 2048
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 06:15:31 +04:00
|
|
|
#ifdef __sun
|
|
|
|
extern "C" {
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/cdio.h>
|
|
|
|
#define BX_CD_FRAMESIZE CDROM_BLK_2048
|
|
|
|
}
|
|
|
|
#endif /* __sun */
|
|
|
|
|
2001-12-08 16:07:07 +03:00
|
|
|
#ifdef __BEOS__
|
2002-02-07 20:38:33 +03:00
|
|
|
#include "cdrom_beos.h"
|
2001-12-08 16:07:07 +03:00
|
|
|
#define BX_CD_FRAMESIZE 2048
|
|
|
|
#endif
|
|
|
|
|
2002-04-18 22:17:45 +04:00
|
|
|
#if (defined (__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__))
|
2001-05-08 23:51:46 +04:00
|
|
|
// OpenBSD pre version 2.7 may require extern "C" { } structure around
|
2001-06-19 01:14:00 +04:00
|
|
|
// all the includes, because the i386 sys/disklabel.h contains code which
|
2001-05-08 23:51:46 +04:00
|
|
|
// c++ considers invalid.
|
2001-04-10 05:04:59 +04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/cdio.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/disklabel.h>
|
|
|
|
|
|
|
|
// XXX
|
|
|
|
#define BX_CD_FRAMESIZE 2048
|
|
|
|
#define CD_FRAMESIZE 2048
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#include <winioctl.h>
|
2001-06-25 06:18:16 +04:00
|
|
|
#include "aspi-win32.h"
|
|
|
|
#include "scsidefs.h"
|
|
|
|
|
|
|
|
DWORD (*GetASPI32SupportInfo)(void);
|
|
|
|
DWORD (*SendASPI32Command)(LPSRB);
|
|
|
|
BOOL (*GetASPI32Buffer)(PASPI32BUFF);
|
|
|
|
BOOL (*FreeASPI32Buffer)(PASPI32BUFF);
|
|
|
|
BOOL (*TranslateASPI32Address)(PDWORD,PDWORD);
|
|
|
|
DWORD (*GetASPI32DLLVersion)(void);
|
|
|
|
|
|
|
|
|
|
|
|
static BOOL bUseASPI = FALSE;
|
|
|
|
static BOOL bHaveDev = FALSE;
|
|
|
|
static int hid = 0;
|
|
|
|
static int tid = 0;
|
|
|
|
static int lun = 0;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
#define BX_CD_FRAMESIZE 2048
|
|
|
|
#define CD_FRAMESIZE 2048
|
|
|
|
HANDLE hFile = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2001-06-19 01:11:46 +04:00
|
|
|
#include <stdio.h>
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-06-25 06:18:16 +04:00
|
|
|
#ifdef WIN32
|
|
|
|
|
|
|
|
int ReadCDSector(unsigned int hid, unsigned int tid, unsigned int lun, unsigned long frame, unsigned char *buf, int bufsize)
|
|
|
|
{
|
|
|
|
HANDLE hEventSRB;
|
|
|
|
SRB_ExecSCSICmd srb;
|
|
|
|
DWORD dwStatus;
|
|
|
|
|
|
|
|
hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
|
|
|
|
memset(&srb,0,sizeof(SRB_ExecSCSICmd));
|
|
|
|
srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
|
|
srb.SRB_HaId = hid;
|
|
|
|
srb.SRB_Target = tid;
|
|
|
|
srb.SRB_Lun = lun;
|
|
|
|
srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
|
|
|
srb.SRB_SenseLen = SENSE_LEN;
|
|
|
|
srb.SRB_PostProc = hEventSRB;
|
|
|
|
srb.SRB_BufPointer = buf;
|
|
|
|
srb.SRB_BufLen = bufsize;
|
|
|
|
srb.SRB_CDBLen = 10;
|
|
|
|
srb.CDBByte[0] = SCSI_READ10;
|
|
|
|
srb.CDBByte[2] = frame>>24;
|
|
|
|
srb.CDBByte[3] = frame>>16;
|
|
|
|
srb.CDBByte[4] = frame>>8;
|
|
|
|
srb.CDBByte[5] = frame;
|
|
|
|
srb.CDBByte[7] = 0;
|
|
|
|
srb.CDBByte[8] = 1; /* read 1 frames */
|
|
|
|
|
|
|
|
ResetEvent(hEventSRB);
|
|
|
|
dwStatus = SendASPI32Command((SRB *)&srb);
|
|
|
|
if(dwStatus == SS_PENDING) {
|
|
|
|
WaitForSingleObject(hEventSRB, 100000);
|
|
|
|
}
|
|
|
|
CloseHandle(hEventSRB);
|
2002-03-02 14:31:18 +03:00
|
|
|
return (srb.SRB_TargStat == STATUS_GOOD);
|
2001-06-25 06:18:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int GetCDCapacity(unsigned int hid, unsigned int tid, unsigned int lun)
|
|
|
|
{
|
|
|
|
HANDLE hEventSRB;
|
|
|
|
SRB_ExecSCSICmd srb;
|
|
|
|
DWORD dwStatus;
|
2002-07-31 09:21:46 +04:00
|
|
|
unsigned char buf[8];
|
2001-06-25 06:18:16 +04:00
|
|
|
|
|
|
|
hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
|
|
|
|
memset(&buf, 0, sizeof(buf));
|
|
|
|
memset(&srb,0,sizeof(SRB_ExecSCSICmd));
|
|
|
|
srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
|
|
srb.SRB_HaId = hid;
|
|
|
|
srb.SRB_Target = tid;
|
|
|
|
srb.SRB_Lun = lun;
|
|
|
|
srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
|
|
|
srb.SRB_SenseLen = SENSE_LEN;
|
|
|
|
srb.SRB_PostProc = hEventSRB;
|
|
|
|
srb.SRB_BufPointer = (unsigned char *)buf;
|
|
|
|
srb.SRB_BufLen = 8;
|
|
|
|
srb.SRB_CDBLen = 10;
|
|
|
|
srb.CDBByte[0] = SCSI_READCDCAP;
|
|
|
|
srb.CDBByte[2] = 0;
|
|
|
|
srb.CDBByte[3] = 0;
|
|
|
|
srb.CDBByte[4] = 0;
|
|
|
|
srb.CDBByte[5] = 0;
|
|
|
|
srb.CDBByte[8] = 0;
|
|
|
|
|
|
|
|
ResetEvent(hEventSRB);
|
|
|
|
dwStatus = SendASPI32Command((SRB *)&srb);
|
|
|
|
if(dwStatus == SS_PENDING) {
|
|
|
|
WaitForSingleObject(hEventSRB, 100000);
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle(hEventSRB);
|
|
|
|
return ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]) * ((buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
cdrom_interface::cdrom_interface(char *dev)
|
|
|
|
{
|
2001-06-27 23:16:01 +04:00
|
|
|
put("CD");
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
settype(CDLOG);
|
2001-04-10 05:04:59 +04:00
|
|
|
fd = -1; // File descriptor not yet allocated
|
|
|
|
|
|
|
|
if ( dev == NULL )
|
|
|
|
path = NULL;
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
else {
|
2001-04-10 05:04:59 +04:00
|
|
|
path = strdup(dev);
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
}
|
2001-06-19 01:11:46 +04:00
|
|
|
using_file=0;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2002-02-01 19:46:27 +03:00
|
|
|
|
2001-06-28 00:11:10 +04:00
|
|
|
void
|
|
|
|
cdrom_interface::init(void) {
|
2002-09-25 03:45:43 +04:00
|
|
|
BX_DEBUG(("Init $Id: cdrom.cc,v 1.43 2002-09-24 23:45:43 cbothamy Exp $"));
|
2001-10-06 21:32:58 +04:00
|
|
|
BX_INFO(("file = '%s'",path));
|
2001-06-28 00:11:10 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
cdrom_interface::~cdrom_interface(void)
|
|
|
|
{
|
2001-06-28 00:11:10 +04:00
|
|
|
if (fd >= 0)
|
|
|
|
close(fd);
|
|
|
|
if (path)
|
|
|
|
free(path);
|
|
|
|
BX_DEBUG(("Exit"));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2002-02-01 19:46:27 +03:00
|
|
|
cdrom_interface::insert_cdrom(char *dev)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
|
|
|
unsigned char buffer[BX_CD_FRAMESIZE];
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
// Load CD-ROM. Returns false if CD is not ready.
|
2002-02-01 19:46:27 +03:00
|
|
|
if (dev != NULL) path = strdup(dev);
|
2001-06-23 07:23:41 +04:00
|
|
|
BX_INFO (("load cdrom with path=%s", path));
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef WIN32
|
2001-04-10 06:17:10 +04:00
|
|
|
char drive[256];
|
2001-06-25 06:18:16 +04:00
|
|
|
OSVERSIONINFO osi;
|
2001-06-19 01:11:46 +04:00
|
|
|
if ( (path[1] == ':') && (strlen(path) == 2) )
|
|
|
|
{
|
2001-06-25 06:18:16 +04:00
|
|
|
osi.dwOSVersionInfoSize = sizeof(osi);
|
|
|
|
GetVersionEx(&osi);
|
|
|
|
if(osi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
|
|
// Use direct device access under windows NT/2k
|
|
|
|
|
|
|
|
// With all the backslashes it's hard to see, but to open D: drive
|
|
|
|
// the name would be: \\.\d:
|
|
|
|
sprintf(drive, "\\\\.\\%s", path);
|
|
|
|
using_file = 0;
|
|
|
|
BX_INFO (("Using direct access for cdrom."));
|
|
|
|
// This trick only works for Win2k and WinNT, so warn the user of that.
|
|
|
|
} else {
|
|
|
|
BX_INFO(("Using ASPI for cdrom."));
|
|
|
|
bUseASPI = TRUE;
|
|
|
|
}
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy(drive,path);
|
|
|
|
using_file = 1;
|
2002-04-18 04:22:20 +04:00
|
|
|
bUseASPI = FALSE;
|
2001-10-07 07:34:54 +04:00
|
|
|
BX_INFO (("Opening image file as a cd"));
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
2001-06-25 06:18:16 +04:00
|
|
|
if(bUseASPI) {
|
|
|
|
DWORD d, cnt, max;
|
|
|
|
int i, j, k;
|
|
|
|
SRB_HAInquiry sh;
|
|
|
|
SRB_GDEVBlock sd;
|
|
|
|
HINSTANCE hASPI = LoadLibrary("WNASPI32.DLL");
|
|
|
|
if(hASPI) {
|
|
|
|
SendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress( hASPI, "SendASPI32Command" );
|
|
|
|
GetASPI32DLLVersion = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32DLLVersion" );
|
|
|
|
GetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32SupportInfo" );
|
|
|
|
BX_INFO(("Using first CDROM. Please upgrade your ASPI drivers to version 4.01 or later if you wish to specify a cdrom driver."));
|
|
|
|
|
|
|
|
d = GetASPI32SupportInfo();
|
|
|
|
cnt = LOBYTE(LOWORD(d));
|
|
|
|
for(i = 0; i < cnt; i++) {
|
|
|
|
memset(&sh, 0, sizeof(sh));
|
|
|
|
sh.SRB_Cmd = SC_HA_INQUIRY;
|
|
|
|
sh.SRB_HaId = i;
|
|
|
|
SendASPI32Command((LPSRB)&sh);
|
|
|
|
if(sh.SRB_Status != SS_COMP)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
max = (int)sh.HA_Unique[3];
|
|
|
|
for(j = 0; j < max; j++) {
|
|
|
|
for(k = 0; k < 8; k++) {
|
|
|
|
memset(&sd, 0, sizeof(sd));
|
|
|
|
sd.SRB_Cmd = SC_GET_DEV_TYPE;
|
|
|
|
sd.SRB_HaId = i;
|
|
|
|
sd.SRB_Target = j;
|
|
|
|
sd.SRB_Lun = k;
|
|
|
|
SendASPI32Command((LPSRB)&sd);
|
|
|
|
if(sd.SRB_Status == SS_COMP) {
|
|
|
|
if(sd.SRB_DeviceType == DTYPE_CDROM) {
|
|
|
|
hid = i;
|
|
|
|
tid = j;
|
|
|
|
lun = k;
|
|
|
|
bHaveDev = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(bHaveDev) break;
|
|
|
|
}
|
|
|
|
if(bHaveDev) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
2001-10-06 21:32:58 +04:00
|
|
|
BX_PANIC(("Could not load ASPI drivers, so cdrom access will fail"));
|
2001-06-25 06:18:16 +04:00
|
|
|
}
|
|
|
|
fd=1;
|
|
|
|
} else {
|
|
|
|
BX_INFO(("Using direct access for CDROM"));
|
2002-09-23 05:23:25 +04:00
|
|
|
hFile=CreateFile((char *)&drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
|
2001-06-25 06:18:16 +04:00
|
|
|
if (hFile !=(void *)0xFFFFFFFF)
|
|
|
|
fd=1;
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
2001-10-06 21:32:58 +04:00
|
|
|
// all platforms except win32
|
2001-06-25 06:18:16 +04:00
|
|
|
fd = open(path, O_RDONLY);
|
2001-06-19 01:11:46 +04:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
if (fd < 0) {
|
2001-10-07 07:34:54 +04:00
|
|
|
BX_ERROR(( "open cd failed for %s: %s", path, strerror(errno)));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(false);
|
|
|
|
}
|
2001-06-19 01:11:46 +04:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
// I just see if I can read a sector to verify that a
|
|
|
|
// CD is in the drive and readable.
|
|
|
|
#ifdef WIN32
|
2002-03-02 14:31:18 +03:00
|
|
|
if(bUseASPI) {
|
|
|
|
return ReadCDSector(hid, tid, lun, 0, buffer, BX_CD_FRAMESIZE);
|
|
|
|
} else {
|
2001-06-25 06:18:16 +04:00
|
|
|
ReadFile(hFile, (void *) buffer, BX_CD_FRAMESIZE, (unsigned long *) &ret, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
CloseHandle(hFile);
|
|
|
|
fd = -1;
|
|
|
|
BX_DEBUG(( "insert_cdrom: read returns error." ));
|
|
|
|
return(false);
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
2001-06-25 06:18:16 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
2001-10-07 07:34:54 +04:00
|
|
|
// do fstat to determine if it's a file or a device, then set using_file.
|
2002-04-10 09:38:34 +04:00
|
|
|
struct stat stat_buf;
|
2001-10-07 07:34:54 +04:00
|
|
|
ret = fstat (fd, &stat_buf);
|
|
|
|
if (ret) {
|
|
|
|
BX_PANIC (("fstat cdrom file returned error: %s", strerror (errno)));
|
|
|
|
}
|
|
|
|
if (S_ISREG (stat_buf.st_mode)) {
|
|
|
|
using_file = 1;
|
|
|
|
BX_INFO (("Opening image file %s as a cd.", path));
|
|
|
|
} else {
|
|
|
|
using_file = 0;
|
|
|
|
BX_INFO (("Using direct access for cdrom."));
|
|
|
|
}
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
ret = read(fd, &buffer, BX_CD_FRAMESIZE);
|
|
|
|
if (ret < 0) {
|
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
2001-10-07 07:34:54 +04:00
|
|
|
BX_DEBUG(( "insert_cdrom: read returns error: %s", strerror (errno) ));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(false);
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
return(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
cdrom_interface::eject_cdrom()
|
|
|
|
{
|
|
|
|
// Logically eject the CD. I suppose we could stick in
|
|
|
|
// some ioctl() calls to really eject the CD as well.
|
|
|
|
|
|
|
|
if (fd >= 0) {
|
2001-05-16 21:39:07 +04:00
|
|
|
#if (defined(__OpenBSD__) || defined(__FreeBSD__))
|
2001-04-10 05:04:59 +04:00
|
|
|
(void) ioctl (fd, CDIOCALLOW);
|
|
|
|
if (ioctl (fd, CDIOCEJECT) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(( "eject_cdrom: eject returns error." ));
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2001-06-19 01:11:46 +04:00
|
|
|
if (using_file == 0)
|
|
|
|
{
|
2001-06-25 06:18:16 +04:00
|
|
|
if(bUseASPI) {
|
|
|
|
} else {
|
|
|
|
DWORD lpBytesReturned;
|
|
|
|
DeviceIoControl(hFile, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &lpBytesReturned, NULL);
|
|
|
|
}
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
2002-03-02 14:31:18 +03:00
|
|
|
#if __linux__
|
|
|
|
if (!using_file)
|
|
|
|
ioctl (fd, CDROMEJECT, NULL);
|
|
|
|
#endif
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2001-06-19 01:14:00 +04:00
|
|
|
cdrom_interface::read_toc(uint8* buf, int* length, bool msf, int start_track)
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
|
|
|
// Read CD TOC. Returns false if start track is out of bounds.
|
|
|
|
|
|
|
|
if (fd < 0) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: file not open."));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
|
2002-07-31 09:21:46 +04:00
|
|
|
#ifdef WIN32
|
|
|
|
if (1) { // This is a hack and works okay if there's one rom track only
|
|
|
|
#else
|
2001-11-11 17:41:53 +03:00
|
|
|
if (using_file) {
|
2002-07-31 09:21:46 +04:00
|
|
|
#endif
|
2002-09-13 18:21:53 +04:00
|
|
|
// From atapi specs : start track can be 0-63, AA
|
|
|
|
if ((start_track > 1) && (start_track != 0xaa))
|
2002-07-30 10:25:57 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
buf[2] = 1;
|
|
|
|
buf[3] = 1;
|
|
|
|
|
|
|
|
int len = 4;
|
2002-09-25 03:45:43 +04:00
|
|
|
if (start_track <= 1) {
|
2002-07-30 10:25:57 +04:00
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
buf[len++] = 0x14; // ADR, control
|
|
|
|
buf[len++] = 1; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = 0; // minute
|
|
|
|
buf[len++] = 2; // second
|
|
|
|
buf[len++] = 0; // frame
|
|
|
|
} else {
|
|
|
|
buf[len++] = 0;
|
|
|
|
buf[len++] = 0;
|
|
|
|
buf[len++] = 0;
|
|
|
|
buf[len++] = 0; // logical sector 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lead out track
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
buf[len++] = 0x16; // ADR, control
|
|
|
|
buf[len++] = 0xaa; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
uint32 blocks = capacity();
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = (uint8)(((blocks + 150) / 75) / 60); // minute
|
|
|
|
buf[len++] = (uint8)(((blocks + 150) / 75) % 60); // second
|
|
|
|
buf[len++] = (uint8)((blocks + 150) % 75); // frame;
|
|
|
|
} else {
|
|
|
|
buf[len++] = (blocks >> 24) & 0xff;
|
|
|
|
buf[len++] = (blocks >> 16) & 0xff;
|
|
|
|
buf[len++] = (blocks >> 8) & 0xff;
|
|
|
|
buf[len++] = (blocks >> 0) & 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = ((len-2) >> 8) & 0xff;
|
|
|
|
buf[1] = (len-2) & 0xff;
|
|
|
|
|
|
|
|
*length = len;
|
|
|
|
|
2001-11-11 17:41:53 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// all these implementations below are the platform-dependent code required
|
|
|
|
// to read the TOC from a physical cdrom.
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef WIN32
|
|
|
|
{
|
|
|
|
/* #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
2001-06-19 01:14:00 +04:00
|
|
|
#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned long iBytesReturned;
|
2001-06-19 01:14:00 +04:00
|
|
|
DeviceIoControl(hFile, IOCTL_CDROM_READ_TOC, NULL, 0, NULL, 0, &iBytesReturned, NULL); */
|
2001-10-07 07:37:02 +04:00
|
|
|
BX_ERROR (("WARNING: read_toc is not implemented, just returning length=1"));
|
2001-10-07 07:34:54 +04:00
|
|
|
*length = 1;
|
|
|
|
return true;
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
2001-04-10 06:15:31 +04:00
|
|
|
#elif __linux__ || defined(__sun)
|
2001-11-11 17:41:53 +03:00
|
|
|
{
|
2001-04-10 05:04:59 +04:00
|
|
|
struct cdrom_tochdr tochdr;
|
|
|
|
if (ioctl(fd, CDROMREADTOCHDR, &tochdr))
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCHDR failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-07-29 20:42:01 +04:00
|
|
|
if ((start_track > tochdr.cdth_trk1) && (start_track != 0xaa))
|
2001-04-10 05:04:59 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
buf[2] = tochdr.cdth_trk0;
|
|
|
|
buf[3] = tochdr.cdth_trk1;
|
|
|
|
|
|
|
|
if (start_track < tochdr.cdth_trk0)
|
|
|
|
start_track = tochdr.cdth_trk0;
|
|
|
|
|
|
|
|
int len = 4;
|
|
|
|
for (int i = start_track; i <= tochdr.cdth_trk1; i++) {
|
|
|
|
struct cdrom_tocentry tocentry;
|
|
|
|
tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA;
|
|
|
|
tocentry.cdte_track = i;
|
|
|
|
if (ioctl(fd, CDROMREADTOCENTRY, &tocentry))
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCENTRY failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = 0; // Reserved
|
2001-06-19 01:14:00 +04:00
|
|
|
buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = i; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.minute;
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.second;
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.frame;
|
|
|
|
} else {
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lead out track
|
|
|
|
struct cdrom_tocentry tocentry;
|
|
|
|
tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA;
|
2001-06-19 01:11:46 +04:00
|
|
|
#ifdef CDROM_LEADOUT
|
2001-04-10 06:15:31 +04:00
|
|
|
tocentry.cdte_track = CDROM_LEADOUT;
|
|
|
|
#else
|
2001-04-10 05:04:59 +04:00
|
|
|
tocentry.cdte_track = 0xaa;
|
2001-04-10 06:15:31 +04:00
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
if (ioctl(fd, CDROMREADTOCENTRY, &tocentry))
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = 0; // Reserved
|
2001-06-19 01:14:00 +04:00
|
|
|
buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = 0xaa; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.minute;
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.second;
|
|
|
|
buf[len++] = tocentry.cdte_addr.msf.frame;
|
|
|
|
} else {
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = ((len-2) >> 8) & 0xff;
|
|
|
|
buf[1] = (len-2) & 0xff;
|
|
|
|
|
|
|
|
*length = len;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2002-04-18 22:17:45 +04:00
|
|
|
#elif (defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__))
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
|
|
|
struct ioc_toc_header h;
|
|
|
|
struct ioc_read_toc_entry t;
|
|
|
|
|
|
|
|
if (ioctl (fd, CDIOREADTOCHEADER, &h) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCHDR failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2002-07-29 20:42:01 +04:00
|
|
|
if ((start_track > h.ending_track) && (start_track != 0xaa))
|
2001-04-10 05:04:59 +04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
buf[2] = h.starting_track;
|
|
|
|
buf[3] = h.ending_track;
|
|
|
|
|
|
|
|
if (start_track < h.starting_track)
|
|
|
|
start_track = h.starting_track;
|
2001-06-19 01:11:46 +04:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
int len = 4;
|
|
|
|
for (int i = start_track; i <= h.ending_track; i++) {
|
|
|
|
struct cd_toc_entry tocentry;
|
|
|
|
t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT;
|
|
|
|
t.starting_track = i;
|
|
|
|
t.data_len = sizeof(tocentry);
|
|
|
|
t.data = &tocentry;
|
|
|
|
|
|
|
|
if (ioctl (fd, CDIOREADTOCENTRYS, &tocentry) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCENTRY failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
buf[len++] = 0; // Reserved
|
2001-06-19 01:14:00 +04:00
|
|
|
buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = i; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = tocentry.addr.msf.minute;
|
|
|
|
buf[len++] = tocentry.addr.msf.second;
|
|
|
|
buf[len++] = tocentry.addr.msf.frame;
|
|
|
|
} else {
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lead out track
|
|
|
|
struct cd_toc_entry tocentry;
|
|
|
|
t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT;
|
|
|
|
t.starting_track = 0xaa;
|
|
|
|
t.data_len = sizeof(tocentry);
|
|
|
|
t.data = &tocentry;
|
|
|
|
|
|
|
|
if (ioctl (fd, CDIOREADTOCENTRYS, &tocentry) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed."));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
buf[len++] = 0; // Reserved
|
2001-06-19 01:14:00 +04:00
|
|
|
buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control
|
2001-04-10 05:04:59 +04:00
|
|
|
buf[len++] = 0xaa; // Track number
|
|
|
|
buf[len++] = 0; // Reserved
|
|
|
|
|
|
|
|
// Start address
|
|
|
|
if (msf) {
|
|
|
|
buf[len++] = 0; // reserved
|
|
|
|
buf[len++] = tocentry.addr.msf.minute;
|
|
|
|
buf[len++] = tocentry.addr.msf.second;
|
|
|
|
buf[len++] = tocentry.addr.msf.frame;
|
|
|
|
} else {
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff;
|
|
|
|
buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[0] = ((len-2) >> 8) & 0xff;
|
|
|
|
buf[1] = (len-2) & 0xff;
|
|
|
|
|
|
|
|
*length = len;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#else
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_INFO(("read_toc: your OS is not supported yet."));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(false); // OS not supported yet, return false always.
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32
|
|
|
|
cdrom_interface::capacity()
|
|
|
|
{
|
|
|
|
// Return CD-ROM capacity. I believe you want to return
|
2002-07-31 09:21:46 +04:00
|
|
|
// the number of blocks of capacity the actual media has.
|
2001-10-07 07:34:54 +04:00
|
|
|
|
|
|
|
#if !defined WIN32
|
|
|
|
// win32 has its own way of doing this
|
|
|
|
if (using_file) {
|
|
|
|
// return length of the image file
|
|
|
|
struct stat stat_buf;
|
|
|
|
int ret = fstat (fd, &stat_buf);
|
|
|
|
if (ret) {
|
|
|
|
BX_PANIC (("fstat on cdrom image returned err: %s", strerror(errno)));
|
|
|
|
}
|
|
|
|
BX_INFO (("cdrom size is %d bytes", stat_buf.st_size));
|
|
|
|
if ((stat_buf.st_size % 2048) != 0) {
|
|
|
|
BX_ERROR (("expected cdrom image to be a multiple of 2048 bytes"));
|
|
|
|
}
|
|
|
|
return stat_buf.st_size / 2048;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-12-10 21:37:39 +03:00
|
|
|
#ifdef __BEOS__
|
|
|
|
return GetNumDeviceBlocks(fd, BX_CD_FRAMESIZE);
|
|
|
|
#elif defined(__sun)
|
2001-04-10 06:15:31 +04:00
|
|
|
{
|
|
|
|
struct stat buf = {0};
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-04-10 06:15:31 +04:00
|
|
|
if (fd < 0) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: capacity: file not open."));
|
2001-04-10 06:15:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if( fstat(fd, &buf) != 0 )
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: capacity: stat() failed."));
|
2001-04-10 06:15:31 +04:00
|
|
|
|
|
|
|
return(buf.st_size);
|
2001-06-19 01:11:46 +04:00
|
|
|
}
|
2002-04-18 22:17:45 +04:00
|
|
|
#elif (defined(__NetBSD__) || defined(__OpenBSD__))
|
2001-04-10 05:04:59 +04:00
|
|
|
{
|
|
|
|
// We just read the disklabel, imagine that...
|
|
|
|
struct disklabel lp;
|
|
|
|
|
|
|
|
if (fd < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: capacity: file not open."));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
if (ioctl(fd, DIOCGDINFO, &lp) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: ioctl(DIOCGDINFO) failed"));
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_DEBUG(( "capacity: %u", lp.d_secperunit ));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(lp.d_secperunit);
|
2001-06-26 12:12:21 +04:00
|
|
|
}
|
|
|
|
#elif defined(__linux__)
|
|
|
|
{
|
|
|
|
// Read the TOC to get the data size, since BLKGETSIZE doesn't work on
|
|
|
|
// non-ATAPI drives. This is based on Keith Jones code below.
|
|
|
|
// <splite@purdue.edu> 21 June 2001
|
|
|
|
|
2002-05-31 13:56:58 +04:00
|
|
|
int i, dtrk_lba, num_sectors;
|
|
|
|
int dtrk = 0;
|
2001-06-26 12:12:21 +04:00
|
|
|
struct cdrom_tochdr td;
|
|
|
|
struct cdrom_tocentry te;
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
BX_PANIC(("cdrom: capacity: file not open."));
|
|
|
|
|
|
|
|
if (ioctl(fd, CDROMREADTOCHDR, &td) < 0)
|
|
|
|
BX_PANIC(("cdrom: ioctl(CDROMREADTOCHDR) failed"));
|
|
|
|
|
|
|
|
num_sectors = -1;
|
|
|
|
dtrk_lba = -1;
|
|
|
|
|
|
|
|
for (i = td.cdth_trk0; i <= td.cdth_trk1; i++) {
|
|
|
|
te.cdte_track = i;
|
|
|
|
te.cdte_format = CDROM_LBA;
|
|
|
|
if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0)
|
|
|
|
BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed"));
|
|
|
|
|
|
|
|
if (dtrk_lba != -1) {
|
|
|
|
num_sectors = te.cdte_addr.lba - dtrk_lba;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (te.cdte_ctrl & CDROM_DATA_TRACK) {
|
|
|
|
dtrk = i;
|
|
|
|
dtrk_lba = te.cdte_addr.lba;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_sectors < 0) {
|
|
|
|
if (dtrk_lba != -1) {
|
|
|
|
te.cdte_track = CDROM_LEADOUT;
|
|
|
|
te.cdte_format = CDROM_LBA;
|
|
|
|
if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0)
|
|
|
|
BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed"));
|
|
|
|
num_sectors = te.cdte_addr.lba - dtrk_lba;
|
|
|
|
} else
|
|
|
|
BX_PANIC(("cdrom: no data track found"));
|
|
|
|
}
|
|
|
|
|
|
|
|
BX_INFO(("cdrom: Data track %d, length %d", dtrk, num_sectors));
|
|
|
|
|
|
|
|
return(num_sectors);
|
|
|
|
|
2001-05-16 21:39:07 +04:00
|
|
|
}
|
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
{
|
|
|
|
// Read the TOC to get the data size, since disklabel doesn't appear
|
|
|
|
// to work, sadly.
|
|
|
|
// Keith Jones, 16 January 2000
|
|
|
|
|
|
|
|
#define MAX_TRACKS 100
|
|
|
|
|
|
|
|
int i, num_tracks, num_sectors;
|
|
|
|
struct ioc_toc_header td;
|
|
|
|
struct ioc_read_toc_entry rte;
|
|
|
|
struct cd_toc_entry toc_buffer[MAX_TRACKS + 1];
|
|
|
|
|
|
|
|
if (fd < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: capacity: file not open."));
|
2001-05-16 21:39:07 +04:00
|
|
|
|
|
|
|
if (ioctl(fd, CDIOREADTOCHEADER, &td) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: ioctl(CDIOREADTOCHEADER) failed"));
|
2001-05-16 21:39:07 +04:00
|
|
|
|
|
|
|
num_tracks = (td.ending_track - td.starting_track) + 1;
|
|
|
|
if (num_tracks > MAX_TRACKS)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: TOC is too large"));
|
2001-05-16 21:39:07 +04:00
|
|
|
|
|
|
|
rte.address_format = CD_LBA_FORMAT;
|
|
|
|
rte.starting_track = td.starting_track;
|
|
|
|
rte.data_len = (num_tracks + 1) * sizeof(struct cd_toc_entry);
|
|
|
|
rte.data = toc_buffer;
|
|
|
|
if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: ioctl(CDIOREADTOCENTRYS) failed"));
|
2001-05-16 21:39:07 +04:00
|
|
|
|
|
|
|
num_sectors = -1;
|
|
|
|
for (i = 0; i < num_tracks; i++) {
|
|
|
|
if (rte.data[i].control & 4) { /* data track */
|
|
|
|
num_sectors = ntohl(rte.data[i + 1].addr.lba)
|
|
|
|
- ntohl(rte.data[i].addr.lba);
|
2001-10-07 07:34:54 +04:00
|
|
|
BX_INFO(( "cdrom: Data track %d, length %d",
|
2001-05-30 22:56:02 +04:00
|
|
|
rte.data[i].track, num_sectors));
|
2001-05-16 21:39:07 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_sectors < 0)
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: no data track found"));
|
2001-05-16 21:39:07 +04:00
|
|
|
|
|
|
|
return(num_sectors);
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
#elif defined WIN32
|
|
|
|
{
|
2001-06-25 06:18:16 +04:00
|
|
|
if(bUseASPI) {
|
2002-07-31 09:21:46 +04:00
|
|
|
return (GetCDCapacity(hid, tid, lun) / 2352);
|
2001-06-25 06:18:16 +04:00
|
|
|
} else {
|
|
|
|
unsigned long FileSize;
|
2002-07-31 09:21:46 +04:00
|
|
|
return (GetFileSize(hFile, &FileSize) / 2048);
|
2001-06-25 06:18:16 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
#else
|
2001-10-06 21:32:58 +04:00
|
|
|
BX_ERROR(( "capacity: your OS is not supported yet." ));
|
2001-04-10 05:04:59 +04:00
|
|
|
return(0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cdrom_interface::read_block(uint8* buf, int lba)
|
|
|
|
{
|
|
|
|
// Read a single block from the CD
|
|
|
|
|
|
|
|
off_t pos;
|
|
|
|
ssize_t n;
|
|
|
|
|
|
|
|
#ifdef WIN32
|
2001-06-25 06:18:16 +04:00
|
|
|
if(bUseASPI) {
|
|
|
|
ReadCDSector(hid, tid, lun, lba, buf, BX_CD_FRAMESIZE);
|
|
|
|
n = BX_CD_FRAMESIZE;
|
|
|
|
} else {
|
|
|
|
pos = SetFilePointer(hFile, lba*BX_CD_FRAMESIZE, NULL, SEEK_SET);
|
|
|
|
if (pos == 0xffffffff) {
|
|
|
|
BX_PANIC(("cdrom: read_block: lseek returned error."));
|
|
|
|
}
|
|
|
|
ReadFile(hFile, (void *) buf, BX_CD_FRAMESIZE, (unsigned long *) &n, NULL);
|
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
|
|
|
pos = lseek(fd, lba*BX_CD_FRAMESIZE, SEEK_SET);
|
|
|
|
if (pos < 0) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_block: lseek returned error."));
|
2001-06-25 06:18:16 +04:00
|
|
|
}
|
2001-04-10 05:04:59 +04:00
|
|
|
n = read(fd, buf, BX_CD_FRAMESIZE);
|
|
|
|
#endif
|
2001-06-19 01:11:46 +04:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
if (n != BX_CD_FRAMESIZE) {
|
2001-05-30 22:56:02 +04:00
|
|
|
BX_PANIC(("cdrom: read_block: read returned %d",
|
merge in BRANCH-io-cleanup.
To see the commit logs for this use either cvsweb or
cvs update -r BRANCH-io-cleanup and then 'cvs log' the various files.
In general this provides a generic interface for logging.
logfunctions:: is a class that is inherited by some classes, and also
. allocated as a standalone global called 'genlog'. All logging uses
. one of the ::info(), ::error(), ::ldebug(), ::panic() methods of this
. class through 'BX_INFO(), BX_ERROR(), BX_DEBUG(), BX_PANIC()' macros
. respectively.
.
. An example usage:
. BX_INFO(("Hello, World!\n"));
iofunctions:: is a class that is allocated once by default, and assigned
as the iofunction of each logfunctions instance. It is this class that
maintains the file descriptor and other output related code, at this
point using vfprintf(). At some future point, someone may choose to
write a gui 'console' for bochs to which messages would be redirected
simply by assigning a different iofunction class to the various logfunctions
objects.
More cleanup is coming, but this works for now. If you want to see alot
of debugging output, in main.cc, change onoff[LOGLEV_DEBUG]=0 to =1.
Comments, bugs, flames, to me: todd@fries.net
2001-05-15 18:49:57 +04:00
|
|
|
(int) n));
|
2001-04-10 05:04:59 +04:00
|
|
|
}
|
|
|
|
}
|
2001-06-19 01:11:46 +04:00
|
|
|
|