CD-ROM: IOCTL now detects medium changes without having to read the host drive's TOC on every operation, improves performance.
This commit is contained in:
@@ -2641,18 +2641,6 @@ cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
cdrom_ext_medium_changed(const cdrom_t *dev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (dev && dev->ops && dev->ops->ext_medium_changed &&
|
|
||||||
(dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))
|
|
||||||
ret = dev->ops->ext_medium_changed(dev->local);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cdrom_is_empty(const uint8_t id)
|
cdrom_is_empty(const uint8_t id)
|
||||||
{
|
{
|
||||||
@@ -2700,6 +2688,44 @@ cdrom_toc_dump(cdrom_t *dev)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
cdrom_set_empty(cdrom_t *dev)
|
||||||
|
{
|
||||||
|
dev->cd_status = CD_STATUS_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cdrom_update_status(cdrom_t *dev)
|
||||||
|
{
|
||||||
|
const int was_empty = (dev->cd_status == CD_STATUS_EMPTY);
|
||||||
|
|
||||||
|
if (dev->ops->load != NULL)
|
||||||
|
dev->ops->load(dev->local);
|
||||||
|
|
||||||
|
/* All good, reset state. */
|
||||||
|
dev->seek_pos = 0;
|
||||||
|
dev->cd_buflen = 0;
|
||||||
|
|
||||||
|
if ((dev->ops->is_empty != NULL) && dev->ops->is_empty(dev->local))
|
||||||
|
dev->cd_status = CD_STATUS_EMPTY;
|
||||||
|
else if (dev->ops->is_dvd(dev->local))
|
||||||
|
dev->cd_status = CD_STATUS_DVD;
|
||||||
|
else
|
||||||
|
dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED :
|
||||||
|
CD_STATUS_DATA_ONLY;
|
||||||
|
|
||||||
|
dev->cdrom_capacity = dev->ops->get_last_block(dev->local);
|
||||||
|
|
||||||
|
if (dev->cd_status != CD_STATUS_EMPTY) {
|
||||||
|
/* Signal media change to the emulated machine. */
|
||||||
|
cdrom_insert(dev->id);
|
||||||
|
|
||||||
|
/* The drive was previously empty, transition directly to UNIT ATTENTION. */
|
||||||
|
if (was_empty)
|
||||||
|
cdrom_insert(dev->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
|
cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
|
||||||
{
|
{
|
||||||
@@ -2728,10 +2754,12 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
|
|||||||
dev->seek_pos = 0;
|
dev->seek_pos = 0;
|
||||||
dev->cd_buflen = 0;
|
dev->cd_buflen = 0;
|
||||||
|
|
||||||
|
if ((dev->ops->is_empty != NULL) && dev->ops->is_empty(dev->local))
|
||||||
|
dev->cd_status = CD_STATUS_EMPTY;
|
||||||
if (dev->ops->is_dvd(dev->local))
|
if (dev->ops->is_dvd(dev->local))
|
||||||
dev->cd_status = CD_STATUS_DVD;
|
dev->cd_status = CD_STATUS_DVD;
|
||||||
else
|
else
|
||||||
dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED :
|
dev->cd_status = dev->ops->has_audio(dev->local) ? CD_STATUS_STOPPED :
|
||||||
CD_STATUS_DATA_ONLY;
|
CD_STATUS_DATA_ONLY;
|
||||||
|
|
||||||
dev->cdrom_capacity = dev->ops->get_last_block(dev->local);
|
dev->cdrom_capacity = dev->ops->get_last_block(dev->local);
|
||||||
@@ -2744,7 +2772,7 @@ cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert)
|
|||||||
cdrom_toc_dump(dev);
|
cdrom_toc_dump(dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!skip_insert) {
|
if (!skip_insert && (dev->cd_status != CD_STATUS_EMPTY)) {
|
||||||
/* Signal media change to the emulated machine. */
|
/* Signal media change to the emulated machine. */
|
||||||
cdrom_insert(dev->id);
|
cdrom_insert(dev->id);
|
||||||
|
|
||||||
|
|||||||
@@ -1992,7 +1992,8 @@ static const cdrom_ops_t image_ops = {
|
|||||||
image_is_dvd,
|
image_is_dvd,
|
||||||
image_has_audio,
|
image_has_audio,
|
||||||
NULL,
|
NULL,
|
||||||
image_close
|
image_close,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Public functions. */
|
/* Public functions. */
|
||||||
|
|||||||
@@ -271,8 +271,9 @@ typedef struct cdrom_ops_t {
|
|||||||
uint32_t *info);
|
uint32_t *info);
|
||||||
int (*is_dvd)(const void *local);
|
int (*is_dvd)(const void *local);
|
||||||
int (*has_audio)(const void *local);
|
int (*has_audio)(const void *local);
|
||||||
int (*ext_medium_changed)(void *local);
|
int (*is_empty)(const void *local);
|
||||||
void (*close)(void *local);
|
void (*close)(void *local);
|
||||||
|
void (*load)(const void *local);
|
||||||
} cdrom_ops_t;
|
} cdrom_ops_t;
|
||||||
|
|
||||||
typedef struct cdrom {
|
typedef struct cdrom {
|
||||||
@@ -423,7 +424,8 @@ extern int cdrom_read_dvd_structure(const cdrom_t *dev, const uint8_
|
|||||||
uint8_t *buffer, uint32_t *info);
|
uint8_t *buffer, uint32_t *info);
|
||||||
extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer);
|
extern void cdrom_read_disc_information(const cdrom_t *dev, uint8_t *buffer);
|
||||||
extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer);
|
extern int cdrom_read_track_information(cdrom_t *dev, const uint8_t *cdb, uint8_t *buffer);
|
||||||
extern int cdrom_ext_medium_changed(const cdrom_t *dev);
|
extern void cdrom_set_empty(cdrom_t *dev);
|
||||||
|
extern void cdrom_update_status(cdrom_t *dev);
|
||||||
extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert);
|
extern int cdrom_load(cdrom_t *dev, const char *fn, const int skip_insert);
|
||||||
|
|
||||||
extern void cdrom_global_init(void);
|
extern void cdrom_global_init(void);
|
||||||
|
|||||||
@@ -219,7 +219,7 @@
|
|||||||
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
|
#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26
|
||||||
#define ASC_WRITE_PROTECTED 0x27
|
#define ASC_WRITE_PROTECTED 0x27
|
||||||
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
|
#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
|
||||||
#define ASC_CAPACITY_DATA_CHANGED 0x2A
|
#define ASC_CAPACITY_DATA_CHANGED 0x2a
|
||||||
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
#define ASC_INCOMPATIBLE_FORMAT 0x30
|
||||||
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
#define ASC_MEDIUM_NOT_PRESENT 0x3a
|
||||||
#define ASC_DATA_PHASE_ERROR 0x4b
|
#define ASC_DATA_PHASE_ERROR 0x4b
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
typedef struct ioctl_t {
|
typedef struct ioctl_t {
|
||||||
cdrom_t *dev;
|
cdrom_t *dev;
|
||||||
void *log;
|
void *log;
|
||||||
int toc_valid;
|
|
||||||
void *handle;
|
void *handle;
|
||||||
char path[256];
|
char path[256];
|
||||||
} ioctl_t;
|
} ioctl_t;
|
||||||
@@ -77,8 +76,6 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl))
|
|||||||
static void
|
static void
|
||||||
ioctl_read_toc(ioctl_t *ioctl)
|
ioctl_read_toc(ioctl_t *ioctl)
|
||||||
{
|
{
|
||||||
if (!ioctl->toc_valid)
|
|
||||||
ioctl->toc_valid = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shared functions. */
|
/* Shared functions. */
|
||||||
@@ -159,6 +156,12 @@ ioctl_has_audio(UNUSED(const void *local))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ioctl_is_empty(const void *local)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ioctl_ext_medium_changed(UNUSED(void *local))
|
ioctl_ext_medium_changed(UNUSED(void *local))
|
||||||
{
|
{
|
||||||
@@ -186,6 +189,18 @@ ioctl_close(void *local)
|
|||||||
ioctl->log = NULL;
|
ioctl->log = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ioctl_load(const void *local)
|
||||||
|
{
|
||||||
|
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||||
|
|
||||||
|
if (ioctl_open_handle((ioctl_t *) ioctl)) {
|
||||||
|
ioctl_close_handle((ioctl_t *) ioctl);
|
||||||
|
|
||||||
|
ioctl_read_toc((ioctl_t *) ioctl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const cdrom_ops_t ioctl_ops = {
|
static const cdrom_ops_t ioctl_ops = {
|
||||||
ioctl_get_track_info,
|
ioctl_get_track_info,
|
||||||
ioctl_get_raw_track_info,
|
ioctl_get_raw_track_info,
|
||||||
@@ -196,8 +211,9 @@ static const cdrom_ops_t ioctl_ops = {
|
|||||||
ioctl_read_dvd_structure,
|
ioctl_read_dvd_structure,
|
||||||
ioctl_is_dvd,
|
ioctl_is_dvd,
|
||||||
ioctl_has_audio,
|
ioctl_has_audio,
|
||||||
ioctl_ext_medium_changed,
|
ioctl_is_empty,
|
||||||
ioctl_close
|
ioctl_close,
|
||||||
|
ioctl_load
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Public functions. */
|
/* Public functions. */
|
||||||
@@ -218,7 +234,6 @@ ioctl_open(cdrom_t *dev, const char *drv)
|
|||||||
ioctl_log(ioctl->log, "Path is %s\n", ioctl->path);
|
ioctl_log(ioctl->log, "Path is %s\n", ioctl->path);
|
||||||
|
|
||||||
ioctl->dev = dev;
|
ioctl->dev = dev;
|
||||||
ioctl->toc_valid = 0;
|
|
||||||
|
|
||||||
dev->ops = &ioctl_ops;
|
dev->ops = &ioctl_ops;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,10 @@
|
|||||||
#include <86box/mouse.h>
|
#include <86box/mouse.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
|
#include <86box/cdrom.h>
|
||||||
#include <86box/video.h>
|
#include <86box/video.h>
|
||||||
|
#include <dbt.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
|
||||||
extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1);
|
extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1);
|
||||||
|
|
||||||
@@ -151,72 +154,142 @@ WindowsRawInputFilter::~WindowsRawInputFilter()
|
|||||||
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
|
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notify_drives(ULONG unitmask, int empty)
|
||||||
|
{
|
||||||
|
char p[1024] = { 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 26; ++i) {
|
||||||
|
if (unitmask & 0x1) {
|
||||||
|
cdrom_t *dev = NULL;
|
||||||
|
|
||||||
|
sprintf(p, "ioctl://\\\\.\\%c:", 'A' + i);
|
||||||
|
|
||||||
|
for (int i = 0; i < CDROM_NUM; i++)
|
||||||
|
if (!stricmp(cdrom[i].image_path, p)) {
|
||||||
|
dev = &(cdrom[i]);
|
||||||
|
if (empty)
|
||||||
|
cdrom_set_empty(dev);
|
||||||
|
else
|
||||||
|
cdrom_update_status(dev);
|
||||||
|
// pclog("CD-ROM %i : Drive notified of media %s\n",
|
||||||
|
// dev->id, empty ? "removal" : "change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unitmask = unitmask >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
device_change(WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lParam;
|
||||||
|
|
||||||
|
switch(wParam) {
|
||||||
|
case DBT_DEVICEARRIVAL:
|
||||||
|
case DBT_DEVICEREMOVECOMPLETE:
|
||||||
|
/* Check whether a CD or DVD was inserted into a drive. */
|
||||||
|
if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) {
|
||||||
|
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME) lpdb;
|
||||||
|
|
||||||
|
if (lpdbv->dbcv_flags & DBTF_MEDIA)
|
||||||
|
notify_drives(lpdbv->dbcv_unitmask,
|
||||||
|
(wParam == DBT_DEVICEREMOVECOMPLETE));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
Process other WM_DEVICECHANGE notifications for other
|
||||||
|
devices or reasons.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result)
|
WindowsRawInputFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result)
|
||||||
{
|
{
|
||||||
if (eventType == "windows_generic_MSG") {
|
if (eventType == "windows_generic_MSG") {
|
||||||
MSG *msg = static_cast<MSG *>(message);
|
MSG *msg = static_cast<MSG *>(message);
|
||||||
|
|
||||||
if (msg->message == WM_INPUT) {
|
if (msg != nullptr) switch(msg->message) {
|
||||||
|
case WM_INPUT:
|
||||||
if (window->isActiveWindow() && menus_open == 0)
|
if (window->isActiveWindow() && (menus_open == 0))
|
||||||
handle_input((HRAWINPUT) msg->lParam);
|
handle_input((HRAWINPUT) msg->lParam);
|
||||||
else
|
else {
|
||||||
{
|
for (auto &w : window->renderers) {
|
||||||
for (auto &w : window->renderers) {
|
if (w && w->isActiveWindow()) {
|
||||||
if (w && w->isActiveWindow()) {
|
handle_input((HRAWINPUT) msg->lParam);
|
||||||
handle_input((HRAWINPUT) msg->lParam);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else if ((msg != nullptr) && (msg->message == WM_SETTINGCHANGE) &&
|
|
||||||
(((void *) msg->lParam) != nullptr) &&
|
|
||||||
(wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) {
|
|
||||||
if (!windows_is_light_theme()) {
|
|
||||||
QFile f(":qdarkstyle/dark/darkstyle.qss");
|
|
||||||
|
|
||||||
if (!f.exists()) {
|
|
||||||
printf("Unable to set stylesheet, file not found\n");
|
|
||||||
} else {
|
|
||||||
f.open(QFile::ReadOnly | QFile::Text);
|
|
||||||
QTextStream ts(&f);
|
|
||||||
qApp->setStyleSheet(ts.readAll());
|
|
||||||
}
|
|
||||||
QTimer::singleShot(1000, [this] () {
|
|
||||||
BOOL DarkMode = TRUE;
|
|
||||||
DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode));
|
|
||||||
window->ui->stackedWidget->switchRenderer((RendererStack::Renderer) vid_api);
|
|
||||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
|
||||||
if (window->renderers[i] && !window->renderers[i]->isHidden())
|
|
||||||
window->renderers[i]->switchRenderer((RendererStack::Renderer) vid_api);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
qApp->setStyleSheet("");
|
|
||||||
QTimer::singleShot(1000, [this] () {
|
|
||||||
BOOL DarkMode = FALSE;
|
|
||||||
DwmSetWindowAttribute((HWND)window->winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, (LPCVOID)&DarkMode, sizeof(DarkMode));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QTimer::singleShot(1000, [this] () {
|
|
||||||
window->resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y);
|
|
||||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
|
||||||
if (window->renderers[i] && !window->renderers[i]->isHidden()) {
|
|
||||||
window->resizeContentsMonitor(monitors[i].mon_scrnsz_x, monitors[i].mon_scrnsz_y, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop processing of Alt-F4 */
|
|
||||||
if (msg->message == WM_SYSKEYDOWN) {
|
|
||||||
if (msg->wParam == 0x73) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
case WM_SETTINGCHANGE:
|
||||||
|
if ((((void *) msg->lParam) != nullptr) &&
|
||||||
|
(wcscmp(L"ImmersiveColorSet", (wchar_t*)msg->lParam) == 0)) {
|
||||||
|
|
||||||
|
if (!windows_is_light_theme()) {
|
||||||
|
QFile f(":qdarkstyle/dark/darkstyle.qss");
|
||||||
|
|
||||||
|
if (!f.exists())
|
||||||
|
printf("Unable to set stylesheet, file not found\n");
|
||||||
|
else {
|
||||||
|
f.open(QFile::ReadOnly | QFile::Text);
|
||||||
|
QTextStream ts(&f);
|
||||||
|
qApp->setStyleSheet(ts.readAll());
|
||||||
|
}
|
||||||
|
QTimer::singleShot(1000, [this] () {
|
||||||
|
BOOL DarkMode = TRUE;
|
||||||
|
auto vid_stack = (RendererStack::Renderer) vid_api;
|
||||||
|
DwmSetWindowAttribute((HWND) window->winId(),
|
||||||
|
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||||
|
(LPCVOID) &DarkMode,
|
||||||
|
sizeof(DarkMode));
|
||||||
|
window->ui->stackedWidget->switchRenderer(vid_stack);
|
||||||
|
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
|
if ((window->renderers[i] != nullptr) &&
|
||||||
|
!window->renderers[i]->isHidden())
|
||||||
|
window->renderers[i]->switchRenderer(vid_stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
qApp->setStyleSheet("");
|
||||||
|
QTimer::singleShot(1000, [this] () {
|
||||||
|
BOOL DarkMode = FALSE;
|
||||||
|
DwmSetWindowAttribute((HWND) window->winId(),
|
||||||
|
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||||
|
(LPCVOID) &DarkMode,
|
||||||
|
sizeof(DarkMode));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QTimer::singleShot(1000, [this] () {
|
||||||
|
window->resizeContents(monitors[0].mon_scrnsz_x,
|
||||||
|
monitors[0].mon_scrnsz_y);
|
||||||
|
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
|
auto mon = &(monitors[i]);
|
||||||
|
|
||||||
|
if ((window->renderers[i] != nullptr) &&
|
||||||
|
!window->renderers[i]->isHidden())
|
||||||
|
window->resizeContentsMonitor(mon->mon_scrnsz_x,
|
||||||
|
mon->mon_scrnsz_y,
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
/* Stop processing of Alt-F4 */
|
||||||
|
if (msg->wParam == 0x73)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case WM_DEVICECHANGE:
|
||||||
|
if (msg->hwnd == (HWND) window->winId())
|
||||||
|
device_change(msg->wParam, msg->lParam);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <86box/86box.h>
|
||||||
#include <86box/cdrom.h>
|
#include <86box/cdrom.h>
|
||||||
#include <86box/log.h>
|
#include <86box/log.h>
|
||||||
#include <86box/plat_cdrom_ioctl.h>
|
#include <86box/plat_cdrom_ioctl.h>
|
||||||
|
#include <86box/scsi_device.h>
|
||||||
|
|
||||||
typedef struct ioctl_t {
|
typedef struct ioctl_t {
|
||||||
cdrom_t *dev;
|
cdrom_t *dev;
|
||||||
@@ -42,7 +44,6 @@ typedef struct ioctl_t {
|
|||||||
int is_dvd;
|
int is_dvd;
|
||||||
int has_audio;
|
int has_audio;
|
||||||
int32_t tracks_num;
|
int32_t tracks_num;
|
||||||
int toc_valid;
|
|
||||||
uint8_t cur_toc[65536];
|
uint8_t cur_toc[65536];
|
||||||
CDROM_READ_TOC_EX cur_read_toc_ex;
|
CDROM_READ_TOC_EX cur_read_toc_ex;
|
||||||
int blocks_num;
|
int blocks_num;
|
||||||
@@ -51,9 +52,8 @@ typedef struct ioctl_t {
|
|||||||
WCHAR path[256];
|
WCHAR path[256];
|
||||||
} ioctl_t;
|
} ioctl_t;
|
||||||
|
|
||||||
static void ioctl_read_toc(ioctl_t *ioctl);
|
static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format,
|
||||||
static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format,
|
uint8_t *buffer, uint32_t *info);
|
||||||
uint8_t *buffer, uint32_t *info);
|
|
||||||
|
|
||||||
#ifdef ENABLE_IOCTL_LOG
|
#ifdef ENABLE_IOCTL_LOG
|
||||||
int ioctl_do_log = ENABLE_IOCTL_LOG;
|
int ioctl_do_log = ENABLE_IOCTL_LOG;
|
||||||
@@ -94,25 +94,6 @@ ioctl_open_handle(ioctl_t *ioctl)
|
|||||||
return (ioctl->handle != INVALID_HANDLE_VALUE);
|
return (ioctl->handle != INVALID_HANDLE_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
ioctl_load(ioctl_t *ioctl)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (ioctl_open_handle(ioctl)) {
|
|
||||||
long size;
|
|
||||||
DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA,
|
|
||||||
NULL, 0, NULL, 0,
|
|
||||||
(LPDWORD) &size, NULL);
|
|
||||||
ret = 1;
|
|
||||||
ioctl_close_handle(ioctl);
|
|
||||||
|
|
||||||
ioctl_read_toc(ioctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf)
|
ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf)
|
||||||
{
|
{
|
||||||
@@ -266,11 +247,8 @@ ioctl_read_raw_toc(ioctl_t *ioctl)
|
|||||||
static void
|
static void
|
||||||
ioctl_read_toc(ioctl_t *ioctl)
|
ioctl_read_toc(ioctl_t *ioctl)
|
||||||
{
|
{
|
||||||
if (!ioctl->toc_valid) {
|
(void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc);
|
||||||
ioctl->toc_valid = 1;
|
ioctl_read_raw_toc(ioctl);
|
||||||
(void) ioctl_read_normal_toc(ioctl, ioctl->cur_toc);
|
|
||||||
ioctl_read_raw_toc(ioctl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -301,8 +279,6 @@ ioctl_is_track_audio(const ioctl_t *ioctl, const uint32_t pos)
|
|||||||
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ioctl_read_toc((ioctl_t *) ioctl);
|
|
||||||
|
|
||||||
if (ioctl->has_audio && !ioctl->is_dvd) {
|
if (ioctl->has_audio && !ioctl->is_dvd) {
|
||||||
const int track = ioctl_get_track(ioctl, pos);
|
const int track = ioctl_get_track(ioctl, pos);
|
||||||
const int control = rti[track].adr_ctl;
|
const int control = rti[track].adr_ctl;
|
||||||
@@ -324,8 +300,6 @@ ioctl_get_track_info(const void *local, const uint32_t track,
|
|||||||
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
|
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
ioctl_read_toc((ioctl_t *) ioctl);
|
|
||||||
|
|
||||||
if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) {
|
if ((track < 1) || (track == 0xaa) || (track > (toc->LastTrack + 1))) {
|
||||||
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track);
|
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@@ -363,8 +337,6 @@ ioctl_is_track_pre(const void *local, const uint32_t sector)
|
|||||||
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ioctl_read_toc((ioctl_t *) ioctl);
|
|
||||||
|
|
||||||
if (ioctl->has_audio && !ioctl->is_dvd) {
|
if (ioctl->has_audio && !ioctl->is_dvd) {
|
||||||
const int track = ioctl_get_track(ioctl, sector);
|
const int track = ioctl_get_track(ioctl, sector);
|
||||||
const int control = rti[track].adr_ctl;
|
const int control = rti[track].adr_ctl;
|
||||||
@@ -572,8 +544,6 @@ ioctl_get_last_block(const void *local)
|
|||||||
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
|
const CDROM_TOC *toc = (const CDROM_TOC *) ioctl->cur_toc;
|
||||||
uint32_t lb = 0;
|
uint32_t lb = 0;
|
||||||
|
|
||||||
ioctl_read_toc((ioctl_t *) ioctl);
|
|
||||||
|
|
||||||
for (int c = 0; c <= toc->LastTrack; c++) {
|
for (int c = 0; c <= toc->LastTrack; c++) {
|
||||||
const TRACK_DATA *td = &toc->TrackData[c];
|
const TRACK_DATA *td = &toc->TrackData[c];
|
||||||
const uint32_t address = MSFtoLBA(td->Address[1], td->Address[2],
|
const uint32_t address = MSFtoLBA(td->Address[1], td->Address[2],
|
||||||
@@ -688,44 +658,80 @@ ioctl_has_audio(const void *local)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ioctl_ext_medium_changed(void *local)
|
ioctl_is_empty(const void *local)
|
||||||
{
|
{
|
||||||
ioctl_t * ioctl = (ioctl_t *) local;
|
typedef struct SCSI_PASS_THROUGH_DIRECT_BUF {
|
||||||
const CDROM_TOC *toc = (CDROM_TOC *) ioctl->cur_toc;
|
SCSI_PASS_THROUGH_DIRECT spt;
|
||||||
const TRACK_DATA *ltd = &toc->TrackData[toc->LastTrack];
|
ULONG Filler;
|
||||||
const uint32_t old_addr = *(uint32_t *) ltd->Address;
|
UCHAR SenseBuf[64];
|
||||||
const int temp = ioctl_read_normal_toc(ioctl, ioctl->cur_toc);
|
} SCSI_PASS_THROUGH_DIRECT_BUF;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (temp == 1) {
|
const ioctl_t * ioctl = (const ioctl_t *) local;
|
||||||
if (ioctl->toc_valid && ((*(uint32_t *) ltd->Address) != old_addr)) {
|
unsigned long int unused = 0;
|
||||||
/* The TOC has changed. */
|
SCSI_PASS_THROUGH_DIRECT_BUF req;
|
||||||
ioctl->toc_valid = 0;
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ioctl->toc_valid) {
|
ioctl_open_handle((ioctl_t *) ioctl);
|
||||||
ioctl->toc_valid = 1;
|
|
||||||
ioctl_read_raw_toc(ioctl);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* There has been some kind of error - not a medium change, but a not ready
|
|
||||||
condition. */
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 1) {
|
memset(&req, 0x00, sizeof(SCSI_PASS_THROUGH_DIRECT_BUF));
|
||||||
if (ioctl->is_dvd)
|
req.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
|
||||||
ioctl->dev->cd_status = CD_STATUS_DVD;
|
req.spt.PathId = 0;
|
||||||
else
|
req.spt.TargetId = 1;
|
||||||
ioctl->dev->cd_status = ioctl->has_audio ? CD_STATUS_STOPPED :
|
req.spt.Lun = 0;
|
||||||
CD_STATUS_DATA_ONLY;
|
req.spt.CdbLength = 12;
|
||||||
|
req.spt.DataIn = SCSI_IOCTL_DATA_IN;
|
||||||
|
req.spt.SenseInfoLength = sizeof(req.SenseBuf);
|
||||||
|
req.spt.DataTransferLength = 0;
|
||||||
|
req.spt.TimeOutValue = 6;
|
||||||
|
req.spt.DataBuffer = NULL;
|
||||||
|
req.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_BUF, SenseBuf);
|
||||||
|
|
||||||
ioctl->dev->cdrom_capacity = ioctl_get_last_block(ioctl);
|
/* Fill in the CDB. */
|
||||||
} else if (ret == -1)
|
req.spt.Cdb[0] = 0x00;
|
||||||
ioctl->dev->cd_status = CD_STATUS_EMPTY;
|
req.spt.Cdb[1] = 0x00;
|
||||||
|
req.spt.Cdb[2] = 0x00;
|
||||||
|
req.spt.Cdb[3] = 0x00;
|
||||||
|
req.spt.Cdb[4] = 0x00;
|
||||||
|
req.spt.Cdb[5] = 0x00;
|
||||||
|
req.spt.Cdb[6] = 0x00;
|
||||||
|
req.spt.Cdb[7] = 0x00;
|
||||||
|
req.spt.Cdb[8] = 0x00;
|
||||||
|
req.spt.Cdb[9] = 0x00;
|
||||||
|
req.spt.Cdb[10] = 0x00;
|
||||||
|
req.spt.Cdb[11] = 0x00;
|
||||||
|
|
||||||
ioctl_log(ioctl->log, "ioctl_ext_medium_changed(): %i\n", ret);
|
DWORD length = sizeof(SCSI_PASS_THROUGH_DIRECT_BUF);
|
||||||
|
|
||||||
|
#ifdef ENABLE_IOCTL_LOG
|
||||||
|
uint8_t *cdb = (uint8_t *) req.spt.Cdb;
|
||||||
|
ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X "
|
||||||
|
"%02X %02X %02X %02X %02X %02X\n",
|
||||||
|
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5],
|
||||||
|
cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int ret = DeviceIoControl(ioctl->handle, IOCTL_SCSI_PASS_THROUGH_DIRECT,
|
||||||
|
&req, length,
|
||||||
|
&req, length,
|
||||||
|
&unused, NULL);
|
||||||
|
|
||||||
|
ioctl_log(ioctl->log, "ioctl_read_dvd_structure(): ret = %d, "
|
||||||
|
"req.spt.DataTransferLength = %lu\n",
|
||||||
|
ret, req.spt.DataTransferLength);
|
||||||
|
ioctl_log(ioctl->log, "Sense: %08X, %08X\n", req.spt.SenseInfoLength,
|
||||||
|
req.spt.SenseInfoOffset);
|
||||||
|
|
||||||
|
if (req.spt.SenseInfoLength >= 16) {
|
||||||
|
uint8_t *sb = (uint8_t *) req.SenseBuf;
|
||||||
|
/* Return sense to the host as is. */
|
||||||
|
ret = ((sb[2] == SENSE_NOT_READY) && (sb[12] == ASC_MEDIUM_NOT_PRESENT));
|
||||||
|
ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||||
|
sb[0], sb[1], sb[ 2], sb[ 3], sb[ 4], sb[ 5], sb[ 6], sb[ 7]);
|
||||||
|
ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||||
|
sb[8], sb[9], sb[10], sb[11], sb[12], sb[13], sb[14], sb[15]);
|
||||||
|
} else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
ioctl_close_handle((ioctl_t *) ioctl);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -744,6 +750,22 @@ ioctl_close(void *local)
|
|||||||
ioctl->log = NULL;
|
ioctl->log = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ioctl_load(const void *local)
|
||||||
|
{
|
||||||
|
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||||
|
|
||||||
|
if (ioctl_open_handle((ioctl_t *) ioctl)) {
|
||||||
|
long size;
|
||||||
|
DeviceIoControl(ioctl->handle, IOCTL_STORAGE_LOAD_MEDIA,
|
||||||
|
NULL, 0, NULL, 0,
|
||||||
|
(LPDWORD) &size, NULL);
|
||||||
|
ioctl_close_handle((ioctl_t *) ioctl);
|
||||||
|
|
||||||
|
ioctl_read_toc((ioctl_t *) ioctl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const cdrom_ops_t ioctl_ops = {
|
static const cdrom_ops_t ioctl_ops = {
|
||||||
ioctl_get_track_info,
|
ioctl_get_track_info,
|
||||||
ioctl_get_raw_track_info,
|
ioctl_get_raw_track_info,
|
||||||
@@ -754,8 +776,9 @@ static const cdrom_ops_t ioctl_ops = {
|
|||||||
ioctl_read_dvd_structure,
|
ioctl_read_dvd_structure,
|
||||||
ioctl_is_dvd,
|
ioctl_is_dvd,
|
||||||
ioctl_has_audio,
|
ioctl_has_audio,
|
||||||
ioctl_ext_medium_changed,
|
ioctl_is_empty,
|
||||||
ioctl_close
|
ioctl_close,
|
||||||
|
ioctl_load
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Public functions. */
|
/* Public functions. */
|
||||||
@@ -776,7 +799,6 @@ ioctl_open(cdrom_t *dev, const char *drv)
|
|||||||
ioctl_log(ioctl->log, "Path is %S\n", ioctl->path);
|
ioctl_log(ioctl->log, "Path is %S\n", ioctl->path);
|
||||||
|
|
||||||
ioctl->dev = dev;
|
ioctl->dev = dev;
|
||||||
ioctl->toc_valid = 0;
|
|
||||||
|
|
||||||
dev->ops = &ioctl_ops;
|
dev->ops = &ioctl_ops;
|
||||||
|
|
||||||
|
|||||||
@@ -678,8 +678,13 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
|
|||||||
dev->callback += period;
|
dev->callback += period;
|
||||||
scsi_cdrom_set_callback(dev);
|
scsi_cdrom_set_callback(dev);
|
||||||
return;
|
return;
|
||||||
|
case 0x43:
|
||||||
|
dev->drv->seek_diff = dev->drv->seek_pos + 150;
|
||||||
|
dev->drv->seek_pos = 0;
|
||||||
|
fallthrough;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
case 0x28:
|
case 0x28:
|
||||||
|
case 0x42: case 0x44:
|
||||||
case 0xa8:
|
case 0xa8:
|
||||||
/* Seek time is in us. */
|
/* Seek time is in us. */
|
||||||
period = cdrom_seek_time(dev->drv);
|
period = cdrom_seek_time(dev->drv);
|
||||||
@@ -693,7 +698,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
|
|||||||
dev->callback += period;
|
dev->callback += period;
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case 0x25:
|
case 0x25:
|
||||||
case 0x42 ... 0x44:
|
// case 0x42 ... 0x44:
|
||||||
case 0x51 ... 0x52:
|
case 0x51 ... 0x52:
|
||||||
case 0xad:
|
case 0xad:
|
||||||
case 0xb8 ... 0xb9:
|
case 0xb8 ... 0xb9:
|
||||||
@@ -702,6 +707,11 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
|
|||||||
dev->callback += 40.0;
|
dev->callback += 40.0;
|
||||||
/* Account for seek time. */
|
/* Account for seek time. */
|
||||||
/* 44100 * 16 bits * 2 channels = 176400 bytes per second */
|
/* 44100 * 16 bits * 2 channels = 176400 bytes per second */
|
||||||
|
/*
|
||||||
|
TODO: This is a bit of a lie - the actual period is closer to
|
||||||
|
75 * 2448 bytes per second, because the subchannel data
|
||||||
|
has to be read as well.
|
||||||
|
*/
|
||||||
bytes_per_second = 176400.0;
|
bytes_per_second = 176400.0;
|
||||||
bytes_per_second *= (double) dev->drv->cur_speed;
|
bytes_per_second *= (double) dev->drv->cur_speed;
|
||||||
break;
|
break;
|
||||||
@@ -730,7 +740,19 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
|
|||||||
period = 1000000.0 / bytes_per_second;
|
period = 1000000.0 / bytes_per_second;
|
||||||
scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n",
|
scsi_cdrom_log(dev->log, "Byte transfer period: %" PRIu64 " us\n",
|
||||||
(uint64_t) period);
|
(uint64_t) period);
|
||||||
period = period * (double) (dev->packet_len);
|
switch (cmd) {
|
||||||
|
default:
|
||||||
|
period = period * (double) (dev->packet_len);
|
||||||
|
break;
|
||||||
|
case 0x42: case 0x44:
|
||||||
|
/* READ SUBCHANNEL or READ HEADER - period of 1 entire sector. */
|
||||||
|
period = period * 2352.0;
|
||||||
|
break;
|
||||||
|
case 0x43:
|
||||||
|
/* READ TOC - period of 175 entire frames. */
|
||||||
|
period = period * 150.0 * 2352.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n",
|
scsi_cdrom_log(dev->log, "Sector transfer period: %" PRIu64 " us\n",
|
||||||
(uint64_t) period);
|
(uint64_t) period);
|
||||||
dev->callback += period;
|
dev->callback += period;
|
||||||
@@ -1181,25 +1203,6 @@ scsi_cdrom_insert(void *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
scsi_cdrom_ext_insert(void *priv, int ext_medium_changed)
|
|
||||||
{
|
|
||||||
scsi_cdrom_t *dev = (scsi_cdrom_t *) priv;
|
|
||||||
|
|
||||||
if ((dev == NULL) || (dev->drv == NULL))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((dev->drv->ops == NULL) || (ext_medium_changed == -1)) {
|
|
||||||
dev->unit_attention = 0;
|
|
||||||
dev->drv->cd_status = CD_STATUS_EMPTY;
|
|
||||||
scsi_cdrom_log(dev->log, "External media removal\n");
|
|
||||||
} else if (ext_medium_changed == 1) {
|
|
||||||
dev->unit_attention = 0;
|
|
||||||
dev->drv->cd_status |= CD_STATUS_TRANSITION;
|
|
||||||
scsi_cdrom_log(dev->log, "External media transition\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb)
|
scsi_command_check_ready(const scsi_cdrom_t *dev, const uint8_t *cdb)
|
||||||
{
|
{
|
||||||
@@ -1223,7 +1226,6 @@ static int
|
|||||||
scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
|
scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
|
||||||
{
|
{
|
||||||
int ready;
|
int ready;
|
||||||
const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv);
|
|
||||||
|
|
||||||
if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) &&
|
if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) &&
|
||||||
(cdb[1] & 0xe0)) {
|
(cdb[1] & 0xe0)) {
|
||||||
@@ -1257,9 +1259,6 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext_medium_changed != 0)
|
|
||||||
scsi_cdrom_ext_insert((void *) dev, ext_medium_changed);
|
|
||||||
|
|
||||||
if ((dev->drv->cd_status == CD_STATUS_PLAYING) ||
|
if ((dev->drv->cd_status == CD_STATUS_PLAYING) ||
|
||||||
(dev->drv->cd_status == CD_STATUS_PAUSED)) {
|
(dev->drv->cd_status == CD_STATUS_PAUSED)) {
|
||||||
ready = 1;
|
ready = 1;
|
||||||
@@ -1270,13 +1269,10 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, const uint8_t *cdb)
|
|||||||
if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE))
|
if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE))
|
||||||
ready = 0;
|
ready = 0;
|
||||||
else {
|
else {
|
||||||
if ((ext_medium_changed != 0) ||
|
if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA))
|
||||||
!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) {
|
|
||||||
scsi_cdrom_log(dev->log, "(ext_medium_changed != 0): scsi_cdrom_insert()\n");
|
|
||||||
scsi_cdrom_insert((void *) dev);
|
scsi_cdrom_insert((void *) dev);
|
||||||
}
|
|
||||||
|
|
||||||
ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1);
|
ready = (dev->drv->cd_status != CD_STATUS_EMPTY);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ready = (dev->drv->cd_status != CD_STATUS_EMPTY);
|
ready = (dev->drv->cd_status != CD_STATUS_EMPTY);
|
||||||
@@ -1469,10 +1465,6 @@ void
|
|||||||
scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
|
scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t alloc_length)
|
||||||
{
|
{
|
||||||
scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
|
scsi_cdrom_t *dev = (scsi_cdrom_t *) sc;
|
||||||
const int ext_medium_changed = cdrom_ext_medium_changed(dev->drv);
|
|
||||||
|
|
||||||
if (ext_medium_changed != 0)
|
|
||||||
scsi_cdrom_ext_insert((void *) dev, ext_medium_changed);
|
|
||||||
|
|
||||||
if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) {
|
if ((dev->drv->cd_status == CD_STATUS_EMPTY) && dev->unit_attention) {
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
typedef struct ioctl_t {
|
typedef struct ioctl_t {
|
||||||
cdrom_t *dev;
|
cdrom_t *dev;
|
||||||
void *log;
|
void *log;
|
||||||
int toc_valid;
|
|
||||||
void *handle;
|
void *handle;
|
||||||
char path[256];
|
char path[256];
|
||||||
} ioctl_t;
|
} ioctl_t;
|
||||||
@@ -77,8 +76,6 @@ ioctl_open_handle(UNUSED(ioctl_t *ioctl))
|
|||||||
static void
|
static void
|
||||||
ioctl_read_toc(ioctl_t *ioctl)
|
ioctl_read_toc(ioctl_t *ioctl)
|
||||||
{
|
{
|
||||||
if (!ioctl->toc_valid)
|
|
||||||
ioctl->toc_valid = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shared functions. */
|
/* Shared functions. */
|
||||||
@@ -159,6 +156,12 @@ ioctl_has_audio(UNUSED(const void *local))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ioctl_is_empty(const void *local)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ioctl_ext_medium_changed(UNUSED(void *local))
|
ioctl_ext_medium_changed(UNUSED(void *local))
|
||||||
{
|
{
|
||||||
@@ -186,6 +189,18 @@ ioctl_close(void *local)
|
|||||||
ioctl->log = NULL;
|
ioctl->log = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ioctl_load(const void *local)
|
||||||
|
{
|
||||||
|
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||||
|
|
||||||
|
if (ioctl_open_handle((ioctl_t *) ioctl)) {
|
||||||
|
ioctl_close_handle((ioctl_t *) ioctl);
|
||||||
|
|
||||||
|
ioctl_read_toc((ioctl_t *) ioctl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const cdrom_ops_t ioctl_ops = {
|
static const cdrom_ops_t ioctl_ops = {
|
||||||
ioctl_get_track_info,
|
ioctl_get_track_info,
|
||||||
ioctl_get_raw_track_info,
|
ioctl_get_raw_track_info,
|
||||||
@@ -196,8 +211,9 @@ static const cdrom_ops_t ioctl_ops = {
|
|||||||
ioctl_read_dvd_structure,
|
ioctl_read_dvd_structure,
|
||||||
ioctl_is_dvd,
|
ioctl_is_dvd,
|
||||||
ioctl_has_audio,
|
ioctl_has_audio,
|
||||||
ioctl_ext_medium_changed,
|
ioctl_is_empty,
|
||||||
ioctl_close
|
ioctl_close,
|
||||||
|
ioctl_load
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Public functions. */
|
/* Public functions. */
|
||||||
@@ -218,7 +234,6 @@ ioctl_open(cdrom_t *dev, const char *drv)
|
|||||||
ioctl_log(ioctl->log, "Path is %s\n", ioctl->path);
|
ioctl_log(ioctl->log, "Path is %s\n", ioctl->path);
|
||||||
|
|
||||||
ioctl->dev = dev;
|
ioctl->dev = dev;
|
||||||
ioctl->toc_valid = 0;
|
|
||||||
|
|
||||||
dev->ops = &ioctl_ops;
|
dev->ops = &ioctl_ops;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user