diff --git a/src/config.c b/src/config.c index 44ee053..77f3cf6 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. * - * Version: @(#)config.c 1.0.35 2018/10/07 + * Version: @(#)config.c 1.0.36 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -958,14 +958,14 @@ load_disks(const char *cat) if (hdd[c].bus == HDD_BUS_ST506) { /* Try new syntax. */ dev = config_get_int(cat, temp, -1); - hdd[c].id.st506_channel = dev; + hdd[c].bus_id.st506_channel = dev; } else config_delete_var(cat, temp); /* ESDI */ sprintf(temp, "hdd_%02i_esdi_channel", c+1); if (hdd[c].bus == HDD_BUS_ESDI) - hdd[c].id.esdi_channel = !!config_get_int(cat, temp, c & 1); + hdd[c].bus_id.esdi_channel = !!config_get_int(cat, temp, c & 1); else config_delete_var(cat, temp); @@ -977,10 +977,10 @@ load_disks(const char *cat) sscanf(p, "%01u:%01u", &board, &dev); board &= 3; dev &= 1; - hdd[c].id.ide_channel = (board<<1) + dev; + hdd[c].bus_id.ide_channel = (board<<1) + dev; - if (hdd[c].id.ide_channel > 7) - hdd[c].id.ide_channel = 7; + if (hdd[c].bus_id.ide_channel > 7) + hdd[c].bus_id.ide_channel = 7; } else { config_delete_var(cat, temp); } @@ -992,12 +992,12 @@ load_disks(const char *cat) p = config_get_string(cat, temp, tmp2); sscanf(p, "%02u:%02u", - (int *)&hdd[c].id.scsi.id, (int *)&hdd[c].id.scsi.lun); + (int *)&hdd[c].bus_id.scsi.id, (int *)&hdd[c].bus_id.scsi.lun); - if (hdd[c].id.scsi.id > 15) - hdd[c].id.scsi.id = 15; - if (hdd[c].id.scsi.lun > 7) - hdd[c].id.scsi.lun = 7; + if (hdd[c].bus_id.scsi.id > 15) + hdd[c].bus_id.scsi.id = 15; + if (hdd[c].bus_id.scsi.lun > 7) + hdd[c].bus_id.scsi.lun = 7; } else { config_delete_var(cat, temp); } @@ -1049,13 +1049,13 @@ save_disks(const char *cat) sprintf(temp, "hdd_%02i_st506_channel", c+1); if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_ST506)) - config_set_int(cat, temp, hdd[c].id.st506_channel); + config_set_int(cat, temp, hdd[c].bus_id.st506_channel); else config_delete_var(cat, temp); sprintf(temp, "hdd_%02i_esdi_channel", c+1); if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_ESDI)) - config_set_int(cat, temp, hdd[c].id.esdi_channel); + config_set_int(cat, temp, hdd[c].bus_id.esdi_channel); else config_delete_var(cat, temp); @@ -1064,8 +1064,8 @@ save_disks(const char *cat) config_delete_var(cat, temp); } else { sprintf(tmp2, "%01u:%01u", - hdd[c].id.ide_channel >> 1, - hdd[c].id.ide_channel & 1); + hdd[c].bus_id.ide_channel >> 1, + hdd[c].bus_id.ide_channel & 1); config_set_string(cat, temp, tmp2); } @@ -1074,7 +1074,7 @@ save_disks(const char *cat) config_delete_var(cat, temp); } else { sprintf(tmp2, "%02i:%02i", - hdd[c].id.scsi.id, hdd[c].id.scsi.lun); + hdd[c].bus_id.scsi.id, hdd[c].bus_id.scsi.lun); config_set_string(cat, temp, tmp2); } @@ -1204,44 +1204,44 @@ load_removable(const char *cat) for (c = 0; c < CDROM_NUM; c++) { sprintf(temp, "cdrom_%02i_host_drive", c+1); - cdrom_drives[c].host_drive = config_get_int(cat, temp, 0); - cdrom_drives[c].prev_host_drive = cdrom_drives[c].host_drive; + cdrom[c].host_drive = config_get_int(cat, temp, 0); + cdrom[c].prev_host_drive = cdrom[c].host_drive; sprintf(temp, "cdrom_%02i_parameters", c+1); p = config_get_string(cat, temp, "0, none"); - sscanf(p, "%01u, %s", (int *)&cdrom_drives[c].sound_on, s); - cdrom_drives[c].bus_type = cdrom_string_to_bus(s); + sscanf(p, "%01u, %s", (int *)&cdrom[c].sound_on, s); + cdrom[c].bus_type = cdrom_string_to_bus(s); sprintf(temp, "cdrom_%02i_speed", c+1); - cdrom_drives[c].speed_idx = config_get_int(cat, temp, cdrom_speed_idx(CDROM_SPEED_DEFAULT)); + cdrom[c].speed_idx = config_get_int(cat, temp, cdrom_speed_idx(CDROM_SPEED_DEFAULT)); /* Default values, needed for proper operation of the Settings dialog. */ - cdrom_drives[c].ide_channel = cdrom_drives[c].scsi_device_id = c + 2; + cdrom[c].bus_id.ide_channel = cdrom[c].bus_id.scsi.id = c + 2; sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_ATAPI) { + if (cdrom[c].bus_type == CDROM_BUS_ATAPI) { sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); board &= 3; dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; + cdrom[c].bus_id.ide_channel = (board<<1)+dev; - if (cdrom_drives[c].ide_channel > 7) - cdrom_drives[c].ide_channel = 7; + if (cdrom[c].bus_id.ide_channel > 7) + cdrom[c].bus_id.ide_channel = 7; } else { sprintf(temp, "cdrom_%02i_scsi_location", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { + if (cdrom[c].bus_type == CDROM_BUS_SCSI) { sprintf(tmp2, "%02u:%02u", c+2, 0); p = config_get_string(cat, temp, tmp2); sscanf(p, "%02u:%02u", - (int *)&cdrom_drives[c].scsi_device_id, - (int *)&cdrom_drives[c].scsi_device_lun); + (int *)&cdrom[c].bus_id.scsi.id, + (int *)&cdrom[c].bus_id.scsi.lun); - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - if (cdrom_drives[c].scsi_device_lun > 7) - cdrom_drives[c].scsi_device_lun = 7; + if (cdrom[c].bus_id.scsi.id > 15) + cdrom[c].bus_id.scsi.id = 15; + if (cdrom[c].bus_id.scsi.lun > 7) + cdrom[c].bus_id.scsi.lun = 7; } else { config_delete_var(cat, temp); } @@ -1251,17 +1251,17 @@ load_removable(const char *cat) wp = config_get_wstring(cat, temp, L""); /* Try to make relative, and copy to destination. */ - pc_path(cdrom_image[c].image_path, sizeof_w(cdrom_image[c].image_path), wp); + pc_path(cdrom[c].image_path, sizeof_w(cdrom[c].image_path), wp); - if (cdrom_drives[c].host_drive < 'A') - cdrom_drives[c].host_drive = 0; + if (cdrom[c].host_drive < 'A') + cdrom[c].host_drive = 0; - if ((cdrom_drives[c].host_drive == 0x200) && - (wcslen(cdrom_image[c].image_path) == 0)) - cdrom_drives[c].host_drive = 0; + if ((cdrom[c].host_drive == 0x200) && + (wcslen(cdrom[c].image_path) == 0)) + cdrom[c].host_drive = 0; /* If the CD-ROM is disabled, delete all its variables. */ - if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED) { + if (cdrom[c].bus_type == CDROM_BUS_DISABLED) { sprintf(temp, "cdrom_%02i_host_drive", c+1); config_delete_var(cat, temp); @@ -1289,7 +1289,7 @@ load_removable(const char *cat) zip_drives[c].bus_type = zip_string_to_bus(s); /* Default values, needed for proper operation of the Settings dialog. */ - zip_drives[c].ide_channel = zip_drives[c].scsi_device_id = c + 2; + zip_drives[c].bus_id.ide_channel = zip_drives[c].bus_id.scsi.id = c + 2; sprintf(temp, "zip_%02i_ide_channel", c+1); if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { @@ -1299,23 +1299,23 @@ load_removable(const char *cat) board &= 3; dev &= 1; - zip_drives[c].ide_channel = (board<<1)+dev; + zip_drives[c].bus_id.ide_channel = (board<<1)+dev; - if (zip_drives[c].ide_channel > 7) - zip_drives[c].ide_channel = 7; + if (zip_drives[c].bus_id.ide_channel > 7) + zip_drives[c].bus_id.ide_channel = 7; } else { sprintf(temp, "zip_%02i_scsi_location", c+1); if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { sprintf(tmp2, "%02u:%02u", c+2, 0); p = config_get_string(cat, temp, tmp2); sscanf(p, "%02u:%02u", - (unsigned *)&zip_drives[c].scsi_device_id, - (unsigned *)&zip_drives[c].scsi_device_lun); + (unsigned *)&zip_drives[c].bus_id.scsi.id, + (unsigned *)&zip_drives[c].bus_id.scsi.lun); - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - if (zip_drives[c].scsi_device_lun > 7) - zip_drives[c].scsi_device_lun = 7; + if (zip_drives[c].bus_id.scsi.id > 15) + zip_drives[c].bus_id.scsi.id = 15; + if (zip_drives[c].bus_id.scsi.lun > 7) + zip_drives[c].bus_id.scsi.lun = 7; } else { config_delete_var(cat, temp); } @@ -1360,54 +1360,54 @@ save_removable(const char *cat) for (c = 0; c < CDROM_NUM; c++) { sprintf(temp, "cdrom_%02i_host_drive", c+1); - if ((cdrom_drives[c].bus_type == 0) || - (cdrom_drives[c].host_drive < 'A') || ((cdrom_drives[c].host_drive > 'Z') && (cdrom_drives[c].host_drive != 200))) { + if ((cdrom[c].bus_type == 0) || + (cdrom[c].host_drive < 'A') || ((cdrom[c].host_drive > 'Z') && (cdrom[c].host_drive != 200))) { config_delete_var(cat, temp); } else { - config_set_int(cat, temp, cdrom_drives[c].host_drive); + config_set_int(cat, temp, cdrom[c].host_drive); } sprintf(temp, "cdrom_%02i_speed", c+1); - if ((cdrom_drives[c].bus_type == 0) || - (cdrom_speeds[cdrom_drives[c].speed_idx].speed == cdrom_speed_idx(CDROM_SPEED_DEFAULT))) { + if ((cdrom[c].bus_type == 0) || + (cdrom_speeds[cdrom[c].speed_idx].speed == cdrom_speed_idx(CDROM_SPEED_DEFAULT))) { config_delete_var(cat, temp); } else { - config_set_int(cat, temp, cdrom_drives[c].speed_idx); + config_set_int(cat, temp, cdrom[c].speed_idx); } sprintf(temp, "cdrom_%02i_parameters", c+1); - if (cdrom_drives[c].bus_type == 0) { + if (cdrom[c].bus_type == 0) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%u, %s", cdrom_drives[c].sound_on, - cdrom_bus_to_string(cdrom_drives[c].bus_type)); + sprintf(tmp2, "%u, %s", cdrom[c].sound_on, + cdrom_bus_to_string(cdrom[c].bus_type)); config_set_string(cat, temp, tmp2); } sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI) { + if (cdrom[c].bus_type != CDROM_BUS_ATAPI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, - cdrom_drives[c].ide_channel & 1); + sprintf(tmp2, "%01u:%01u", cdrom[c].bus_id.ide_channel>>1, + cdrom[c].bus_id.ide_channel & 1); config_set_string(cat, temp, tmp2); } sprintf(temp, "cdrom_%02i_scsi_location", c + 1); - if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) { + if (cdrom[c].bus_type != CDROM_BUS_SCSI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%02u:%02u", cdrom_drives[c].scsi_device_id, - cdrom_drives[c].scsi_device_lun); + sprintf(tmp2, "%02u:%02u", + cdrom[c].bus_id.scsi.id, cdrom[c].bus_id.scsi.lun); config_set_string(cat, temp, tmp2); } sprintf(temp, "cdrom_%02i_image_path", c + 1); - if ((cdrom_drives[c].bus_type == 0) || - (wcslen(cdrom_image[c].image_path) == 0)) { + if ((cdrom[c].bus_type == 0) || + (wcslen(cdrom[c].image_path) == 0)) { config_delete_var(cat, temp); } else { - config_set_wstring(cat, temp, cdrom_image[c].image_path); + config_set_wstring(cat, temp, cdrom[c].image_path); } } @@ -1425,8 +1425,8 @@ save_removable(const char *cat) if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%01u:%01u", zip_drives[c].ide_channel>>1, - zip_drives[c].ide_channel & 1); + sprintf(tmp2, "%01u:%01u", zip_drives[c].bus_id.ide_channel>>1, + zip_drives[c].bus_id.ide_channel & 1); config_set_string(cat, temp, tmp2); } @@ -1434,8 +1434,8 @@ save_removable(const char *cat) if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%02u:%02u", zip_drives[c].scsi_device_id, - zip_drives[c].scsi_device_lun); + sprintf(tmp2, "%02u:%02u", zip_drives[c].bus_id.scsi.id, + zip_drives[c].bus_id.scsi.lun); config_set_string(cat, temp, tmp2); } diff --git a/src/device.c b/src/device.c index 348b866..87fb467 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,7 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.15 2018/10/05 + * Version: @(#)device.c 1.0.16 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -216,7 +216,7 @@ device_close_all(void) { int c; - for (c = 0; c < DEVICE_MAX; c++) { + for (c = (DEVICE_MAX - 1); c >= 0; c--) { if (devices[c] != NULL) { if (devices[c]->close != NULL) devices[c]->close(device_priv[c]); diff --git a/src/devices/cdrom/cdrom.c b/src/devices/cdrom/cdrom.c index 9920379..deebefc 100644 --- a/src/devices/cdrom/cdrom.c +++ b/src/devices/cdrom/cdrom.c @@ -6,18 +6,15 @@ * * This file is part of the VARCem Project. * - * Implementation of the CD-ROM drive with SCSI(-like) - * commands, for both ATAPI and SCSI usage. + * Generic interface for CD-ROM/DVD/BD implementations. * - * Version: @(#)cdrom.c 1.0.17 2018/10/11 + * Version: @(#)cdrom.c 1.0.19 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,339 +46,26 @@ #include "../../emu.h" #include "../../version.h" #include "../../timer.h" -#include "../../device.h" -#include "../../nvr.h" #include "../../ui/ui.h" #include "../../plat.h" -#include "../system/intel_piix.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../scsi/scsi_device.h" #include "../sound/sound.h" #include "cdrom.h" #include "cdrom_image.h" #include "cdrom_null.h" -/* Bits of 'status' */ -#define ERR_STAT 0x01 -#define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits of 'error' */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* Media change request */ - #define MIN_SEEK 2000 #define MAX_SEEK 333333 -#define cdbufferb dev->buffer - - -cdrom_t *cdrom[CDROM_NUM]; -cdrom_image_t cdrom_image[CDROM_NUM]; -cdrom_drive_t cdrom_drives[CDROM_NUM]; -uint8_t atapi_cdrom_drives[8] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; -uint8_t scsi_cdrom_drives[16][8] = { - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xfF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } -}; - - -#pragma pack(push,1) -typedef struct { - uint8_t opcode; - uint8_t polled; - uint8_t reserved2[2]; - uint8_t opc_class; - uint8_t reserved3[2]; - uint16_t len; - uint8_t control; -} gesn_cdb_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint16_t len; - uint8_t notification_class; - uint8_t supported_events; -} gesn_event_header_t; -#pragma pack(pop) - - -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -static const uint8_t cdrom_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, /* 0x02 */ - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - 0, 0, 0, 0, /* 0x04-0x07 */ - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, 0, /* 0x09-0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, 0, 0, 0, 0, 0, /* 0x0C-0x11 */ - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, /* 0x14 */ - IMPLEMENTED, /* 0x15 */ - 0, 0, 0, 0, /* 0x16-0x19 */ - IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, 0, /* 0x1C-0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */ - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, /* 0x26-0x27 */ - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, 0, /* 0x29-0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, 0, /* 0x2C-0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ - 0, 0, /* 0x40-0x41 */ - IMPLEMENTED | CHECK_READY, /* 0x42 */ - IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - IMPLEMENTED | CHECK_READY, /* 0x44 */ - IMPLEMENTED | CHECK_READY, /* 0x45 */ - IMPLEMENTED | ALLOW_UA, /* 0x46 */ - IMPLEMENTED | CHECK_READY, /* 0x47 */ - IMPLEMENTED | CHECK_READY, /* 0x48 */ - 0, /* 0x49 */ - IMPLEMENTED | ALLOW_UA, /* 0x4A */ - IMPLEMENTED | CHECK_READY, /* 0x4B */ - 0, 0, /* 0x4C-0x4D */ - IMPLEMENTED | CHECK_READY, /* 0x4E */ - 0, 0, /* 0x4F-0x50 */ - IMPLEMENTED | CHECK_READY, /* 0x51 */ - IMPLEMENTED | CHECK_READY, /* 0x52 */ - 0, 0, /* 0x53-0x54 */ - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, /* 0x56-0x59 */ - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, /* 0x5B-0x5F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ - 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ - IMPLEMENTED | CHECK_READY, /* 0xA5 */ - 0, 0, /* 0xA6-0xA7 */ - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - 0, 0, 0, 0, /* 0xA9-0xAC */ - IMPLEMENTED | CHECK_READY, /* 0xAD */ - 0, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, /* 0xB0-0xB3 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ - 0, 0, 0, /* 0xB5-0xB7 */ - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ - IMPLEMENTED | CHECK_READY, /* 0xB9 */ - IMPLEMENTED | CHECK_READY, /* 0xBA */ - IMPLEMENTED, /* 0xBB */ - IMPLEMENTED | CHECK_READY, /* 0xBC */ - IMPLEMENTED, /* 0xBD */ - IMPLEMENTED | CHECK_READY, /* 0xBE */ - IMPLEMENTED | CHECK_READY, /* 0xBF */ - 0, 0, /* 0xC0-0xC1 */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC3-0xCC */ - IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ - IMPLEMENTED | SCSI_ONLY, /* 0xDA */ - 0, 0, 0, 0, 0, /* 0xDB-0xDF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ -}; - -static const uint64_t cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_CDROM_PAGE | - GPMODEP_CDROM_AUDIO_PAGE | - GPMODEP_CAPABILITIES_PAGE | - GPMODEP_ALL_PAGES); - - -static const mode_sense_pages_t cdrom_mode_sense_pages_default = { - { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } -} }; - -static const mode_sense_pages_t cdrom_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } -} }; - -static const mode_sense_pages_t cdrom_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } -} }; - -uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static gesn_cdb_t *gesn_cdb; -static gesn_event_header_t *gesn_event_header; - - -static void cdrom_command_complete(cdrom_t *dev); - -static void cdrom_mode_sense_load(cdrom_t *dev); - -static void cdrom_init(cdrom_t *dev); -void cdrom_phase_callback(cdrom_t *dev); - #ifdef ENABLE_CDROM_LOG int cdrom_do_log = ENABLE_CDROM_LOG; #endif +cdrom_t cdrom[CDROM_NUM]; + + void cdrom_log(int level, const char *fmt, ...) { @@ -397,482 +81,26 @@ cdrom_log(int level, const char *fmt, ...) } -int -find_cdrom_for_channel(uint8_t channel) -{ - uint8_t i = 0; - - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) && (cdrom_drives[i].ide_channel == channel)) - return i; - } - return 0xff; -} - - -void -build_atapi_cdrom_map(void) -{ - uint8_t i = 0; - - memset(atapi_cdrom_drives, 0xff, 8); - - for (i = 0; i < 8; i++) - atapi_cdrom_drives[i] = find_cdrom_for_channel(i); -} - - -int -find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i = 0; - - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (cdrom_drives[i].scsi_device_id == scsi_id) && (cdrom_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - return 0xff; -} - - -void -build_scsi_cdrom_map(void) -{ - uint8_t i = 0; - uint8_t j = 0; - - for (i = 0; i < 16; i++) - memset(scsi_cdrom_drives[i], 0xff, 8); - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) - scsi_cdrom_drives[i][j] = find_cdrom_for_scsi_id(i, j); - } -} - - -static void -cdrom_set_callback(cdrom_t *dev) -{ - if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) - ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); -} - - -void -cdrom_set_signature(cdrom_t *dev) -{ - if (!dev) - return; - dev->phase = 1; - dev->request_length = 0xEB14; -} - - -static void -cdrom_init(cdrom_t *dev) -{ - if (!dev) - return; - - /* Tell the cdrom_t struct what cdrom_drives element corresponds to it. */ - dev->drv = &(cdrom_drives[dev->id]); - - /* Do a reset (which will also rezero it). */ - cdrom_reset(dev); - - /* Configure the drive. */ - dev->requested_blocks = 1; - - dev->drv->bus_mode = 0; - if (dev->drv->bus_type >= CDROM_BUS_ATAPI) - dev->drv->bus_mode |= 2; - if (dev->drv->bus_type < CDROM_BUS_SCSI) - dev->drv->bus_mode |= 1; - DEBUG("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); - dev->cdb_len = 12; - - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; - dev->packet_status = 0xff; - cdrom_sense_key = cdrom_asc = cdrom_ascq = dev->unit_attention = 0; - dev->cur_speed = dev->drv->speed_idx; - cdrom_mode_sense_load(dev); -} - - -static int -cdrom_supports_pio(cdrom_t *dev) -{ - return (dev->drv->bus_mode & 1); -} - - -static int -cdrom_supports_dma(cdrom_t *dev) -{ - return (dev->drv->bus_mode & 2); -} - - -/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ -static int -cdrom_current_mode(cdrom_t *dev) -{ - if (!cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) - return 0; - if (cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) { - DEBUG("CD-ROM %i: Drive does not support DMA, setting to PIO\n", dev->id); - return 1; - } - if (!cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) - return 2; - if (cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) { - DEBUG("CD-ROM %i: Drive supports both, setting to %s\n", dev->id, - (dev->features & 1) ? "DMA" : "PIO", - dev->id); - return (dev->features & 1) ? 2 : 1; - } - - return 0; -} - - -/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int -cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev) -{ - if (dev->status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; -} - - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -cdrom_atapi_phase_to_scsi(cdrom_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - - int cdrom_lba_to_msf_accurate(int lba) { - int temp_pos; + int pos; int m, s, f; - temp_pos = lba + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; + pos = lba + 150; + f = pos % 75; + pos -= f; + pos /= 75; + s = pos % 60; + pos -= s; + pos /= 60; + m = pos; return ((m << 16) | (s << 8) | f); } -uint32_t -cdrom_mode_sense_get_channel(cdrom_t *dev, int channel) -{ - return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; -} - - -uint32_t -cdrom_mode_sense_get_volume(cdrom_t *dev, int channel) -{ - return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; -} - - -static void -cdrom_mode_sense_load(cdrom_t *dev) -{ - FILE *f; - wchar_t file_name[512]; - int i; - - memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { - if (dev->drv->bus_type == CDROM_BUS_SCSI) - memcpy(dev->ms_pages_saved.pages[i], - cdrom_mode_sense_pages_default_scsi.pages[i], - cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(dev->ms_pages_saved.pages[i], - cdrom_mode_sense_pages_default.pages[i], - cdrom_mode_sense_pages_default.pages[i][1] + 2); - } - } - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) { - fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - - -static void -cdrom_mode_sense_save(cdrom_t *dev) -{ - FILE *f; - wchar_t file_name[512]; - - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (dev->drv->bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) { - fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - - -int -cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int size = 0; - - size = dev->handler->size(dev->id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 8; /* 2048 = 0x0800 */ - *len = 8; - - return 1; -} - - -/*SCSI Mode Sense 6/10*/ -static uint8_t -cdrom_mode_sense_read(cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) -{ - switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - break; - case 1: - return cdrom_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (dev->drv->bus_type == CDROM_BUS_SCSI) - return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; - else - return cdrom_mode_sense_pages_default.pages[page][pos]; - break; - } - - return 0; -} - - -static uint32_t -cdrom_mode_sense(cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) -{ - uint8_t page_control = (type >> 6) & 3; - int i = 0, j = 0; - - uint8_t msplen; - - type &= 0x3f; - - if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = 0; /* Number of blocks (0 = all). */ - buf[pos++] = 0; - buf[pos++] = 0; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ - buf[pos++] = 8; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (cdrom_mode_sense_page_flags & (1LL << dev->current_page_code)) { - buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 0); - msplen = cdrom_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - DEBUG("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) { - if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { - if (j & 1) - buf[pos++] = ((cdrom_speeds[dev->drv->speed_idx].speed * 176) & 0xff); - else - buf[pos++] = ((cdrom_speeds[dev->drv->speed_idx].speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { - if (j & 1) - buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) & 0xff); - else - buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) >> 8); - } else - buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 2 + j); - } - } - } - } - - return pos; -} - - -static void -cdrom_update_request_length(cdrom_t *dev, int len, int block_len) -{ - int32_t bt, min_len = 0; - - dev->max_transfer_len = dev->request_length; - - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (dev->current_cdb[0]) { - case 0x08: - case 0x28: - case 0xa8: - case 0xb9: - case 0xbe: - /* Make sure total length is not bigger than sum of the lengths of - all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; - - min_len = block_len; - - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } - default: - dev->packet_len = len; - break; - } - - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; - - if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; - else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; - - return; -} - - -#if 0 -static double -cdrom_get_short_seek(cdrom_t *dev) -{ - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); - return 0.0; - case 1: - return 240.0; - case 2: - return 160.0; - case 3: - return 150.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 112.0; - case 12: case 13: case 14: case 15: - return 75.0; - case 16: case 17: case 18: case 19: - return 58.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 50.0; - default: - /* 24-32, 52+ */ - return 45.0; - } -} - - -static double -cdrom_get_long_seek(cdrom_t *dev) -{ - switch(dev->cur_speed) { - case 0: - fatal("CD-ROM %i: 0x speed\n", dev->id); - return 0.0; - case 1: - return 1446.0; - case 2: - return 1000.0; - case 3: - return 900.0; - case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: - return 675.0; - case 12: case 13: case 14: case 15: - return 400.0; - case 16: case 17: case 18: case 19: - return 350.0; - case 20: case 21: case 22: case 23: - case 40: case 41: case 42: case 43: - case 44: case 45: case 46: case 47: - case 48: - return 300.0; - default: - /* 24-32, 52+ */ - return 270.0; - } -} -#endif - - -static double +double cdrom_seek_time(cdrom_t *dev) { uint32_t diff = dev->seek_diff; @@ -885,2402 +113,95 @@ cdrom_seek_time(cdrom_t *dev) diff -= MIN_SEEK; -#if 1 return cdrom_speeds[dev->cur_speed].seek1 + ((cdrom_speeds[dev->cur_speed].seek2 * ((double) diff)) / sd); -#else - return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); -#endif -} - - -static double -cdrom_bus_speed(cdrom_t *dev) -{ - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return 0.0; - } else { - if (cdrom_current_mode(dev) == 2) - return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } -} - - -static void -cdrom_command_bus(cdrom_t *dev) -{ - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 1LL * CDROM_TIME; - cdrom_set_callback(dev); -} - - -static void -cdrom_command_common(cdrom_t *dev) -{ - double bytes_per_second, period; - double dusec; - - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 0LL; - - DEBUG("CD-ROM %i: Current speed: %ix\n", - dev->id, cdrom_speeds[dev->cur_speed].speed); - - if (dev->packet_status == CDROM_PHASE_COMPLETE) { - cdrom_phase_callback(dev); - dev->callback = 0LL; - } else { - switch(dev->current_cdb[0]) { - case GPCMD_REZERO_UNIT: - case 0x0b: - case 0x2b: - /* Seek time is in us. */ - period = cdrom_seek_time(dev); - DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (int64_t) period); - period = period * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - cdrom_set_callback(dev); - return; - case 0x08: - case 0x28: - case 0xa8: - /* Seek time is in us. */ - period = cdrom_seek_time(dev); - DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", - dev->id, (int64_t) period); - period = period * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - /*FALLTHROUGH*/ - case 0x25: - case 0x42: - case 0x43: - case 0x44: - case 0x51: - case 0x52: - case 0xad: - case 0xb8: - case 0xb9: - case 0xbe: - if (dev->current_cdb[0] == 0x42) - dev->callback += 200LL * CDROM_TIME; - /* Account for seek time. */ - bytes_per_second = 176.0 * 1024.0; - bytes_per_second *= (double) cdrom_speeds[dev->cur_speed].speed; - break; - default: - bytes_per_second = cdrom_bus_speed(dev); - if (bytes_per_second == 0.0) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return; - } - break; - } - - period = 1000000.0 / bytes_per_second; - DEBUG("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); - period = period * (double) (dev->packet_len); - DEBUG("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); - dusec = period * ((double) TIMER_USEC); - dev->callback += ((int64_t) dusec); - } - cdrom_set_callback(dev); -} - - -static void -cdrom_command_complete(cdrom_t *dev) -{ - dev->packet_status = CDROM_PHASE_COMPLETE; - cdrom_command_common(dev); -} - - -static void -cdrom_command_read(cdrom_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_IN; - cdrom_command_common(dev); - dev->total_read = 0; -} - - -static void -cdrom_command_read_dma(cdrom_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_IN_DMA; - cdrom_command_common(dev); - dev->total_read = 0; -} - - -static void -cdrom_command_write(cdrom_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_OUT; - cdrom_command_common(dev); -} - - -static void cdrom_command_write_dma(cdrom_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; - cdrom_command_common(dev); -} - - -/* id = Current CD-ROM device ID; - len = Total transfer length; - block_len = Length of a single block (why does it matter?!); - alloc_len = Allocated transfer length; - direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void cdrom_data_command_finish(cdrom_t *dev, int len, int block_len, int alloc_len, int direction) -{ - DEBUG("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; - if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; - } - if ((len == 0) || (cdrom_current_mode(dev) == 0)) { - if (dev->drv->bus_type != CDROM_BUS_SCSI) - dev->packet_len = 0; - - cdrom_command_complete(dev); - } else { - if (cdrom_current_mode(dev) == 2) { - if (dev->drv->bus_type != CDROM_BUS_SCSI) - dev->packet_len = alloc_len; - - if (direction == 0) - cdrom_command_read_dma(dev); - else - cdrom_command_write_dma(dev); - } else { - cdrom_update_request_length(dev, len, block_len); - if (direction == 0) - cdrom_command_read(dev); - else - cdrom_command_write(dev); - } - } - - DEBUG("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); -} - - -static void -cdrom_sense_clear(cdrom_t *dev, int command) -{ - dev->previous_command = command; - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; -} - - -static void -cdrom_set_phase(cdrom_t *dev, uint8_t phase) -{ - uint8_t scsi_id = dev->drv->scsi_device_id; - uint8_t scsi_lun = dev->drv->scsi_device_lun; - - if (dev->drv->bus_type != CDROM_BUS_SCSI) - return; - - SCSIDevices[scsi_id][scsi_lun].Phase = phase; -} - - -static void -cdrom_cmd_error(cdrom_t *dev) -{ - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(dev); - DEBUG("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, cdrom_sense_key, cdrom_asc, cdrom_ascq); -} - - -static void -cdrom_unit_attention(cdrom_t *dev) -{ - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(dev); - DEBUG("CD-ROM %i: UNIT ATTENTION\n", dev->id); -} - - -static void -cdrom_bus_master_error(cdrom_t *dev) -{ - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_not_ready(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_NOT_READY; - cdrom_asc = ASC_MEDIUM_NOT_PRESENT; - cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_invalid_lun(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_LUN; - cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_illegal_opcode(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_OPCODE; - cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_lba_out_of_range(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_LBA_OUT_OF_RANGE; - cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_invalid_field(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; - cdrom_ascq = 0; - cdrom_cmd_error(dev); - dev->status = 0x53; -} - - -static void -cdrom_invalid_field_pl(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - cdrom_ascq = 0; - cdrom_cmd_error(dev); - dev->status = 0x53; -} - - -static void -cdrom_illegal_mode(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - cdrom_ascq = 0; - cdrom_cmd_error(dev); -} - - -static void -cdrom_incompatible_format(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INCOMPATIBLE_FORMAT; - cdrom_ascq = 2; - cdrom_cmd_error(dev); -} - - -static void -cdrom_data_phase_error(cdrom_t *dev) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_DATA_PHASE_ERROR; - cdrom_ascq = 0; - cdrom_cmd_error(dev); } void -cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) -{ - int temp = 0; - - switch(cdb[0]) { - case GPCMD_READ_6: - cdb[1] = (lba_pos >> 16) & 0xff; - cdb[2] = (lba_pos >> 8) & 0xff; - cdb[3] = lba_pos & 0xff; - break; - - case GPCMD_READ_10: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; - - case GPCMD_READ_12: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 24) & 0xff; - cdb[7] = (number_of_blocks >> 16) & 0xff; - cdb[8] = (number_of_blocks >> 8) & 0xff; - cdb[9] = number_of_blocks & 0xff; - break; - - case GPCMD_READ_CD_MSF: - temp = cdrom_lba_to_msf_accurate(lba_pos); - cdb[3] = (temp >> 16) & 0xff; - cdb[4] = (temp >> 8) & 0xff; - cdb[5] = temp & 0xff; - - temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); - cdb[6] = (temp >> 16) & 0xff; - cdb[7] = (temp >> 8) & 0xff; - cdb[8] = temp & 0xff; - break; - - case GPCMD_READ_CD: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 16) & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; - } -} - - -static int -cdrom_read_data(cdrom_t *dev, int msf, int type, int flags, int32_t *len) -{ - int ret = 0; - uint32_t cdsize = 0; - - int i = 0; - int temp_len = 0; - - cdsize = dev->handler->size(dev->id); - - if (dev->sector_pos >= cdsize) { - DEBUG("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, - dev->sector_pos, cdsize); - cdrom_lba_out_of_range(dev); - return 0; - } - - if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { - DEBUG("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, - (dev->sector_pos + dev->sector_len - 1), cdsize); - cdrom_lba_out_of_range(dev); - return 0; - } - - dev->old_len = 0; - *len = 0; - - for (i = 0; i < dev->requested_blocks; i++) { - ret = dev->handler->readsector_raw(dev->id, cdbufferb + dev->data_pos, dev->sector_pos + i, - msf, type, flags, &temp_len); - - dev->data_pos += temp_len; - dev->old_len += temp_len; - - *len += temp_len; - - if (!ret) { - cdrom_illegal_mode(dev); - return 0; - } - } - - return 1; -} - - -static int -cdrom_read_blocks(cdrom_t *dev, int32_t *len, int first_batch) -{ - int ret = 0, msf = 0; - int type = 0, flags = 0; - - if (dev->current_cdb[0] == 0xb9) - msf = 1; - - if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { - type = (dev->current_cdb[1] >> 2) & 7; - flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); - } else { - type = 8; - flags = 0x10; - } - - dev->data_pos = 0; - - if (!dev->sector_len) { - cdrom_command_complete(dev); - return -1; - } - - DEBUG("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - - cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); - - ret = cdrom_read_data(dev, msf, type, flags, len); - - DEBUG("Read %i bytes of blocks...\n", *len); - - if (!ret || ((dev->old_len != *len) && !first_batch)) { - if ((dev->old_len != *len) && !first_batch) - cdrom_illegal_mode(dev); - - return 0; - } - - dev->sector_pos += dev->requested_blocks; - dev->sector_len -= dev->requested_blocks; - - return 1; -} - - -/*SCSI Read DVD Structure*/ -static int -cdrom_read_dvd_structure(cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) -{ - int layer = packet[6]; - uint64_t total_sectors; - - switch (format) { - case 0x00: /* Physical format information */ - total_sectors = (uint64_t) dev->handler->size(dev->id); - - if (layer != 0) { - cdrom_invalid_field(dev); - return 0; - } - - total_sectors >>= 2; - if (total_sectors == 0) { - /* return -ASC_MEDIUM_NOT_PRESENT; */ - cdrom_not_ready(dev); - return 0; - } - - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; - - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 +2 ) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4 + 2) >> 8) & 0xff; - buf[1] = (4 + 2) & 0xff; - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - cdrom_invalid_field(dev); - return 0; - - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 + 2) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048 + 4) >> 8) & 0xff; - buf[7] = (2048 + 4) & 0xff; - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4 + 4) >> 8) & 0xff; - buf[11] = (4 + 4) & 0xff; - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188 + 4) >> 8) & 0xff; - buf[15] = (188 + 4) & 0xff; - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048 + 4) >> 8) & 0xff; - buf[19] = (2048 + 4) & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16 + 2) >> 8) & 0xff; - buf[7] = (16 + 2) & 0xff; - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - cdrom_invalid_field(dev); - return 0; - } -} - - -void -cdrom_insert(cdrom_t *dev) -{ - dev->unit_attention = 1; - DEBUG("CD-ROM %i: Media insert\n", dev->id); -} - - -/*SCSI Sense Initialization*/ -void -cdrom_sense_code_ok(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - cdrom_sense_key = SENSE_NONE; - cdrom_asc = 0; - cdrom_ascq = 0; -} - - -static int -cdrom_pre_execution_check(cdrom_t *dev, uint8_t *cdb) -{ - int ready = 0, status = 0; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if (((dev->request_length >> 5) & 7) != dev->drv->scsi_device_lun) { - DEBUG("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); - cdrom_invalid_lun(dev); - return 0; - } - } - - if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - DEBUG("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], - (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); - - cdrom_illegal_opcode(dev); - return 0; - } - - if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { - DEBUG("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); - cdrom_illegal_opcode(dev); - return 0; - } - - if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { - DEBUG("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); - cdrom_illegal_opcode(dev); - return 0; - } - - status = dev->handler->status(dev->id); - - if ((status == CD_STATUS_PLAYING) || (status == CD_STATUS_PAUSED)) { - ready = 1; - goto skip_ready_check; - } - - if (dev->handler->medium_changed(dev->id)) - cdrom_insert(dev); - - ready = dev->handler->ready(dev->id); - -skip_ready_check: - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - if (!ready && dev->unit_attention) - dev->unit_attention = 0; - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - /* DEBUG("CD-ROM %i: Unit attention now 2\n", dev->id); */ - dev->unit_attention++; - DEBUG("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); - cdrom_unit_attention(dev); - return 0; - } - } else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* DEBUG("CD-ROM %i: Unit attention now 0\n", dev->id); */ - dev->unit_attention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - cdrom_sense_clear(dev, cdb[0]); - - /* Next it's time for NOT READY. */ - if (!ready) - dev->media_status = MEC_MEDIA_REMOVAL; - else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - - if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { - DEBUG("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); - cdrom_not_ready(dev); - return 0; - } - - DEBUG("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); - - return 1; -} - - -static void cdrom_seek(cdrom_t *dev, uint32_t pos) { - /* DEBUG("CD-ROM %i: Seek %08X\n", dev->id, pos); */ - dev->seek_pos = pos; - if (dev->handler && dev->handler->stop) - dev->handler->stop(dev->id); -} - - -static void -cdrom_rezero(cdrom_t *dev) -{ - if (dev->handler && dev->handler->stop) - dev->handler->stop(dev->id); - dev->sector_pos = dev->sector_len = 0; - cdrom_seek(dev, 0); -} - - -void -cdrom_reset(cdrom_t *dev) -{ - if (!dev) + if (! dev) return; - cdrom_rezero(dev); - dev->status = 0; - dev->callback = 0LL; - cdrom_set_callback(dev); - dev->packet_status = 0xff; - dev->unit_attention = 0xff; + DEBUG("CD-ROM %i: Seek %08lx\n", dev->id, pos); + + dev->seek_pos = pos; + + if (dev->ops && dev->ops->stop) + dev->ops->stop(dev); } -static int +int cdrom_playing_completed(cdrom_t *dev) { dev->prev_status = dev->cd_status; - dev->cd_status = dev->handler->status(dev->id); - if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) + + dev->cd_status = dev->ops->status(dev); + if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && + ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) return 1; - else - return 0; -} - - -static void -cdrom_request_sense(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) -{ - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - memcpy(buffer, dev->sense, alloc_length); - } - - buffer[0] = 0x70; - - if ((cdrom_sense_key > 0) && ((dev->cd_status < CD_STATUS_PLAYING) || - (dev->cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(dev)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } else if ((cdrom_sense_key == 0) && (dev->cd_status >= CD_STATUS_PLAYING) && - (dev->cd_status != CD_STATUS_STOPPED)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=(dev->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } else { - if (dev->unit_attention && (cdrom_sense_key == 0)) { - buffer[2]=SENSE_UNIT_ATTENTION; - buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[13]=0; - } - } - - DEBUG("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); - - if (buffer[2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - dev->unit_attention = 0; - } - - /* Clear the sense stuff as per the spec. */ - cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); -} - - -void -cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) -{ - int ready = 0; - - if (dev->handler->medium_changed(dev->id)) - cdrom_insert(dev); - - ready = dev->handler->ready(dev->id); - - if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; - } - - /* Do *NOT* advance the unit attention phase. */ - cdrom_request_sense(dev, buffer, alloc_length); -} - - -static void -cdrom_set_buf_len(cdrom_t *dev, int32_t *BufLen, int32_t *src_len) -{ - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - DEBUG("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); - } -} - - -static void -cdrom_buf_alloc(cdrom_t *dev, uint32_t len) -{ - DEBUG("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len); - cdbufferb = (uint8_t *) mem_alloc(len); -} - - -static void -cdrom_buf_free(cdrom_t *dev) -{ - if (cdbufferb) { - DEBUG("CD-ROM %i: Freeing buffer...\n", dev->id); - free(cdbufferb); - cdbufferb = NULL; - } -} - - -void -cdrom_command(cdrom_t *dev, uint8_t *cdb) -{ - int len, max_len, used_len, alloc_length, msf; - int pos = 0, i= 0, size_idx, idx = 0; - uint32_t feature; - unsigned preamble_len; - int toc_format, block_desc = 0; - int ret, format = 0; - int real_pos, track = 0; - char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int32_t blen = 0, *BufLen; - uint8_t *b; - uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; - dev->status &= ~ERR_STAT; - } else { - BufLen = &blen; - dev->error = 0; - } - - dev->packet_len = 0; - dev->request_pos = 0; - - device_identify[7] = dev->id + 0x30; - - device_identify_ex[7] = dev->id + 0x30; - device_identify_ex[10] = EMU_VERSION[0]; - device_identify_ex[12] = EMU_VERSION[2]; - device_identify_ex[13] = EMU_VERSION[3]; - - dev->data_pos = 0; - - memcpy(dev->current_cdb, cdb, dev->cdb_len); - - dev->cd_status = dev->handler->status(dev->id); - - if (cdb[0] != 0) { - DEBUG("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, dev->unit_attention); - DEBUG("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); - - DEBUG("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], - cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); - } - - msf = cdb[1] & 2; - dev->sector_len = 0; - - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (cdrom_pre_execution_check(dev, cdb) == 0) - return; - - switch (cdb[0]) { - case GPCMD_TEST_UNIT_READY: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - cdrom_command_complete(dev); - break; - - case GPCMD_REZERO_UNIT: - if (dev->handler->stop) - dev->handler->stop(dev->id); - dev->sector_pos = dev->sector_len = 0; - dev->seek_diff = dev->seek_pos; - cdrom_seek(dev, 0); - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - - if (!max_len) { - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20LL * CDROM_TIME; - cdrom_set_callback(dev); - break; - } - - cdrom_buf_alloc(dev, 256); - cdrom_set_buf_len(dev, BufLen, &max_len); - cdrom_request_sense(dev, cdbufferb, max_len); - cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - len = (cdb[3] | (cdb[2] << 8)) / 176; - dev->cur_speed = cdrom_speed_idx(len); - if (dev->cur_speed > dev->drv->speed_idx) - dev->cur_speed = dev->drv->speed_idx; - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - cdrom_command_complete(dev); - break; - - case GPCMD_MECHANISM_STATUS: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - cdrom_buf_alloc(dev, 8); - - cdrom_set_buf_len(dev, BufLen, &len); - - memset(cdbufferb, 0, 8); - cdbufferb[5] = 1; - - cdrom_data_command_finish(dev, 8, 8, len, 0); - break; - - case GPCMD_READ_TOC_PMA_ATIP: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(dev, 65536); - - toc_format = cdb[2] & 0xf; - - if (toc_format == 0) - toc_format = (cdb[9] >> 6) & 3; - - switch (toc_format) { - case 0: /*Normal*/ - len = dev->handler->readtoc(dev->id, cdbufferb, cdb[6], msf, max_len, - 0); - break; - case 1: /*Multi session*/ - len = dev->handler->readtoc_session(dev->id, cdbufferb, msf, max_len); - cdbufferb[0] = 0; cdbufferb[1] = 0xA; - break; - case 2: /*Raw*/ - len = dev->handler->readtoc_raw(dev->id, cdbufferb, max_len); - break; - default: - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - if (len > max_len) { - len = max_len; - - cdbufferb[0] = ((len - 2) >> 8) & 0xff; - cdbufferb[1] = (len - 2) & 0xff; - } - - cdrom_set_buf_len(dev, BufLen, &len); - - if (len >= 8) { - DEBUG("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], - cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - } - - if (len >= 16) { - DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11], - cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]); - } - - if (len >= 24) { - DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19], - cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]); - } - - if (len >= 32) { - DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27], - cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]); - } - - if (len >= 36) { - DEBUG(" %02X %02X %02X %02X\n", - cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]); - } - - cdrom_data_command_finish(dev, len, len, len, 0); - /* DEBUG("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", dev->id, - toc_format, ide->cylinder, cdbufferb[1]); */ - return; - - case GPCMD_READ_CD_OLD: - /* IMPORTANT: Convert the command to new read CD - for pass through purposes. */ - dev->current_cdb[0] = 0xbe; - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - alloc_length = 2048; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - msf = 0; - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_CD_MSF: - alloc_length = 2856; - dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); - dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); - - dev->sector_len -= dev->sector_pos; - dev->sector_len++; - msf = 1; - break; - case GPCMD_READ_CD_OLD: - case GPCMD_READ_CD: - alloc_length = 2856; - dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - msf = 0; - break; - } - - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - dev->seek_pos = dev->sector_pos; - - if (!dev->sector_len) { - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - /* DEBUG("CD-ROM %i: All done - callback set\n", dev->id); */ - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20LL * CDROM_TIME; - cdrom_set_callback(dev); - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - dev->packet_len = max_len * alloc_length; - cdrom_buf_alloc(dev, dev->packet_len); - - ret = cdrom_read_blocks(dev, &alloc_length, 1); - if (ret <= 0) { - cdrom_buf_free(dev); - return; - } - - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; - - cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - - cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, - alloc_length, 0); - - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != CDROM_PHASE_COMPLETE) - ui_sb_icon_update(SB_CDROM | dev->id, 1); - else - ui_sb_icon_update(SB_CDROM | dev->id, 0); - return; - - case GPCMD_READ_HEADER: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - alloc_length = ((cdb[7] << 8) | cdb[8]); - cdrom_buf_alloc(dev, 8); - - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; - if (msf) - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - else - real_pos = dev->sector_pos; - cdbufferb[0] = 1; /*2048 bytes user data*/ - cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; - cdbufferb[4] = (real_pos >> 24); - cdbufferb[5] = ((real_pos >> 16) & 0xff); - cdbufferb[6] = ((real_pos >> 8) & 0xff); - cdbufferb[7] = real_pos & 0xff; - - len = 8; - len = MIN(len, alloc_length); - - cdrom_set_buf_len(dev, BufLen, &len); - - cdrom_data_command_finish(dev, len, len, len, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - cdrom_buf_alloc(dev, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - cdrom_buf_alloc(dev, 65536); - } - - dev->current_page_code = cdb[2] & 0x3F; - - if (!(cdrom_mode_sense_page_flags & (1LL << dev->current_page_code))) { - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - memset(cdbufferb, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdrom_mode_sense(dev, cdbufferb, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0] = len - 1; - cdbufferb[1] = dev->handler->media_type_id(dev->id); - if (block_desc) - cdbufferb[3] = 8; - } else { - len = cdrom_mode_sense(dev, cdbufferb, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0]=(len - 2) >> 8; - cdbufferb[1]=(len - 2) & 255; - cdbufferb[2] = dev->handler->media_type_id(dev->id); - if (block_desc) { - cdbufferb[6] = 0; - cdbufferb[7] = 8; - } - } - - cdrom_set_buf_len(dev, BufLen, &len); - - DEBUG("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - cdrom_data_command_finish(dev, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - cdrom_buf_alloc(dev, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - cdrom_buf_alloc(dev, 65536); - } - - cdrom_set_buf_len(dev, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - dev->current_page_pos = 0; - - cdrom_data_command_finish(dev, len, len, len, 1); - return; - - case GPCMD_GET_CONFIGURATION: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - /* XXX: could result in alignment problems in some architectures */ - feature = (cdb[2] << 8) | cdb[3]; - max_len = (cdb[7] << 8) | cdb[8]; - - /* only feature 0 is supported */ - if ((cdb[2] != 0) || (cdb[3] > 2)) { - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - cdrom_buf_alloc(dev, 65536); - memset(cdbufferb, 0, max_len); - - alloc_length = 0; - b = cdbufferb; - - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (dev->handler->ready(dev->id)) { - len = dev->handler->size(dev->id); - if (len > CD_MAX_SECTORS) { - b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_DVD_ROM & 0xff; - ret = 1; - } else { - b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_CD_ROM & 0xff; - ret = 0; - } - } else - ret = 2; - - alloc_length = 8; - b += 8; - - if ((feature == 0) || ((cdb[1] & 3) < 2)) { - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - alloc_length += 4; - b += 4; - - for (i = 0; i < 2; i++) { - b[0] = (profiles[i] >> 8) & 0xff; - b[1] = profiles[i] & 0xff; - - if (ret == i) - b[2] |= 1; - - alloc_length += 4; - b += 4; - } - } - if ((feature == 1) || ((cdb[1] & 3) < 2)) { - b[1] = 1; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - b[7] = 1; - else - b[7] = 2; - b[8] = 1; - - alloc_length += 12; - b += 12; - } - if ((feature == 2) || ((cdb[1] & 3) < 2)) { - b[1] = 2; - b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 4; - - b[4] = 2; - - alloc_length += 8; - b += 8; - } - - cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; - cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; - cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; - cdbufferb[3] = (alloc_length - 4) & 0xff; - - alloc_length = MIN(alloc_length, max_len); - - cdrom_set_buf_len(dev, BufLen, &alloc_length); - - cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header_t)); - - gesn_cdb = (gesn_cdb_t *) cdb; - gesn_event_header = (gesn_event_header_t *) cdbufferb; - - /* It is fine by the MMC spec to not support async mode operations. */ - if (!(gesn_cdb->polled & 0x01)) { - /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->opc_class & (1 << GESN_MEDIA)) { - gesn_event_header->notification_class |= GESN_MEDIA; - - cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ - cdbufferb[5] = 1; /* Power Status (1 = Active) */ - cdbufferb[6] = 0; - cdbufferb[7] = 0; - used_len = 8; - } else { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = used_len - sizeof(*gesn_event_header); - - memcpy(cdbufferb, gesn_event_header, 4); - - cdrom_set_buf_len(dev, BufLen, &used_len); - - cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); - break; - - case GPCMD_READ_DISC_INFORMATION: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(dev, 65536); - - memset(cdbufferb, 0, 34); - memset(cdbufferb, 1, 9); - cdbufferb[0] = 0; - cdbufferb[1] = 32; - cdbufferb[2] = 0xe; /* last session complete, disc finalized */ - cdbufferb[7] = 0x20; /* unrestricted use */ - cdbufferb[8] = 0x00; /* CD-ROM */ - - len=34; - len = MIN(len, max_len); - - cdrom_set_buf_len(dev, BufLen, &len); - - cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_READ_TRACK_INFORMATION: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(dev, 65536); - - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; - - if (((cdb[1] & 0x03) != 1) || (track != 1)) { - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - len = 36; - - memset(cdbufferb, 0, 36); - cdbufferb[0] = 0; - cdbufferb[1] = 34; - cdbufferb[2] = 1; /* track number (LSB) */ - cdbufferb[3] = 1; /* session number (LSB) */ - cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - cdbufferb[24] = (dev->handler->size(dev->id) >> 24) & 0xff; /* track size */ - cdbufferb[25] = (dev->handler->size(dev->id) >> 16) & 0xff; /* track size */ - cdbufferb[26] = (dev->handler->size(dev->id) >> 8) & 0xff; /* track size */ - cdbufferb[27] = dev->handler->size(dev->id) & 0xff; /* track size */ - - if (len > max_len) { - len = max_len; - cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; - cdbufferb[1] = (max_len - 2) & 0xff; - } - - cdrom_set_buf_len(dev, BufLen, &len); - - cdrom_data_command_finish(dev, len, len, max_len, 0); - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_12: - case GPCMD_PLAY_AUDIO_MSF: - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_PLAY_AUDIO_10: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_12: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - break; - case GPCMD_PLAY_AUDIO_MSF: - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ - msf = 1; - pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - msf = 2; - pos = (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - } - - if ((dev->drv->host_drive < 1) || (dev->cd_status <= CD_STATUS_DATA_ONLY)) { - cdrom_illegal_mode(dev); - break; - } - - if (dev->handler->playaudio) - ret = dev->handler->playaudio(dev->id, pos, len, msf); - else - ret = 0; - - if (ret) - cdrom_command_complete(dev); - else - cdrom_illegal_mode(dev); - break; - - case GPCMD_READ_SUBCHANNEL: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - msf = (cdb[1] >> 1) & 1; - - cdrom_buf_alloc(dev, 32); - - DEBUG("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); - - if (cdb[3] > 3) { - /* DEBUG("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, - cdb[3]); */ - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - - switch(cdb[3]) { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - - memset(cdbufferb, 0, 24); - pos = 0; - cdbufferb[pos++] = 0; - cdbufferb[pos++] = 0; /*Audio status*/ - cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ - cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ - if (cdb[3] == 1) { - cdbufferb[1] = dev->handler->getcurrentsubchannel(dev->id, &cdbufferb[5], msf); - switch(dev->cd_status) { - case CD_STATUS_PLAYING: - cdbufferb[1] = 0x11; - break; - case CD_STATUS_PAUSED: - cdbufferb[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - cdbufferb[1] = 0x15; - break; - default: - cdbufferb[1] = 0x13; - break; - } - } - - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - len = 4; - else - len = alloc_length; - - len = MIN(len, max_len); - cdrom_set_buf_len(dev, BufLen, &len); - - DEBUG("CD-ROM %i: Read subchannel:", dev->id); - for (i = 0; i < 32; i += 8) { - DEBUG("[%02X] %02X %02X %02X %02X %02X %02X %02X %02X\n", i, - cdbufferb[i], cdbufferb[i + 1], cdbufferb[i + 2], cdbufferb[i + 3], - cdbufferb[i + 4], cdbufferb[i + 5], cdbufferb[i + 6], cdbufferb[i + 7]); - } - - cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_READ_DVD_STRUCTURE: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - - cdrom_buf_alloc(dev, alloc_length); - - len = dev->handler->size(dev->id); - - if ((cdb[7] < 0xc0) && (len <= CD_MAX_SECTORS)) { - cdrom_incompatible_format(dev); - cdrom_buf_free(dev); - return; - } - - memset(cdbufferb, 0, alloc_length); - - if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { - if (cdb[1] == 0) { - ret = cdrom_read_dvd_structure(dev, format, cdb, cdbufferb); - if (ret) { - cdrom_set_buf_len(dev, BufLen, &alloc_length); - cdrom_data_command_finish(dev, alloc_length, alloc_length, - len, 0); - } else - cdrom_buf_free(dev); - return; - } - } else { - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - break; - - case GPCMD_START_STOP_UNIT: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - if (dev->handler->stop) - dev->handler->stop(dev->id); - break; - case 1: /* Start the disc and read the TOC. */ - dev->handler->medium_changed(dev->id); /* This causes a TOC reload. */ - break; - case 2: /* Eject the disc if possible. */ - if (dev->handler->stop) - dev->handler->stop(dev->id); - ui_cdrom_eject(dev->id); - break; - case 3: /* Load the disc (close tray). */ - ui_cdrom_reload(dev->id); - break; - } - - cdrom_command_complete(dev); - break; - - case GPCMD_INQUIRY: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - cdrom_buf_alloc(dev, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - cdbufferb[idx++] = 05; - cdbufferb[idx++] = cdb[2]; - cdbufferb[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - cdrom_data_phase_error(dev); - cdrom_buf_free(dev); - return; - } - - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 20; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x01; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 68; - ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - DEBUG("INQUIRY: Invalid page: %02X\n", cdb[2]); - cdrom_invalid_field(dev); - cdrom_buf_free(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(cdbufferb, 0, 8); - cdbufferb[0] = 5; /*CD-ROM*/ - cdbufferb[1] = 0x80; /*Removable*/ - cdbufferb[2] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - cdbufferb[3] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; - cdbufferb[4] = 31; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - cdbufferb[6] = 1; /* 16-bit transfers supported */ - cdbufferb[7] = 0x20; /* Wide bus supported */ - } - - ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ - ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ - idx = 36; - - if (max_len == 96) { - cdbufferb[4] = 91; - idx = 96; - } - } - -atapi_out: - cdbufferb[size_idx] = idx - preamble_len; - len=idx; - - len = MIN(len, max_len); - cdrom_set_buf_len(dev, BufLen, &len); - - cdrom_data_command_finish(dev, len, len, max_len, 0); - break; - - case GPCMD_PREVENT_REMOVAL: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - cdrom_command_complete(dev); - break; - - case GPCMD_PAUSE_RESUME_ALT: - case GPCMD_PAUSE_RESUME: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - if (cdb[8] & 1) { - if (dev->handler->resume) - dev->handler->resume(dev->id); - else { - cdrom_illegal_mode(dev); - break; - } - } else { - if (dev->handler->pause) - dev->handler->pause(dev->id); - else { - cdrom_illegal_mode(dev); - break; - } - } - cdrom_command_complete(dev); - break; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - cdrom_seek(dev, pos); - cdrom_command_complete(dev); - break; - - case GPCMD_READ_CDROM_CAPACITY: - cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - - cdrom_buf_alloc(dev, 8); - - if (cdrom_read_capacity(dev, dev->current_cdb, cdbufferb, (uint32_t *) &len) == 0) { - cdrom_buf_free(dev); - return; - } - - cdrom_set_buf_len(dev, BufLen, &len); - - cdrom_data_command_finish(dev, len, len, len, 0); - break; - - case GPCMD_STOP_PLAY_SCAN: - cdrom_set_phase(dev, SCSI_PHASE_STATUS); - - if (dev->handler->stop) - dev->handler->stop(dev->id); - else { - cdrom_illegal_mode(dev); - break; - } - cdrom_command_complete(dev); - break; - - default: - cdrom_illegal_opcode(dev); - break; - } - - /* DEBUG("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ - - if (cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) - cdrom_buf_free(dev); -} - - -/* The command second phase function, needed for Mode Select. */ -static uint8_t -cdrom_phase_data_out(cdrom_t *dev) -{ - uint16_t block_desc_len, pos; - uint16_t i = 0; - - uint8_t error = 0; - uint8_t page, page_len, hdr_len, val, old_val, ch; - - FILE *f; - - switch(dev->current_cdb[0]) { - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - f = plat_fopen(nvr_path(L"modeselect.bin"), L"wb"); - fwrite(cdbufferb, 1, dev->total_length, f); - fclose(f); - - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; - else - hdr_len = 4; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = cdbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[3]; - } else { - block_desc_len = cdbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[7]; - } - } else - block_desc_len = 0; - - pos = hdr_len + block_desc_len; - - while(1) { - page = cdbufferb[pos] & 0x3F; - page_len = cdbufferb[pos + 1]; - - pos += 2; - - if (!(cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { - DEBUG("Unimplemented page %02X\n", page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = cdrom_mode_sense_pages_changeable.pages[page][i + 2]; - val = cdbufferb[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else { - DEBUG("Unchangeable value on position %02X on page %02X\n", i + 2, page); - error |= 1; - } - } - } - } - - pos += page_len; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; - - if (dev->do_page_save && val) - cdrom_mode_sense_save(dev); - - if (pos >= dev->total_length) - break; - } - - if (error) { - cdrom_invalid_field_pl(dev); - return 0; - } - break; - } - - return 1; -} - - -/* This is the general ATAPI PIO request function. */ -static void -cdrom_pio_request(cdrom_t *dev, uint8_t out) -{ - int ret = 0; - - if (dev->drv->bus_type < CDROM_BUS_SCSI) { - DEBUG("CD-ROM %i: Lowering IDE IRQ\n", dev->id); - ide_irq_lower(ide_drives[dev->drv->ide_channel]); - } - - dev->status = BUSY_STAT; - - if (dev->pos >= dev->packet_len) { - DEBUG("CD-ROM %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); - - dev->pos = dev->request_pos = 0; - if (out) { - ret = cdrom_phase_data_out(dev); - /* If ret = 0 (phase 1 error), then we do not do anything else other than - free the buffer, as the phase and callback have already been set by the - error function. */ - if (ret) - cdrom_command_complete(dev); - } else - cdrom_command_complete(dev); - cdrom_buf_free(dev); - } else { - DEBUG("CD-ROM %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, - out ? "written" : "read", dev->packet_len - dev->pos); - - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) - dev->max_transfer_len = dev->packet_len - dev->pos; - DEBUG("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, - dev->max_transfer_len); - - dev->packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; - - dev->status = BUSY_STAT; - dev->phase = 1; - cdrom_phase_callback(dev); - dev->callback = 0LL; - cdrom_set_callback(dev); - - dev->request_pos = 0; - } -} - - -static int -cdrom_read_from_ide_dma(uint8_t channel) -{ - cdrom_t *dev; - - uint8_t id = atapi_cdrom_drives[channel]; - int ret; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - if (ide_bus_master_write) { - ret = ide_bus_master_write(channel >> 1, - cdbufferb, dev->packet_len, - ide_bus_master_priv[channel >> 1]); - if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ - return 2; - else if (ret == 1) { /* DMA error. */ - cdrom_bus_master_error(dev); - return 0; - } else - return 1; - } else - return 0; return 0; } -static int -cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - cdrom_t *dev; - - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - DEBUG("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - - return 1; -} - - -static void -cdrom_irq_raise(cdrom_t *dev) -{ - if (dev->drv->bus_type < CDROM_BUS_SCSI) - ide_irq_raise(ide_drives[dev->drv->ide_channel]); -} - - -static int -cdrom_read_from_dma(cdrom_t *dev) -{ -#ifdef _LOGGING - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; -#endif - int ret = 0; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - ret = cdrom_read_from_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); - else - ret = cdrom_read_from_ide_dma(dev->drv->ide_channel); - - if (ret != 1) - return ret; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - DEBUG("CD-ROM %i: SCSI Input data length: %i\n", dev->id, *BufLen); - else - DEBUG("CD-ROM %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); - - ret = cdrom_phase_data_out(dev); - - if (ret) - return 1; - else - return 0; -} - - -static int -cdrom_write_to_ide_dma(uint8_t channel) -{ - cdrom_t *dev; - - uint8_t id = atapi_cdrom_drives[channel]; - int ret; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - if (ide_bus_master_read) { - ret = ide_bus_master_read(channel >> 1, - cdbufferb, dev->packet_len, - ide_bus_master_priv[channel >> 1]); - if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ - return 2; - else if (ret == 1) { /* DMA error. */ - cdrom_bus_master_error(dev); - return 0; - } else - return 1; - } else - return 0; -} - - -static int -cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - cdrom_t *dev; - - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - DEBUG("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen); - DEBUG("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], - cdbufferb[6], cdbufferb[7]); - DEBUG("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); - - return 1; -} - - -static int -cdrom_write_to_dma(cdrom_t *dev) -{ -#ifdef _LOGGING - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; -#endif - int ret = 0; - - if (dev->drv->bus_type == CDROM_BUS_SCSI) { - DEBUG("Write to SCSI DMA: (%02X:%02X)\n", dev->drv->scsi_device_id, dev->drv->scsi_device_lun); - ret = cdrom_write_to_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); - } else - ret = cdrom_write_to_ide_dma(dev->drv->ide_channel); - - if (dev->drv->bus_type == CDROM_BUS_SCSI) - DEBUG("CD-ROM %i: SCSI Output data length: %i\n", dev->id, *BufLen); - else - DEBUG("CD-ROM %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); - - return ret; -} - - -void -cdrom_phase_callback(cdrom_t *dev) -{ - int ret; - - switch(dev->packet_status) { - case CDROM_PHASE_IDLE: - DEBUG("CD-ROM %i: CDROM_PHASE_IDLE\n", dev->id); - dev->pos = 0; - dev->phase = 1; - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - return; - case CDROM_PHASE_COMMAND: - DEBUG("CD-ROM %i: CDROM_PHASE_COMMAND\n", dev->id); - dev->status = BUSY_STAT | (dev->status & ERR_STAT); - memcpy(dev->atapi_cdb, cdbufferb, dev->cdb_len); - cdrom_command(dev, dev->atapi_cdb); - return; - case CDROM_PHASE_COMPLETE: - DEBUG("CD-ROM %i: CDROM_PHASE_COMPLETE\n", dev->id); - dev->status = READY_STAT; - dev->phase = 3; - dev->packet_status = 0xFF; - ui_sb_icon_update(SB_CDROM | dev->id, 0); - cdrom_irq_raise(dev); - return; - case CDROM_PHASE_DATA_OUT: - DEBUG("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", dev->id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 0; - cdrom_irq_raise(dev); - return; - case CDROM_PHASE_DATA_OUT_DMA: - DEBUG("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", dev->id); - ret = cdrom_read_from_dma(dev); - - if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { - DEBUG("CD-ROM %i: DMA data out phase done\n", dev->id); - cdrom_buf_free(dev); - cdrom_command_complete(dev); - } else if (ret == 2) { - DEBUG("CD-ROM %i: DMA out not enabled, wait\n", dev->id); - cdrom_command_bus(dev); - } else { - DEBUG("CD-ROM %i: DMA data out phase failure\n", dev->id); - cdrom_buf_free(dev); - } - return; - case CDROM_PHASE_DATA_IN: - DEBUG("CD-ROM %i: CDROM_PHASE_DATA_IN\n", dev->id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 2; - cdrom_irq_raise(dev); - return; - case CDROM_PHASE_DATA_IN_DMA: - DEBUG("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", dev->id); - ret = cdrom_write_to_dma(dev); - - if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { - DEBUG("CD-ROM %i: DMA data in phase done\n"); - cdrom_buf_free(dev); - cdrom_command_complete(dev); - } else if (ret == 2) { - DEBUG("CD-ROM %i: DMA in not enabled, wait\n"); - cdrom_command_bus(dev); - } else { - DEBUG("CD-ROM %i: DMA data in phase failure\n"); - cdrom_buf_free(dev); - } - return; - case CDROM_PHASE_ERROR: - DEBUG("CD-ROM %i: CDROM_PHASE_ERROR\n", dev->id); - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - cdrom_irq_raise(dev); - ui_sb_icon_update(SB_CDROM | dev->id, 0); - return; - } -} - - -uint32_t -cdrom_read(uint8_t channel, int length) -{ - cdrom_t *dev; - - uint16_t *cdbufferw; - uint32_t *cdbufferl; - - uint8_t id = atapi_cdrom_drives[channel]; - - uint32_t temp = 0; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; - - if (!cdbufferb) - return 0; - - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ - switch(length) { - case 1: - temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; - dev->pos++; - dev->request_pos++; - break; - case 2: - temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return 0; - } - - if (dev->packet_status == CDROM_PHASE_DATA_IN) { - DEBUG("CD-ROM %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", - id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - DEBUG("CD-ROM %i: Issuing read callback\n", id); - cdrom_pio_request(dev, 0); - } - return temp; - } else { - DEBUG("CD-ROM %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", - id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); - return 0; - } -} - - -void -cdrom_write(uint8_t channel, uint32_t val, int length) -{ - cdrom_t *dev; - - uint16_t *cdbufferw; - uint32_t *cdbufferl; - - uint8_t id = atapi_cdrom_drives[channel]; - - if (id > CDROM_NUM) - return; - - dev = cdrom[id]; - - if ((dev->packet_status == CDROM_PHASE_IDLE) && !cdbufferb) - cdrom_buf_alloc(dev, dev->cdb_len); - - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; - - if (!cdbufferb) - return; - - switch(length) { - case 1: - cdbufferb[dev->pos] = val & 0xff; - dev->pos++; - dev->request_pos++; - break; - case 2: - cdbufferw[dev->pos >> 1] = val & 0xffff; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - cdbufferl[dev->pos >> 2] = val; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return; - } - - if (dev->packet_status == CDROM_PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - cdrom_pio_request(dev, 1); - } - return; - } else if (dev->packet_status == CDROM_PHASE_IDLE) { - if (dev->pos >= dev->cdb_len) { - dev->pos = 0; - dev->status = BUSY_STAT; - dev->packet_status = CDROM_PHASE_COMMAND; - timer_process(); - cdrom_phase_callback(dev); - timer_update_outstanding(); - } - return; - } -} - - /* Peform a master init on the entire module. */ void cdrom_global_init(void) { /* Clear the global data. */ +//FIXME: allocate these on the heap.. memset(cdrom, 0x00, sizeof(cdrom)); - memset(cdrom_drives, 0x00, sizeof(cdrom_drives)); +} + + +static void +cdrom_drive_reset(cdrom_t *dev) +{ + dev->p = NULL; + dev->insert = NULL; + dev->close = NULL; + dev->get_volume = NULL; + dev->get_channel = NULL; } void cdrom_hard_reset(void) { - int c; cdrom_t *dev; + int i; - for (c = 0; c < CDROM_NUM; c++) { - if (cdrom_drives[c].bus_type) { - DEBUG("CDROM hard_reset drive=%d host=%02x\n", c, cdrom_drives[c].host_drive); + for (i = 0; i < CDROM_NUM; i++) { + dev = &cdrom[i]; + if (dev->bus_type) { + DEBUG("CDROM %i: hard_reset\n", i); - if (!cdrom[c]) { - cdrom[c] = (cdrom_t *) mem_alloc(sizeof(cdrom_t)); - memset(cdrom[c], 0, sizeof(cdrom_t)); + dev->id = i; + + cdrom_drive_reset(dev); + + switch(dev->bus_type) { + case CDROM_BUS_ATAPI: + case CDROM_BUS_SCSI: + scsi_cdrom_drive_reset(i); + break; + + default: + break; } - dev = cdrom[c]; - /* Set the numerical ID because of ->handler and logging. */ - dev->id = c; - - cdrom_init(dev); - - if (dev->drv->host_drive == 200) { - image_open(c, cdrom_image[c].image_path); - image_reset(c); + if (dev->host_drive == 200) { + cdrom_image_open(dev, dev->image_path); + cdrom_image_reset(dev); } else - cdrom_null_open(c); + cdrom_null_open(dev); } } - build_atapi_cdrom_map(); - sound_cd_stop(); } @@ -3288,16 +209,22 @@ cdrom_hard_reset(void) void cdrom_close_handler(uint8_t id) { - cdrom_t *dev = cdrom[id]; + cdrom_t *dev = &cdrom[id]; - switch (dev->drv->host_drive) { + if (! dev) + return; + + switch (dev->host_drive) { case 200: - image_close(id); + cdrom_image_close(dev); break; + default: - null_close(id); + null_close(dev); break; } + + dev->ops = NULL; } @@ -3305,18 +232,117 @@ void cdrom_close(void) { cdrom_t *dev; - int c; + int i; - for (c = 0; c < CDROM_NUM; c++) { - dev = cdrom[c]; + for (i = 0; i < CDROM_NUM; i++) { + dev = &cdrom[i]; - if (dev) { - if (dev->drv && dev->handler) - cdrom_close_handler(c); + if (dev->ops) + cdrom_close_handler(i); - free(cdrom[c]); - cdrom[c] = NULL; + if (dev->close) + dev->close(dev->p); + + cdrom_drive_reset(dev); + } +} + + +/* Signal disc change to the emulated machine. */ +void +cdrom_insert(uint8_t id) +{ + cdrom_t *dev = &cdrom[id]; + + if (dev->bus_type) { + if (dev->insert) + dev->insert(dev->p); + } +} + + +/* The mechanics of ejecting a CD-ROM from a drive. */ +void +cdrom_eject(uint8_t id) +{ + cdrom_t *dev = &cdrom[id]; + + /* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */ + if (dev->host_drive == 0) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + if ((dev->host_drive >= 'A') && (dev->host_drive <= 'Z')) { + ui_sb_menu_set_item(SB_CDROM | id, + IDM_CDROM_HOST_DRIVE | id | ((dev->host_drive - 'A') << 3), 0); + } + + if (dev->prev_image_path) { + free(dev->prev_image_path); + dev->prev_image_path = NULL; + } + + if (dev->host_drive == 200) { + dev->prev_image_path = (wchar_t *)mem_alloc(1024); + wcscpy(dev->prev_image_path, dev->image_path); + } + + dev->prev_host_drive = dev->host_drive; + dev->host_drive = 0; + + dev->ops->exit(dev); + cdrom_close_handler(id); + memset(dev->image_path, 0, sizeof(dev->image_path)); + cdrom_null_open(dev); + + cdrom_insert(id); +} + + +/* The mechanics of re-loading a CD-ROM drive. */ +void +cdrom_reload(uint8_t id) +{ + cdrom_t *dev = &cdrom[id]; +#ifdef USE_CDROM_IOCTL + int new_cdrom_drive; +#endif + + if ((dev->host_drive == dev->prev_host_drive) || + (dev->prev_host_drive == 0) || (dev->host_drive != 0)) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + cdrom_close_handler(id); + memset(dev->image_path, 0, sizeof(dev->image_path)); + + if (dev->prev_host_drive == 200) { + /* Reload a previous image. */ + wcscpy(dev->image_path, dev->prev_image_path); + free(dev->prev_image_path); + dev->prev_image_path = NULL; + cdrom_image_open(dev, dev->image_path); + + cdrom_insert(id); + + if (wcslen(dev->image_path) == 0) + dev->host_drive = 0; + else + dev->host_drive = 200; +#ifdef USE_CDROM_IOCTL + } else { + /* Reload the previous host drive. */ + new_cdrom_drive = dev->prev_host_drive; + ioctl_open(id, new_cdrom_drive); + if (dev->bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(dev); } + + dev->new_cdrom_drive; +#endif } } diff --git a/src/devices/cdrom/cdrom.h b/src/devices/cdrom/cdrom.h index a8195fe..5668822 100644 --- a/src/devices/cdrom/cdrom.h +++ b/src/devices/cdrom/cdrom.h @@ -8,15 +8,13 @@ * * Definitions for the CDROM module.. * - * Version: @(#)cdrom.h 1.0.11 2018/09/19 + * Version: @(#)cdrom.h 1.0.12 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,10 +38,6 @@ #define EMU_CDROM_H -#ifdef __cplusplus -extern "C" { -#endif - #define CDROM_NUM 4 #define CDROM_SPEED_DEFAULT 8 @@ -55,21 +49,14 @@ extern "C" { #define CD_STATUS_PAUSED 3 #define CD_STATUS_STOPPED 4 -#define CDROM_PHASE_IDLE 0x00 -#define CDROM_PHASE_COMMAND 0x01 -#define CDROM_PHASE_COMPLETE 0x02 -#define CDROM_PHASE_DATA_IN 0x03 -#define CDROM_PHASE_DATA_IN_DMA 0x04 -#define CDROM_PHASE_DATA_OUT 0x05 -#define CDROM_PHASE_DATA_OUT_DMA 0x06 -#define CDROM_PHASE_ERROR 0x80 - #define BUF_SIZE 32768 #define CDROM_IMAGE 200 -#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) +#ifdef __cplusplus +extern "C" { +#endif enum { CDROM_BUS_DISABLED = 0, @@ -80,102 +67,74 @@ enum { #define CDROM_BUS_MAX (CDROM_BUS_USB) /* USB exclusive */ +/* Define the various CD-ROM drive operations (ops). */ typedef struct { - int (*ready)(uint8_t id); - int (*medium_changed)(uint8_t id); - int (*media_type_id)(uint8_t id); + int (*ready)(struct cdrom *dev); + int (*medium_changed)(struct cdrom *dev); + int (*media_type_id)(struct cdrom *dev); - int (*audio_callback)(uint8_t id, int16_t *output, int len); - void (*audio_stop)(uint8_t id); - int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); - int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); - int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); - uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); - int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); - uint8_t (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); - void (*pause)(uint8_t id); - void (*resume)(uint8_t id); - uint32_t (*size)(uint8_t id); - int (*status)(uint8_t id); - void (*stop)(uint8_t id); - void (*exit)(uint8_t id); -} CDROM; + int (*audio_callback)(struct cdrom *dev, int16_t *output, int len); + void (*audio_stop)(struct cdrom *dev); + int (*readtoc)(struct cdrom *dev, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); + int (*readtoc_session)(struct cdrom *dev, uint8_t *b, int msf, int maxlen); + int (*readtoc_raw)(struct cdrom *dev, uint8_t *b, int maxlen); + uint8_t (*getcurrentsubchannel)(struct cdrom *dev, uint8_t *b, int msf); + int (*readsector_raw)(struct cdrom *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); + uint8_t (*playaudio)(struct cdrom *dev, uint32_t pos, uint32_t len, int ismsf); + void (*pause)(struct cdrom *dev); + void (*resume)(struct cdrom *dev); + uint32_t (*size)(struct cdrom *dev); + int (*status)(struct cdrom *dev); + void (*stop)(struct cdrom *dev); + void (*exit)(struct cdrom *dev); +} cdrom_ops_t; -typedef struct { - int host_drive, - prev_host_drive; +/* Define the generic CD-ROM drive. */ +typedef struct cdrom { + int id; + uint8_t speed_idx, /* default speed [index] */ + cur_speed; /* currently set speed [index] */ int8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ bus_mode, /* Bit 0 = PIO suported; - Bit 1 = DMA supportd. */ - sound_on, - speed_idx; + * Bit 1 = DMA supportd. */ + sound_on; -#if 0 union { - int ide_channel; - struct { - int8_t id; - int8_t lun; + uint8_t ide_channel; /* IDE drive: channel (0/1) */ + struct { /* SCSI drive: ID and LUN */ + int8_t id; + int8_t lun; } scsi; - } id; -#else - int ide_channel; - int8_t scsi_device_id, - scsi_device_lun; -#endif -} cdrom_drive_t; + } bus_id; -typedef struct { - mode_sense_pages_t ms_pages_saved; + FILE *img_fp; + int img_is_iso; + int host_drive, prev_host_drive; - CDROM *handler; - cdrom_drive_t *drv; + int cd_status, prev_status, + cd_buflen, cd_state; - uint8_t previous_command, - error, features, - status, phase, - id, *buffer, - atapi_cdb[16], - current_cdb[16], - sense[256]; + uint32_t seek_pos, seek_diff, + cd_end, + cdrom_capacity; - uint16_t request_length, max_transfer_len; - int16_t cd_buffer[BUF_SIZE]; + const cdrom_ops_t *ops; /* device ops */ - int media_status, is_dma, - packet_status, requested_blocks, - current_page_len, current_page_pos, - mode_select_phase, do_page_save, - total_length, written_length, - data_pos, - cd_status, prev_status, - unit_attention, request_pos, - total_read, cur_speed, - block_total, all_blocks_total, - old_len, block_descriptor_len, - init_length, last_subchannel_pos, - cd_buflen, cd_state, - handler_inited, disc_changed; + void *image; /* opaque image data */ - uint32_t sector_pos, sector_len, - seek_pos, seek_diff, - pos, packet_len, - cdb_len, cd_end, - cdrom_capacity; + void *p; - uint64_t current_page_code; - - int64_t callback; -} cdrom_t; - -typedef struct { - int image_is_iso; - FILE *image; + void (*insert)(void *p); + void (*close)(void *p); + uint32_t (*get_volume)(void *p, int channel); + uint32_t (*get_channel)(void *p, int channel); wchar_t image_path[1024], *prev_image_path; -} cdrom_image_t; + + int16_t cd_buffer[BUF_SIZE]; +} cdrom_t; typedef struct { int speed; @@ -186,55 +145,38 @@ typedef struct { extern const cdrom_speed_t cdrom_speeds[]; -extern cdrom_t *cdrom[CDROM_NUM]; -extern cdrom_drive_t cdrom_drives[CDROM_NUM]; -extern cdrom_image_t cdrom_image[CDROM_NUM]; -extern uint8_t atapi_cdrom_drives[8]; -extern uint8_t scsi_cdrom_drives[16][8]; +extern cdrom_t cdrom[CDROM_NUM]; -#define cdrom_sense_error dev->sense[0] -#define cdrom_sense_key dev->sense[2] -#define cdrom_asc dev->sense[12] -#define cdrom_ascq dev->sense[13] -#define cdrom_drive cdrom_drives[id].host_drive +extern void cdrom_log(int level, const char *fmt, ...); +extern int cdrom_speed_idx(int realspeed); -extern void cdrom_log(int level, const char *fmt, ...); -extern int cdrom_speed_idx(int realspeed); +extern int cdrom_string_to_bus(const char *str); +extern const char *cdrom_bus_to_string(int bus); -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); -extern void (*ide_bus_master_set_irq)(int channel, void *priv); -extern void *ide_bus_master_priv[2]; +extern int cdrom_lba_to_msf_accurate(int lba); +extern double cdrom_seek_time(cdrom_t *dev); +extern void cdrom_seek(cdrom_t *dev, uint32_t pos); +extern int cdrom_playing_completed(cdrom_t *dev); -extern uint32_t cdrom_mode_sense_get_channel(cdrom_t *dev, int channel); -extern uint32_t cdrom_mode_sense_get_volume(cdrom_t *dev, int channel); -extern void build_atapi_cdrom_map(void); -extern void build_scsi_cdrom_map(void); -extern int cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev); -extern int cdrom_atapi_phase_to_scsi(cdrom_t *dev); -extern void cdrom_command(cdrom_t *dev, uint8_t *cdb); -extern void cdrom_phase_callback(cdrom_t *dev); -extern uint32_t cdrom_read(uint8_t channel, int length); -extern void cdrom_write(uint8_t channel, uint32_t val, int length); +extern void cdrom_close_handler(uint8_t id); +extern void cdrom_insert(uint8_t id); +extern void cdrom_eject(uint8_t id); +extern void cdrom_reload(uint8_t id); -extern int cdrom_lba_to_msf_accurate(int lba); +extern int cdrom_image_open(cdrom_t *dev, const wchar_t *fn); +extern void cdrom_image_close(cdrom_t *dev); +extern void cdrom_image_reset(cdrom_t *dev); -extern void cdrom_close_handler(uint8_t id); -extern void cdrom_close(void); -extern void cdrom_reset(cdrom_t *dev); -extern void cdrom_set_signature(cdrom_t *dev); -extern void cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length); -extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -extern void cdrom_insert(cdrom_t *dev); +extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, + int number_of_blocks); -extern int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int find_cdrom_for_scsi_id(uint8_t scsi_id); -extern void cdrom_global_init(void); -extern void cdrom_global_reset(void); -extern void cdrom_hard_reset(void); -extern int cdrom_string_to_bus(const char *str); -extern const char *cdrom_bus_to_string(int bus); +extern void cdrom_close(void); +extern void cdrom_global_init(void); +extern void cdrom_global_reset(void); +extern void cdrom_hard_reset(void); +extern void scsi_cdrom_drive_reset(int c); #ifdef __cplusplus } diff --git a/src/devices/cdrom/cdrom_image.cpp b/src/devices/cdrom/cdrom_image.cpp index fb2d818..cbd0b5c 100644 --- a/src/devices/cdrom/cdrom_image.cpp +++ b/src/devices/cdrom/cdrom_image.cpp @@ -8,7 +8,7 @@ * * CD-ROM image support. * - * Version: @(#)cdrom_image.cpp 1.0.10 2018/10/05 + * Version: @(#)cdrom_image.cpp 1.0.11 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,7 +48,6 @@ #define dbglog cdrom_image_log #include "../../emu.h" #include "../../plat.h" -#include "../scsi/scsi_device.h" #include "cdrom.h" #include "cdrom_image.h" #include "cdrom_dosbox.h" @@ -61,14 +60,14 @@ int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; void -cdrom_image_log(int level, const char *format, ...) +cdrom_image_log(int level, const char *fmt, ...) { #ifdef ENABLE_CDROM_IMAGE_LOG va_list ap; if (cdrom_image_do_log >= level) { - va_start(ap, format); - pclog_ex(format, ap); + va_start(ap, fmt); + pclog_ex(fmt, ap); va_end(ap); } #endif @@ -87,7 +86,6 @@ cdrom_image_log(int level, const char *format, ...) of the audio while audio still plays. With an absolute conversion, the counter is fine. */ #define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) -extern CDROM image_cdrom; #pragma pack(push,1) typedef struct { @@ -132,12 +130,6 @@ typedef union { #pragma pack(pop) -sector_buffer_t cdrom_sector_buffer; - -int cdrom_sector_size; -uint8_t raw_buffer[2448]; -uint8_t extra_buffer[296]; - enum { CD_STOPPED = 0, CD_PLAYING, @@ -145,30 +137,31 @@ enum { }; -static CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL }; -static char afn[1024]; - -void image_close(uint8_t id); +static int cdrom_sector_size; +static uint8_t raw_buffer[2448]; +static uint8_t extra_buffer[296]; -int -image_audio_callback(uint8_t id, int16_t *output, int len) +static int +audio_callback(cdrom_t *dev, int16_t *output, int len) { - cdrom_t *dev = cdrom[id]; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int ret = 1; - if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) { - DEBUG("image_audio_callback(i): Not playing\n", id); + if (!dev->sound_on || (dev->cd_state != CD_PLAYING) || dev->img_is_iso) { + DEBUG("image_audio_callback(i): Not playing\n", dev->id); if (dev->cd_state == CD_PLAYING) dev->seek_pos += (len >> 11); memset(output, 0, len * 2); return 0; } + while (dev->cd_buflen < len) { if (dev->seek_pos < dev->cd_end) { - if (!cdimg[id]->ReadSector((unsigned char*)&dev->cd_buffer[dev->cd_buflen], true, - dev->seek_pos)) { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + if (!img->ReadSector((uint8_t *)&dev->cd_buffer[dev->cd_buflen], + true, dev->seek_pos)) { + memset(&dev->cd_buffer[dev->cd_buflen], + 0x00, (BUF_SIZE - dev->cd_buflen) * 2); dev->cd_state = CD_STOPPED; dev->cd_buflen = len; ret = 0; @@ -178,7 +171,8 @@ image_audio_callback(uint8_t id, int16_t *output, int len) ret = 1; } } else { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + memset(&dev->cd_buffer[dev->cd_buflen], + 0x00, (BUF_SIZE - dev->cd_buflen) * 2); dev->cd_state = CD_STOPPED; dev->cd_buflen = len; ret = 0; @@ -188,30 +182,30 @@ image_audio_callback(uint8_t id, int16_t *output, int len) memcpy(output, dev->cd_buffer, len * 2); memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); dev->cd_buflen -= len; + return ret; } -void -image_audio_stop(uint8_t id) +static void +audio_stop(cdrom_t *dev) /* audio_stop */ { - cdrom_t *dev = cdrom[id]; - dev->cd_state = CD_STOPPED; } static uint8_t -image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) +audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf) { - cdrom_t *dev = cdrom[id]; - if (!cdimg[id]) - return 0; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int number; - unsigned char attr; + uint8_t attr; TMSF tmsf; int m = 0, s = 0, f = 0; - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + + if (!img) return 0; + + img->GetAudioTrackInfo(img->GetTrack(pos), number, tmsf, attr); if (attr == DATA_TRACK) { DEBUG("Can't play data track\n"); dev->seek_pos = 0; @@ -221,9 +215,9 @@ image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) DEBUG("Play audio - %08X %08X %i\n", pos, len, ismsf); if (ismsf == 2) { - cdimg[id]->GetAudioTrackInfo(pos, number, tmsf, attr); + img->GetAudioTrackInfo(pos, number, tmsf, attr); pos = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - cdimg[id]->GetAudioTrackInfo(len, number, tmsf, attr); + img->GetAudioTrackInfo(len, number, tmsf, attr); len = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; } else if (ismsf == 1) { m = (pos >> 16) & 0xff; @@ -250,8 +244,8 @@ image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) len += pos; } - dev->seek_pos = pos; - dev->cd_end = len; + dev->seek_pos = pos; + dev->cd_end = len; dev->cd_state = CD_PLAYING; dev->cd_buflen = 0; @@ -260,43 +254,35 @@ image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) static void -image_pause(uint8_t id) +audio_pause(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if (!img || dev->img_is_iso) return; - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; if (dev->cd_state == CD_PLAYING) dev->cd_state = CD_PAUSED; } static void -image_resume(uint8_t id) +audio_resume(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if (!img || dev->img_is_iso) return; - if (!cdimg[id] || cdrom_image[id].image_is_iso) - return; if (dev->cd_state == CD_PAUSED) dev->cd_state = CD_PLAYING; } -static void -image_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) - return; - dev->cd_state = CD_STOPPED; -} - - static int -image_ready(uint8_t id) +image_ready(cdrom_t *dev) { - if (!cdimg[id] || (wcslen(cdrom_image[id].image_path) == 0)) + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if (!img || (wcslen(dev->image_path) == 0)) return 0; return 1; @@ -304,32 +290,33 @@ image_ready(uint8_t id) static int -image_get_last_block(uint8_t id) +image_get_last_block(cdrom_t *dev) { + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int first_track, last_track; int number, c; unsigned char attr; TMSF tmsf; - uint32_t lb=0; + uint32_t lb = 0; + uint32_t address; - if (!cdimg[id]) - return 0; + if (!img) return 0; - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + img->GetAudioTracks(first_track, last_track, tmsf); for (c = 0; c <= last_track; c++) { - uint32_t address; - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + img->GetAudioTrackInfo(c+1, number, tmsf, attr); address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ if (address > lb) lb = address; } + return lb; } static int -image_medium_changed(UNUSED(uint8_t id)) +image_medium_changed(UNUSED(cdrom_t *dev)) { /* There is no way to change the medium within an already mounted image. */ return 0; @@ -337,23 +324,21 @@ image_medium_changed(UNUSED(uint8_t id)) static uint8_t -image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) +image_getcurrentsubchannel(cdrom_t *dev, uint8_t *b, int msf) { - cdrom_t *dev = cdrom[id]; - uint8_t ret; - int pos = 0; - uint32_t cdpos; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + uint8_t attr, track, index, ret; TMSF relPos, absPos; - unsigned char attr, track, index; + uint32_t cdpos; + int pos = 0; cdpos = dev->seek_pos; - if (!cdimg[id]) - return 0; + if (!img) return 0; - cdimg[id]->GetAudioSub(cdpos, attr, track, index, relPos, absPos); + img->GetAudioSub(cdpos, attr, track, index, relPos, absPos); - if (cdrom_image[id].image_is_iso) + if (dev->img_is_iso) ret = 0x15; else { if (dev->cd_state == CD_PLAYING) @@ -369,14 +354,14 @@ image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) b[pos++] = index; if (msf) { - b[pos + 3] = (uint8_t) absPos.fr; - b[pos + 2] = (uint8_t) absPos.sec; - b[pos + 1] = (uint8_t) absPos.min; + b[pos + 3] = (uint8_t)absPos.fr; + b[pos + 2] = (uint8_t)absPos.sec; + b[pos + 1] = (uint8_t)absPos.min; b[pos] = 0; pos += 4; - b[pos + 3] = (uint8_t) relPos.fr; - b[pos + 2] = (uint8_t) relPos.sec; - b[pos + 1] = (uint8_t) relPos.min; + b[pos + 3] = (uint8_t)relPos.fr; + b[pos + 2] = (uint8_t)relPos.sec; + b[pos + 1] = (uint8_t)relPos.min; b[pos] = 0; pos += 4; } else { @@ -397,15 +382,15 @@ image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) static int -image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) +image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf) { - int m, s, f; - unsigned char attr; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + uint8_t attr; TMSF tmsf; + int m, s, f; int number; - if (!cdimg[id] || cdrom_image[id].image_is_iso) - return 0; + if (!img || dev->img_is_iso) return 0; if (ismsf) { m = (pos >> 16) & 0xff; @@ -415,7 +400,7 @@ image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) } /* GetTrack requires LBA. */ - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + img->GetAudioTrackInfo(img->GetTrack(pos), number, tmsf, attr); return attr == AUDIO_TRACK; } @@ -472,11 +457,12 @@ is_legal(UNUSED(int id), int type, int flags, int audio, int mode2) static void -read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int len) +read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len) { - uint8_t *bb = raw_buffer; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + uint8_t *bb = rbuf; - cdimg[id]->ReadSector(raw_buffer + 16, false, lba); + img->ReadSector(rbuf + 16, false, lba); /* Sync bytes */ bb[0] = 0; @@ -500,39 +486,44 @@ read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lb static void -read_audio(int id, uint32_t lba, uint8_t *b) +read_audio(cdrom_t *dev, uint32_t lba, uint8_t *b) { - if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if (img->GetSectorSize(lba) == 2352) + img->ReadSector(raw_buffer, true, lba); else - cdimg[id]->ReadSectorSub(raw_buffer, lba); + img->ReadSectorSub(raw_buffer, lba); memcpy(b, raw_buffer, 2352); + cdrom_sector_size = 2352; } static void -read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +read_mode1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if ((dev->img_is_iso) || (img->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + else if (img->GetSectorSize(lba) == 2352) + img->ReadSector(raw_buffer, true, lba); else - cdimg[id]->ReadSectorSub(raw_buffer, lba); + img->ReadSectorSub(raw_buffer, lba); cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ - DEBUG("CD-ROM %i: [Mode 1] Sync\n", id); + DEBUG("CD-ROM %i: [Mode 1] Sync\n", dev->id); memcpy(b, raw_buffer, 12); cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ - DEBUG("CD-ROM %i: [Mode 1] Header\n", id); + DEBUG("CD-ROM %i: [Mode 1] Header\n", dev->id); memcpy(b, raw_buffer + 12, 4); cdrom_sector_size += 4; b += 4; @@ -540,7 +531,7 @@ read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2 if (cdrom_sector_flags & 0x40) { /* Sub-header */ if (!(cdrom_sector_flags & 0x10)) { /* No user data */ - DEBUG("CD-ROM %i: [Mode 1] Sub-header\n", id); + DEBUG("CD-ROM %i: [Mode 1] Sub-header\n", dev->id); memcpy(b, raw_buffer + 16, 8); cdrom_sector_size += 8; b += 8; @@ -548,14 +539,14 @@ read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2 } if (cdrom_sector_flags & 0x10) { /* User data */ - DEBUG("CD-ROM %i: [Mode 1] User data\n", id); + DEBUG("CD-ROM %i: [Mode 1] User data\n", dev->id); memcpy(b, raw_buffer + 16, 2048); cdrom_sector_size += 2048; b += 2048; } if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - DEBUG("CD-ROM %i: [Mode 1] EDC/ECC\n", id); + DEBUG("CD-ROM %i: [Mode 1] EDC/ECC\n", dev->id); memcpy(b, raw_buffer + 2064, 288); cdrom_sector_size += 288; b += 288; @@ -564,26 +555,28 @@ read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2 static void -read_mode2_non_xa(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +read_mode2_non_xa(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2336); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if ((dev->img_is_iso) || (img->GetSectorSize(lba) == 2336)) + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2336); + else if (img->GetSectorSize(lba) == 2352) + img->ReadSector(raw_buffer, true, lba); else - cdimg[id]->ReadSectorSub(raw_buffer, lba); + img->ReadSectorSub(raw_buffer, lba); cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ - DEBUG("CD-ROM %i: [Mode 2 Formless] Sync\n", id); + DEBUG("CD-ROM %i: [Mode 2 Formless] Sync\n", dev->id); memcpy(b, raw_buffer, 12); cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ - DEBUG("CD-ROM %i: [Mode 2 Formless] Header\n", id); + DEBUG("CD-ROM %i: [Mode 2 Formless] Header\n", dev->id); memcpy(b, raw_buffer + 12, 4); cdrom_sector_size += 4; b += 4; @@ -591,14 +584,14 @@ read_mode2_non_xa(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, in /* Mode 1 sector, expected type is 1 type. */ if (cdrom_sector_flags & 0x40) { /* Sub-header */ - DEBUG("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id); + DEBUG("CD-ROM %i: [Mode 2 Formless] Sub-header\n", dev->id); memcpy(b, raw_buffer + 16, 8); cdrom_sector_size += 8; b += 8; } if (cdrom_sector_flags & 0x10) { /* User data */ - DEBUG("CD-ROM %i: [Mode 2 Formless] User data\n", id); + DEBUG("CD-ROM %i: [Mode 2 Formless] User data\n", dev->id); memcpy(b, raw_buffer + 24, 2336); cdrom_sector_size += 2336; b += 2336; @@ -607,47 +600,49 @@ read_mode2_non_xa(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, in static void -read_mode2_xa_form1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +read_mode2_xa_form1(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if ((dev->img_is_iso) || (img->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2048); + else if (img->GetSectorSize(lba) == 2352) + img->ReadSector(raw_buffer, true, lba); else - cdimg[id]->ReadSectorSub(raw_buffer, lba); + img->ReadSectorSub(raw_buffer, lba); cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", dev->id); memcpy(b, raw_buffer, 12); cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Header\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Header\n", dev->id); memcpy(b, raw_buffer + 12, 4); cdrom_sector_size += 4; b += 4; } if (cdrom_sector_flags & 0x40) { /* Sub-header */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", dev->id); memcpy(b, raw_buffer + 16, 8); cdrom_sector_size += 8; b += 8; } if (cdrom_sector_flags & 0x10) { /* User data */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] User data\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] User data\n", dev->id); memcpy(b, raw_buffer + 24, 2048); cdrom_sector_size += 2048; b += 2048; } if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", dev->id); memcpy(b, raw_buffer + 2072, 280); cdrom_sector_size += 280; b += 280; @@ -656,40 +651,42 @@ read_mode2_xa_form1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, static void -read_mode2_xa_form2(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +read_mode2_xa_form2(cdrom_t *dev, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) { - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2324); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; + + if ((dev->img_is_iso) || (img->GetSectorSize(lba) == 2324)) + read_sector_to_buffer(dev, raw_buffer, msf, lba, mode2, 2324); + else if (img->GetSectorSize(lba) == 2352) + img->ReadSector(raw_buffer, true, lba); else - cdimg[id]->ReadSectorSub(raw_buffer, lba); + img->ReadSectorSub(raw_buffer, lba); cdrom_sector_size = 0; if (cdrom_sector_flags & 0x80) { /* Sync */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", dev->id); memcpy(b, raw_buffer, 12); cdrom_sector_size += 12; b += 12; } if (cdrom_sector_flags & 0x20) { /* Header */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Header\n", dev->id); memcpy(b, raw_buffer + 12, 4); cdrom_sector_size += 4; b += 4; } if (cdrom_sector_flags & 0x40) { /* Sub-header */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", dev->id); memcpy(b, raw_buffer + 16, 8); cdrom_sector_size += 8; b += 8; } if (cdrom_sector_flags & 0x10) { /* User data */ - DEBUG("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] User data\n", dev->id); memcpy(b, raw_buffer + 24, 2328); cdrom_sector_size += 2328; b += 2328; @@ -698,19 +695,16 @@ read_mode2_xa_form2(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, static int -image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, +image_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; uint8_t *b, *temp_b; uint32_t msf, lba; int audio, mode2; int m, s, f; - if (!cdimg[id]) - return 0; - - if (!cdrom_drives[id].host_drive) - return 0; + if (!img || !dev->host_drive) return 0; b = temp_b = buffer; @@ -727,122 +721,122 @@ image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdr msf = cdrom_lba_to_msf_accurate(sector); } - if (cdrom_image[id].image_is_iso) { + if (dev->img_is_iso) { audio = 0; - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + mode2 = img->IsMode2(lba) ? 1 : 0; } else { - audio = image_is_track_audio(id, sector, ismsf); - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + audio = image_is_track_audio(dev, sector, ismsf); + mode2 = img->IsMode2(lba) ? 1 : 0; } mode2 <<= 2; - mode2 |= cdimg[id]->GetMode2Form(lba); + mode2 |= img->GetMode2Form(lba); memset(raw_buffer, 0, 2448); memset(extra_buffer, 0, 296); if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */ - DEBUG("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", id); + DEBUG("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", dev->id); return 0; } - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) + if (!is_legal(dev->id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) return 0; if ((cdrom_sector_type == 3) || ((cdrom_sector_type > 4) && (cdrom_sector_type != 8))) { if (cdrom_sector_type == 3) { - DEBUG("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", id); + DEBUG("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", dev->id); } if (cdrom_sector_type > 4) { - DEBUG("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", id); + DEBUG("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", dev->id); } return 0; } else if (cdrom_sector_type == 1) { - if (!audio || cdrom_image[id].image_is_iso) { - DEBUG("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", id); + if (!audio || dev->img_is_iso) { + DEBUG("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", dev->id); return 0; } - read_audio(id, lba, temp_b); + read_audio(dev, lba, temp_b); } else if (cdrom_sector_type == 2) { if (audio || mode2) { - DEBUG("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id); + DEBUG("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 3) { if (audio || !mode2 || (mode2 & 0x03)) { - DEBUG("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id); + DEBUG("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 4) { if (audio || !mode2 || ((mode2 & 0x03) != 1)) { - DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 5) { if (audio || !mode2 || ((mode2 & 0x03) != 2)) { - DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id); + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", dev->id); return 0; } - read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else if (cdrom_sector_type == 8) { if (audio) { - DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id); + DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", dev->id); return 0; } if (mode2 && ((mode2 & 0x03) == 1)) - read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else if (!mode2) - read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else { - DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", id); + DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", dev->id); return 0; } } else { if (mode2) { if ((mode2 & 0x03) == 0x01) - read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else if ((mode2 & 0x03) == 0x02) - read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_xa_form2(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); else - read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode2_non_xa(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } else { if (audio) - read_audio(id, lba, temp_b); + read_audio(dev, lba, temp_b); else - read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + read_mode1(dev, cdrom_sector_flags, lba, msf, mode2, temp_b); } } if ((cdrom_sector_flags & 0x06) == 0x02) { /* Add error flags. */ - DEBUG("CD-ROM %i: Error flags\n", id); + DEBUG("CD-ROM %i: Error flags\n", dev->id); memcpy(b + cdrom_sector_size, extra_buffer, 294); cdrom_sector_size += 294; } else if ((cdrom_sector_flags & 0x06) == 0x04) { /* Add error flags. */ - DEBUG("CD-ROM %i: Full error flags\n", id); + DEBUG("CD-ROM %i: Full error flags\n", dev->id); memcpy(b + cdrom_sector_size, extra_buffer, 296); cdrom_sector_size += 296; } if ((cdrom_sector_flags & 0x700) == 0x100) { - DEBUG("CD-ROM %i: Raw subchannel data\n", id); + DEBUG("CD-ROM %i: Raw subchannel data\n", dev->id); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); cdrom_sector_size += 96; } else if ((cdrom_sector_flags & 0x700) == 0x200) { - DEBUG("CD-ROM %i: Q subchannel data\n", id); + DEBUG("CD-ROM %i: Q subchannel data\n", dev->id); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); cdrom_sector_size += 16; } else if ((cdrom_sector_flags & 0x700) == 0x400) { - DEBUG("CD-ROM %i: R/W subchannel data\n", id); + DEBUG("CD-ROM %i: R/W subchannel data\n", dev->id); memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); cdrom_sector_size += 96; } @@ -854,34 +848,32 @@ image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdr static uint32_t -image_size(uint8_t id) +image_size(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - return dev->cdrom_capacity; } static int -image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, UNUSED(int maxlen), int single) +image_readtoc(cdrom_t *dev, unsigned char *b, unsigned char starttrack, int msf, UNUSED(int maxlen), int single) { + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int number, len = 4; int c, d, first_track, last_track; uint32_t temp; unsigned char attr; TMSF tmsf; - if (!cdimg[id]) - return 0; + if (!img) return 0; - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + img->GetAudioTracks(first_track, last_track, tmsf); b[2] = first_track; b[3] = last_track; d = 0; for (c = 0; c <= last_track; c++) { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + img->GetAudioTrackInfo(c+1, number, tmsf, attr); if (number >= starttrack) { d=c; break; @@ -889,12 +881,12 @@ image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, U } if (starttrack != 0xAA) { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + img->GetAudioTrackInfo(c+1, number, tmsf, attr); b[2] = number; } for (c = d; c <= last_track; c++) { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + img->GetAudioTrackInfo(c+1, number, tmsf, attr); b[len++] = 0; /* reserved */ b[len++] = attr; @@ -926,17 +918,17 @@ image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, U static int -image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) +image_readtoc_session(cdrom_t *dev, unsigned char *b, int msf, int maxlen) { + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int number, len = 4; - TMSF tmsf; - unsigned char attr; + uint8_t attr; uint32_t temp; + TMSF tmsf; - if (!cdimg[id]) - return 0; + if (!img) return 0; - cdimg[id]->GetAudioTrackInfo(1, number, tmsf, attr); + img->GetAudioTrackInfo(1, number, tmsf, attr); if (number == 0) number = 1; @@ -967,24 +959,23 @@ image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) static int -image_readtoc_raw(uint8_t id, unsigned char *b, UNUSED(int maxlen)) +image_readtoc_raw(cdrom_t *dev, unsigned char *b, UNUSED(int maxlen)) { - int track, len = 4; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; int first_track, last_track; - int number; - unsigned char attr; + int number, track, len = 4; + uint8_t attr; TMSF tmsf; - if (!cdimg[id]) - return 0; + if (!img) return 0; - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + img->GetAudioTracks(first_track, last_track, tmsf); b[2] = first_track; b[3] = last_track; for (track = first_track; track <= last_track; track++) { - cdimg[id]->GetAudioTrackInfo(track, number, tmsf, attr); + img->GetAudioTrackInfo(track, number, tmsf, attr); b[len++] = track; b[len++]= attr; @@ -1004,22 +995,23 @@ image_readtoc_raw(uint8_t id, unsigned char *b, UNUSED(int maxlen)) static int -image_status(uint8_t id) +image_status(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; - if (!cdimg[id]) - return CD_STATUS_EMPTY; + if (!img) return CD_STATUS_EMPTY; - if (cdrom_image[id].image_is_iso) + if (dev->img_is_iso) return CD_STATUS_DATA_ONLY; - if (cdimg[id]->HasAudioTracks()) { + if (img->HasAudioTracks()) { switch(dev->cd_state) { case CD_PLAYING: return CD_STATUS_PLAYING; + case CD_PAUSED: return CD_STATUS_PAUSED; + case CD_STOPPED: default: return CD_STATUS_STOPPED; @@ -1030,97 +1022,121 @@ image_status(uint8_t id) } -void -image_reset(UNUSED(uint8_t id)) +static void +image_stop(cdrom_t *dev) { - return; -} + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; - -void -image_close(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; + if (!img || dev->img_is_iso) return; dev->cd_state = CD_STOPPED; - if (cdimg[id]) { - delete cdimg[id]; - cdimg[id] = NULL; - } -} - - -int -image_open(uint8_t id, wchar_t *fn) -{ - cdrom_t *dev = cdrom[id]; - - wcscpy(cdrom_image[id].image_path, fn); - - if (! wcscasecmp(plat_get_extension(fn), L"ISO")) - cdrom_image[id].image_is_iso = 1; - else - cdrom_image[id].image_is_iso = 0; - - cdimg[id] = new CDROM_Interface_Image(); - memset(afn, 0, sizeof(afn)); - wcstombs(afn, fn, sizeof(afn)); - if (!cdimg[id]->SetDevice(afn, false)) { - image_close(id); - cdrom_set_null_handler(id); - DEBUG("[f] image_open(): cdrom[%i]->handler = %08X\n", id, cdrom[id]->handler); - return 1; - } - dev->cd_state = CD_STOPPED; - dev->seek_pos = 0; - dev->cd_buflen = 0; - dev->cdrom_capacity = image_get_last_block(id) + 1; - cdrom[id]->handler = &image_cdrom; - - return 0; } static void -image_exit(uint8_t id) +image_exit(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; + CDROM_Interface_Image *img = (CDROM_Interface_Image *)dev->image; - dev->handler_inited = 0; +INFO("CDROM: image_exit(%ls)\n", dev->image_path); + dev->cd_state = CD_STOPPED; + + if (img) { + delete img; + dev->image = NULL; + } + + dev->ops = NULL; } /* TODO: Check for what data type a mixed CD is. */ -static int image_media_type_id(uint8_t id) +static int +image_media_type_id(cdrom_t *dev) { - if (image_size(id) > 405000) - return 65; /* DVD. */ - else { - if (cdrom_image[id].image_is_iso) - return 1; /* Data CD. */ - else - return 3; /* Mixed mode CD. */ - } + if (image_size(dev) > 405000) + return 65; /* DVD. */ + + if (dev->img_is_iso) + return 1; /* Data CD. */ + + return 3; /* Mixed mode CD. */ } -CDROM image_cdrom = -{ +static const cdrom_ops_t cdrom_image_ops = { image_ready, image_medium_changed, image_media_type_id, - image_audio_callback, - image_audio_stop, + audio_callback, + audio_stop, image_readtoc, image_readtoc_session, image_readtoc_raw, image_getcurrentsubchannel, image_readsector_raw, - image_playaudio, - image_pause, - image_resume, + audio_play, + audio_pause, + audio_resume, image_size, image_status, image_stop, image_exit }; + + +int +cdrom_image_open(cdrom_t *dev, const wchar_t *fn) +{ + char temp[1024]; + CDROM_Interface_Image *img; + + wcscpy(dev->image_path, fn); + + if (! wcscasecmp(plat_get_extension(fn), L"ISO")) + dev->img_is_iso = 1; + else + dev->img_is_iso = 0; + + /* Create new instance of the CDROM_Image class. */ + img = new CDROM_Interface_Image(); + dev->image = img; + + /* Convert filename and open the image. */ + memset(temp, '\0', sizeof(temp)); + wcstombs(temp, fn, sizeof(temp)); + if (!img->SetDevice(temp, false)) { + cdrom_image_close(dev); + cdrom_set_null_handler(dev); + DEBUG("[f] image_open(): cdrom[%i]->ops = %08X\n", dev->id, dev->ops); + return 1; + } + + /* All good, reset state. */ + dev->cd_state = CD_STOPPED; + dev->seek_pos = 0; + dev->cd_buflen = 0; + dev->cdrom_capacity = image_get_last_block(dev) + 1; + + /* Attach this handler to the drive. */ + dev->ops = &cdrom_image_ops; + + return 0; +} + + +void +cdrom_image_close(cdrom_t *dev) +{ +INFO("CDROM: image_close(%ls)\n", dev->image_path); + if (dev->ops->exit) + dev->ops->exit(dev); +} + + +void +cdrom_image_reset(UNUSED(cdrom_t *dev)) +{ +INFO("CDROM: image_reset(%ls)\n", dev->image_path); + /* Nothing to do. */ +} diff --git a/src/devices/cdrom/cdrom_image.h b/src/devices/cdrom/cdrom_image.h index e6a9b1e..684eaaa 100644 --- a/src/devices/cdrom/cdrom_image.h +++ b/src/devices/cdrom/cdrom_image.h @@ -8,10 +8,7 @@ * * Definitions for the CD-ROM image file handlers. * - * This header file lists the functions provided by - * various platform specific cdrom-ioctl files. - * - * Version: @(#)cdrom_image.h 1.0.5 2018/09/14 + * Version: @(#)cdrom_image.h 1.0.6 2018/10/14 * * Authors: Miran Grca, * RichardG, @@ -46,18 +43,17 @@ extern "C" { #endif extern int cdrom_image_do_log; +extern const cdrom_ops_t cdrom_image_ops; extern void cdrom_image_log(int level, const char *fmt, ...); -extern void cdrom_set_null_handler(uint8_t id); +extern int image_open(cdrom_t *dev, wchar_t *fn); +extern void image_close(cdrom_t *dev); +extern void image_reset(cdrom_t *dev); -extern int image_open(uint8_t id, wchar_t *fn); -extern void image_close(uint8_t id); -extern void image_reset(uint8_t id); - -extern int image_audio_callback(uint8_t id, int16_t *output, int len); -extern void image_audio_stop(uint8_t id); +extern int image_audio_callback(cdrom_t *dev, int16_t *output, int len); +extern void image_audio_stop(cdrom_t *dev); #ifdef __cplusplus } diff --git a/src/devices/cdrom/cdrom_null.c b/src/devices/cdrom/cdrom_null.c index aa9166a..96ab94e 100644 --- a/src/devices/cdrom/cdrom_null.c +++ b/src/devices/cdrom/cdrom_null.c @@ -9,7 +9,9 @@ * Implementation of the CD-ROM null interface for unmounted * guest CD-ROM drives. * - * Version: @(#)cdrom_null.c 1.0.4 2018/10/05 + * FIXME: TO BE REMOVED + * + * Version: @(#)cdrom_null.c 1.0.5 2018/10/14 * * Author: Miran Grca, * Sarah Walker, @@ -40,13 +42,12 @@ #include #include #include "../../emu.h" -#include "../scsi/scsi_device.h" #include "cdrom.h" #include "cdrom_null.h" static int -null_ready(uint8_t id) +null_ready(cdrom_t *dev) { return(0); } @@ -54,21 +55,21 @@ null_ready(uint8_t id) /* Always return 0, the contents of a null CD-ROM drive never change. */ static int -null_medium_changed(uint8_t id) +null_medium_changed(cdrom_t *dev) { return(0); } static uint8_t -null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) +null_getcurrentsubchannel(cdrom_t *dev, uint8_t *b, int msf) { return(0x13); } static int -null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) +null_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { *len = 0; @@ -77,77 +78,75 @@ null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdro static int -null_readtoc(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single) +null_readtoc(cdrom_t *dev, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single) { return(0); } static int -null_readtoc_session(uint8_t id, uint8_t *b, int msf, int maxlen) +null_readtoc_session(cdrom_t *dev, uint8_t *b, int msf, int maxlen) { return(0); } static int -null_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) +null_readtoc_raw(cdrom_t *dev, uint8_t *b, int maxlen) { return(0); } static uint32_t -null_size(uint8_t id) +null_size(cdrom_t *dev) { return(0); } static int -null_status(uint8_t id) +null_status(cdrom_t *dev) { return(CD_STATUS_EMPTY); } void -cdrom_null_reset(uint8_t id) +cdrom_null_reset(cdrom_t *dev) { } -void cdrom_set_null_handler(uint8_t id); - int -cdrom_null_open(uint8_t id) +cdrom_null_open(cdrom_t *dev) { - cdrom_set_null_handler(id); + cdrom_set_null_handler(dev); return(0); } void -null_close(uint8_t id) +null_close(cdrom_t *dev) { } static -void null_exit(uint8_t id) +void null_exit(cdrom_t *dev) { } static int -null_media_type_id(uint8_t id) +null_media_type_id(cdrom_t *dev) { return(0x70); } -static CDROM null_cdrom = { +static cdrom_ops_t cdrom_null_ops = { null_ready, null_medium_changed, null_media_type_id, @@ -169,9 +168,10 @@ static CDROM null_cdrom = { void -cdrom_set_null_handler(uint8_t id) +cdrom_set_null_handler(cdrom_t *dev) { - cdrom[id]->handler = &null_cdrom; - cdrom_drives[id].host_drive = 0; - memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); + dev->ops = &cdrom_null_ops; + + dev->host_drive = 0; + memset(dev->image_path, 0, sizeof(dev->image_path)); } diff --git a/src/devices/cdrom/cdrom_null.h b/src/devices/cdrom/cdrom_null.h index d352de2..2dee939 100644 --- a/src/devices/cdrom/cdrom_null.h +++ b/src/devices/cdrom/cdrom_null.h @@ -8,7 +8,9 @@ * * Definitions for the NULL CD-ROM handler. * - * Version: @(#)cdrom_null.h 1.0.2 2018/09/04 + * FIXME: TO BE REMOVED + * + * Version: @(#)cdrom_null.h 1.0.3 2018/10/14 * * Authors: Miran Grca, * Sarah Walker, @@ -42,9 +44,11 @@ extern "C" { #endif -extern int cdrom_null_open(uint8_t id); -extern void cdrom_null_reset(uint8_t id); -extern void null_close(uint8_t id); +extern int cdrom_null_open(cdrom_t *dev); +extern void cdrom_null_reset(cdrom_t *dev); +extern void null_close(cdrom_t *dev); + +extern void cdrom_set_null_handler(cdrom_t *dev); #ifdef __cplusplus } diff --git a/src/devices/disk/hdc_esdi_at.c b/src/devices/disk/hdc_esdi_at.c index 28e3069..c9cb306 100644 --- a/src/devices/disk/hdc_esdi_at.c +++ b/src/devices/disk/hdc_esdi_at.c @@ -8,7 +8,7 @@ * * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * - * Version: @(#)hdc_esdi_at.c 1.0.12 2018/09/22 + * Version: @(#)hdc_esdi_at.c 1.0.13 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -797,8 +797,8 @@ wd1007vse1_init(const device_t *info) c = 0; for (d = 0; d < HDD_NUM; d++) { - if ((hdd[d].bus==HDD_BUS_ESDI) && (hdd[d].id.esdi_channel * Sarah Walker, @@ -1099,9 +1099,9 @@ esdi_init(const device_t *info) c = 0; for (i = 0; i < HDD_NUM; i++) { if ((hdd[i].bus == HDD_BUS_ESDI) && - (hdd[i].id.esdi_channel < ESDI_NUM)) { + (hdd[i].bus_id.esdi_channel < ESDI_NUM)) { /* This is an ESDI drive. */ - drive = &dev->drives[hdd[i].id.esdi_channel]; + drive = &dev->drives[hdd[i].bus_id.esdi_channel]; hdd_active(drive->hdd_num, 0); diff --git a/src/devices/disk/hdc_ide.h b/src/devices/disk/hdc_ide.h index f0f2574..e1d346c 100644 --- a/src/devices/disk/hdc_ide.h +++ b/src/devices/disk/hdc_ide.h @@ -8,7 +8,7 @@ * * Definitions for the IDE module. * - * Version: @(#)hdc_ide.h 1.0.10 2018/09/28 + * Version: @(#)hdc_ide.h 1.0.11 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,27 +40,80 @@ # define EMU_IDE_H +enum { + IDE_NONE = 0, + IDE_HDD, + IDE_ATAPI +}; + +/* Type: + * 0 = PIO, + * 1 = SDMA, + * 2 = MDMA, + * 3 = UDMA + * Return: + * -1 = Not supported, + * Anything else = maximum mode + * + * This will eventually be hookable. +*/ +enum { + TYPE_PIO = 0, + TYPE_SDMA, + TYPE_MDMA, + TYPE_UDMA +}; + +/* Return: + * 0 = Not supported, + * Anything else = timings + * + * This will eventually be hookable. + */ +enum { + TIMINGS_DMA = 0, + TIMINGS_PIO, + TIMINGS_PIO_FC +}; + + typedef struct { - uint8_t atastat, error, - command, fdisk; + uint8_t atastat, error, + command, fdisk; - int type, board, - irqstat, service, - blocksize, blockcount, - hdd_num, channel, - pos, sector_pos, - skip512, reset, - mdma_mode, do_initial_read; + int type, board, + irqstat, service, + blocksize, blockcount, + hdd_num, channel, + pos, sector_pos, + lba, skip512, + reset, mdma_mode, + do_initial_read; - uint32_t secount, sector, - cylinder, head, - drive, cylprecomp, - tracks, spt, hpc, - cfg_spt, cfg_hpc, - lba, lba_addr; + uint32_t secount, sector, + cylinder, head, + drive, cylprecomp, + cfg_spt, cfg_hpc, + lba_addr, tracks, + spt, hpc; - uint16_t *buffer; - uint8_t *sector_buffer; + uint16_t *buffer; + + uint8_t *sector_buffer; + + /* Stuff mostly used by ATAPI */ + void *p; + int interrupt_drq; + + int (*get_max)(int ide_has_dma, int type); + int (*get_timings)(int ide_has_dma, int type); + void (*identify)(void *p, int ide_has_dma); + void (*set_signature)(void *p); + void (*packet_write)(void *p, uint32_t val, int length); + uint32_t (*packet_read)(void *p, int length); + void (*stop)(void *p); + void (*packet_callback)(void *p); + void (*device_reset)(void *p); } ide_t; @@ -102,6 +155,8 @@ extern void ide_sec_disable(void); extern void ide_set_callback(uint8_t channel, int64_t callback); extern void secondary_ide_check(void); + +extern void ide_padstr(char *str, const char *src, int len); extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); @@ -110,6 +165,8 @@ extern void (*ide_bus_master_set_irq)(int channel, void *priv); extern void *ide_bus_master_priv[2]; extern void ide_enable_pio_override(void); +extern void ide_allocate_buffer(ide_t *dev); +extern void ide_atapi_attach(ide_t *dev); #endif /*EMU_IDE_H*/ diff --git a/src/devices/disk/hdc_ide_ata.c b/src/devices/disk/hdc_ide_ata.c index e9ab20d..65fff1a 100644 --- a/src/devices/disk/hdc_ide_ata.c +++ b/src/devices/disk/hdc_ide_ata.c @@ -14,7 +14,7 @@ * Devices currently implemented are hard disk, CD-ROM and * ZIP IDE/ATAPI devices. * - * Version: @(#)hdc_ide_ata.c 1.0.23 2018/10/05 + * Version: @(#)hdc_ide_ata.c 1.0.24 2018/10/14 * * Authors: Miran Grca, * Sarah Walker, @@ -72,26 +72,6 @@ #include "zip.h" -enum { - IDE_NONE = 0, -#if 0 -/* In the future, there's going to be just the IDE_ATAPI type, - leaving it to the common ATAPI/SCSI device handler to know - what type the device is. */ - IDE_DISK, - IDE_ATAPI -#else - IDE_HDD, - IDE_CDROM, - IDE_ZIP -#endif -}; - - -#define IDE_PCI (PCI && pio_override) -#define IDE_TIME (20LL * TIMER_USEC) / 3LL - - /* Bits of 'atastat' */ #define ERR_STAT 0x01 /* Error */ #define IDX_STAT 0x02 /* Index */ @@ -113,7 +93,6 @@ enum { #define UNC_ERR 0x40 /* Uncorrectable data error */ #define BBK_ERR 0x80 /* Bad block mark detected */ - /* ATA Commands */ #define WIN_NOP 0x00 #define WIN_SRST 0x08 /* ATAPI Device Reset */ @@ -123,32 +102,28 @@ enum { #define WIN_WRITE 0x30 /* 28-Bit Write */ #define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write - no retry */ #define WIN_VERIFY 0x40 /* 28-Bit Verify */ -#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected - * older ATA command, according - * to the specification I found, - * it is identical to 0x40 - */ +#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */ #define WIN_FORMAT 0x50 #define WIN_SEEK 0x70 #define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */ #define WIN_SPECIFY 0x91 /* Initialize Drive Parameters */ -#define WIN_PACKETCMD 0xa0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xa1 /* Identify ATAPI device */ -#define WIN_READ_MULTIPLE 0xc4 -#define WIN_WRITE_MULTIPLE 0xc5 -#define WIN_SET_MULTIPLE_MODE 0xc6 -#define WIN_READ_DMA 0xc8 -#define WIN_READ_DMA_ALT 0xc9 -#define WIN_WRITE_DMA 0xca -#define WIN_WRITE_DMA_ALT 0xcb -#define WIN_STANDBYNOW1 0xe0 -#define WIN_IDLENOW1 0xe1 -#define WIN_SETIDLE1 0xe3 -#define WIN_CHECKPOWERMODE1 0xe5 -#define WIN_SLEEP1 0xe6 -#define WIN_IDENTIFY 0xec /* Ask drive to identify itself */ -#define WIN_SET_FEATURES 0xef -#define WIN_READ_NATIVE_MAX 0xf8 +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* Identify ATAPI device */ +#define WIN_READ_MULTIPLE 0xC4 +#define WIN_WRITE_MULTIPLE 0xC5 +#define WIN_SET_MULTIPLE_MODE 0xC6 +#define WIN_READ_DMA 0xC8 +#define WIN_READ_DMA_ALT 0xC9 +#define WIN_WRITE_DMA 0xCA +#define WIN_WRITE_DMA_ALT 0xCB +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLENOW1 0xE1 +#define WIN_SETIDLE1 0xE3 +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEP1 0xE6 +#define WIN_IDENTIFY 0xEC /* Ask drive to identify itself */ +#define WIN_SET_FEATURES 0xEF +#define WIN_READ_NATIVE_MAX 0xF8 #define FEATURE_SET_TRANSFER_MODE 0x03 #define FEATURE_ENABLE_IRQ_OVERLAPPED 0x5d @@ -158,21 +133,17 @@ enum { #define FEATURE_DISABLE_IRQ_OVERLAPPED 0xdd #define FEATURE_DISABLE_IRQ_SERVICE 0xde +#define IDE_PCI (PCI && pio_override) + typedef struct { - int bit32, - cur_dev, - irq; - - int64_t callback; + int bit32, cur_dev, + irq; + int64_t callback; } ide_board_t; - static ide_board_t *ide_boards[4]; static int pio_override = 0; -static uint16_t ide_base_main[4] = { 0x1f0, 0x170, 0x168, 0x1e8 }; -static uint16_t ide_side_main[4] = { 0x3f6, 0x376, 0x36e, 0x3ee }; - ide_t *ide_drives[IDE_NUM+XTIDE_NUM]; int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); @@ -182,13 +153,17 @@ void *ide_bus_master_priv[2]; int ide_inited = 0; int ide_ter_enabled = 0, ide_qua_enabled = 0; +static uint16_t ide_base_main[4] = { 0x1f0, 0x170, 0x168, 0x1e8 }; +static uint16_t ide_side_main[4] = { 0x3f6, 0x376, 0x36e, 0x3ee }; static void ide_callback(void *priv); +#define IDE_TIME (20LL * TIMER_USEC) / 3LL + + uint8_t -getstat(ide_t *ide) -{ +getstat(ide_t *ide) { return ide->atastat; } @@ -198,7 +173,7 @@ ide_get_period(ide_t *ide, int size) { double period = 10.0 / 3.0; - switch(ide->mdma_mode & 0x300) { + switch(ide->mdma_mode & 0x300) { case 0x000: /* PIO */ switch(ide->mdma_mode & 0xff) { case 0: @@ -218,7 +193,6 @@ ide_get_period(ide_t *ide, int size) break; } break; - case 0x100: /* Single Word DMA */ switch(ide->mdma_mode & 0xff) { case 0: @@ -232,7 +206,6 @@ ide_get_period(ide_t *ide, int size) break; } break; - case 0x200: /* Multiword DMA */ switch(ide->mdma_mode & 0xff) { case 0: @@ -246,7 +219,6 @@ ide_get_period(ide_t *ide, int size) break; } break; - case 0x300: /* Ultra DMA */ switch(ide->mdma_mode & 0xff) { case 0: @@ -270,6 +242,7 @@ ide_get_period(ide_t *ide, int size) } break; } + period *= 1048576.0; /* period * MB */ period = 1000000.0 / period; period *= (double) TIMER_USEC; @@ -287,12 +260,16 @@ ide_get_seek_time(ide_t *ide, uint32_t new_pos) uint32_t t, nt; t = pos / ide->spt; nt = new_pos / ide->spt; + dusec = (double) TIMER_USEC; time = (1000000.0 / 2800.0) * dusec; /* Revolution (1/2800 s). */ + if ((t % ide->hpc) != (pos % ide->hpc)) /* Head change. */ time += (dusec / 250.0); /* 4ns */ + t /= ide->hpc; nt /= ide->hpc; + if (t != nt) { t = ABS(t - nt); time += ((40000.0 * dusec) / ((double) ide->tracks)) * ((double) t); @@ -303,35 +280,14 @@ ide_get_seek_time(ide_t *ide, uint32_t new_pos) int -ide_drive_is_cdrom(ide_t *ide) +ide_drive_is_atapi(ide_t *ide) { int ch = ide->channel; if (ch >= 8) return 0; - if (atapi_cdrom_drives[ch] >= CDROM_NUM) - return 0; - - if (cdrom_drives[atapi_cdrom_drives[ch]].bus_type == CDROM_BUS_ATAPI) - return 1; - - return 0; -} - - -int -ide_drive_is_zip(ide_t *ide) -{ - int ch = ide->channel; - - if (ch >= 8) - return 0; - - if (atapi_zip_drives[ch] >= ZIP_NUM) - return 0; - - if (zip_drives[atapi_zip_drives[ch]].bus_type == ZIP_BUS_ATAPI) + if (ide->type == IDE_ATAPI) return 1; return 0; @@ -344,9 +300,9 @@ ide_irq_raise(ide_t *ide) if (!ide_boards[ide->board]) return; - DBGLOG(1, "Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); + DBGLOG(1, "IDE: raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); - if (!(ide->fdisk & 0x02) && (ide_boards[ide->board]->irq != -1)) { + if (!(ide->fdisk & 2) && (ide_boards[ide->board]->irq != -1)) { if ((ide->board < 2) && ide_bus_master_set_irq) ide_bus_master_set_irq(ide->board | 0x40, ide_bus_master_priv[ide->board]); else @@ -364,7 +320,7 @@ ide_irq_lower(ide_t *ide) if (!ide_boards[ide->board]) return; - DBGLOG(1, "Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); + DBGLOG(1, "IDE: lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); if ((ide_boards[ide->board]->irq != -1) && ide->irqstat) { if ((ide->board < 2) && ide_bus_master_set_irq) @@ -386,16 +342,15 @@ ide_irq_lower(ide_t *ide) * @param len Length of destination buffer to fill in. Strings shorter than * this length will be padded with spaces. */ -static void +void ide_padstr(char *str, const char *src, int len) { - char v; - int i; + int i, v; for (i = 0; i < len; i++) { if (*src != '\0') v = *src++; - else + else v = ' '; str[i ^ 1] = v; } @@ -411,69 +366,47 @@ ide_padstr(char *str, const char *src, int len) * this length will be padded with spaces. * @param src Source string */ -void -ide_padstr8(uint8_t *buf, int buf_size, const char *src) +void ide_padstr8(uint8_t *buf, int buf_size, const char *src) { int i; for (i = 0; i < buf_size; i++) { if (*src != '\0') - buf[i] = (uint8_t)*src++; - else - buf[i] = (uint8_t)' '; + buf[i] = *src++; + else + buf[i] = ' '; } } -enum { - TYPE_PIO = 0, - TYPE_SDMA, - TYPE_MDMA, - TYPE_UDMA -}; - - -/* - * Type: - * 0 = PIO, - * 1 = SDMA, - * 2 = MDMA, - * 3 = UDMA - * - * Return: - * -1 = Not supported, - * Anything else = maximum mode - * - * This will eventually be hookable. - */ static int ide_get_max(ide_t *ide, int type) { + if (ide_drive_is_atapi(ide)) + return ide->get_max(!IDE_PCI || (ide->board >= 2), type); + switch(type) { case TYPE_PIO: /* PIO */ if (!IDE_PCI || (ide->board >= 2)) return 0; /* Maximum PIO 0 for legacy PIO-only drive. */ - if (ide_drive_is_zip(ide)) - return 3; - return 4; - + else + return 4; + break; case TYPE_SDMA: /* SDMA */ - if (!IDE_PCI || (ide->board >= 2) || ide_drive_is_zip(ide)) + if (!IDE_PCI || (ide->board >= 2)) return -1; - return 2; - + else + return 2; case TYPE_MDMA: /* MDMA */ if (!IDE_PCI || (ide->board >= 2)) return -1; - if (ide_drive_is_zip(ide)) - return 1; - return 2; - + else + return 2; case TYPE_UDMA: /* UDMA */ if (!IDE_PCI || (ide->board >= 2)) return -1; - return 2; - + else + return 2; default: fatal("Unknown transfer type: %i\n", type); return -1; @@ -481,45 +414,28 @@ ide_get_max(ide_t *ide, int type) } -enum { - TIMINGS_DMA = 0, - TIMINGS_PIO, - TIMINGS_PIO_FC -}; - - -/* - * Return: - * 0 = Not supported, - * Anything else = timings - * - * This will eventually be hookable. - */ static int ide_get_timings(ide_t *ide, int type) { + if (ide_drive_is_atapi(ide)) + return ide->get_timings(!IDE_PCI || (ide->board >= 2), type); + switch(type) { case TIMINGS_DMA: if (!IDE_PCI || (ide->board >= 2)) return 0; - if (ide_drive_is_zip(ide)) - return 0x96; - return 120; - + else + return 120; + break; case TIMINGS_PIO: if (!IDE_PCI || (ide->board >= 2)) return 0; - if (ide_drive_is_zip(ide)) - return 0xb4; - return 120; - + else + return 120; + break; case TIMINGS_PIO_FC: - if (!IDE_PCI || (ide->board >= 2)) - return 0; - if (ide_drive_is_zip(ide)) - return 0xb4; return 0; - + break; default: fatal("Unknown transfer type: %i\n", type); return 0; @@ -534,6 +450,7 @@ static void ide_hd_identify(ide_t *ide) { char device_identify[9] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', 0 }; + uint32_t d_hpc, d_spt, d_tracks; uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); @@ -554,45 +471,40 @@ ide_hd_identify(ide_t *ide) /* Specify default CHS translation */ if (full_size <= 16514064) { - ide->buffer[1] = d_tracks; - ide->buffer[3] = d_hpc; - ide->buffer[6] = d_spt; + ide->buffer[1] = d_tracks; /* Tracks in default CHS translation. */ + ide->buffer[3] = d_hpc; /* Heads in default CHS translation. */ + ide->buffer[6] = d_spt; /* Heads in default CHS translation. */ } else { - ide->buffer[1] = 16383; - ide->buffer[3] = 16; - ide->buffer[6] = 63; + ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ + ide->buffer[3] = 16; /* Heads in default CHS translation. */ + ide->buffer[6] = 63; /* Heads in default CHS translation. */ } DEBUG("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); - /* Serial Number, Firmware and Model. */ - ide_padstr((char *) (ide->buffer + 10), "", 20); - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); - - /* Buffer type and size. */ - ide->buffer[20] = 3; - ide->buffer[21] = 512; - - /* Capabilities. */ - ide->buffer[50] = 0x4000; + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + ide->buffer[20] = 3; /*Buffer type*/ + ide->buffer[21] = 512; /*Buffer size*/ + ide->buffer[50] = 0x4000; /* Capabilities */ ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; + if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) { ide->buffer[49] = (1 << 9); DEBUG("LBA supported\n"); - /* Total addressable sectors (LBA) */ - ide->buffer[60] = full_size & 0xFFFF; + ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[61] = (full_size >> 16) & 0x0FFF; DEBUG("Full size: %" PRIu64 "\n", full_size); /* - * Bit 0 = The fields reported in words 54-58 are valid; - * Bit 1 = The fields reported in words 64-70 are valid; - * Bit 2 = The fields reported in word 88 are valid. - */ + Bit 0 = The fields reported in words 54-58 are valid; + Bit 1 = The fields reported in words 64-70 are valid; + Bit 2 = The fields reported in word 88 are valid. */ ide->buffer[53] = 1; + if (ide->cfg_spt != 0) { - ide->buffer[54] = (uint16_t) ((full_size / ide->cfg_hpc) / ide->cfg_spt); + ide->buffer[54] = (uint16_t)(full_size / ide->cfg_hpc) / ide->cfg_spt; ide->buffer[55] = ide->cfg_hpc; ide->buffer[56] = ide->cfg_spt; } else { @@ -600,6 +512,7 @@ ide_hd_identify(ide_t *ide) ide->buffer[54] = d_tracks; ide->buffer[55] = d_hpc; ide->buffer[56] = d_spt; + } else { ide->buffer[54] = 16383; ide->buffer[55] = 16; ide->buffer[56] = 63; @@ -608,143 +521,39 @@ ide_hd_identify(ide_t *ide) full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); - /* Total addressable sectors (LBA) */ - ide->buffer[57] = full_size & 0xFFFF; + ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[58] = (full_size >> 16) & 0x0FFF; DEBUG("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); } if (IDE_PCI && (ide->board < 2)) { - /* Max sectors on multiple transfer command. */ - ide->buffer[47] = 32 | 0x8000; - - ide->buffer[80] = 0x1e; /* ATA-1 to ATA-4 supported */ - ide->buffer[81] = 0x18; /* ATA-4 revision 18 supported */ + ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ + ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ + ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ } else { - /* Max sectors on multiple transfer command. */ - ide->buffer[47] = 16 | 0x8000; - - ide->buffer[80] = 0x0e; /* ATA-1 to ATA-3 supported */ + ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ + ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ } } -/** - * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command - */ -static void -ide_atapi_cdrom_identify(ide_t *ide) -{ - char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; - uint8_t cdrom_id; - cdrom_id = atapi_cdrom_drives[ide->channel]; - - device_identify[7] = cdrom_id + 0x30; - - DEBUG("ATAPI Identify: %s\n", device_identify); - - /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); - - /* Serial Number, Firmware and Model. */ - ide_padstr((char *) (ide->buffer + 10), "", 20); -#if 1 - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); -#else - ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); - ide_padstr((char *) (ide->buffer + 27), - "NEC CD-ROM DRIVE:273 ", 40); -#endif - - /* LBA supported */ - ide->buffer[49] = 0x200; - - /* Interpret zero byte count limit as maximum length. */ - ide->buffer[126] = 0xfffe; - - if (IDE_PCI && (ide->board < 2)) { - ide->buffer[71] = 30; - ide->buffer[72] = 30; - } -} - - -static void -ide_atapi_zip_100_identify(ide_t *ide) -{ - /* Firmware and Model. */ - ide_padstr((char *) (ide->buffer + 23), "E.08", 8); - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); -} - - -static void -ide_atapi_zip_250_identify(ide_t *ide) -{ - /* Firmware and Model. */ - ide_padstr((char *) (ide->buffer + 23), "42.S", 8); - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); - - if (IDE_PCI && (ide->board < 2)) { - /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ - ide->buffer[80] = 0x30; - - /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ - ide->buffer[81] = 0x15; - } -} - - -static void -ide_atapi_zip_identify(ide_t *ide) -{ - uint8_t zip_id; - - zip_id = atapi_zip_drives[ide->channel]; - - /* - * ATAPI device, direct-access device, removable media, interrupt DRQ. - * - * Using (2<<5) here makes the ASUS P/I-P54TP4XE misidentify the ZIP - * drive as an LS-120. - */ - ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); - - /* Serial Number. */ - ide_padstr((char *) (ide->buffer + 10), "", 20); - - /* LBA supported. */ - ide->buffer[49] = 0x200; - - /* Interpret zero byte count limit as maximum length. */ - ide->buffer[126] = 0xfffe; - - if (zip_drives[zip_id].is_250) - ide_atapi_zip_250_identify(ide); - else - ide_atapi_zip_100_identify(ide); -} - - static void ide_identify(ide_t *ide) { int d, i, max_pio, max_sdma, max_mdma, max_udma; - DEBUG("IDE IDENTIFY (PACKET DEVICE) on board %i (channel %i)\n", - ide->board, ide->channel); + DEBUG("IDE IDENTIFY or IDENTIFY PACKET DEVICE on board %i (channel %i)\n", ide->board, ide->channel); + memset(ide->buffer, 0, 512); - if (ide_drive_is_cdrom(ide)) - ide_atapi_cdrom_identify(ide); - else if (ide_drive_is_zip(ide)) - ide_atapi_zip_identify(ide); - else if (ide->type != IDE_NONE) + if (ide_drive_is_atapi(ide)) + ide->identify(ide, IDE_PCI && (ide->board < 2)); + else if (ide->type != IDE_NONE) ide_hd_identify(ide); - else { - fatal("IDE IDENTIFY (PACKET DEVICE) on non-attached IDE device\n"); + else { + fatal("IDE IDENTIFY or IDENTIFY PACKET DEVICE on non-attached IDE device\n"); + return; } max_pio = ide_get_max(ide, TYPE_PIO); @@ -780,14 +589,17 @@ ide_identify(ide_t *ide) for (i = 0; i <= max_udma; i++) ide->buffer[88] |= (1 << i); } + if ((max_sdma != -1) || (max_mdma != -1) || (max_udma != -1)) { ide->buffer[49] |= 0x100; /* DMA supported */ ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); } + if ((max_mdma != -1) || (max_udma != -1)) { ide->buffer[65] = ide_get_timings(ide, TIMINGS_DMA); ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); } + if (ide->mdma_mode != -1) { d = (ide->mdma_mode & 0xff); d <<= 8; @@ -800,7 +612,6 @@ ide_identify(ide_t *ide) ide->buffer[63] |= d; else if ((ide->mdma_mode & 0x300) == 0x300) ide->buffer[88] |= d; - DEBUG("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); } } @@ -816,12 +627,13 @@ ide_get_sector(ide_t *ide) if (ide->lba) return (off64_t)ide->lba_addr + ide->skip512; + else { + heads = ide->cfg_hpc; + sectors = ide->cfg_spt; - heads = ide->cfg_hpc; - sectors = ide->cfg_spt; - - return ((((off64_t) ide->cylinder * heads) + ide->head) * + return ((((off64_t) ide->cylinder * heads) + ide->head) * sectors) + (ide->sector - 1) + ide->skip512; + } } @@ -834,9 +646,11 @@ ide_next_sector(ide_t *ide) if (ide->lba) ide->lba_addr++; else { - if (++ide->sector == (ide->cfg_spt + 1)) { + ide->sector++; + if (ide->sector == (ide->cfg_spt + 1)) { ide->sector = 1; - if (++ide->head == ide->cfg_hpc) { + ide->head++; + if (ide->head == ide->cfg_hpc) { ide->head = 0; ide->cylinder++; } @@ -864,20 +678,15 @@ loadhd(ide_t *ide, int d, const wchar_t *fn) void ide_set_signature(ide_t *ide) { - uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; - uint8_t zip_id = atapi_zip_drives[ide->channel]; + scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p; - ide->sector = 1; - ide->head = 0; + ide->sector=1; + ide->head=0; - if (ide_drive_is_zip(ide)) { - zip_set_signature(zip[zip_id]); - ide->secount = zip[zip_id]->phase; - ide->cylinder = zip[zip_id]->request_length; - } else if (ide_drive_is_cdrom(ide)) { - cdrom_set_signature(cdrom[cdrom_id]); - ide->secount = cdrom[cdrom_id]->phase; - ide->cylinder = cdrom[cdrom_id]->request_length; + if (ide_drive_is_atapi(ide)) { + ide->set_signature(ide->p); + ide->secount = atapi->phase; + ide->cylinder = atapi->request_length; } else { ide->secount=1; ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); @@ -896,14 +705,17 @@ ide_set_features(ide_t *ide) features = ide->cylprecomp; features_data = ide->secount; - DEBUG("IDE %02X: Set features: %02X, %02X\n", - ide->channel, features, features_data); + DEBUG("Features code %02X\n", features); + + DEBUG("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); switch(features) { case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ DEBUG("Transfer mode %02X\n", features_data >> 3); + mode = (features_data >> 3); submode = features_data & 7; + switch(mode) { case 0x00: /* PIO default */ if (submode != 0) @@ -974,15 +786,15 @@ ide_set_features(ide_t *ide) void ide_set_sector(ide_t *ide, int64_t sector_num) { - uint32_t cyl, r; + unsigned int cyl, r; if (ide->lba) { - ide->head = (uint32_t) (sector_num >> 24); - ide->cylinder = (uint32_t) (sector_num >> 8); - ide->sector = (uint32_t) sector_num; + ide->head = (uint16_t)(sector_num >> 24); + ide->cylinder = (uint32_t)(sector_num >> 8); + ide->sector = (uint32_t)(sector_num); } else { - cyl = (uint32_t) (sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); - r = (uint32_t) (sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); + cyl = (unsigned int)(sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); + r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); ide->cylinder = cyl; ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); ide->sector = (r % hdd[ide->hdd_num].spt) + 1; @@ -994,8 +806,7 @@ static void ide_zero(int d) { ide_t *dev; - - ide_drives[d] = (ide_t *) mem_alloc(sizeof(ide_t)); + ide_drives[d] = (ide_t *)mem_alloc(sizeof(ide_t)); memset(ide_drives[d], 0, sizeof(ide_t)); dev = ide_drives[d]; dev->channel = d; @@ -1010,10 +821,9 @@ ide_zero(int d) static void ide_board_close(int board) { - cdrom_t *cddev; - zip_t *zipdev; ide_t *dev; int c, d; + scsi_device_data_t *atapi; /* Close hard disk image files (if previously open) */ for (d = 0; d < 2; d++) { @@ -1024,14 +834,9 @@ ide_board_close(int board) hdd_image_close(dev->hdd_num); if (board < 4) { - if (ide_drive_is_zip(dev)) { - zipdev = zip[atapi_zip_drives[c]]; - if (zipdev != NULL) - zipdev->status = DRDY_STAT | DSC_STAT; - } else if (ide_drive_is_cdrom(dev)) { - cddev = cdrom[atapi_cdrom_drives[c]]; - if (cddev != NULL) - cddev->status = DRDY_STAT | DSC_STAT; + if (ide_drive_is_atapi(dev)) { + atapi = (scsi_device_data_t *) dev->p; + atapi->status = DRDY_STAT | DSC_STAT; } } @@ -1041,24 +846,50 @@ ide_board_close(int board) if (dev->sector_buffer) free(dev->sector_buffer); - free(dev); + if (dev) + free(dev); } } +void +ide_allocate_buffer(ide_t *dev) +{ + if (dev->buffer) + return; + + dev->buffer = (uint16_t *)mem_alloc(65536 * sizeof(uint16_t)); + memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); +} + + +void +ide_atapi_attach(ide_t *dev) +{ + if (dev->type != IDE_NONE) + return; + + dev->type = IDE_ATAPI; + ide_allocate_buffer(dev); + ide_set_signature(dev); + dev->mdma_mode = (1 << dev->get_max(!IDE_PCI || (dev->board >= 2), TYPE_PIO)); + dev->error = 1; + dev->cfg_spt = dev->cfg_hpc = 0; +} + + static void ide_board_init(int board) { ide_t *dev; int c, d; - int max, ch; - int is_ide, valid_ch; + int ch, is_ide, valid_ch; int min_ch, max_ch; min_ch = (board << 1); max_ch = min_ch + 1; - DEBUG("IDE: board %i: loading disks...\n", board); + DEBUG("IDE: board %i: loading disks...\n", board); for (d = 0; d < 2; d++) { c = (board << 1) + d; ide_zero(c); @@ -1067,7 +898,7 @@ ide_board_init(int board) c = 0; for (d = 0; d < HDD_NUM; d++) { is_ide = (hdd[d].bus == HDD_BUS_IDE); - ch = hdd[d].id.ide_channel; + ch = hdd[d].bus_id.ide_channel; if (board == 4) { valid_ch = ((ch >= 0) && (ch <= 1)); @@ -1078,7 +909,7 @@ ide_board_init(int board) if (is_ide && valid_ch) { DEBUG("Found IDE hard disk on channel %i\n", ch); loadhd(ide_drives[ch], d, hdd[d].fn); - ide_drives[ch]->sector_buffer = (uint8_t *) mem_alloc(256*512); + ide_drives[ch]->sector_buffer = (uint8_t *)mem_alloc(256*512); memset(ide_drives[ch]->sector_buffer, 0, 256*512); if (++c >= 2) break; } @@ -1089,22 +920,14 @@ ide_board_init(int board) c = (board << 1) + d; dev = ide_drives[c]; - if (board < 4) { - if (ide_drive_is_zip(dev) && (dev->type == IDE_NONE)) - dev->type = IDE_ZIP; - else if (ide_drive_is_cdrom(dev) && (dev->type == IDE_NONE)) - dev->type = IDE_CDROM; - } + if (dev->type == IDE_NONE) + continue; - if (dev->type != IDE_NONE) { - dev->buffer = (uint16_t *) mem_alloc(65536 * sizeof(uint16_t)); - memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); - } + ide_allocate_buffer(dev); ide_set_signature(dev); - max = ide_get_max(dev, TYPE_PIO); - dev->mdma_mode = (1 << max); + dev->mdma_mode = (1 << ide_get_max(dev, TYPE_PIO)); dev->error = 1; dev->cfg_spt = dev->cfg_hpc = 0; } @@ -1117,19 +940,22 @@ ide_set_callback(uint8_t board, int64_t callback) ide_board_t *dev = ide_boards[board]; DEBUG("ide_set_callback(%i)\n", board); - if (dev == NULL) { + + if (!dev) { DEBUG("Set callback failed\n"); return; } - dev->callback = callback; + if (callback) + dev->callback = callback; + else + dev->callback = 0LL; } void ide_write_data(ide_t *ide, uint32_t val, int length) { - int ch = ide->channel; uint8_t *idebufferb = (uint8_t *) ide->buffer; uint16_t *idebufferw = ide->buffer; uint32_t *idebufferl = (uint32_t *) ide->buffer; @@ -1137,14 +963,11 @@ ide_write_data(ide_t *ide, uint32_t val, int length) if (ide->command == WIN_PACKETCMD) { ide->pos = 0; - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) + if (!ide_drive_is_atapi(ide)) return; - if (ide_drive_is_zip(ide)) - zip_write(ch, val, length); - else - cdrom_write(ch, val, length); - + if (ide_drive_is_atapi(ide)) + ide->packet_write(ide->p, val, length); return; } @@ -1153,17 +976,14 @@ ide_write_data(ide_t *ide, uint32_t val, int length) idebufferb[ide->pos] = val & 0xff; ide->pos++; break; - case 2: idebufferw[ide->pos >> 1] = val & 0xffff; ide->pos += 2; break; - case 4: idebufferl[ide->pos >> 2] = val; ide->pos += 4; break; - default: return; } @@ -1181,7 +1001,6 @@ ide_write_data(ide_t *ide, uint32_t val, int length) } - void ide_writew(uint16_t addr, uint16_t val, void *priv) { @@ -1191,6 +1010,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; + DBGLOG(1, "ide_writew %04X %04X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); addr &= 0x7; @@ -1215,6 +1035,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; + DBGLOG(1, "ide_writel %04X %08X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); addr &= 0x7; @@ -1235,6 +1056,7 @@ void ide_write_devctl(uint16_t addr, uint8_t val, void *priv) { ide_board_t *dev = (ide_board_t *) priv; + scsi_device_data_t *atapi; ide_t *ide, *ide_other; int ch; @@ -1245,11 +1067,11 @@ ide_write_devctl(uint16_t addr, uint8_t val, void *priv) DEBUG("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { + atapi = (scsi_device_data_t *) ide->p; + timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 0LL; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + if (ide_drive_is_atapi(ide)) + atapi->callback = 0LL; ide_set_callback(ide->board, 500LL * IDE_TIME); timer_update_outstanding(); @@ -1257,10 +1079,8 @@ ide_write_devctl(uint16_t addr, uint8_t val, void *priv) ide->reset = 1; if (ide_other->type != IDE_NONE) ide->reset = 1; - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; ide->atastat = ide_other->atastat = BSY_STAT; } @@ -1280,6 +1100,7 @@ void ide_writeb(uint16_t addr, uint8_t val, void *priv) { ide_board_t *dev = (ide_board_t *) priv; + scsi_device_data_t *atapi, *atapi_other; ide_t *ide, *ide_other; int ch; @@ -1294,45 +1115,37 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) return; + atapi = (scsi_device_data_t *) ide->p; + atapi_other = (scsi_device_data_t *) ide_other->p; + switch (addr) { case 0x0: /* Data */ ide_write_data(ide, val | (val << 8), 2); return; - /* Note: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ + /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ case 0x1: /* Features */ - if (ide_drive_is_zip(ide)) { + if (ide_drive_is_atapi(ide)) { DEBUG("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - zip[atapi_zip_drives[ch]]->features = val; - } else if (ide_drive_is_cdrom(ide)) { - DEBUG("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - cdrom[atapi_cdrom_drives[ch]]->features = val; + atapi->features = val; } ide->cylprecomp = val; - if (ide_drive_is_zip(ide_other)) - zip[atapi_zip_drives[ch ^ 1]]->features = val; - else if (ide_drive_is_cdrom(ide_other)) - cdrom[atapi_cdrom_drives[ch ^ 1]]->features = val; + if (ide_drive_is_atapi(ide_other)) + atapi_other->features = val; ide_other->cylprecomp = val; return; case 0x2: /* Sector count */ - if (ide_drive_is_zip(ide)) { + if (ide_drive_is_atapi(ide)) { DEBUG("Sector count write: %i\n", val); - zip[atapi_zip_drives[ch]]->phase = val; - } else if (ide_drive_is_cdrom(ide)) { - DEBUG("Sector count write: %i\n", val); - cdrom[atapi_cdrom_drives[ch]]->phase = val; + atapi->phase = val; } ide->secount = val; - if (ide_drive_is_zip(ide_other)) { + if (ide_drive_is_atapi(ide_other)) { DEBUG("Other sector count write: %i\n", val); - zip[atapi_zip_drives[ch ^ 1]]->phase = val; - } else if (ide_drive_is_cdrom(ide_other)) { - DEBUG("Other sector count write: %i\n", val); - cdrom[atapi_cdrom_drives[ch ^ 1]]->phase = val; + atapi_other->phase = val; } ide_other->secount = val; return; @@ -1345,44 +1158,32 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) return; case 0x4: /* Cylinder low */ - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ch]]->request_length &= 0xFF00; - zip[atapi_zip_drives[ch]]->request_length |= val; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[ch]]->request_length |= val; + if (ide_drive_is_atapi(ide)) { + atapi->request_length &= 0xFF00; + atapi->request_length |= val; } ide->cylinder = (ide->cylinder & 0xFF00) | val; ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); - if (ide_drive_is_zip(ide_other)) { - zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF00; - zip[atapi_zip_drives[ch ^ 1]]->request_length |= val; - } else if (ide_drive_is_cdrom(ide_other)) { - cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= val; + if (ide_drive_is_atapi(ide_other)) { + atapi_other->request_length &= 0xFF00; + atapi_other->request_length |= val; } ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val; ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8); return; case 0x5: /* Cylinder high */ - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ch]]->request_length &= 0xFF; - zip[atapi_zip_drives[ch]]->request_length |= (val << 8); - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[ch]]->request_length |= (val << 8); + if (ide_drive_is_atapi(ide)) { + atapi->request_length &= 0xFF; + atapi->request_length |= (val << 8); } ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); - if (ide_drive_is_zip(ide_other)) { - zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF; - zip[atapi_zip_drives[ch ^ 1]]->request_length |= (val << 8); - } else if (ide_drive_is_cdrom(ide_other)) { - cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= (val << 8); + if (ide_drive_is_atapi(ide_other)) { + atapi_other->request_length &= 0xFF; + atapi_other->request_length |= (val << 8); } ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); @@ -1402,35 +1203,21 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->cylinder = ide_other->cylinder = 0; ide->reset = ide_other->reset = 0; - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]]->error = 1; - zip[atapi_zip_drives[ide->channel]]->phase = 1; - zip[atapi_zip_drives[ide->channel]]->request_length = 0xEB14; - zip[atapi_zip_drives[ide->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | DSC_STAT; + atapi->error = 1; + atapi->phase = 1; + atapi->request_length = 0xEB14; + atapi->callback = 0LL; ide->cylinder = 0xEB14; } - if (ide_drive_is_zip(ide_other)) { - zip[atapi_zip_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide_other->channel]]->error = 1; - zip[atapi_zip_drives[ide_other->channel]]->phase = 1; - zip[atapi_zip_drives[ide_other->channel]]->request_length = 0xEB14; - zip[atapi_zip_drives[ide_other->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } else if (ide_drive_is_cdrom(ide_other)) { - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide_other->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide_other->channel]]->callback = 0LL; + if (ide_drive_is_atapi(ide_other)) { + atapi_other->status = DRDY_STAT | DSC_STAT; + atapi_other->error = 1; + atapi_other->phase = 1; + atapi_other->request_length = 0xEB14; + atapi_other->callback = 0LL; ide->cylinder = 0xEB14; } @@ -1459,24 +1246,18 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->command=val; ide->error=0; - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->error = 0; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->error = 0; + if (ide_drive_is_atapi(ide)) + atapi->error = 0; if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) { - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = DRDY_STAT; else ide->atastat = BSY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 100LL * IDE_TIME; ide_set_callback(ide->board, 100LL * IDE_TIME); timer_update_outstanding(); return; @@ -1484,18 +1265,14 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) switch (val) { case WIN_SRST: /* ATAPI Device Reset */ - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = DRDY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 100LL * IDE_TIME; ide_set_callback(ide->board, 100LL * IDE_TIME); timer_update_outstanding(); return; @@ -1509,24 +1286,21 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->blockcount = 0; /* Turn on the activity indicator *here* so that it gets turned on less times. */ - /* hdd_active(ide->hdd_num, 1); */ + /* ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); */ case WIN_READ: case WIN_READ_NORETRY: case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = BSY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 200LL * IDE_TIME; + if (ide->type == IDE_HDD) { if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { if (ide->secount) @@ -1542,21 +1316,18 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) return; case WIN_WRITE_MULTIPLE: - if (!ide->blocksize && !ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) + if (!ide->blocksize && !ide_drive_is_atapi(ide)) fatal("Write_MULTIPLE - blocksize = 0\n"); ide->blockcount = 0; /* Turn on the activity indicator *here* so that it gets turned on less times. */ - /* hdd_active(ide->hdd_num, 1); */ + /* ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); */ case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; - zip[atapi_zip_drives[ide->channel]]->pos = 0; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; - cdrom[atapi_cdrom_drives[ide->channel]]->pos = 0; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRQ_STAT | DSC_STAT | DRDY_STAT; + atapi->pos = 0; } else { ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; ide->pos=0; @@ -1570,18 +1341,14 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_IDENTIFY: /* Identify Device */ case WIN_SET_FEATURES: /* Set Features */ case WIN_READ_NATIVE_MAX: - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = BSY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 200LL * IDE_TIME; if ((ide->type == IDE_HDD) && ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { if (ide->secount) @@ -1597,7 +1364,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) return; case WIN_FORMAT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto ide_bad_command; else { ide->atastat = DRQ_STAT; @@ -1606,42 +1373,32 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = BSY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 30LL*IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 30LL*IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 30LL * IDE_TIME; ide_set_callback(ide->board, 30LL * IDE_TIME); timer_update_outstanding(); return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = BSY_STAT; - if (ide_drive_is_zip(ide_other)) - zip[atapi_zip_drives[ide_other->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide_other)) - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide_other)) + atapi_other->status = BSY_STAT; else ide_other->atastat = BSY_STAT; timer_process(); - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->callback = 200LL * IDE_TIME; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL * IDE_TIME; + if (ide_drive_is_atapi(ide)) + atapi->callback = 200LL * IDE_TIME; ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); return; @@ -1654,10 +1411,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_SETIDLE1: /* Idle */ case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: - if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = BSY_STAT; else ide->atastat = BSY_STAT; timer_process(); @@ -1667,17 +1422,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_PACKETCMD: /* ATAPI Packet */ /* Skip the command callback wait, and process immediately. */ - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ide->channel]]->packet_status = ZIP_PHASE_IDLE; - zip[atapi_zip_drives[ide->channel]]->pos=0; - zip[atapi_zip_drives[ide->channel]]->phase = 1; - zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; - ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]]->packet_status = CDROM_PHASE_IDLE; - cdrom[atapi_cdrom_drives[ide->channel]]->pos=0; - cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; + if (ide_drive_is_atapi(ide)) { + atapi->packet_status = PHASE_IDLE; + atapi->pos = 0; + atapi->phase = 1; + atapi->status = DRDY_STAT | DRQ_STAT; + if (ide->interrupt_drq) + ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ } else { ide->atastat = BSY_STAT; timer_process(); @@ -1690,12 +1441,9 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case 0xF0: default: ide_bad_command: - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]]->error = ABRT_ERR; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide->channel]]->error = ABRT_ERR; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | ERR_STAT | DSC_STAT; + atapi->error = ABRT_ERR; } else { ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; @@ -1711,20 +1459,17 @@ ide_bad_command: static uint32_t ide_read_data(ide_t *ide, int length) { - int ch = ide->channel; + scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p; uint32_t temp; if (!ide->buffer) { switch (length) { case 1: return 0xff; - case 2: return 0xffff; - case 4: return 0xffffffff; - default: return 0; } @@ -1736,49 +1481,38 @@ ide_read_data(ide_t *ide, int length) if (ide->command == WIN_PACKETCMD) { ide->pos = 0; - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { - DEBUG("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); + if (!ide_drive_is_atapi(ide)) { + DEBUG("Drive not ATAPI (position: %i)\n", ide->pos); return 0; } - if (ide_drive_is_zip(ide)) - temp = zip_read(ch, length); - else - temp = cdrom_read(ch, length); + if (ide_drive_is_atapi(ide)) + temp = ide->packet_read(ide->p, length); } else { switch (length) { case 1: temp = idebufferb[ide->pos]; ide->pos++; break; - case 2: temp = idebufferw[ide->pos >> 1]; ide->pos += 2; break; - case 4: temp = idebufferl[ide->pos >> 2]; ide->pos += 4; break; - default: return 0; } } - - if (ide->pos>=512 && ide->command != WIN_PACKETCMD) { - ide->pos=0; + if ((ide->pos >= 512) && (ide->command != WIN_PACKETCMD)) { + ide->pos = 0; ide->atastat = DRDY_STAT | DSC_STAT; - - if (ide_drive_is_zip(ide)) { - zip[atapi_zip_drives[ch]]->status = DRDY_STAT | DSC_STAT; - zip[atapi_zip_drives[ch]]->packet_status = ZIP_PHASE_IDLE; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[atapi_cdrom_drives[ch]]->status = DRDY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ch]]->packet_status = CDROM_PHASE_IDLE; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | DSC_STAT; + atapi->packet_status = PHASE_IDLE; } - - if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) { + if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || (ide->command == WIN_READ_MULTIPLE)) { ide->secount = (ide->secount - 1) & 0xff; if (ide->secount) { ide_next_sector(ide); @@ -1791,7 +1525,7 @@ ide_read_data(ide_t *ide, int length) timer_update_outstanding(); } else { if (ide->command != WIN_READ_MULTIPLE) - hdd_active(ide->hdd_num, 0); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 0); } } } @@ -1803,13 +1537,13 @@ ide_read_data(ide_t *ide, int length) static uint8_t ide_status(ide_t *ide, int ch) { + scsi_device_data_t *atapi = (scsi_device_data_t *) ide->p; + if (ide->type == IDE_NONE) return 0; else { - if (ide_drive_is_zip(ide)) - return (zip[atapi_zip_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - else if (ide_drive_is_cdrom(ide)) - return (cdrom[atapi_cdrom_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + if (ide_drive_is_atapi(ide)) + return (atapi->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); else return ide->atastat; } @@ -1820,19 +1554,22 @@ uint8_t ide_readb(uint16_t addr, void *priv) { ide_board_t *dev = (ide_board_t *) priv; - uint8_t temp = 0xff; - uint16_t tempw; - ide_t *ide; + scsi_device_data_t *atapi; int ch; + ide_t *ide; ch = dev->cur_dev; ide = ide_drives[ch]; + atapi = (scsi_device_data_t *) ide->p; + + uint8_t temp = 0xff; + uint16_t tempw; addr |= 0x90; addr &= 0xFFF7; switch (addr & 0x7) { - case 0: /* Data */ + case 0x0: /* Data */ tempw = ide_read_data(ide, 2); temp = tempw & 0xff; break; @@ -1840,14 +1577,12 @@ ide_readb(uint16_t addr, void *priv) /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), and Bit 0 = ILI (illegal length indication). */ - case 1: /* Error */ + case 0x1: /* Error */ if (ide->type == IDE_NONE) temp = 0; else { - if (ide_drive_is_zip(ide)) - temp = zip[atapi_zip_drives[ch]]->error; - else if (ide_drive_is_cdrom(ide)) - temp = cdrom[atapi_cdrom_drives[ch]]->error; + if (ide_drive_is_atapi(ide)) + temp = atapi->error; else temp = ide->error; } @@ -1866,59 +1601,52 @@ ide_readb(uint16_t addr, void *priv) 1 1 0 Data to host 0 1 0 Data from host 1 0 1 Status. */ - case 2: /* Sector count */ - if (ide_drive_is_zip(ide)) - temp = zip[atapi_zip_drives[ch]]->phase; - else if (ide_drive_is_cdrom(ide)) - temp = cdrom[atapi_cdrom_drives[ch]]->phase; + case 0x2: /* Sector count */ + if (ide_drive_is_atapi(ide)) + temp = atapi->phase; else temp = ide->secount; break; - case 3: /* Sector */ + case 0x3: /* Sector */ temp = (uint8_t)ide->sector; break; - case 4: /* Cylinder low */ + case 0x4: /* Cylinder low */ if (ide->type == IDE_NONE) temp = 0xFF; else { - if (ide_drive_is_zip(ide)) - temp = zip[atapi_zip_drives[ch]]->request_length & 0xff; - else if (ide_drive_is_cdrom(ide)) - temp = cdrom[atapi_cdrom_drives[ch]]->request_length & 0xff; + if (ide_drive_is_atapi(ide)) + temp = atapi->request_length & 0xff; else temp = ide->cylinder & 0xff; } break; - case 5: /* Cylinder high */ + case 0x5: /* Cylinder high */ if (ide->type == IDE_NONE) temp = 0xFF; else { - if (ide_drive_is_zip(ide)) - temp = zip[atapi_zip_drives[ch]]->request_length >> 8; - else if (ide_drive_is_cdrom(ide)) - temp = cdrom[atapi_cdrom_drives[ch]]->request_length >> 8; + if (ide_drive_is_atapi(ide)) + temp = atapi->request_length >> 8; else temp = ide->cylinder >> 8; } break; - case 6: /* Drive/Head */ + case 0x6: /* Drive/Head */ temp = (uint8_t)(ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); break; /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is DF (drive fault). */ - case 7: /* Status */ + case 0x7: /* Status */ ide_irq_lower(ide); temp = ide_status(ide, ch); break; } - DBGLOG(2, "ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); - + DEBUG("ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); return temp; } @@ -1926,8 +1654,10 @@ ide_readb(uint16_t addr, void *priv) uint8_t ide_read_alt_status(uint16_t addr, void *priv) { - ide_board_t *dev = (ide_board_t *) priv; uint8_t temp = 0xff; + + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; int ch; @@ -1938,8 +1668,7 @@ ide_read_alt_status(uint16_t addr, void *priv) Reading the alternate status does *NOT* clear the IRQ. */ temp = ide_status(ide, ch); - DBGLOG(2, "ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); - + DEBUG("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); return temp; } @@ -1959,13 +1688,9 @@ ide_readw(uint16_t addr, void *priv) case 0x0: /* Data */ temp = ide_read_data(ide, 2); break; - - default: - break; } - DBGLOG(3, "ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); - + DBGLOG(1, "ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); return temp; } @@ -1989,8 +1714,7 @@ ide_readl(uint16_t addr, void *priv) break; } - DBGLOG(3, "ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); - + DBGLOG(1, "ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); return temp; } @@ -1999,14 +1723,16 @@ static void ide_callback(void *priv) { ide_board_t *dev = (ide_board_t *) priv; + scsi_device_data_t *atapi, *atapi_other; ide_t *ide, *ide_other; int snum, ret, ch; - int cdrom_id, cdrom_id_other; - int zip_id, zip_id_other; ch = dev->cur_dev; + ide = ide_drives[ch]; + atapi = (scsi_device_data_t *) ide->p; ide_other = ide_drives[ch ^ 1]; + atapi_other = (scsi_device_data_t *) ide_other->p; ide_set_callback(ide->board, 0LL); @@ -2026,29 +1752,19 @@ ide_callback(void *priv) ide->reset = ide_other->reset = 0; ide_set_signature(ide); - if (ide_drive_is_zip(ide)) { - zip_id = atapi_zip_drives[ch]; - zip[zip_id]->status = DRDY_STAT | DSC_STAT; - zip[zip_id]->error = 1; - } else if (ide_drive_is_cdrom(ide)) { - cdrom_id = atapi_cdrom_drives[ch]; - cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - if (cdrom[cdrom_id]->handler->stop) - cdrom[cdrom_id]->handler->stop(cdrom_id); + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | DSC_STAT; + atapi->error = 1; + if (ide->stop) + ide->stop(ide->p); } ide_set_signature(ide_other); - if (ide_drive_is_zip(ide_other)) { - zip_id_other = atapi_zip_drives[ch ^ 1]; - zip[zip_id_other]->status = DRDY_STAT | DSC_STAT; - zip[zip_id_other]->error = 1; - } else if (ide_drive_is_cdrom(ide_other)) { - cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; - cdrom[cdrom_id_other]->status = DRDY_STAT | DSC_STAT; - cdrom[cdrom_id_other]->error = 1; - if (cdrom[cdrom_id_other]->handler->stop) - cdrom[cdrom_id_other]->handler->stop(cdrom_id_other); + if (ide_drive_is_atapi(ide_other)) { + atapi_other->status = DRDY_STAT | DSC_STAT; + atapi_other->error = 1; + if (ide_other->stop) + ide_other->stop(ide_other->p); } return; @@ -2056,12 +1772,6 @@ ide_callback(void *priv) DEBUG("CALLBACK %02X %i %i\n", ide->command, ide->reset,ch); - cdrom_id = atapi_cdrom_drives[ch]; - cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; - - zip_id = atapi_zip_drives[ch]; - zip_id_other = atapi_zip_drives[ch ^ 1]; - if (((ide->command >= WIN_RECAL) && (ide->command <= 0x1F)) || ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { if (ide->type != IDE_HDD) @@ -2080,24 +1790,22 @@ ide_callback(void *priv) /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ case WIN_SRST: /*ATAPI Device Reset */ + ide->atastat = DRDY_STAT | DSC_STAT; ide->error = 1; /*Device passed*/ ide->secount = 1; - ide->sector = 1; + ide->sector = 1; ide_set_signature(ide); - if (ide_drive_is_zip(ide)) { - zip[zip_id]->status = DRDY_STAT | DSC_STAT; - zip[zip_id]->error = 1; - zip_reset(zip[zip_id]); - } else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - cdrom_reset(cdrom[cdrom_id]); + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | DSC_STAT; + atapi->error = 1; + if (ide->device_reset) + ide->device_reset(ide->p); } ide_irq_raise(ide); - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) ide->service = 0; return; @@ -2105,10 +1813,8 @@ ide_callback(void *priv) case WIN_STANDBYNOW1: case WIN_IDLENOW1: case WIN_SETIDLE1: - if (ide_drive_is_zip(ide)) - zip[zip_id]->status = DRDY_STAT | DSC_STAT; - else if (ide_drive_is_cdrom(ide)) - cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + if (ide_drive_is_atapi(ide)) + atapi->status = DRDY_STAT | DSC_STAT; else ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); @@ -2116,12 +1822,9 @@ ide_callback(void *priv) case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: - if (ide_drive_is_zip(ide)) { - zip[zip_id]->phase = 0xFF; - zip[zip_id]->status = DRDY_STAT | DSC_STAT; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->phase = 0xFF; - cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + if (ide_drive_is_atapi(ide)) { + atapi->phase = 0xFF; + atapi->status = DRDY_STAT | DSC_STAT; } ide->secount = 0xFF; ide->atastat = DRDY_STAT | DSC_STAT; @@ -2130,7 +1833,7 @@ ide_callback(void *priv) case WIN_READ: case WIN_READ_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { + if (ide_drive_is_atapi(ide)) { ide_set_signature(ide); goto abort_cmd; } @@ -2155,12 +1858,12 @@ ide_callback(void *priv) ide_irq_raise(ide); - hdd_active(ide->hdd_num, 1); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); return; case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + if (ide_drive_is_atapi(ide) || !IDE_PCI || (ide->board >= 2)) { DEBUG("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); goto abort_cmd; } @@ -2199,7 +1902,7 @@ ide_callback(void *priv) ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - hdd_active(ide->hdd_num, 0); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 0); } } else { DEBUG("IDE %i: DMA read aborted (no bus master)\n", ide->channel); @@ -2214,7 +1917,7 @@ ide_callback(void *priv) command has been executed or when Read Multiple commands are disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) + if (ide_drive_is_atapi(ide) || !ide->blocksize) goto abort_cmd; if (ide->cfg_spt == 0) goto id_not_found; @@ -2243,7 +1946,7 @@ ide_callback(void *priv) case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; if (ide->cfg_spt == 0) goto id_not_found; @@ -2254,16 +1957,16 @@ ide_callback(void *priv) ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide->pos=0; ide_next_sector(ide); - hdd_active(ide->hdd_num, 1); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); } else { ide->atastat = DRDY_STAT | DSC_STAT; - hdd_active(ide->hdd_num, 0); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 0); } return; case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + if (ide_drive_is_atapi(ide) || !IDE_PCI || (ide->board >= 2)) { DEBUG("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); goto abort_cmd; } @@ -2300,7 +2003,7 @@ ide_callback(void *priv) ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - hdd_active(ide->hdd_num, 1); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 0); } } else { DEBUG("IDE %i: DMA write aborted (no bus master)\n", ide->channel); @@ -2310,7 +2013,7 @@ ide_callback(void *priv) return; case WIN_WRITE_MULTIPLE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; if (ide->cfg_spt == 0) goto id_not_found; @@ -2327,24 +2030,24 @@ ide_callback(void *priv) ide_next_sector(ide); } else { ide->atastat = DRDY_STAT | DSC_STAT; - hdd_active(ide->hdd_num, 0); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 0); } return; case WIN_VERIFY: case WIN_VERIFY_ONCE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; if (ide->cfg_spt == 0) goto id_not_found; ide->pos=0; ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - hdd_active(ide->hdd_num, 1); + ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); return; case WIN_FORMAT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; if (ide->cfg_spt == 0) goto id_not_found; @@ -2353,20 +2056,16 @@ ide_callback(void *priv) ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - /* hdd_active(ide->hdd_num, 1); */ + /* ui_sb_icon_update(SB_DISK | hdd[ide->hdd_num].bus, 1); */ return; case WIN_DRIVE_DIAGNOSTICS: ide_set_signature(ide); ide->error=1; /*No error detected*/ - if (ide_drive_is_zip(ide)) { - zip[zip_id]->status = 0; - zip[zip_id]->error = 1; - ide_irq_raise(ide); - } else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = 0; - cdrom[cdrom_id]->error = 1; + if (ide_drive_is_atapi(ide)) { + atapi->status = 0; + atapi->error = 1; ide_irq_raise(ide); } else { ide->atastat = DRDY_STAT | DSC_STAT; @@ -2377,12 +2076,9 @@ ide_callback(void *priv) ide_set_signature(ide_other); ide_other->error=1; /*No error detected*/ - if (ide_drive_is_zip(ide_other)) { - zip[zip_id_other]->status = 0; - zip[zip_id_other]->error = 1; - } else if (ide_drive_is_cdrom(ide_other)) { - cdrom[cdrom_id_other]->status = 0; - cdrom[cdrom_id_other]->error = 1; + if (ide_drive_is_atapi(ide_other)) { + atapi_other->status = 0; + atapi_other->error = 1; } else { ide_other->atastat = DRDY_STAT | DSC_STAT; ide_other->error = 1; @@ -2393,7 +2089,7 @@ ide_callback(void *priv) return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; if (ide->cfg_spt == 0) { /* Only accept after RESET or DIAG. */ @@ -2407,29 +2103,20 @@ ide_callback(void *priv) return; case WIN_PIDENTIFY: /* Identify Packet Device */ - if (ide_drive_is_zip(ide)) { + if (ide_drive_is_atapi(ide)) { ide_identify(ide); ide->pos = 0; - zip[zip_id]->phase = 2; - zip[zip_id]->pos = 0; - zip[zip_id]->error = 0; - zip[zip_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } else if (ide_drive_is_cdrom(ide)) { - ide_identify(ide); - ide->pos = 0; - cdrom[cdrom_id]->phase = 2; - cdrom[cdrom_id]->pos = 0; - cdrom[cdrom_id]->error = 0; - cdrom[cdrom_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + atapi->phase = 2; + atapi->pos = 0; + atapi->error = 0; + atapi->status = DRQ_STAT | DRDY_STAT | DSC_STAT; ide_irq_raise(ide); return; } goto abort_cmd; case WIN_SET_MULTIPLE_MODE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + if (ide_drive_is_atapi(ide)) goto abort_cmd; ide->blocksize = ide->secount; ide->atastat = DRDY_STAT | DSC_STAT; @@ -2443,12 +2130,9 @@ ide_callback(void *priv) if (!ide_set_features(ide)) goto abort_cmd; else { - if (ide_drive_is_zip(ide)) { - zip[zip_id]->status = DRDY_STAT | DSC_STAT; - zip[zip_id]->pos = 0; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; - cdrom[cdrom_id]->pos = 0; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | DSC_STAT; + atapi->pos = 0; } ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); @@ -2479,13 +2163,10 @@ ide_callback(void *priv) return; case WIN_PACKETCMD: /* ATAPI Packet */ - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) + if (!ide_drive_is_atapi(ide) || !ide->packet_callback) goto abort_cmd; - if (ide_drive_is_zip(ide)) - zip_phase_callback(zip[atapi_zip_drives[ch]]); - else - cdrom_phase_callback(cdrom[atapi_cdrom_drives[ch]]); + ide->packet_callback(ide->p); return; case 0xFF: @@ -2494,14 +2175,10 @@ ide_callback(void *priv) abort_cmd: ide->command = 0; - if (ide_drive_is_zip(ide)) { - zip[zip_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; - zip[zip_id]->error = ABRT_ERR; - zip[zip_id]->pos = 0; - } else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; - cdrom[cdrom_id]->error = ABRT_ERR; - cdrom[cdrom_id]->pos = 0; + if (ide_drive_is_atapi(ide)) { + atapi->status = DRDY_STAT | ERR_STAT | DSC_STAT; + atapi->error = ABRT_ERR; + atapi->pos = 0; } else { ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; @@ -2534,15 +2211,14 @@ ide_set_handlers(uint8_t board) ide_boards[board]); } io_sethandler(ide_base_main[board] + 1, 7, - ide_readb, NULL, NULL, - ide_writeb, NULL, NULL, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, ide_boards[board]); } - if (ide_side_main[board] & 0x300) { io_sethandler(ide_side_main[board], 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, ide_boards[board]); } } @@ -2563,13 +2239,12 @@ ide_remove_handlers(uint8_t board) ide_boards[board]); } io_removehandler(ide_base_main[board] + 1, 7, - ide_readb, NULL, NULL, - ide_writeb, NULL, NULL, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, ide_boards[board]); - io_removehandler(ide_side_main[board], 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, ide_boards[board]); } @@ -2619,21 +2294,19 @@ ide_set_side(int controller, uint16_t port) static void * ide_ter_init(const device_t *info) { - ide_board_t *dev; + ide_boards[2] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(ide_boards[2], 0, sizeof(ide_board_t)); - dev = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); - memset(dev, 0x00, sizeof(ide_board_t)); - dev->irq = device_get_config_int("irq"); - dev->cur_dev = 4; - ide_boards[2] = dev; + ide_boards[2]->irq = device_get_config_int("irq"); + ide_boards[2]->cur_dev = 4; ide_set_handlers(2); - timer_add(ide_callback, &dev->callback, &dev->callback, dev); + timer_add(ide_callback, &ide_boards[2]->callback, &ide_boards[2]->callback, ide_boards[2]); ide_board_init(2); - return(dev); + return(ide_drives); } @@ -2653,22 +2326,19 @@ ide_ter_close(void *priv) static void * ide_qua_init(const device_t *info) { - ide_board_t *dev; + ide_boards[3] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(ide_boards[3], 0, sizeof(ide_board_t)); - dev = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); - memset(dev, 0x00, sizeof(ide_board_t)); - dev->irq = device_get_config_int("irq"); - dev->cur_dev = 6; - - ide_boards[3] = dev; + ide_boards[3]->irq = device_get_config_int("irq"); + ide_boards[3]->cur_dev = 6; ide_set_handlers(3); - timer_add(ide_callback, &dev->callback, &dev->callback, dev); + timer_add(ide_callback, &ide_boards[3]->callback, &ide_boards[3]->callback, ide_boards[3]); ide_board_init(3); - return(dev); + return(ide_drives); } @@ -2700,7 +2370,7 @@ ide_xtide_init(void) ide_clear_bus_master(); if (!ide_boards[0]) { - ide_boards[0] = (ide_board_t *) mem_alloc(sizeof(ide_board_t)); + ide_boards[0] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); memset(ide_boards[0], 0, sizeof(ide_board_t)); ide_boards[0]->cur_dev = 0; @@ -2748,14 +2418,14 @@ secondary_ide_check(void) int secondary_cdroms = 0; int secondary_zips = 0; - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].ide_channel >= 2) && (zip_drives[i].ide_channel <= 3) && + for (i=0; i= 2) && (zip_drives[i].bus_id.ide_channel <= 3) && (zip_drives[i].bus_type == ZIP_BUS_ATAPI)) secondary_zips++; } - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom_drives[i].ide_channel >= 2) && (cdrom_drives[i].ide_channel <= 3) && - (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI)) + for (i=0; i= 2) && (cdrom[i].bus_id.ide_channel <= 3) && + (cdrom[i].bus_type == CDROM_BUS_ATAPI)) secondary_cdroms++; } if (!secondary_zips && !secondary_cdroms) @@ -2763,15 +2433,12 @@ secondary_ide_check(void) } -/* Initialization of standalone IDE controller instance. */ static void * ide_init(const device_t *info) { - int type = info->local & 255; + DEBUG("Initializing IDE...\n"); - DEBUG("Initializing IDE (type %i) ...\n", type); - - switch(type) { + switch(info->local) { case 0: /* ISA, single-channel */ case 2: /* ISA, dual-channel */ case 3: /* ISA, dual-channel, optional 2nd channel */ @@ -2779,10 +2446,10 @@ ide_init(const device_t *info) case 6: /* VLB, dual-channel */ case 8: /* PCI, single-channel */ case 10: /* PCI, dual-channel */ - if (! ide_inited) { + if (!ide_inited) { pio_override = 0; - if (! (type & 8)) + if (!(info->local & 8)) ide_clear_bus_master(); } @@ -2791,14 +2458,13 @@ ide_init(const device_t *info) memset(ide_boards[0], 0, sizeof(ide_board_t)); ide_boards[0]->irq = 14; ide_boards[0]->cur_dev = 0; - if (type & 8) + if (info->local & 8) ide_boards[0]->bit32 = 1; ide_base_main[0] = 0x1f0; ide_side_main[0] = 0x3f6; ide_set_handlers(0); - - timer_add(ide_callback, &ide_boards[0]->callback, - &ide_boards[0]->callback, ide_boards[0]); + timer_add(ide_callback, &ide_boards[0]->callback, &ide_boards[0]->callback, + ide_boards[0]); DEBUG("Callback 0 pointer: %08X\n", &ide_boards[0]->callback); ide_board_init(0); @@ -2806,24 +2472,23 @@ ide_init(const device_t *info) ide_inited |= 1; } - if ((type & 3) && !(ide_inited & 2)) { + if ((info->local & 3) && !(ide_inited & 2)) { ide_boards[1] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); memset(ide_boards[1], 0, sizeof(ide_board_t)); ide_boards[1]->irq = 15; ide_boards[1]->cur_dev = 2; - if (type & 8) + if (info->local & 8) ide_boards[1]->bit32 = 1; ide_base_main[1] = 0x170; ide_side_main[1] = 0x376; ide_set_handlers(1); - - timer_add(ide_callback, &ide_boards[1]->callback, - &ide_boards[1]->callback, ide_boards[1]); + timer_add(ide_callback, &ide_boards[1]->callback, &ide_boards[1]->callback, + ide_boards[1]); DEBUG("Callback 1 pointer: %08X\n", &ide_boards[1]->callback); ide_board_init(1); - if (type & 1) + if (info->local & 1) secondary_ide_check(); ide_inited |= 2; diff --git a/src/devices/disk/hdc_ide_xta.c b/src/devices/disk/hdc_ide_xta.c index 4a719c6..15777e8 100644 --- a/src/devices/disk/hdc_ide_xta.c +++ b/src/devices/disk/hdc_ide_xta.c @@ -46,7 +46,7 @@ * * NOTE: The XTA interface is 0-based for sector numbers !! * - * Version: @(#)hdc_ide_xta.c 1.0.9 2018/10/05 + * Version: @(#)hdc_ide_xta.c 1.0.10 2018/10/15 * * Author: Fred N. van Kempen, * @@ -1070,8 +1070,8 @@ xta_init(const device_t *info) /* Load any disks for this device class. */ c = 0; for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == bus) && (hdd[i].id.ide_channel < XTA_NUM)) { - drive = &dev->drives[hdd[i].id.ide_channel]; + if ((hdd[i].bus == bus) && (hdd[i].bus_id.ide_channel < XTA_NUM)) { + drive = &dev->drives[hdd[i].bus_id.ide_channel]; if (! hdd_image_load(i)) { drive->present = 0; @@ -1092,7 +1092,7 @@ xta_init(const device_t *info) drive->tracks = drive->cfg_tracks; INFO("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", - dev->name, hdd[i].id.ide_channel, drive->tracks, + dev->name, hdd[i].bus_id.ide_channel, drive->tracks, drive->hpc, drive->spt, i); if (++c > XTA_NUM) break; diff --git a/src/devices/disk/hdc_st506_at.c b/src/devices/disk/hdc_st506_at.c index cac46f6..e83baa4 100644 --- a/src/devices/disk/hdc_st506_at.c +++ b/src/devices/disk/hdc_st506_at.c @@ -12,7 +12,7 @@ * based design. Most cards were WD1003-WA2 or -WAH, where the * -WA2 cards had a floppy controller as well (to save space.) * - * Version: @(#)hdc_st506_at.c 1.0.11 2018/09/22 + * Version: @(#)hdc_st506_at.c 1.0.12 2018/10/15 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -710,8 +710,8 @@ st506_init(const device_t *info) c = 0; for (d = 0; d < HDD_NUM; d++) { - if ((hdd[d].bus == HDD_BUS_ST506) && (hdd[d].id.st506_channel < ST506_NUM)) { - loadhd(dev, hdd[d].id.st506_channel, d, hdd[d].fn); + if ((hdd[d].bus == HDD_BUS_ST506) && (hdd[d].bus_id.st506_channel < ST506_NUM)) { + loadhd(dev, hdd[d].bus_id.st506_channel, d, hdd[d].fn); hdd_active(d, 0); diff --git a/src/devices/disk/hdc_st506_xt.c b/src/devices/disk/hdc_st506_xt.c index aea54d1..a95a454 100644 --- a/src/devices/disk/hdc_st506_xt.c +++ b/src/devices/disk/hdc_st506_xt.c @@ -41,7 +41,7 @@ * Since all controllers (including the ones made by DTC) use * (mostly) the same API, we keep them all in this module. * - * Version: @(#)hdc_st506_xt.c 1.0.13 2018/10/05 + * Version: @(#)hdc_st506_xt.c 1.0.14 2018/10/15 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -854,9 +854,9 @@ st506_init(const device_t *info) c = 0; for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_ST506) && (hdd[i].id.st506_channel < ST506_NUM)) { - DEBUG("Found ST506 hard disk on channel %i\n", hdd[i].id.st506_channel); - loadhd(dev, hdd[i].id.st506_channel, i, hdd[i].fn); + if ((hdd[i].bus == HDD_BUS_ST506) && (hdd[i].bus_id.st506_channel < ST506_NUM)) { + DEBUG("Found ST506 hard disk on channel %i\n", hdd[i].bus_id.st506_channel); + loadhd(dev, hdd[i].bus_id.st506_channel, i, hdd[i].fn); if (++c > ST506_NUM) break; } diff --git a/src/devices/disk/hdd.h b/src/devices/disk/hdd.h index 0ca1852..de91009 100644 --- a/src/devices/disk/hdd.h +++ b/src/devices/disk/hdd.h @@ -8,7 +8,7 @@ * * Definitions for the hard disk image handler. * - * Version: @(#)hdd.h 1.0.10 2018/09/16 + * Version: @(#)hdd.h 1.0.11 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -99,11 +99,11 @@ typedef struct { uint8_t st506_channel; /* bus channel ID's */ uint8_t esdi_channel; uint8_t ide_channel; - union { + struct { int8_t id; int8_t lun; } scsi; - } id; + } bus_id; uint32_t base; diff --git a/src/devices/disk/zip.c b/src/devices/disk/zip.c index 61f64e6..764f5c9 100644 --- a/src/devices/disk/zip.c +++ b/src/devices/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.16 2018/10/11 + * Version: @(#)zip.c 1.0.17 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog zip_log #include "../../emu.h" #include "../../config.h" #include "../../timer.h" @@ -70,36 +71,13 @@ #define zipbufferb dev->buffer -#ifdef ENABLE_ZIP_LOG -int zip_do_log = ENABLE_ZIP_LOG; -#endif -zip_t *zip[ZIP_NUM]; +zip_t *zip[ZIP_NUM] = { NULL, NULL, NULL, NULL }; zip_drive_t zip_drives[ZIP_NUM]; -uint8_t atapi_zip_drives[8] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; -uint8_t scsi_zip_drives[16][8] = { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } -}; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t zip_command_flags[0x100] = { +const uint8_t zip_command_flags[0x100] = +{ IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, @@ -169,21 +147,21 @@ const uint8_t zip_command_flags[0x100] = { }; static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_UNK_PAGE_02 | - GPMODEP_UNK_PAGE_2F | + GPMODEP_DISCONNECT_PAGE | + GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); - static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | - GPMODEP_UNK_PAGE_05 | - GPMODEP_UNK_PAGE_08 | - GPMODEP_UNK_PAGE_2F | + GPMODEP_FLEXIBLE_DISK_PAGE | + GPMODEP_CACHING_PAGE | + GPMODEP_IOMEGA_PAGE | GPMODEP_ALL_PAGES); -static const mode_sense_pages_t zip_mode_sense_pages_default = { - { + +static const mode_sense_pages_t zip_mode_sense_pages_default = +{ { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -228,7 +206,7 @@ static const mode_sense_pages_t zip_mode_sense_pages_default = { { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } }; static const mode_sense_pages_t zip_250_mode_sense_pages_default = @@ -238,10 +216,10 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -279,14 +257,14 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } }; static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -331,7 +309,7 @@ static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0xff, 0x0f } } }; static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = @@ -341,10 +319,10 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -383,14 +361,15 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } } }; static const mode_sense_pages_t zip_mode_sense_pages_changeable = { { { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xFF, 0xFF, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -435,20 +414,20 @@ static const mode_sense_pages_t zip_mode_sense_pages_changeable = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } }; static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = { { { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xFF, 0xFF, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + {GPMODE_FLEXIBLE_DISK_PAGE, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { GPMODE_CACHING_PAGE, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -487,19 +466,30 @@ static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } + { GPMODE_IOMEGA_PAGE, 0x04, 0xff, 0xff, 0xff, 0xff } } }; +static void zip_command_complete(zip_t *dev); +static void zip_init(zip_t *dev); + +static void zip_callback(void *p); + + +#ifdef ENABLE_ZIP_LOG +int zip_do_log = ENABLE_ZIP_LOG; +#endif + + static void -zip_log(const char *format, ...) +zip_log(int level, const char *fmt, ...) { #ifdef ENABLE_ZIP_LOG va_list ap; - if (zip_do_log) { - va_start(ap, format); - pclog_ex(format, ap); + if (zip_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); va_end(ap); } #endif @@ -512,7 +502,8 @@ find_zip_for_channel(uint8_t channel) uint8_t i = 0; for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && + (zip_drives[i].bus_id.ide_channel == channel)) return i; } return 0xff; @@ -543,7 +534,7 @@ zip_load(zip_t *dev, const wchar_t *fn) if (dev->drv->is_250) { if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", + DEBUG("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); fclose(dev->drv->f); dev->drv->f = NULL; @@ -553,7 +544,7 @@ zip_load(zip_t *dev, const wchar_t *fn) } } else { if (size != (ZIP_SECTORS << 9)) { - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", + DEBUG("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", ZIP_SECTORS << 9); fclose(dev->drv->f); dev->drv->f = NULL; @@ -608,69 +599,19 @@ zip_disk_close(zip_t *dev) } -void -zip_build_atapi_map(void) -{ - uint8_t i; - - memset(atapi_zip_drives, 0xff, 8); - - for (i = 0; i < 8; i++) - atapi_zip_drives[i] = find_zip_for_channel(i); -} - - -int -find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i; - - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && - (zip_drives[i].scsi_device_id == scsi_id) && - (zip_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - - return 0xff; -} - - -void -zip_build_scsi_map(void) -{ - uint8_t i, j; - - for (i = 0; i < 16; i++) { - memset(scsi_zip_drives[i], 0xff, 8); - - for (j = 0; j < 8; j++) - scsi_zip_drives[i][j] = find_zip_for_scsi_id(i, j); - } -} - - static void zip_set_callback(zip_t *dev) { if (dev->drv->bus_type != ZIP_BUS_SCSI) - ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); + ide_set_callback(dev->drv->bus_id.ide_channel >> 1, dev->callback); } -#if 0 /*UNUSED*/ static void -zip_reset_cdb_len(zip_t *dev) +zip_set_signature(void *p) { - if (dev->drv->bus_type != ZIP_BUS_SCSI) - dev->cdb_len = dev->cdb_len_setting ? 16 : 12; -} -#endif + zip_t *dev = (zip_t *) p; - -void -zip_set_signature(zip_t *dev) -{ if (dev->id >= ZIP_NUM) return; dev->phase = 1; @@ -678,7 +619,7 @@ zip_set_signature(zip_t *dev) } -void +static void zip_init(zip_t *dev) { if (dev->id >= ZIP_NUM) @@ -692,7 +633,7 @@ zip_init(zip_t *dev) dev->drv->bus_mode |= 2; if (dev->drv->bus_type < ZIP_BUS_SCSI) dev->drv->bus_mode |= 1; - zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + DEBUG("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); if (dev->drv->bus_type < ZIP_BUS_SCSI) zip_set_signature(dev); dev->status = READY_STAT | DSC_STAT; @@ -723,13 +664,13 @@ zip_current_mode(zip_t *dev) if (!zip_supports_pio(dev) && !zip_supports_dma(dev)) return 0; if (zip_supports_pio(dev) && !zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); + DEBUG("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); return 1; } if (!zip_supports_pio(dev) && zip_supports_dma(dev)) return 2; if (zip_supports_pio(dev) && zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); + DEBUG("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); return (dev->features & 1) ? 2 : 1; } @@ -738,13 +679,15 @@ zip_current_mode(zip_t *dev) /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int -zip_ZIP_PHASE_to_scsi(zip_t *dev) +static int +zip_err_stat_to_scsi(void *p) { + zip_t *dev = (zip_t *) p; + if (dev->status & ERR_STAT) return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; + + return SCSI_STATUS_OK; } @@ -778,9 +721,7 @@ static void zip_mode_sense_load(zip_t *dev) { wchar_t file_name[512]; -#if 0 FILE *f; -#endif int i; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); @@ -816,13 +757,9 @@ zip_mode_sense_load(zip_t *dev) swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", dev->id); else swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", dev->id); - -#if 0 - /* FIXME: Doesnt do anything. Maybe "rb+" was meant? --FvK */ f = plat_fopen(nvr_path(file_name), L"rb"); if (f) fclose(f); -#endif } @@ -843,9 +780,10 @@ zip_mode_sense_save(zip_t *dev) } -int -zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +static int +zip_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { + zip_t *dev = (zip_t *) p; int size = 0; if (dev->drv->is_250) @@ -903,19 +841,22 @@ zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) static uint32_t -zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) { - uint8_t page_control = (type >> 6) & 3; - uint8_t msplen; uint64_t pf; - int i, j; + uint8_t page_control = (page >> 6) & 3; if (dev->drv->is_250) pf = zip_250_mode_sense_page_flags; else pf = zip_mode_sense_page_flags; - type &= 0x3f; + int i = 0; + int j = 0; + + uint8_t msplen; + + page &= 0x3f; if (block_descriptor_len) { if (dev->drv->is_250) { @@ -936,12 +877,12 @@ zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t blo } for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (pf & (1LL << dev->current_page_code)) { + if ((page == GPMODE_ALL_PAGES) || (page == i)) { + if (pf & (1LL << ((uint64_t) page))) { buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); msplen = zip_mode_sense_read(dev, page_control, i, 1); buf[pos++] = msplen; - zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + DEBUG("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); for (j = 0; j < msplen; j++) buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); } @@ -1008,7 +949,6 @@ zip_command_bus(zip_t *dev) dev->phase = 1; dev->pos = 0; dev->callback = 1LL * ZIP_TIME; - zip_set_callback(dev); } @@ -1022,9 +962,8 @@ zip_command_common(zip_t *dev) dev->status = BUSY_STAT; dev->phase = 1; dev->pos = 0; - - if (dev->packet_status == ZIP_PHASE_COMPLETE) { - zip_phase_callback(dev); + if (dev->packet_status == PHASE_COMPLETE) { + zip_callback((void *) dev); dev->callback = 0LL; } else { if (dev->drv->bus_type == ZIP_BUS_SCSI) { @@ -1040,7 +979,7 @@ zip_command_common(zip_t *dev) period = 1000000.0 / bytes_per_second; dusec = (double) TIMER_USEC; dusec = dusec * period * (double) (dev->packet_len); - dev->callback = (int64_t)dusec; + dev->callback = ((int64_t) dusec); } zip_set_callback(dev); @@ -1050,8 +989,7 @@ zip_command_common(zip_t *dev) static void zip_command_complete(zip_t *dev) { - dev->packet_status = ZIP_PHASE_COMPLETE; - + dev->packet_status = PHASE_COMPLETE; zip_command_common(dev); } @@ -1059,26 +997,23 @@ zip_command_complete(zip_t *dev) static void zip_command_read(zip_t *dev) { - dev->packet_status = ZIP_PHASE_DATA_IN; + dev->packet_status = PHASE_DATA_IN; zip_command_common(dev); - dev->total_read = 0; } static void zip_command_read_dma(zip_t *dev) { - dev->packet_status = ZIP_PHASE_DATA_IN_DMA; + dev->packet_status = PHASE_DATA_IN_DMA; zip_command_common(dev); - dev->total_read = 0; } static void zip_command_write(zip_t *dev) { - dev->packet_status = ZIP_PHASE_DATA_OUT; - + dev->packet_status = PHASE_DATA_OUT; zip_command_common(dev); } @@ -1086,13 +1021,12 @@ zip_command_write(zip_t *dev) static void zip_command_write_dma(zip_t *dev) { - dev->packet_status = ZIP_PHASE_DATA_OUT_DMA; - + dev->packet_status = PHASE_DATA_OUT_DMA; zip_command_common(dev); } -/* dev = Current ZIP device; +/* id = Current ZIP device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; @@ -1100,9 +1034,8 @@ zip_command_write_dma(zip_t *dev) static void zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) { - zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, - alloc_len, direction, dev->request_length); + DEBUG("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); dev->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) @@ -1131,16 +1064,14 @@ zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int d } } - zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, - dev->packet_len, dev->pos, dev->phase); + DEBUG("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); } static void zip_sense_clear(zip_t *dev, int command) { - dev->previous_command = command; zip_sense_key = zip_asc = zip_ascq = 0; } @@ -1148,13 +1079,10 @@ zip_sense_clear(zip_t *dev, int command) static void zip_set_phase(zip_t *dev, uint8_t phase) { - uint8_t scsi_id = dev->drv->scsi_device_id; - uint8_t scsi_lun = dev->drv->scsi_device_lun; - if (dev->drv->bus_type != ZIP_BUS_SCSI) return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].phase = phase; } @@ -1162,7 +1090,6 @@ static void zip_cmd_error(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) dev->error |= MCR_ERR; @@ -1171,11 +1098,8 @@ zip_cmd_error(zip_t *dev) dev->pos = 0; dev->packet_status = 0x80; dev->callback = 50LL * ZIP_TIME; - zip_set_callback(dev); - - zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", - dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); + DEBUG("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); } @@ -1183,7 +1107,6 @@ static void zip_unit_attention(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) dev->error |= MCR_ERR; @@ -1192,10 +1115,8 @@ zip_unit_attention(zip_t *dev) dev->pos = 0; dev->packet_status = 0x80; dev->callback = 50LL * ZIP_TIME; - zip_set_callback(dev); - - zip_log("ZIP %i: UNIT ATTENTION\n", dev->id); + DEBUG("ZIP %i: UNIT ATTENTION\n", dev->id); } @@ -1203,7 +1124,6 @@ static void zip_bus_master_error(zip_t *dev) { zip_sense_key = zip_asc = zip_ascq = 0; - zip_cmd_error(dev); } @@ -1214,7 +1134,6 @@ zip_not_ready(zip_t *dev) zip_sense_key = SENSE_NOT_READY; zip_asc = ASC_MEDIUM_NOT_PRESENT; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1225,7 +1144,6 @@ zip_write_protected(zip_t *dev) zip_sense_key = SENSE_UNIT_ATTENTION; zip_asc = ASC_WRITE_PROTECTED; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1236,7 +1154,6 @@ zip_invalid_lun(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_LUN; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1247,7 +1164,6 @@ zip_illegal_opcode(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_ILLEGAL_OPCODE; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1258,7 +1174,6 @@ zip_lba_out_of_range(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_LBA_OUT_OF_RANGE; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1269,9 +1184,7 @@ zip_invalid_field(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; zip_ascq = 0; - zip_cmd_error(dev); - dev->status = 0x53; } @@ -1282,9 +1195,7 @@ zip_invalid_field_pl(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; zip_ascq = 0; - zip_cmd_error(dev); - dev->status = 0x53; } @@ -1295,7 +1206,6 @@ zip_data_phase_error(zip_t *dev) zip_sense_key = SENSE_ILLEGAL_REQUEST; zip_asc = ASC_DATA_PHASE_ERROR; zip_ascq = 0; - zip_cmd_error(dev); } @@ -1303,21 +1213,17 @@ zip_data_phase_error(zip_t *dev) static int zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) { - dev->data_pos = 0; - *len = 0; - if (! dev->sector_len) { + if (!dev->sector_len) { zip_command_complete(dev); return -1; } - zip_log("%sing %i blocks starting from %i...\n", - out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); + DEBUG("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); if (dev->sector_pos >= dev->drv->medium_size) { - zip_log("ZIP %i: Trying to %s beyond the end of disk\n", - dev->id, out ? "write" : "read"); + DEBUG("ZIP %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); zip_lba_out_of_range(dev); return 0; } @@ -1330,7 +1236,7 @@ zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) else fread(zipbufferb, 1, *len, dev->drv->f); - zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + DEBUG("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); dev->sector_pos += dev->requested_blocks; dev->sector_len -= dev->requested_blocks; @@ -1362,40 +1268,29 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) int ready = 0; if (dev->drv->bus_type == ZIP_BUS_SCSI) { -#if 0 - if (((dev->request_length >> 5) & 7) != dev->drv->scsi_device_lun) { -#else if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { -#endif - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); + DEBUG("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); zip_invalid_lun(dev); return 0; } } if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { - zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", - dev->id, cdb[0], -//FIXME: use function zip_bus_name(bus_type) .. --FvK + DEBUG("ZIP %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); zip_illegal_opcode(dev); return 0; } - if ((dev->drv->bus_type != ZIP_BUS_SCSI) && - (zip_command_flags[cdb[0]] & SCSI_ONLY)) { - zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", - dev->id, cdb[0]); + if ((dev->drv->bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { + DEBUG("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); zip_illegal_opcode(dev); return 0; } - if ((dev->drv->bus_type != ZIP_BUS_ATAPI) && - (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { - zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", - dev->id, cdb[0]); + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { + DEBUG("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); zip_illegal_opcode(dev); return 0; } @@ -1413,15 +1308,15 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) if (dev->unit_attention == 1) { /* Only increment the unit attention phase if the command can not pass through it. */ if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { - /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ + DBGLOG(1, "ZIP %i: Unit attention now 2\n", dev->id); dev->unit_attention = 2; - zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + DEBUG("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); zip_unit_attention(dev); return 0; } } else if (dev->unit_attention == 2) { if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ + DBGLOG(1, "ZIP %i: Unit attention now 0\n", dev->id); dev->unit_attention = 0; } } @@ -1432,18 +1327,13 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) zip_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ - if (! ready) - dev->media_status = MEC_MEDIA_REMOVAL; - else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { - zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); + DEBUG("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); zip_not_ready(dev); return 0; } - zip_log("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); + DEBUG("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); return 1; } @@ -1452,7 +1342,7 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) static void zip_seek(zip_t *dev, uint32_t pos) { - /* zip_log("ZIP %i: Seek %08X\n", dev->id, pos); */ + DBGLOG(1, "ZIP %i: Seek %08X\n", dev->id, pos); dev->sector_pos = pos; } @@ -1461,21 +1351,19 @@ static void zip_rezero(zip_t *dev) { dev->sector_pos = dev->sector_len = 0; - zip_seek(dev, 0); } void -zip_reset(zip_t *dev) +zip_reset(void *p) { - zip_rezero(dev); + zip_t *dev = (zip_t *) p; + zip_rezero(dev); dev->status = 0; dev->callback = 0LL; - zip_set_callback(dev); - dev->packet_status = 0xff; dev->unit_attention = 0; } @@ -1487,7 +1375,7 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) /*Will return 18 bytes of 0*/ if (alloc_length != 0) { memset(buffer, 0, alloc_length); - if (! desc) + if (!desc) memcpy(buffer, dev->sense, alloc_length); else { buffer[1] = zip_sense_key; @@ -1504,8 +1392,7 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) buffer[desc ? 3 : 13] = 0; } - zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", - dev->id, buffer[2], buffer[12], buffer[13]); + DEBUG("ZIP %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { /* If the last remaining sense is unit attention, clear @@ -1518,10 +1405,11 @@ zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) } -void -zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length) +static void +zip_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length) { - int ready; + zip_t *dev = (zip_t *) p; + int ready = 0; ready = (dev->drv->f != NULL); @@ -1548,7 +1436,7 @@ zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); + DEBUG("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); } } @@ -1556,9 +1444,8 @@ zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) static void zip_buf_alloc(zip_t *dev, uint32_t len) { - zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len); - - zipbufferb = (uint8_t *)mem_alloc(len); + DEBUG("ZIP %i: Allocated buffer length: %i\n", dev->id, len); + zipbufferb = (uint8_t *) malloc(len); } @@ -1566,29 +1453,29 @@ static void zip_buf_free(zip_t *dev) { if (zipbufferb) { - zip_log("ZIP %i: Freeing buffer...\n", dev->id); + DEBUG("ZIP %i: Freeing buffer...\n", dev->id); free(zipbufferb); zipbufferb = NULL; } } -void -zip_command(zip_t *dev, uint8_t *cdb) +static void +zip_command(void *p, uint8_t *cdb) { + zip_t *dev = (zip_t *) p; int pos = 0, block_desc = 0; + int ret; int32_t len, max_len; int32_t alloc_length; + uint32_t i = 0; int size_idx, idx = 0; unsigned preamble_len; - uint32_t i = 0; int32_t blen = 0; int32_t *BufLen; - uint32_t ulen; - int ret; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; dev->status &= ~ERR_STAT; } else { BufLen = &blen; @@ -1597,15 +1484,15 @@ zip_command(zip_t *dev, uint8_t *cdb) dev->packet_len = 0; dev->request_pos = 0; - dev->data_pos = 0; memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); - zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); + DEBUG("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); + DEBUG("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); - zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + DEBUG("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } @@ -1632,8 +1519,7 @@ zip_command(zip_t *dev, uint8_t *cdb) break; case GPCMD_FORMAT_UNIT: - if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) - { + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { zip_write_protected(dev); return; } @@ -1687,7 +1573,7 @@ zip_command(zip_t *dev, uint8_t *cdb) if (!max_len) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = ZIP_PHASE_COMPLETE; + dev->packet_status = PHASE_COMPLETE; dev->callback = 20LL * ZIP_TIME; zip_set_callback(dev); break; @@ -1724,12 +1610,12 @@ zip_command(zip_t *dev, uint8_t *cdb) case GPCMD_READ_6: dev->sector_len = cdb[4]; dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + DEBUG("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + DEBUG("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_READ_12: dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); @@ -1739,8 +1625,8 @@ zip_command(zip_t *dev, uint8_t *cdb) if (!dev->sector_len) { zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = ZIP_PHASE_COMPLETE; + DBGLOG(1, "ZIP %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20LL * ZIP_TIME; zip_set_callback(dev); break; @@ -1763,12 +1649,11 @@ zip_command(zip_t *dev, uint8_t *cdb) dev->requested_blocks = max_len; dev->packet_len = alloc_length; - zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != ZIP_PHASE_COMPLETE) + if (dev->packet_status != PHASE_COMPLETE) ui_sb_icon_update(SB_ZIP | dev->id, 1); else ui_sb_icon_update(SB_ZIP | dev->id, 0); @@ -1806,7 +1691,7 @@ zip_command(zip_t *dev, uint8_t *cdb) case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + DEBUG("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: @@ -1832,8 +1717,8 @@ zip_command(zip_t *dev, uint8_t *cdb) if (!dev->sector_len) { zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = ZIP_PHASE_COMPLETE; + DBGLOG(1, "ZIP %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20LL * ZIP_TIME; zip_set_callback(dev); break; @@ -1850,12 +1735,11 @@ zip_command(zip_t *dev, uint8_t *cdb) dev->requested_blocks = max_len; dev->packet_len = max_len << 9; - zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != ZIP_PHASE_COMPLETE) + if (dev->packet_status != PHASE_COMPLETE) ui_sb_icon_update(SB_ZIP | dev->id, 1); else ui_sb_icon_update(SB_ZIP | dev->id, 0); @@ -1894,8 +1778,8 @@ zip_command(zip_t *dev, uint8_t *cdb) if (!dev->sector_len) { zip_set_phase(dev, SCSI_PHASE_STATUS); - /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ - dev->packet_status = ZIP_PHASE_COMPLETE; + DBGLOG(1, "ZIP %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20LL * ZIP_TIME; zip_set_callback(dev); break; @@ -1912,12 +1796,11 @@ zip_command(zip_t *dev, uint8_t *cdb) dev->requested_blocks = max_len; dev->packet_len = alloc_length; - zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); + zip_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != ZIP_PHASE_COMPLETE) + if (dev->packet_status != PHASE_COMPLETE) ui_sb_icon_update(SB_ZIP | dev->id, 1); else ui_sb_icon_update(SB_ZIP | dev->id, 0); @@ -1940,10 +1823,7 @@ zip_command(zip_t *dev, uint8_t *cdb) zip_buf_alloc(dev, 65536); } - dev->current_page_code = cdb[2] & 0x3F; - zip_log("Mode sense page: %02X\n", dev->current_page_code); - - if (!(zip_mode_sense_page_flags & (1LL << dev->current_page_code))) { + if (!(zip_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { zip_invalid_field(dev); zip_buf_free(dev); return; @@ -1973,7 +1853,7 @@ zip_command(zip_t *dev, uint8_t *cdb) zip_set_buf_len(dev, BufLen, &len); - zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + DEBUG("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); zip_data_command_finish(dev, len, len, alloc_length, 0); return; @@ -1995,8 +1875,6 @@ zip_command(zip_t *dev, uint8_t *cdb) dev->total_length = len; dev->do_page_save = cdb[1] & 1; - dev->current_page_pos = 0; - zip_data_command_finish(dev, len, len, len, 1); return; @@ -2010,7 +1888,7 @@ zip_command(zip_t *dev, uint8_t *cdb) case 1: /* Start the disc and read the TOC. */ break; case 2: /* Eject the disc if possible. */ - /* ui_zip_eject(dev->id); */ + /* zip_eject(dev->id); */ break; case 3: /* Load the disc (close tray). */ ui_zip_reload(dev->id); @@ -2075,7 +1953,7 @@ zip_command(zip_t *dev, uint8_t *cdb) idx += 20; break; default: - zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + DEBUG("INQUIRY: Invalid page: %02X\n", cdb[2]); zip_invalid_field(dev); zip_buf_free(dev); return; @@ -2128,7 +2006,7 @@ zip_command(zip_t *dev, uint8_t *cdb) atapi_out: zipbufferb[size_idx] = idx - preamble_len; - len = idx; + len=idx; len = MIN(len, max_len); zip_set_buf_len(dev, BufLen, &len); @@ -2162,11 +2040,10 @@ atapi_out: zip_buf_alloc(dev, 8); - if (zip_read_capacity(dev, dev->current_cdb, zipbufferb, &ulen) == 0) { + if (zip_read_capacity(dev, dev->current_cdb, zipbufferb, (uint32_t *) &len) == 0) { zip_buf_free(dev); return; } - len = (int32_t)ulen; zip_set_buf_len(dev, BufLen, &len); @@ -2248,7 +2125,7 @@ atapi_out: break; } - /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ + DBGLOG(1, "ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) zip_buf_free(dev); @@ -2261,12 +2138,17 @@ zip_phase_data_out(zip_t *dev) { uint16_t block_desc_len; uint16_t pos; + uint8_t error = 0; uint8_t page, page_len; + uint32_t i = 0; + uint8_t hdr_len, val, old_val, ch; + uint32_t last_to_write = 0; uint32_t c, h, s; + int len = 0; switch(dev->current_cdb[0]) { @@ -2389,17 +2271,15 @@ zip_pio_request(zip_t *dev, uint8_t out) { int ret = 0; - if (dev->drv->bus_type == ZIP_BUS_ATAPI) { - zip_log("ZIP %i: Lowering IDE IRQ\n", dev->id); -//FIXME: should be ide_lower_irq(dev->drv->ide_channel) .. --FvK - ide_irq_lower(ide_drives[dev->drv->ide_channel]); + if (dev->drv->bus_type < ZIP_BUS_SCSI) { + DEBUG("ZIP %i: Lowering IDE IRQ\n", dev->id); + ide_irq_lower(ide_drives[dev->drv->bus_id.ide_channel]); } dev->status = BUSY_STAT; if (dev->pos >= dev->packet_len) { - zip_log("ZIP %i: %i bytes %s, command done\n", - dev->id, dev->pos, out ? "written" : "read"); + DEBUG("ZIP %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); dev->pos = dev->request_pos = 0; if (out) { @@ -2413,20 +2293,21 @@ zip_pio_request(zip_t *dev, uint8_t out) zip_command_complete(dev); zip_buf_free(dev); } else { - zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", - dev->id, dev->pos, out ? "written" : "read", dev->packet_len - dev->pos); + DEBUG("ZIP %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, + out ? "written" : "read", dev->packet_len - dev->pos); /* If less than (packet length) bytes are remaining, update packet length accordingly. */ if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) dev->max_transfer_len = dev->packet_len - dev->pos; - zip_log("ZIP %i: Packet length %i, request length %i\n", - dev->id, dev->packet_len, dev->max_transfer_len); + DEBUG("ZIP %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); + + dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN; - dev->packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; dev->status = BUSY_STAT; dev->phase = 1; - zip_phase_callback(dev); + zip_callback((void *) dev); dev->callback = 0LL; zip_set_callback(dev); @@ -2436,51 +2317,40 @@ zip_pio_request(zip_t *dev, uint8_t out) static int -zip_read_from_ide_dma(uint8_t channel) +zip_read_from_ide_dma(zip_t *dev) { - zip_t *dev; - uint8_t id; int ret; - id = atapi_zip_drives[channel]; - if (id > ZIP_NUM) + if (!dev) return 0; - dev = zip[id]; - if (ide_bus_master_write) { - ret = ide_bus_master_write(channel >> 1, + ret = ide_bus_master_write(dev->drv->bus_id.ide_channel >> 1, zipbufferb, dev->packet_len, - ide_bus_master_priv[channel >> 1]); - if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + ide_bus_master_priv[dev->drv->bus_id.ide_channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ return 2; else if (ret == 1) { /* DMA error. */ zip_bus_master_error(dev); return 0; } else return 1; - } - - return 0; + } else + return 0; } static int -zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +zip_read_from_scsi_dma(scsi_device_t *sd, UNUSED(uint8_t scsi_id)) { - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - zip_t *dev; - uint8_t id; + zip_t *dev = (zip_t *)sd->p; + int32_t *BufLen = &sd->buffer_length; - id = scsi_zip_drives[scsi_id][scsi_lun]; - if (id > ZIP_NUM) + if (!dev) return 0; - dev = zip[id]; - - zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - + DEBUG("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(zipbufferb, sd->cmd_buffer, *BufLen); return 1; } @@ -2489,29 +2359,29 @@ static void zip_irq_raise(zip_t *dev) { if (dev->drv->bus_type < ZIP_BUS_SCSI) -//FIXME: should be ide_lower_irq(dev->drv->ide_channel) .. --FvK - ide_irq_raise(ide_drives[dev->drv->ide_channel]); + ide_irq_raise(ide_drives[dev->drv->bus_id.ide_channel]); } static int zip_read_from_dma(zip_t *dev) { - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + scsi_device_t *sd = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun]; + int32_t *BufLen = &sd->buffer_length; int ret = 0; if (dev->drv->bus_type == ZIP_BUS_SCSI) - ret = zip_read_from_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + ret = zip_read_from_scsi_dma(sd, dev->drv->bus_id.scsi.id); else - ret = zip_read_from_ide_dma(dev->drv->ide_channel); + ret = zip_read_from_ide_dma(dev); if (ret != 1) return ret; if (dev->drv->bus_type == ZIP_BUS_SCSI) - zip_log("ZIP %i: SCSI Input data length: %i\n", dev->id, *BufLen); + DEBUG("ZIP %i: SCSI Input data length: %i\n", dev->id, *BufLen); else - zip_log("ZIP %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + DEBUG("ZIP %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); ret = zip_phase_data_out(dev); @@ -2523,58 +2393,43 @@ zip_read_from_dma(zip_t *dev) static int -zip_write_to_ide_dma(uint8_t channel) +zip_write_to_ide_dma(zip_t *dev) { - uint8_t id = atapi_zip_drives[channel]; - zip_t *dev; int ret; - if (id > ZIP_NUM) { - zip_log("ZIP %i: Drive not found\n", id); + if (!dev) return 0; - } - - dev = zip[id]; if (ide_bus_master_read) { - ret = ide_bus_master_read(channel >> 1, + ret = ide_bus_master_read(dev->drv->bus_id.ide_channel >> 1, zipbufferb, dev->packet_len, - ide_bus_master_priv[channel >> 1]); - if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + ide_bus_master_priv[dev->drv->bus_id.ide_channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ return 2; else if (ret == 1) { /* DMA error. */ zip_bus_master_error(dev); return 0; } else return 1; - } - - return 0; + } else + return 0; } static int -zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +zip_write_to_scsi_dma(scsi_device_t *sd, UNUSED(uint8_t scsi_id)) { - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - zip_t *dev; + zip_t *dev = (zip_t *)sd->p; + int32_t BufLen = sd->buffer_length; - uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; - if (id > ZIP_NUM) + if (!dev) return 0; - dev = zip[id]; - - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, zipbufferb, *BufLen); - zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + DEBUG("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, BufLen); + memcpy(sd->cmd_buffer, zipbufferb, BufLen); + DEBUG("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], zipbufferb[6], zipbufferb[7]); - zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], - SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); - return 1; } @@ -2582,97 +2437,98 @@ zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) static int zip_write_to_dma(zip_t *dev) { - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + scsi_device_t *sd = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun]; + int32_t BufLen = sd->buffer_length; int ret = 0; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - zip_log("Write to SCSI DMA: (%02X:%02X)\n", dev->drv->scsi_device_id, dev->drv->scsi_device_lun); - ret = zip_write_to_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + DEBUG("Write to SCSI DMA: (ID %02X)\n", dev->drv->bus_id.scsi.id); + ret = zip_write_to_scsi_dma(sd, dev->drv->bus_id.scsi.id); } else - ret = zip_write_to_ide_dma(dev->drv->ide_channel); + ret = zip_write_to_ide_dma(dev); if (dev->drv->bus_type == ZIP_BUS_SCSI) - zip_log("ZIP %i: SCSI Output data length: %i\n", dev->id, *BufLen); + DEBUG("ZIP %i: SCSI Output data length: %i\n", dev->id, BufLen); else - zip_log("ZIP %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); + DEBUG("ZIP %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); return ret; } -/* If the result is 1, issue an IRQ, otherwise not. */ -void -zip_phase_callback(zip_t *dev) +static void +zip_callback(void *p) { + zip_t *dev = (zip_t *) p; int ret; switch(dev->packet_status) { - case ZIP_PHASE_IDLE: - zip_log("ZIP %i: ZIP_PHASE_IDLE\n", dev->id); + case PHASE_IDLE: + DEBUG("ZIP %i: PHASE_IDLE\n", dev->id); dev->pos = 0; dev->phase = 1; dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); return; - case ZIP_PHASE_COMMAND: - zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", dev->id); + case PHASE_COMMAND: + DEBUG("ZIP %i: PHASE_COMMAND\n", dev->id); dev->status = BUSY_STAT | (dev->status & ERR_STAT); memcpy(dev->atapi_cdb, zipbufferb, 12); zip_command(dev, dev->atapi_cdb); return; - case ZIP_PHASE_COMPLETE: - zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", dev->id); + case PHASE_COMPLETE: + DEBUG("ZIP %i: PHASE_COMPLETE\n", dev->id); dev->status = READY_STAT; dev->phase = 3; dev->packet_status = 0xFF; ui_sb_icon_update(SB_ZIP | dev->id, 0); zip_irq_raise(dev); return; - case ZIP_PHASE_DATA_OUT: - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", dev->id); + case PHASE_DATA_OUT: + DEBUG("ZIP %i: PHASE_DATA_OUT\n", dev->id); dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); dev->phase = 0; zip_irq_raise(dev); return; - case ZIP_PHASE_DATA_OUT_DMA: - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", dev->id); + case PHASE_DATA_OUT_DMA: + DEBUG("ZIP %i: PHASE_DATA_OUT_DMA\n", dev->id); ret = zip_read_from_dma(dev); if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { - zip_log("ZIP %i: DMA data out phase done\n", dev->id); + DEBUG("ZIP %i: DMA data out phase done\n"); zip_buf_free(dev); zip_command_complete(dev); } else if (ret == 2) { - zip_log("ZIP %i: DMA out not enabled, wait\n", dev->id); + DEBUG("ZIP %i: DMA out not enabled, wait\n"); zip_command_bus(dev); } else { - zip_log("ZIP %i: DMA data out phase failure\n", dev->id); + DEBUG("ZIP %i: DMA data out phase failure\n"); zip_buf_free(dev); } return; - case ZIP_PHASE_DATA_IN: - zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", dev->id); + case PHASE_DATA_IN: + DEBUG("ZIP %i: PHASE_DATA_IN\n", dev->id); dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); dev->phase = 2; zip_irq_raise(dev); return; - case ZIP_PHASE_DATA_IN_DMA: - zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", dev->id); + case PHASE_DATA_IN_DMA: + DEBUG("ZIP %i: PHASE_DATA_IN_DMA\n", dev->id); ret = zip_write_to_dma(dev); if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { - zip_log("ZIP %i: DMA data in phase done\n", dev->id); + DEBUG("ZIP %i: DMA data in phase done\n", dev->id); zip_buf_free(dev); zip_command_complete(dev); } else if (ret == 2) { - zip_log("ZIP %i: DMA in not enabled, wait\n", dev->id); + DEBUG("ZIP %i: DMA in not enabled, wait\n", dev->id); zip_command_bus(dev); } else { - zip_log("ZIP %i: DMA data in phase failure\n", dev->id); + DEBUG("ZIP %i: DMA data in phase failure\n", dev->id); zip_buf_free(dev); } return; - case ZIP_PHASE_ERROR: - zip_log("ZIP %i: ZIP_PHASE_ERROR\n", dev->id); + case PHASE_ERROR: + DEBUG("ZIP %i: PHASE_ERROR\n", dev->id); dev->status = READY_STAT | ERR_STAT; dev->phase = 3; dev->packet_status = 0xFF; @@ -2683,20 +2539,19 @@ zip_phase_callback(zip_t *dev) } -uint32_t -zip_read(uint8_t channel, int length) +static uint32_t +zip_packet_read(void *p, int length) { - uint8_t id = atapi_zip_drives[channel]; + zip_t *dev = (zip_t *) p; + uint16_t *zipbufferw; uint32_t *zipbufferl; + uint32_t temp = 0; - zip_t *dev; - if (id > ZIP_NUM) + if (!dev) return 0; - dev = zip[id]; - zipbufferw = (uint16_t *) zipbufferb; zipbufferl = (uint32_t *) zipbufferb; @@ -2726,37 +2581,29 @@ zip_read(uint8_t channel, int length) return 0; } - if (dev->packet_status == ZIP_PHASE_DATA_IN) { - zip_log("ZIP %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", - id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + if (dev->packet_status == PHASE_DATA_IN) { if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { /* Time for a DRQ. */ - zip_log("ZIP %i: Issuing read callback\n", id); zip_pio_request(dev, 0); } return temp; - } else { - zip_log("ZIP %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", - id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + } else return 0; - } } -void -zip_write(uint8_t channel, uint32_t val, int length) +static void +zip_packet_write(void *p, uint32_t val, int length) { - uint8_t id = atapi_zip_drives[channel]; + zip_t *dev = (zip_t *) p; + uint16_t *zipbufferw; uint32_t *zipbufferl; - zip_t *dev; - if (id > ZIP_NUM) + if (!dev) return; - dev = zip[id]; - - if (dev->packet_status == ZIP_PHASE_IDLE) { + if (dev->packet_status == PHASE_IDLE) { if (!zipbufferb) zip_buf_alloc(dev, 12); } @@ -2787,19 +2634,19 @@ zip_write(uint8_t channel, uint32_t val, int length) return; } - if (dev->packet_status == ZIP_PHASE_DATA_OUT) { + if (dev->packet_status == PHASE_DATA_OUT) { if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { /* Time for a DRQ. */ zip_pio_request(dev, 1); } return; - } else if (dev->packet_status == ZIP_PHASE_IDLE) { + } else if (dev->packet_status == PHASE_IDLE) { if (dev->pos >= 12) { dev->pos = 0; dev->status = BUSY_STAT; - dev->packet_status = ZIP_PHASE_COMMAND; + dev->packet_status = PHASE_COMMAND; timer_process(); - zip_phase_callback(dev); + zip_callback((void *) dev); timer_update_outstanding(); } return; @@ -2817,32 +2664,185 @@ zip_global_init(void) } +static void +zip_100_identify(ide_t *ide) +{ + ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ +} + + +static void +zip_250_identify(ide_t *ide, int ide_has_dma) +{ + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ + + if (ide_has_dma) { + ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ + ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ + } +} + + +static int +zip_get_max(int ide_has_dma, int type) +{ + int ret; + + switch(type) { + case TYPE_PIO: + ret = ide_has_dma ? 3 : 0; + break; + case TYPE_SDMA: + default: + ret = -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? -1 : 1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? -1 : 2; + break; + } + + return ret; +} + + +static int +zip_get_timings(int ide_has_dma, int type) +{ + int ret; + + switch(type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 0x96 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 0xb4 : 0; + break; + case TIMINGS_PIO_FC: + ret = ide_has_dma ? 0xb4 : 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + + +static void +zip_identify(void *p, int ide_has_dma) +{ + ide_t *ide = (ide_t *) p; + zip_t *zip; + + zip = (zip_t *) ide->p; + + /* Using (2<<5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive + as a LS-120. */ + ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + + if (zip_drives[zip->id].is_250) + zip_250_identify(ide, ide_has_dma); + else + zip_100_identify(ide); +} + + +static zip_t * +zip_drive_reset(int c) +{ + scsi_device_t *sd; + ide_t *id; + + if (!zip[c]) { + zip[c] = (zip_t *) malloc(sizeof(zip_t)); + memset(zip[c], 0, sizeof(zip_t)); + } + + zip[c]->id = c; + + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + /* SCSI ZIP, attach to the SCSI bus. */ + sd = &scsi_devices[zip_drives[c].bus_id.scsi.id][zip_drives[c].bus_id.scsi.lun]; + + sd->p = zip[c]; + sd->command = zip_command; + sd->callback = zip_callback; + sd->err_stat_to_scsi = zip_err_stat_to_scsi; + sd->request_sense = zip_request_sense_for_scsi; + sd->reset = zip_reset; + sd->read_capacity = zip_read_capacity; + sd->type = SCSI_REMOVABLE_DISK; + } else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { + /* ATAPI CD-ROM, attach to the IDE bus. */ + id = ide_drives[zip_drives[c].bus_id.ide_channel]; + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + id->p = zip[c]; + id->get_max = zip_get_max; + id->get_timings = zip_get_timings; + id->identify = zip_identify; + id->set_signature = zip_set_signature; + id->packet_write = zip_packet_write; + id->packet_read = zip_packet_read; + id->stop = NULL; + id->packet_callback = zip_callback; + id->device_reset = zip_reset; + id->interrupt_drq = 1; + + ide_atapi_attach(id); + } + } + + return zip[c]; +} + + void zip_hard_reset(void) { int c; for (c = 0; c < ZIP_NUM; c++) { - if (zip_drives[c].bus_type) { - zip_log("ZIP hard_reset drive=%d\n", c); + if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) || (zip_drives[c].bus_type == ZIP_BUS_SCSI)) { + DEBUG("ZIP hard_reset drive=%d\n", c); - if (! zip[c]) { - zip[c] = (zip_t *)mem_alloc(sizeof(zip_t)); - memset(zip[c], 0, sizeof(zip_t)); - } + /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ + if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].bus_id.scsi.id > SCSI_ID_MAX)) + continue; + + /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ + if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI) && (zip_drives[c].bus_id.ide_channel > 7)) + continue; + + zip[c] = zip_drive_reset(c); zip[c]->id = c; zip[c]->drv = &zip_drives[c]; + zip_init(zip[c]); if (wcslen(zip_drives[c].image_path)) zip_load(zip[c], zip_drives[c].image_path); zip_mode_sense_load(zip[c]); + + if (zip_drives[c].bus_type == ZIP_BUS_SCSI) + DEBUG("SCSI ZIP drive %i attached to SCSI ID %i\n", c, zip_drives[c].bus_id.scsi.id); + else if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) + DEBUG("ATAPI ZIP drive %i attached to IDE channel %i\n", c, zip_drives[c].bus_id.ide_channel); } } - - zip_build_atapi_map(); } @@ -2854,8 +2854,10 @@ zip_close(void) for (c = 0; c < ZIP_NUM; c++) { dev = zip[c]; + if (dev) { zip_disk_close(dev); + free(zip[c]); zip[c] = NULL; } diff --git a/src/devices/disk/zip.h b/src/devices/disk/zip.h index 9475182..036d097 100644 --- a/src/devices/disk/zip.h +++ b/src/devices/disk/zip.h @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.h 1.0.7 2018/09/09 + * Version: @(#)zip.h 1.0.8 2018/10/14 * * Author: Miran Grca, * @@ -39,15 +39,6 @@ #define ZIP_NUM 4 -#define ZIP_PHASE_IDLE 0x00 -#define ZIP_PHASE_COMMAND 0x01 -#define ZIP_PHASE_COMPLETE 0x02 -#define ZIP_PHASE_DATA_IN 0x03 -#define ZIP_PHASE_DATA_IN_DMA 0x04 -#define ZIP_PHASE_DATA_OUT 0x05 -#define ZIP_PHASE_DATA_OUT_DMA 0x06 -#define ZIP_PHASE_ERROR 0x80 - #define BUF_SIZE 32768 #define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) @@ -73,9 +64,13 @@ typedef struct { read_only, ui_writeprot; - uint8_t ide_channel; - uint8_t scsi_device_id, - scsi_device_lun; + union { + uint8_t ide_channel; + struct { + int8_t id; + int8_t lun; + } scsi; + } bus_id; wchar_t image_path[1024], prev_image_path[1024]; @@ -86,41 +81,35 @@ typedef struct { } zip_drive_t; typedef struct { - mode_sense_pages_t ms_pages_saved; + uint8_t id, + error, status, + phase, + features, + is_dma, + do_page_save, + unit_attention; zip_drive_t *drv; - uint8_t id, - previous_command, - error, features, - status, phase, - *buffer, - atapi_cdb[16], - current_cdb[16], - sense[256]; - uint16_t request_length, max_transfer_len; - int toctimes, media_status, - is_dma, requested_blocks, - current_page_len, current_page_pos, - total_length, written_length, - mode_select_phase, do_page_save, - data_pos, - packet_status, unit_attention, - cdb_len_setting, cdb_len, - request_pos, total_read, - block_total, all_blocks_total, - old_len, block_descriptor_len, - init_length; + int requested_blocks, packet_status, + request_pos, old_len, + total_length; uint32_t sector_pos, sector_len, packet_len, pos, seek_pos; - uint64_t current_page_code; int64_t callback; + + mode_sense_pages_t ms_pages_saved; + + uint8_t *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; } zip_t; @@ -140,33 +129,18 @@ extern uint8_t scsi_zip_drives[16][8]; extern "C" { #endif -extern int zip_ZIP_PHASE_to_scsi(zip_t *dev); -extern int zip_atapi_phase_to_scsi(zip_t *dev); -extern void zip_command(zip_t *dev, uint8_t *cdb); -extern void zip_phase_callback(zip_t *dev); extern void zip_disk_close(zip_t *dev); extern void zip_disk_reload(zip_t *dev); -extern void zip_reset(zip_t *dev); -extern void zip_set_signature(zip_t *dev); -extern void zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length); -extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); extern void zip_insert(zip_t *dev); -extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); - -extern uint32_t zip_read(uint8_t channel, int length); -extern void zip_write(uint8_t channel, uint32_t val, int length); extern void zip_global_init(void); extern void zip_hard_reset(void); -extern void zip_build_atapi_map(void); -extern void zip_build_scsi_map(void); extern int zip_string_to_bus(const char *str); extern const char *zip_bus_to_string(int bus); -extern void zip_close(void); +extern void zip_reset(void *p); extern int zip_load(zip_t *dev, const wchar_t *fn); -extern void zip_disk_close(zip_t *dev); +extern void zip_close(void); #ifdef __cplusplus } diff --git a/src/devices/floppy/fdd.c b/src/devices/floppy/fdd.c index b6d6142..889fd0f 100644 --- a/src/devices/floppy/fdd.c +++ b/src/devices/floppy/fdd.c @@ -8,7 +8,7 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.14 2018/10/05 + * Version: @(#)fdd.c 1.0.15 2018/10/12 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -222,7 +222,7 @@ static const struct void fdd_log(int level, const char *fmt, ...) { -#ifdef ENABLE_FDC_LOG +#ifdef ENABLE_FDD_LOG va_list ap; if (fdd_do_log >= level) { @@ -247,7 +247,7 @@ const char *fdd_get_internal_name(int type) int fdd_get_from_internal_name(const char *s) { int c = 0; - + while (drive_types[c].internal_name != NULL) { if (! strcmp(drive_types[c].internal_name, s)) @@ -271,7 +271,7 @@ void fdd_do_seek(int drive, int track) void fdd_forced_seek(int drive, int track_diff) { fdd[drive].track += track_diff; - + if (fdd[drive].track < 0) fdd[drive].track = 0; @@ -480,7 +480,7 @@ int fdd_load(int drive, const wchar_t *fn) if (!f) return(0); fseek(f, -1, SEEK_END); size = ftell(f) + 1; - fclose(f); + fclose(f); while (loaders[c].ext) { if (!wcscasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1)) @@ -635,7 +635,7 @@ void fdd_poll_3(void *priv) int fdd_get_bitcell_period(int rate) { int bit_rate = 250; - + switch (rate) { case 0: /*High density*/ @@ -651,7 +651,7 @@ int fdd_get_bitcell_period(int rate) bit_rate = 1000; break; } - + return 1000000 / bit_rate*2; /*Bitcell period in ns*/ } diff --git a/src/devices/scsi/scsi.c b/src/devices/scsi/scsi.c index 4e6728c..9c03c66 100644 --- a/src/devices/scsi/scsi.c +++ b/src/devices/scsi/scsi.c @@ -8,7 +8,7 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.11 2018/10/05 + * Version: @(#)scsi.c 1.0.12 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,7 +50,6 @@ #include "../disk/hdd.h" #include "scsi.h" #include "scsi_device.h" -#include "scsi_disk.h" #include "../cdrom/cdrom.h" #include "../disk/zip.h" #include "scsi_aha154x.h" @@ -68,9 +67,6 @@ int scsi_do_log = ENABLE_SCSI_LOG; #ifdef ENABLE_SCSI_DEV_LOG int scsi_dev_do_log = ENABLE_SCSI_DEV_LOG; #endif -scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; - -uint32_t SCSI_BufferLength; static struct { @@ -199,31 +195,21 @@ scsi_card_init(void) { int i, j; - if (! scsi_cards[scsi_card].device) return; - - DEBUG("SCSI: building hard disk map...\n"); - build_scsi_disk_map(); - - DEBUG("SCSI: building CD-ROM map...\n"); - build_scsi_cdrom_map(); - - DEBUG("SCSI: building ZIP map...\n"); - zip_build_scsi_map(); - + /* Reset the devices table, in case we have one. */ for (i = 0; i < SCSI_ID_MAX; i++) { for (j = 0; j < SCSI_LUN_MAX; j++) { - if (scsi_disks[i][j] != 0xff) - SCSIDevices[i][j].LunType = SCSI_DISK; - else if (scsi_cdrom_drives[i][j] != 0xff) - SCSIDevices[i][j].LunType = SCSI_CDROM; - else if (scsi_zip_drives[i][j] != 0xff) - SCSIDevices[i][j].LunType = SCSI_ZIP; - else - SCSIDevices[i][j].LunType = SCSI_NONE; + if (scsi_devices[i][j].cmd_buffer) { + free(scsi_devices[i][j].cmd_buffer); + scsi_devices[i][j].cmd_buffer = NULL; + } - SCSIDevices[i][j].CmdBuffer = NULL; + memset(&scsi_devices[i][j], 0x00, sizeof(scsi_device_t)); + + scsi_devices[i][j].type = SCSI_NONE; } } - device_add(scsi_cards[scsi_card].device); + /* If we have one, initialize the configured SCSI controller. */ + if (scsi_cards[scsi_card].device != NULL) + device_add(scsi_cards[scsi_card].device); } diff --git a/src/devices/scsi/scsi_buslogic.c b/src/devices/scsi/scsi_buslogic.c index d4e3d95..934c054 100644 --- a/src/devices/scsi/scsi_buslogic.c +++ b/src/devices/scsi/scsi_buslogic.c @@ -13,7 +13,7 @@ * 1 - BT-545S ISA; * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.11 2018/09/22 + * Version: @(#)scsi_buslogic.c 1.0.12 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -578,6 +578,7 @@ SCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir) int DataLength = ESCSICmd->DataLength; uint32_t Address; uint32_t TransferLength; + scsi_device_t *dev = &scsi_devices[TargetID][LUN]; if (ESCSICmd->DataDirection == 0x03) { /* Non-data command. */ @@ -589,16 +590,16 @@ SCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir) /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && (SCSIDevices[TargetID][LUN].BufferLength > 0)) { + if ((DataLength > 0) && (dev->buffer_length > 0)) { Address = DataPointer; - TransferLength = MIN(DataLength, SCSIDevices[TargetID][LUN].BufferLength); + TransferLength = MIN(DataLength, dev->buffer_length); if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { DEBUG("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); - DMAPageRead(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); + DMAPageRead(Address, (uint8_t *)dev->cmd_buffer, TransferLength); } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { DEBUG("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); - DMAPageWrite(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); + DMAPageWrite(Address, (uint8_t *)dev->cmd_buffer, TransferLength); } } } @@ -608,6 +609,7 @@ static void SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) { ESCMD *ESCSICmd = (ESCMD *)CmdBuf; + scsi_device_t *sd = &scsi_devices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit]; uint32_t i; uint8_t temp_cdb[12]; int target_cdb_len = 12; @@ -623,14 +625,14 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D DEBUG("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); - SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status = SCSI_STATUS_OK; + sd->status = SCSI_STATUS_OK; - if (!scsi_device_present(ESCSICmd->TargetId, 0)) { - DEBUG("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId,ESCSICmd->LogicalUnit); + if (! scsi_device_present(sd)) { + DEBUG("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId); DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { - DEBUG("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + DEBUG("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId); DEBUG("Transfer Control %02X\n", ESCSICmd->DataDirection); DEBUG("CDB Length %i\n", ESCSICmd->CDBLength); @@ -639,13 +641,14 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D } } - x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->DataLength); + x54x_buf_alloc(sd, ESCSICmd->DataLength); target_cdb_len = 12; - if (!scsi_device_valid(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) fatal("SCSI target on ID %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + if (! scsi_device_valid(sd)) + fatal("SCSI target on ID %i:%i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - DEBUG("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + DEBUG("SCSI target command being executed on: ID %i, LUN %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); DEBUG("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); for (i = 1; i < ESCSICmd->CDBLength; i++) { @@ -658,26 +661,26 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D else memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); - SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].BufferLength = ESCSICmd->DataLength; - scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, temp_cdb); + sd->buffer_length = ESCSICmd->DataLength; + scsi_device_command_phase0(sd, temp_cdb); - phase = SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Phase; + phase = sd->phase; if (phase != SCSI_PHASE_STATUS) { if (phase == SCSI_PHASE_DATA_IN) - scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + scsi_device_command_phase1(sd); SCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit, (phase == SCSI_PHASE_DATA_OUT)); if (phase == SCSI_PHASE_DATA_OUT) - scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + scsi_device_command_phase1(sd); } - x54x_buf_free(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + x54x_buf_free(sd); DEBUG("BIOS Request complete\n"); - if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_OK) { + if (sd->status == SCSI_STATUS_OK) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_OK; - } else if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_CHECK_CONDITION) { + } else if (sd->status == SCSI_STATUS_CHECK_CONDITION) { DataInBuf[2] = CCB_COMPLETE; DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; } @@ -716,10 +719,11 @@ buslogic_cmds(void *priv) case 0x23: memset(dev->DataBuf, 0, 8); for (i = 8; i < 15; i++) { - dev->DataBuf[i-8] = 0; + dev->DataBuf[i - 8] = 0; for (j = 0; j < 8; j++) { - if (scsi_device_present(i, j) && (i != get_host_id(dev))) - dev->DataBuf[i-8] |= (1<DataBuf[i - 8] |= (1 << j); } } dev->DataReplyLeft = 8; @@ -727,7 +731,8 @@ buslogic_cmds(void *priv) case 0x24: for (i = 0; i < 15; i++) { - if (scsi_device_present(i, 0) && (i != get_host_id(dev))) + if (scsi_device_present(&scsi_devices[i][0]) && + (i != get_host_id(dev))) TargetsPresentMask |= (1 << i); } dev->DataBuf[0] = TargetsPresentMask & 0xff; diff --git a/src/devices/scsi/scsi_cdrom.c b/src/devices/scsi/scsi_cdrom.c new file mode 100644 index 0000000..aee1571 --- /dev/null +++ b/src/devices/scsi/scsi_cdrom.c @@ -0,0 +1,3140 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of SCSI (and ATAPI) CD-ROM drives. + * + * Version: @(#)scsi_cdrom.c 1.0.1 2018/10/15 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#define dbglog scsi_cdrom_log +#include "../../emu.h" +#include "../../version.h" +#include "../../timer.h" +#include "../../device.h" +#include "../../nvr.h" +#include "../../ui/ui.h" +#include "../../plat.h" +#include "../disk/hdc.h" +#include "../disk/hdc_ide.h" +#include "../cdrom/cdrom.h" +#include "../cdrom/cdrom_image.h" +#include "../cdrom/cdrom_null.h" +#include "scsi_device.h" +#include "scsi_cdrom.h" + + +/* Bits of 'status' */ +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits of 'error' */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ + +#define cdbufferb dev->buffer + + +scsi_cdrom_t *scsi_cdrom[CDROM_NUM] = { NULL, NULL, NULL, NULL }; + + +#pragma pack(push,1) +typedef struct { + uint8_t opcode; + uint8_t polled; + uint8_t reserved2[2]; + uint8_t class; + uint8_t reserved3[2]; + uint16_t len; + uint8_t control; +} gesn_cdb_t; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; +} gesn_event_header_t; +#pragma pack(pop) + + +/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +const uint8_t scsi_cdrom_command_flags[0x100] = +{ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + 0, /* 0x02 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + 0, 0, 0, 0, /* 0x04-0x07 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ + 0, 0, /* 0x09-0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, 0, 0, 0, 0, 0, /* 0x0C-0x11 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + 0, /* 0x14 */ + IMPLEMENTED, /* 0x15 */ + 0, 0, 0, 0, /* 0x16-0x19 */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ + 0, 0, /* 0x1C-0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ + 0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ + 0, 0, /* 0x26-0x27 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ + 0, 0, /* 0x29-0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, 0, /* 0x2C-0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ + 0, 0, /* 0x40-0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x42 */ + IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ + IMPLEMENTED | CHECK_READY, /* 0x44 */ + IMPLEMENTED | CHECK_READY, /* 0x45 */ + IMPLEMENTED | ALLOW_UA, /* 0x46 */ + IMPLEMENTED | CHECK_READY, /* 0x47 */ + IMPLEMENTED | CHECK_READY, /* 0x48 */ + 0, /* 0x49 */ + IMPLEMENTED | ALLOW_UA, /* 0x4A */ + IMPLEMENTED | CHECK_READY, /* 0x4B */ + 0, 0, /* 0x4C-0x4D */ + IMPLEMENTED | CHECK_READY, /* 0x4E */ + 0, 0, /* 0x4F-0x50 */ + IMPLEMENTED | CHECK_READY, /* 0x51 */ + IMPLEMENTED | CHECK_READY, /* 0x52 */ + 0, 0, /* 0x53-0x54 */ + IMPLEMENTED, /* 0x55 */ + 0, 0, 0, 0, /* 0x56-0x59 */ + IMPLEMENTED, /* 0x5A */ + 0, 0, 0, 0, 0, /* 0x5B-0x5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ + 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ + IMPLEMENTED | CHECK_READY, /* 0xA5 */ + 0, 0, /* 0xA6-0xA7 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ + 0, 0, 0, 0, /* 0xA9-0xAC */ + IMPLEMENTED | CHECK_READY, /* 0xAD */ + 0, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + 0, 0, 0, 0, /* 0xB0-0xB3 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ + 0, 0, 0, /* 0xB5-0xB7 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ + IMPLEMENTED | CHECK_READY, /* 0xB9 */ + IMPLEMENTED | CHECK_READY, /* 0xBA */ + IMPLEMENTED, /* 0xBB */ + IMPLEMENTED | CHECK_READY, /* 0xBC */ + IMPLEMENTED, /* 0xBD */ + IMPLEMENTED | CHECK_READY, /* 0xBE */ + IMPLEMENTED | CHECK_READY, /* 0xBF */ + 0, 0, /* 0xC0-0xC1 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC3-0xCC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ + IMPLEMENTED | SCSI_ONLY, /* 0xDA */ + 0, 0, 0, 0, 0, /* 0xDB-0xDF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ +}; + +static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_CDROM_PAGE | + GPMODEP_CDROM_AUDIO_PAGE | + GPMODEP_CAPABILITIES_PAGE | + GPMODEP_ALL_PAGES); + +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; + +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; + +static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x8E, 0xE, 0xFF, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +} }; + +uint8_t scsi_cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static gesn_cdb_t *gesn_cdb; +static gesn_event_header_t *gesn_event_header; + + +static void scsi_cdrom_command_complete(scsi_cdrom_t *dev); + +static void scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev); + +static void scsi_cdrom_init(scsi_cdrom_t *dev); + +static void scsi_cdrom_callback(void *p); + + +#ifdef ENABLE_SCSI_CDROM_LOG +int scsi_cdrom_do_log = ENABLE_SCSI_CDROM_LOG; +#endif + + +static void +scsi_cdrom_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_SCSI_CDROM_LOG + va_list ap; + + if (scsi_cdrom_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +static void +scsi_cdrom_set_callback(scsi_cdrom_t *dev) +{ + if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) + ide_set_callback(dev->drv->bus_id.ide_channel >> 1, dev->callback); +} + + +static void +scsi_cdrom_set_signature(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (!dev) + return; + dev->phase = 1; + dev->request_length = 0xEB14; +} + + +static void +scsi_cdrom_init(scsi_cdrom_t *dev) +{ + if (!dev) + return; + + /* Tell the scsi_cdrom_t struct what cdrom_drives element corresponds to it. */ + dev->drv = &cdrom[dev->id]; + + /* Do a reset (which will also rezero it). */ + scsi_cdrom_reset(dev); + + /* Configure the drive. */ + dev->requested_blocks = 1; + + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= CDROM_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < CDROM_BUS_SCSI) + dev->drv->bus_mode |= 1; + DEBUG("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->status = READY_STAT | DSC_STAT; + dev->pos = 0; + dev->packet_status = 0xff; + scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; + dev->drv->cur_speed = dev->drv->speed_idx; + + scsi_cdrom_mode_sense_load(dev); +} + + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +static int +scsi_cdrom_current_mode(scsi_cdrom_t *dev) +{ + if (dev->drv->bus_type == CDROM_BUS_SCSI) + return 2; + else if (dev->drv->bus_type == CDROM_BUS_ATAPI) { + DEBUG("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id, + (dev->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->features & 1) ? 2 : 1; + } + + return 0; +} + + +/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ +int +scsi_cdrom_err_stat_to_scsi(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; +} + + +/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ +int +scsi_cdrom_atapi_phase_to_scsi(scsi_cdrom_t *dev) +{ + if (dev->status & 8) { + switch (dev->phase & 3) { + case 0: + return 0; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; + } + } else { + if ((dev->phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; +} + + +static uint32_t +scsi_cdrom_get_channel(void *p, int channel) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (!dev) + return channel + 1; + + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; +} + + +static uint32_t +scsi_cdrom_get_volume(void *p, int channel) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (!dev) + return 255; + + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; +} + + +static void +scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) +{ + wchar_t file_name[512]; + FILE *f; + int i; + + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (scsi_cdrom_mode_sense_pages_default.pages[i][1] != 0) { + if (dev->drv->bus_type == CDROM_BUS_SCSI) + memcpy(dev->ms_pages_saved.pages[i], + scsi_cdrom_mode_sense_pages_default_scsi.pages[i], + scsi_cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(dev->ms_pages_saved.pages[i], + scsi_cdrom_mode_sense_pages_default.pages[i], + scsi_cdrom_mode_sense_pages_default.pages[i][1] + 2); + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) { + fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +static void +scsi_cdrom_mode_sense_save(scsi_cdrom_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) { + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +int +scsi_cdrom_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + int size = 0; + + size = dev->drv->ops->size(dev->drv) - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 8; /* 2048 = 0x0800 */ + *len = 8; + + return 1; +} + + +/*SCSI Mode Sense 6/10*/ +static uint8_t +scsi_cdrom_mode_sense_read(scsi_cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) +{ + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + return scsi_cdrom_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + return scsi_cdrom_mode_sense_pages_default_scsi.pages[page][pos]; + else + return scsi_cdrom_mode_sense_pages_default.pages[page][pos]; + break; + } + + return 0; +} + + +static uint32_t +scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) +{ + uint8_t page_control = (page >> 6) & 3; + int i = 0, j = 0; + uint8_t msplen; + + page &= 0x3f; + + if (block_descriptor_len) { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } + + for (i = 0; i < 0x40; i++) { + if ((page == GPMODE_ALL_PAGES) || (page == i)) { + if (scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) (page & 0x3f)))) { + buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 0); + msplen = scsi_cdrom_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + DEBUG("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) { + if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { + if (j & 1) + buf[pos++] = ((dev->drv->speed_idx * 176) & 0xff); + else + buf[pos++] = ((dev->drv->speed_idx * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { + if (j & 1) + buf[pos++] = ((dev->drv->cur_speed * 176) & 0xff); + else + buf[pos++] = ((dev->drv->cur_speed * 176) >> 8); + } else + buf[pos++] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j); + } + } + } + } + + return pos; +} + + +static void +scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) +{ + int32_t bt, min_len = 0; + + dev->max_transfer_len = dev->request_length; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + default: + dev->packet_len = len; + break; + } + + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; + + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->request_length = dev->max_transfer_len; + + return; +} + + +static double +scsi_cdrom_bus_speed(scsi_cdrom_t *dev) +{ + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return 0.0; + } else { + /* TODO: Get the actual selected speed from IDE. */ + if (scsi_cdrom_current_mode(dev) == 2) + return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ + else + return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ + } +} + + +static void +scsi_cdrom_command_bus(scsi_cdrom_t *dev) +{ + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 1LL * CDROM_TIME; + + scsi_cdrom_set_callback(dev); +} + + +static void +scsi_cdrom_command_common(scsi_cdrom_t *dev) +{ + double bytes_per_second, period; + double dusec; + + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 0LL; + + DEBUG("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed); + + if (dev->packet_status == PHASE_COMPLETE) { + scsi_cdrom_callback(dev); + dev->callback = 0LL; + } else { + switch(dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = cdrom_seek_time(dev->drv); + DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t)period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + scsi_cdrom_set_callback(dev); + return; + case 0x08: + case 0x28: + case 0xa8: + /* Seek time is in us. */ + period = cdrom_seek_time(dev->drv); + DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t) period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + case 0x25: + case 0x42: + case 0x43: + case 0x44: + case 0x51: + case 0x52: + case 0xad: + case 0xb8: + case 0xb9: + case 0xbe: + if (dev->current_cdb[0] == 0x42) + dev->callback += 200LL * CDROM_TIME; + /* Account for seek time. */ + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) dev->drv->cur_speed; + break; + default: + bytes_per_second = scsi_cdrom_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return; + } + break; + } + + period = 1000000.0 / bytes_per_second; + DEBUG("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + period = period * (double) (dev->packet_len); + DEBUG("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + dusec = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) dusec); + } + + scsi_cdrom_set_callback(dev); +} + + +static void +scsi_cdrom_command_complete(scsi_cdrom_t *dev) +{ + dev->packet_status = PHASE_COMPLETE; + scsi_cdrom_command_common(dev); +} + + +static void +scsi_cdrom_command_read(scsi_cdrom_t *dev) +{ + dev->packet_status = PHASE_DATA_IN; + scsi_cdrom_command_common(dev); + dev->total_read = 0; +} + + +static void +scsi_cdrom_command_read_dma(scsi_cdrom_t *dev) +{ + dev->packet_status = PHASE_DATA_IN_DMA; + scsi_cdrom_command_common(dev); + dev->total_read = 0; +} + + +static void +scsi_cdrom_command_write(scsi_cdrom_t *dev) +{ + dev->packet_status = PHASE_DATA_OUT; + scsi_cdrom_command_common(dev); +} + + +static void +scsi_cdrom_command_write_dma(scsi_cdrom_t *dev) +{ + dev->packet_status = PHASE_DATA_OUT_DMA; + scsi_cdrom_command_common(dev); +} + + +/* id = Current CD-ROM device ID; + len = Total transfer length; + block_len = Length of a single block (it matters because media access commands on ATAPI); + alloc_len = Allocated transfer length; + direction = Transfer direction (0 = read from host, 1 = write to host). */ +static void +scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int alloc_len, int direction) +{ + DEBUG("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + dev->pos = 0; + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + + if ((len == 0) || (scsi_cdrom_current_mode(dev) == 0)) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = 0; + + scsi_cdrom_command_complete(dev); + } else { + if (scsi_cdrom_current_mode(dev) == 2) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + scsi_cdrom_command_read_dma(dev); + else + scsi_cdrom_command_write_dma(dev); + } else { + scsi_cdrom_update_request_length(dev, len, block_len); + if (direction == 0) + scsi_cdrom_command_read(dev); + else + scsi_cdrom_command_write(dev); + } + } + + DEBUG("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); +} + + +static void +scsi_cdrom_sense_clear(scsi_cdrom_t *dev, int command) +{ + dev->previous_command = command; + scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0; +} + + +static void +scsi_cdrom_set_phase(scsi_cdrom_t *dev, uint8_t phase) +{ + if (dev->drv->bus_type != CDROM_BUS_SCSI) + return; + + scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].phase = phase; +} + + +static void +scsi_cdrom_cmd_error(scsi_cdrom_t *dev) +{ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + + scsi_cdrom_set_callback(dev); + + DEBUG("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq); +} + + +static void +scsi_cdrom_unit_attention(scsi_cdrom_t *dev) +{ + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + + scsi_cdrom_set_callback(dev); + + DEBUG("CD-ROM %i: UNIT ATTENTION\n", dev->id); +} + + +static void +scsi_cdrom_bus_master_error(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_not_ready(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_NOT_READY; + scsi_cdrom_asc = ASC_MEDIUM_NOT_PRESENT; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_invalid_lun(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_INV_LUN; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_illegal_opcode(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_ILLEGAL_OPCODE; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_lba_out_of_range(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_LBA_OUT_OF_RANGE; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_invalid_field(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); + + dev->status = 0x53; +} + + +static void +scsi_cdrom_invalid_field_pl(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); + + dev->status = 0x53; +} + + +static void +scsi_cdrom_illegal_mode(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_incompatible_format(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + + scsi_cdrom_ascq = 2; + + scsi_cdrom_cmd_error(dev); +} + + +static void +scsi_cdrom_data_phase_error(scsi_cdrom_t *dev) +{ + scsi_cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_cdrom_asc = ASC_DATA_PHASE_ERROR; + scsi_cdrom_ascq = 0; + + scsi_cdrom_cmd_error(dev); +} + + +void +scsi_cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) +{ + int temp = 0; + + switch(cdb[0]) { + case GPCMD_READ_6: + cdb[1] = (lba_pos >> 16) & 0xff; + cdb[2] = (lba_pos >> 8) & 0xff; + cdb[3] = lba_pos & 0xff; + break; + + case GPCMD_READ_10: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_12: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 24) & 0xff; + cdb[7] = (number_of_blocks >> 16) & 0xff; + cdb[8] = (number_of_blocks >> 8) & 0xff; + cdb[9] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_CD_MSF: + temp = cdrom_lba_to_msf_accurate(lba_pos); + cdb[3] = (temp >> 16) & 0xff; + cdb[4] = (temp >> 8) & 0xff; + cdb[5] = temp & 0xff; + + temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); + cdb[6] = (temp >> 16) & 0xff; + cdb[7] = (temp >> 8) & 0xff; + cdb[8] = temp & 0xff; + break; + + case GPCMD_READ_CD: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 16) & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + } +} + + +static int +scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *len) +{ + int ret = 0; + uint32_t cdsize = 0; + int i = 0; + int temp_len = 0; + + cdsize = dev->drv->ops->size(dev->drv); + + if (dev->sector_pos >= cdsize) { + DEBUG("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, + dev->sector_pos, cdsize); + scsi_cdrom_lba_out_of_range(dev); + return 0; + } + + if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { + DEBUG("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, + (dev->sector_pos + dev->sector_len - 1), cdsize); + scsi_cdrom_lba_out_of_range(dev); + return 0; + } + + dev->old_len = 0; + *len = 0; + + for (i = 0; i < dev->requested_blocks; i++) { + ret = dev->drv->ops->readsector_raw(dev->drv, cdbufferb + dev->data_pos, dev->sector_pos + i, + msf, type, flags, &temp_len); + + dev->data_pos += temp_len; + dev->old_len += temp_len; + + *len += temp_len; + + if (!ret) { + scsi_cdrom_illegal_mode(dev); + return 0; + } + } + + return 1; +} + + +static int +scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch) +{ + int ret = 0, msf = 0; + int type = 0, flags = 0; + + if (dev->current_cdb[0] == GPCMD_READ_CD_MSF) + msf = 1; + + if ((dev->current_cdb[0] == GPCMD_READ_CD_MSF) || (dev->current_cdb[0] == GPCMD_READ_CD)) { + type = (dev->current_cdb[1] >> 2) & 7; + flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); + } else { + type = 8; + flags = 0x10; + } + + dev->data_pos = 0; + + if (!dev->sector_len) { + scsi_cdrom_command_complete(dev); + return -1; + } + + DEBUG("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); + + scsi_cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); + + ret = scsi_cdrom_read_data(dev, msf, type, flags, len); + + DEBUG("Read %i bytes of blocks...\n", *len); + + if (!ret || ((dev->old_len != *len) && !first_batch)) { + if ((dev->old_len != *len) && !first_batch) + scsi_cdrom_illegal_mode(dev); + + return 0; + } + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; +} + + +/*SCSI Read DVD Structure*/ +static int +scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) +{ + int layer = packet[6]; + uint64_t total_sectors; + + switch (format) { + case 0x00: /* Physical format information */ + total_sectors = (uint64_t) dev->drv->ops->size(dev->drv); + + if (layer != 0) { + scsi_cdrom_invalid_field(dev); + return 0; + } + + total_sectors >>= 2; + if (total_sectors == 0) { + /* return -ASC_MEDIUM_NOT_PRESENT; */ + scsi_cdrom_not_ready(dev); + return 0; + } + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ + buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ + buf[13] = (total_sectors >> 16) & 0xff; + buf[14] = (total_sectors >> 8) & 0xff; + buf[15] = total_sectors & 0xff; + + buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ + buf[17] = (total_sectors >> 16) & 0xff; + buf[18] = (total_sectors >> 8) & 0xff; + buf[19] = total_sectors & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 +2 ) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((4 + 2) >> 8) & 0xff; + buf[1] = (4 + 2) & 0xff; + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + scsi_cdrom_invalid_field(dev); + return 0; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 + 2) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + buf[6] = ((2048 + 4) >> 8) & 0xff; + buf[7] = (2048 + 4) & 0xff; + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + buf[10] = ((4 + 4) >> 8) & 0xff; + buf[11] = (4 + 4) & 0xff; + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + buf[14] = ((188 + 4) >> 8) & 0xff; + buf[15] = (188 + 4) & 0xff; + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + buf[18] = ((2048 + 4) >> 8) & 0xff; + buf[19] = (2048 + 4) & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[6] = ((16 + 2) >> 8) & 0xff; + buf[7] = (16 + 2) & 0xff; + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + scsi_cdrom_invalid_field(dev); + return 0; + } +} + + +static void +scsi_cdrom_insert(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (!dev) + return; + + dev->unit_attention = 1; + DEBUG("CD-ROM %i: Media insert\n", dev->id); +} + + +static int +scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) +{ + int ready = 0, status = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { + DEBUG("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); + scsi_cdrom_invalid_lun(dev); + return 0; + } + } + + if (!(scsi_cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { + DEBUG("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); + + scsi_cdrom_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { + DEBUG("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + scsi_cdrom_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { + DEBUG("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + scsi_cdrom_illegal_opcode(dev); + return 0; + } + + status = dev->drv->ops->status(dev->drv); + + if ((status == CD_STATUS_PLAYING) || (status == CD_STATUS_PAUSED)) { + ready = 1; + goto skip_ready_check; + } + + if (dev->drv->ops->medium_changed(dev->drv)) + scsi_cdrom_insert((void *) dev); + + ready = dev->drv->ops->ready(dev->drv); + +skip_ready_check: + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && dev->unit_attention) + dev->unit_attention = 0; + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (dev->unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(scsi_cdrom_command_flags[cdb[0]] & ALLOW_UA)) { + DBGLOG(1, "CD-ROM %i: Unit attention now 2\n", dev->id); + dev->unit_attention++; + DEBUG("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", + dev->id, cdb[0]); + scsi_cdrom_unit_attention(dev); + return 0; + } + } else if (dev->unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + DBGLOG(1, "CD-ROM %i: Unit attention now 0\n", dev->id); + dev->unit_attention = 0; + } + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + scsi_cdrom_sense_clear(dev, cdb[0]); + + /* Next it's time for NOT READY. */ + if (!ready) + dev->media_status = MEC_MEDIA_REMOVAL; + else + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { + DEBUG("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + scsi_cdrom_not_ready(dev); + return 0; + } + + DEBUG("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); + + return 1; +} + + +static void +scsi_cdrom_rezero(scsi_cdrom_t *dev) +{ + dev->sector_pos = dev->sector_len = 0; + + cdrom_seek(dev->drv, 0); +} + + +void +scsi_cdrom_reset(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (!dev) + return; + + scsi_cdrom_rezero(dev); + + dev->status = 0; + dev->callback = 0LL; + + scsi_cdrom_set_callback(dev); + + dev->packet_status = 0xff; + dev->unit_attention = 0xff; +} + + +static void +scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) +{ + int status = dev->drv->cd_status; + + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + memcpy(buffer, dev->sense, alloc_length); + } + + buffer[0] = 0x70; + + if ((scsi_cdrom_sense_key > 0) && ((status < CD_STATUS_PLAYING) || + (status == CD_STATUS_STOPPED)) && cdrom_playing_completed(dev->drv)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } else if ((scsi_cdrom_sense_key == 0) && (status >= CD_STATUS_PLAYING) && + (status != CD_STATUS_STOPPED)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=(status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + } else { + if (dev->unit_attention && (scsi_cdrom_sense_key == 0)) { + buffer[2]=SENSE_UNIT_ATTENTION; + buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[13]=0; + } + } + + DEBUG("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + + if (buffer[2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + scsi_cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); +} + + +void +scsi_cdrom_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + int ready = 0; + + if (dev->drv->ops->medium_changed(dev->drv)) + scsi_cdrom_insert((void *) dev); + + ready = dev->drv->ops->ready(dev->drv); + + if (!ready && dev->unit_attention) { + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + dev->unit_attention = 0; + } + + /* Do *NOT* advance the unit attention phase. */ + scsi_cdrom_request_sense(dev, buffer, alloc_length); +} + + +static void +scsi_cdrom_set_buf_len(scsi_cdrom_t *dev, int32_t *BufLen, int32_t *src_len) +{ + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + DEBUG("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); + } +} + + +static void +scsi_cdrom_buf_alloc(scsi_cdrom_t *dev, uint32_t len) +{ + DEBUG("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len); + + cdbufferb = (uint8_t *) malloc(len); +} + + +static void +scsi_cdrom_buf_free(scsi_cdrom_t *dev) +{ + if (cdbufferb) { + DEBUG("CD-ROM %i: Freeing buffer...\n", dev->id); + free(cdbufferb); + cdbufferb = NULL; + } +} + + +void +scsi_cdrom_command(void *p, uint8_t *cdb) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + int len, max_len, used_len, alloc_length, msf; + int pos = 0, i= 0, size_idx, idx = 0; + uint32_t feature; + unsigned preamble_len; + int toc_format, block_desc = 0; + int ret, format = 0; + int real_pos, track = 0; + char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', ' ', 'v', '0'+EMU_VER_MAJOR, '.', '0'+EMU_VER_MINOR, '0'+EMU_VER_REV, 0 }; + int32_t blen = 0, *BufLen; + uint8_t *b; + uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; + dev->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->error = 0; + } + + dev->packet_len = 0; + dev->request_pos = 0; + + device_identify[7] = dev->id + 0x30; + + device_identify_ex[7] = dev->id + 0x30; + device_identify_ex[10] = EMU_VERSION[0]; + device_identify_ex[12] = EMU_VERSION[2]; + device_identify_ex[13] = EMU_VERSION[3]; + + dev->data_pos = 0; + + memcpy(dev->current_cdb, cdb, 12); + + dev->drv->cd_status = dev->drv->ops->status(dev->drv); + + if (cdb[0] != 0) { + DEBUG("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, dev->unit_attention); + DEBUG("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); + + DEBUG("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); + } + + msf = cdb[1] & 2; + dev->sector_len = 0; + + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (scsi_cdrom_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_TEST_UNIT_READY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + if (dev->drv->ops->stop) + dev->drv->ops->stop(dev->drv); + dev->sector_pos = dev->sector_len = 0; + dev->drv->seek_diff = dev->drv->seek_pos; + cdrom_seek(dev->drv, 0); + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + + if (!max_len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20LL * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + scsi_cdrom_buf_alloc(dev, 256); + scsi_cdrom_set_buf_len(dev, BufLen, &max_len); + scsi_cdrom_request_sense(dev, cdbufferb, max_len); + scsi_cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); + break; + + case GPCMD_SET_SPEED: + case GPCMD_SET_SPEED_ALT: + dev->drv->cur_speed = (cdb[3] | (cdb[2] << 8)) / 176; + if (dev->drv->cur_speed < 1) + dev->drv->cur_speed = 1; + else if (dev->drv->cur_speed > dev->drv->speed_idx) + dev->drv->cur_speed = dev->drv->speed_idx; + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_MECHANISM_STATUS: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + scsi_cdrom_buf_alloc(dev, 8); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + memset(cdbufferb, 0, 8); + cdbufferb[5] = 1; + + scsi_cdrom_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_TOC_PMA_ATIP: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + toc_format = cdb[2] & 0xf; + + if (toc_format == 0) + toc_format = (cdb[9] >> 6) & 3; + + switch (toc_format) { + case 0: /*Normal*/ + len = dev->drv->ops->readtoc(dev->drv, cdbufferb, cdb[6], msf, max_len, + 0); + break; + case 1: /*Multi session*/ + len = dev->drv->ops->readtoc_session(dev->drv, cdbufferb, msf, max_len); + cdbufferb[0] = 0; cdbufferb[1] = 0xA; + break; + case 2: /*Raw*/ + len = dev->drv->ops->readtoc_raw(dev->drv, cdbufferb, max_len); + break; + default: + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + if (len > max_len) { + len = max_len; + + cdbufferb[0] = ((len - 2) >> 8) & 0xff; + cdbufferb[1] = (len - 2) & 0xff; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); +#if 0 + DBGLOG(1, "CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", dev->id, + toc_format, ide->cylinder, cdbufferb[1]); +#endif + return; + + case GPCMD_READ_CD_OLD: + /* IMPORTANT: Convert the command to new read CD + for pass through purposes. */ + dev->current_cdb[0] = 0xbe; + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 2048; + + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + msf = 0; + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, + dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_CD_MSF: + alloc_length = 2856; + dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); + dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); + + dev->sector_len -= dev->sector_pos; + dev->sector_len++; + msf = 1; + break; + case GPCMD_READ_CD_OLD: + case GPCMD_READ_CD: + alloc_length = 2856; + dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + msf = 0; + break; + } + + dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); + dev->drv->seek_pos = dev->sector_pos; + + if (!dev->sector_len) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + DBGLOG(1, "CD-ROM %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20LL * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + scsi_cdrom_buf_alloc(dev, dev->packet_len); + + ret = scsi_cdrom_read_blocks(dev, &alloc_length, 1); + if (ret <= 0) { + scsi_cdrom_buf_free(dev); + return; + } + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + scsi_cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, + alloc_length, 0); + + if (dev->packet_status != PHASE_COMPLETE) + ui_sb_icon_update(SB_CDROM | dev->id, 1); + else + ui_sb_icon_update(SB_CDROM | dev->id, 0); + return; + + case GPCMD_READ_HEADER: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = ((cdb[7] << 8) | cdb[8]); + scsi_cdrom_buf_alloc(dev, 8); + + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; + if (msf) + real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); + else + real_pos = dev->sector_pos; + cdbufferb[0] = 1; /*2048 bytes user data*/ + cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; + cdbufferb[4] = (real_pos >> 24); + cdbufferb[5] = ((real_pos >> 16) & 0xff); + cdbufferb[6] = ((real_pos >> 8) & 0xff); + cdbufferb[7] = real_pos & 0xff; + + len = 8; + len = MIN(len, alloc_length); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + scsi_cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + scsi_cdrom_buf_alloc(dev, 65536); + } + + if (!(scsi_cdrom_mode_sense_page_flags & (1LL << (uint64_t) (cdb[2] & 0x3f)))) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + memset(cdbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = scsi_cdrom_mode_sense(dev, cdbufferb, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + cdbufferb[0] = len - 1; + cdbufferb[1] = dev->drv->ops->media_type_id(dev->drv); + if (block_desc) + cdbufferb[3] = 8; + } else { + len = scsi_cdrom_mode_sense(dev, cdbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + cdbufferb[0]=(len - 2) >> 8; + cdbufferb[1]=(len - 2) & 255; + cdbufferb[2] = dev->drv->ops->media_type_id(dev->drv); + if (block_desc) { + cdbufferb[6] = 0; + cdbufferb[7] = 8; + } + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + DEBUG("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + scsi_cdrom_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + scsi_cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + scsi_cdrom_buf_alloc(dev, 65536); + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + scsi_cdrom_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_GET_CONFIGURATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + /* XXX: could result in alignment problems in some architectures */ + feature = (cdb[2] << 8) | cdb[3]; + max_len = (cdb[7] << 8) | cdb[8]; + + /* only feature 0 is supported */ + if ((cdb[2] != 0) || (cdb[3] > 2)) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_buf_alloc(dev, 65536); + memset(cdbufferb, 0, max_len); + + alloc_length = 0; + b = cdbufferb; + + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (dev->drv->ops->ready(dev->drv)) { + len = dev->drv->ops->size(dev->drv); + if (len > CD_MAX_SECTORS) { + b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_DVD_ROM & 0xff; + ret = 1; + } else { + b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_CD_ROM & 0xff; + ret = 0; + } + } else + ret = 2; + + alloc_length = 8; + b += 8; + + if ((feature == 0) || ((cdb[1] & 3) < 2)) { + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + alloc_length += 4; + b += 4; + + for (i = 0; i < 2; i++) { + b[0] = (profiles[i] >> 8) & 0xff; + b[1] = profiles[i] & 0xff; + + if (ret == i) + b[2] |= 1; + + alloc_length += 4; + b += 4; + } + } + if ((feature == 1) || ((cdb[1] & 3) < 2)) { + b[1] = 1; + b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + b[7] = 1; + else + b[7] = 2; + b[8] = 1; + + alloc_length += 12; + b += 12; + } + if ((feature == 2) || ((cdb[1] & 3) < 2)) { + b[1] = 2; + b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; + + b[4] = 2; + + alloc_length += 8; + b += 8; + } + + cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; + cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; + cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; + cdbufferb[3] = (alloc_length - 4) & 0xff; + + alloc_length = MIN(alloc_length, max_len); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + break; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + scsi_cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header_t)); + + gesn_cdb = (void *) cdb; + gesn_event_header = (void *) cdbufferb; + + /* It is fine by the MMC spec to not support async mode operations. */ + if (!(gesn_cdb->polled & 0x01)) { + /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + * Notification class requests and supported event classes are bitmasks, + * but they are built from the same values as the "notification class" + * field. + */ + gesn_event_header->supported_events = 1 << GESN_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->class & (1 << GESN_MEDIA)) { + gesn_event_header->notification_class |= GESN_MEDIA; + + cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ + cdbufferb[5] = 1; /* Power Status (1 = Active) */ + cdbufferb[6] = 0; + cdbufferb[7] = 0; + used_len = 8; + } else { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + memcpy(cdbufferb, gesn_event_header, 4); + + scsi_cdrom_set_buf_len(dev, BufLen, &used_len); + + scsi_cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); + break; + + case GPCMD_READ_DISC_INFORMATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + memset(cdbufferb, 0, 34); + memset(cdbufferb, 1, 9); + cdbufferb[0] = 0; + cdbufferb[1] = 32; + cdbufferb[2] = 0xe; /* last session complete, disc finalized */ + cdbufferb[7] = 0x20; /* unrestricted use */ + cdbufferb[8] = 0x00; /* CD-ROM */ + + len=34; + len = MIN(len, max_len); + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_TRACK_INFORMATION: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + scsi_cdrom_buf_alloc(dev, 65536); + + track = ((uint32_t) cdb[2]) << 24; + track |= ((uint32_t) cdb[3]) << 16; + track |= ((uint32_t) cdb[4]) << 8; + track |= (uint32_t) cdb[5]; + + if (((cdb[1] & 0x03) != 1) || (track != 1)) { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + len = 36; + + memset(cdbufferb, 0, 36); + cdbufferb[0] = 0; + cdbufferb[1] = 34; + cdbufferb[2] = 1; /* track number (LSB) */ + cdbufferb[3] = 1; /* session number (LSB) */ + cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + cdbufferb[24] = (dev->drv->ops->size(dev->drv) >> 24) & 0xff; /* track size */ + cdbufferb[25] = (dev->drv->ops->size(dev->drv) >> 16) & 0xff; /* track size */ + cdbufferb[26] = (dev->drv->ops->size(dev->drv) >> 8) & 0xff; /* track size */ + cdbufferb[27] = dev->drv->ops->size(dev->drv) & 0xff; /* track size */ + + if (len > max_len) { + len = max_len; + cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; + cdbufferb[1] = (max_len - 2) & 0xff; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PLAY_AUDIO_10: + case GPCMD_PLAY_AUDIO_12: + case GPCMD_PLAY_AUDIO_MSF: + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_PLAY_AUDIO_10: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_12: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + case GPCMD_PLAY_AUDIO_MSF: + /* This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it. */ + msf = 1; + pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + msf = 2; + pos = (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + } + + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + + if (dev->drv->ops->playaudio) + ret = dev->drv->ops->playaudio(dev->drv, pos, len, msf); + else + ret = 0; + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + + case GPCMD_READ_SUBCHANNEL: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = (cdb[1] >> 1) & 1; + + scsi_cdrom_buf_alloc(dev, 32); + + DEBUG("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); + + if (cdb[3] > 3) { + DBGLOG(1, "CD-ROM %i: Read subchannel check condition %02X\n", dev->id, + cdb[3]); + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + + switch(cdb[3]) { + case 0: + alloc_length = 4; + break; + case 1: + alloc_length = 16; + break; + default: + alloc_length = 24; + break; + } + + memset(cdbufferb, 0, 24); + pos = 0; + cdbufferb[pos++] = 0; + cdbufferb[pos++] = 0; /*Audio status*/ + cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ + cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ + if (cdb[3] == 1) { + cdbufferb[1] = dev->drv->ops->getcurrentsubchannel(dev->drv, &cdbufferb[5], msf); + switch(dev->drv->cd_status) { + case CD_STATUS_PLAYING: + cdbufferb[1] = 0x11; + break; + case CD_STATUS_PAUSED: + cdbufferb[1] = 0x12; + break; + case CD_STATUS_DATA_ONLY: + cdbufferb[1] = 0x15; + break; + default: + cdbufferb[1] = 0x13; + break; + } + } + + if (!(cdb[2] & 0x40) || (cdb[3] == 0)) + len = 4; + else + len = alloc_length; + + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_DVD_STRUCTURE: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + + scsi_cdrom_buf_alloc(dev, alloc_length); + + len = dev->drv->ops->size(dev->drv); + + if ((cdb[7] < 0xc0) && (len <= CD_MAX_SECTORS)) { + scsi_cdrom_incompatible_format(dev); + scsi_cdrom_buf_free(dev); + return; + } + + memset(cdbufferb, 0, alloc_length); + + if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { + if (cdb[1] == 0) { + ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, cdbufferb); + if (ret) { + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, + len, 0); + } else + scsi_cdrom_buf_free(dev); + return; + } + } else { + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + break; + + case GPCMD_START_STOP_UNIT: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + if (dev->drv->ops->stop) + dev->drv->ops->stop(dev->drv); + break; + case 1: /* Start the disc and read the TOC. */ + dev->drv->ops->medium_changed(dev->drv); /* This causes a TOC reload. */ + break; + case 2: /* Eject the disc if possible. */ + if (dev->drv->ops->stop) + dev->drv->ops->stop(dev->drv); + ui_cdrom_eject(dev->id); + break; + case 3: /* Load the disc (close tray). */ + ui_cdrom_reload(dev->id); + break; + } + + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_INQUIRY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + scsi_cdrom_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + cdbufferb[idx++] = 05; + cdbufferb[idx++] = cdb[2]; + cdbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + scsi_cdrom_data_phase_error(dev); + scsi_cdrom_buf_free(dev); + return; + } + + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 20; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + goto atapi_out; + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x01; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 68; + ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ + idx += 8; + ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + DEBUG("INQUIRY: Invalid page: %02X\n", cdb[2]); + scsi_cdrom_invalid_field(dev); + scsi_cdrom_buf_free(dev); + return; + } + } else { + preamble_len = 5; + size_idx = 4; + + memset(cdbufferb, 0, 8); + cdbufferb[0] = 5; /*CD-ROM*/ + cdbufferb[1] = 0x80; /*Removable*/ + cdbufferb[2] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + cdbufferb[3] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; + cdbufferb[4] = 31; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + cdbufferb[6] = 1; /* 16-bit transfers supported */ + cdbufferb[7] = 0x20; /* Wide bus supported */ + } + + ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ + ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ + idx = 36; + + if (max_len == 96) { + cdbufferb[4] = 91; + idx = 96; + } + } + +atapi_out: + cdbufferb[size_idx] = idx - preamble_len; + len=idx; + + len = MIN(len, max_len); + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PREVENT_REMOVAL: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_PAUSE_RESUME_ALT: + case GPCMD_PAUSE_RESUME: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (cdb[8] & 1) { + if (dev->drv->ops->resume) + dev->drv->ops->resume(dev->drv); + else { + scsi_cdrom_illegal_mode(dev); + break; + } + } else { + if (dev->drv->ops->pause) + dev->drv->ops->pause(dev->drv); + else { + scsi_cdrom_illegal_mode(dev); + break; + } + } + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); + cdrom_seek(dev->drv, pos); + scsi_cdrom_command_complete(dev); + break; + + case GPCMD_READ_CDROM_CAPACITY: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + scsi_cdrom_buf_alloc(dev, 8); + + if (scsi_cdrom_read_capacity(dev, dev->current_cdb, cdbufferb, (uint32_t *) &len) == 0) { + scsi_cdrom_buf_free(dev); + return; + } + + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_STOP_PLAY_SCAN: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (dev->drv->ops->stop) + dev->drv->ops->stop(dev->drv); + else { + scsi_cdrom_illegal_mode(dev); + break; + } + scsi_cdrom_command_complete(dev); + break; + + default: + scsi_cdrom_illegal_opcode(dev); + break; + } + + DBGLOG(1, "CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); + + if (scsi_cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + scsi_cdrom_buf_free(dev); +} + + +/* The command second phase function, needed for Mode Select. */ +static uint8_t +scsi_cdrom_phase_data_out(scsi_cdrom_t *dev) +{ + uint16_t block_desc_len, pos; + uint16_t i = 0; + + uint8_t error = 0; + uint8_t page, page_len, hdr_len, val, old_val, ch; + + switch(dev->current_cdb[0]) { + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = cdbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[3]; + } else { + block_desc_len = cdbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[7]; + } + } else + block_desc_len = 0; + + pos = hdr_len + block_desc_len; + + while(1) { + page = cdbufferb[pos] & 0x3F; + page_len = cdbufferb[pos + 1]; + + pos += 2; + + if (!(scsi_cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { + DEBUG("Unimplemented page %02X\n", page); + error |= 1; + } else { + for (i = 0; i < page_len; i++) { + ch = scsi_cdrom_mode_sense_pages_changeable.pages[page][i + 2]; + val = cdbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + DEBUG("Unchangeable value on position %02X on page %02X\n", i + 2, page); + error |= 1; + } + } + } + } + + pos += page_len; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + val = scsi_cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = scsi_cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + + if (dev->do_page_save && val) + scsi_cdrom_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) { + scsi_cdrom_invalid_field_pl(dev); + return 0; + } + break; + } + + return 1; +} + + +/* This is the general ATAPI PIO request function. */ +static void +scsi_cdrom_pio_request(scsi_cdrom_t *dev, uint8_t out) +{ + int ret = 0; + + if (dev->drv->bus_type < CDROM_BUS_SCSI) { + DEBUG("CD-ROM %i: Lowering IDE IRQ\n", dev->id); + ide_irq_lower(ide_drives[dev->drv->bus_id.ide_channel]); + } + + dev->status = BUSY_STAT; + + if (dev->pos >= dev->packet_len) { + DEBUG("CD-ROM %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); + + dev->pos = dev->request_pos = 0; + if (out) { + ret = scsi_cdrom_phase_data_out(dev); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ + if (ret) + scsi_cdrom_command_complete(dev); + } else + scsi_cdrom_command_complete(dev); + scsi_cdrom_buf_free(dev); + } else { + DEBUG("CD-ROM %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, + out ? "written" : "read", dev->packet_len - dev->pos); + + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) + dev->max_transfer_len = dev->packet_len - dev->pos; + DEBUG("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); + + dev->packet_status = out ? PHASE_DATA_OUT : PHASE_DATA_IN; + + dev->status = BUSY_STAT; + dev->phase = 1; + scsi_cdrom_callback(dev); + dev->callback = 0LL; + scsi_cdrom_set_callback(dev); + + dev->request_pos = 0; + } +} + + +static int +scsi_cdrom_read_from_ide_dma(scsi_cdrom_t *dev) +{ + int ret; + + if (!dev) + return 0; + + if (ide_bus_master_write) { + ret = ide_bus_master_write(dev->drv->bus_id.ide_channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[dev->drv->bus_id.ide_channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + scsi_cdrom_bus_master_error(dev); + return 0; + } else + return 1; + } + + return 0; +} + + +static int +scsi_cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + scsi_cdrom_t *dev = scsi_devices[scsi_id][scsi_lun].p; + int32_t *BufLen = &scsi_devices[scsi_id][scsi_lun].buffer_length; + + if (dev) + return 0; + + DEBUG("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(cdbufferb, scsi_devices[scsi_id][scsi_lun].cmd_buffer, *BufLen); + + return 1; +} + + +static void +scsi_cdrom_irq_raise(scsi_cdrom_t *dev) +{ + if (dev->drv->bus_type < CDROM_BUS_SCSI) + ide_irq_raise(ide_drives[dev->drv->bus_id.ide_channel]); +} + + +static int +scsi_cdrom_read_from_dma(scsi_cdrom_t *dev) +{ + int32_t *BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; + int ret = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + ret = scsi_cdrom_read_from_scsi_dma(dev->drv->bus_id.scsi.id, dev->drv->bus_id.scsi.lun); + else + ret = scsi_cdrom_read_from_ide_dma(dev); + + if (ret != 1) + return ret; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + DEBUG("CD-ROM %i: SCSI Input data length: %i\n", dev->id, *BufLen); + else + DEBUG("CD-ROM %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + + ret = scsi_cdrom_phase_data_out(dev); + if (ret) + return 1; + + return 0; +} + + +static int +scsi_cdrom_write_to_ide_dma(scsi_cdrom_t *dev) +{ + int ret; + + if (!dev) + return 0; + + if (ide_bus_master_read) { + ret = ide_bus_master_read(dev->drv->bus_id.ide_channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[dev->drv->bus_id.ide_channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + scsi_cdrom_bus_master_error(dev); + return 0; + } else + return 1; + } + + return 0; +} + + +static int +scsi_cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + scsi_cdrom_t *dev = scsi_devices[scsi_id][scsi_lun].p; + int32_t *BufLen = &scsi_devices[scsi_id][scsi_lun].buffer_length; + + if (!dev) + return 0; + + DEBUG("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(scsi_devices[scsi_id][scsi_lun].cmd_buffer, cdbufferb, *BufLen); + DEBUG("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], + cdbufferb[6], cdbufferb[7]); + + return 1; +} + + +static int +scsi_cdrom_write_to_dma(scsi_cdrom_t *dev) +{ + scsi_device_t *sd = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun]; + int32_t *BufLen = &sd->buffer_length; + int ret = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + DEBUG("Write to SCSI DMA: (ID %02X)\n", dev->drv->bus_id.scsi.id); + ret = scsi_cdrom_write_to_scsi_dma(dev->drv->bus_id.scsi.id, dev->drv->bus_id.scsi.lun); + } else + ret = scsi_cdrom_write_to_ide_dma(dev); + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + DEBUG("CD-ROM %i: SCSI Output data length: %i\n", dev->id, *BufLen); + else + DEBUG("CD-ROM %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); + + return ret; +} + + +static void +scsi_cdrom_callback(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + int ret; + + switch(dev->packet_status) { + case PHASE_IDLE: + DEBUG("CD-ROM %i: PHASE_IDLE\n", dev->id); + dev->pos = 0; + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + return; + case PHASE_COMMAND: + DEBUG("CD-ROM %i: PHASE_COMMAND\n", dev->id); + dev->status = BUSY_STAT | (dev->status & ERR_STAT); + memcpy(dev->atapi_cdb, cdbufferb, 12); + scsi_cdrom_command(dev, dev->atapi_cdb); + return; + case PHASE_COMPLETE: + DEBUG("CD-ROM %i: PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + ui_sb_icon_update(SB_CDROM | dev->id, 0); + scsi_cdrom_irq_raise(dev); + return; + case PHASE_DATA_OUT: + DEBUG("CD-ROM %i: PHASE_DATA_OUT\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 0; + scsi_cdrom_irq_raise(dev); + return; + case PHASE_DATA_OUT_DMA: + DEBUG("CD-ROM %i: PHASE_DATA_OUT_DMA\n", dev->id); + ret = scsi_cdrom_read_from_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + DEBUG("CD-ROM %i: DMA data out phase done\n"); + scsi_cdrom_buf_free(dev); + scsi_cdrom_command_complete(dev); + } else if (ret == 2) { + DEBUG("CD-ROM %i: DMA out not enabled, wait\n"); + scsi_cdrom_command_bus(dev); + } else { + DEBUG("CD-ROM %i: DMA data out phase failure\n"); + scsi_cdrom_buf_free(dev); + } + return; + case PHASE_DATA_IN: + DEBUG("CD-ROM %i: PHASE_DATA_IN\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 2; + scsi_cdrom_irq_raise(dev); + return; + case PHASE_DATA_IN_DMA: + DEBUG("CD-ROM %i: PHASE_DATA_IN_DMA\n", dev->id); + ret = scsi_cdrom_write_to_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + DEBUG("CD-ROM %i: DMA data in phase done\n", dev->id); + scsi_cdrom_buf_free(dev); + scsi_cdrom_command_complete(dev); + } else if (ret == 2) { + DEBUG("CD-ROM %i: DMA in not enabled, wait\n", dev->id); + scsi_cdrom_command_bus(dev); + } else { + DEBUG("CD-ROM %i: DMA data in phase failure\n", dev->id); + scsi_cdrom_buf_free(dev); + } + return; + case PHASE_ERROR: + DEBUG("CD-ROM %i: PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + scsi_cdrom_irq_raise(dev); + ui_sb_icon_update(SB_CDROM | dev->id, 0); + return; + } +} + + +static uint32_t +scsi_cdrom_packet_read(void *p, int length) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + uint32_t temp = 0; + + if (!dev) + return 0; + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 2048 bytes). */ + switch(length) { + case 1: + temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; + dev->pos++; + dev->request_pos++; + break; + case 2: + temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return 0; + } + + if (dev->packet_status == PHASE_DATA_IN) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + scsi_cdrom_pio_request(dev, 0); + } + return temp; + } else + return 0; +} + + +static void +scsi_cdrom_packet_write(void *p, uint32_t val, int length) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + if (!dev) + return; + + if ((dev->packet_status == PHASE_IDLE) && !cdbufferb) + scsi_cdrom_buf_alloc(dev, 12); + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return; + + switch(length) { + case 1: + cdbufferb[dev->pos] = val & 0xff; + dev->pos++; + dev->request_pos++; + break; + case 2: + cdbufferw[dev->pos >> 1] = val & 0xffff; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + cdbufferl[dev->pos >> 2] = val; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return; + } + + if (dev->packet_status == PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + scsi_cdrom_pio_request(dev, 1); + } + return; + } else if (dev->packet_status == PHASE_IDLE) { + if (dev->pos >= 12) { + dev->pos = 0; + dev->status = BUSY_STAT; + dev->packet_status = PHASE_COMMAND; + timer_process(); + scsi_cdrom_callback(dev); + timer_update_outstanding(); + } + return; + } +} + + +static void +scsi_cdrom_close(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (dev) { + free(scsi_cdrom[dev->id]); + scsi_cdrom[dev->id] = NULL; + } +} + + +static void +scsi_cdrom_stop(void *p) +{ + scsi_cdrom_t *dev = (scsi_cdrom_t *) p; + + if (dev->drv->ops->stop) + dev->drv->ops->stop(dev->drv); +} + + +static int +scsi_cdrom_get_max(int ide_has_dma, int type) +{ + int ret; + + switch(type) { + case TYPE_PIO: + ret = ide_has_dma ? 4 : 0; + break; + case TYPE_SDMA: + ret = ide_has_dma ? -1 : 2; + break; + case TYPE_MDMA: + ret = ide_has_dma ? -1 : 2; + break; + case TYPE_UDMA: + ret = ide_has_dma ? -1 : 2; + break; + default: + ret = -1; + break; + } + + return ret; +} + + +static int +scsi_cdrom_get_timings(int ide_has_dma, int type) +{ + int ret; + + switch(type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO_FC: + ret = 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + + +/** + * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command + */ +static void +scsi_cdrom_identify(void *p, int ide_has_dma) +{ + ide_t *ide = (ide_t *) p; + scsi_cdrom_t *dev; + char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; + + dev = (scsi_cdrom_t *) ide->p; + + device_identify[7] = dev->id + 0x30; + DEBUG("ATAPI Identify: %s\n", device_identify); + + ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ +#if 0 + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ +#else + ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */ +#endif + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + + if (ide_has_dma) { + ide->buffer[71] = 30; + ide->buffer[72] = 30; + } +} + + +void +scsi_cdrom_drive_reset(int c) +{ + cdrom_t *drv = &cdrom[c]; + scsi_device_t *sd; + ide_t *id; + + /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ + if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->bus_id.scsi.id > SCSI_ID_MAX)) + return; + + /* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */ + if ((drv->bus_type == CDROM_BUS_ATAPI) && (drv->bus_id.ide_channel > 7)) + return; + + if (!scsi_cdrom[c]) { + scsi_cdrom[c] = (scsi_cdrom_t *)mem_alloc(sizeof(scsi_cdrom_t)); + memset(scsi_cdrom[c], 0, sizeof(scsi_cdrom_t)); + } + + scsi_cdrom[c]->id = c; + scsi_cdrom[c]->drv = drv; + drv->p = scsi_cdrom[c]; + drv->insert = scsi_cdrom_insert; + drv->get_volume = scsi_cdrom_get_volume; + drv->get_channel = scsi_cdrom_get_channel; + drv->close = scsi_cdrom_close; + + scsi_cdrom_init(scsi_cdrom[c]); + + if (drv->bus_type == CDROM_BUS_SCSI) { + /* SCSI CD-ROM, attach to the SCSI bus. */ + sd = &scsi_devices[drv->bus_id.scsi.id][drv->bus_id.scsi.lun]; + + sd->p = scsi_cdrom[c]; + sd->command = scsi_cdrom_command; + sd->callback = scsi_cdrom_callback; + sd->err_stat_to_scsi = scsi_cdrom_err_stat_to_scsi; + sd->request_sense = scsi_cdrom_request_sense_for_scsi; + sd->reset = scsi_cdrom_reset; + sd->read_capacity = scsi_cdrom_read_capacity; + sd->type = SCSI_REMOVABLE_CDROM; + + DEBUG("SCSI CD-ROM drive %i attached to SCSI ID %i LUN %i\n", c, cdrom[c].bus_id.scsi.id, cdrom[c].bus_id.scsi.lun); + } else if (drv->bus_type == CDROM_BUS_ATAPI) { + /* ATAPI CD-ROM, attach to the IDE bus. */ + id = ide_drives[drv->bus_id.ide_channel]; + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + id->p = scsi_cdrom[c]; + id->get_max = scsi_cdrom_get_max; + id->get_timings = scsi_cdrom_get_timings; + id->identify = scsi_cdrom_identify; + id->set_signature = scsi_cdrom_set_signature; + id->packet_write = scsi_cdrom_packet_write; + id->packet_read = scsi_cdrom_packet_read; + id->stop = scsi_cdrom_stop; + id->packet_callback = scsi_cdrom_callback; + id->device_reset = scsi_cdrom_reset; + id->interrupt_drq = 0; + + ide_atapi_attach(id); + } + + DEBUG("ATAPI CD-ROM drive %i attached to IDE channel %i\n", c, cdrom[c].bus_id.ide_channel); + } +} diff --git a/src/devices/scsi/scsi_cdrom.h b/src/devices/scsi/scsi_cdrom.h new file mode 100644 index 0000000..fcdecec --- /dev/null +++ b/src/devices/scsi/scsi_cdrom.h @@ -0,0 +1,95 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the SCSI CD-ROM module. + * + * Version: @(#)scsi_cdrom.h 1.0.1 2018/10/14 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef EMU_SCSI_CDROM_H +#define EMU_SCSI_CDROM_H + + +#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) + + +#ifdef EMU_SCSI_DEVICE_H +typedef struct { + mode_sense_pages_t ms_pages_saved; + + cdrom_t *drv; + + uint8_t *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; + + uint8_t status, phase, + error, id, + features, pad0, + pad1, pad2; + + uint16_t request_length, max_transfer_len; + + int requested_blocks, packet_status, + total_length, do_page_save, + unit_attention; + + uint32_t sector_pos, sector_len, + packet_len, pos; + + int64_t callback; + + int media_status, data_pos, + request_pos, total_read, + old_len; + + uint8_t previous_command, + pad3, pad4, pad5; +} scsi_cdrom_t; + + +extern scsi_cdrom_t *scsi_cdrom[CDROM_NUM]; +#endif + +#define scsi_cdrom_sense_error dev->sense[0] +#define scsi_cdrom_sense_key dev->sense[2] +#define scsi_cdrom_asc dev->sense[12] +#define scsi_cdrom_ascq dev->sense[13] +#define scsi_cdrom_drive cdrom[id].host_drive + + +extern void scsi_cdrom_log(int level, const char *fmt, ...); + +extern void scsi_cdrom_reset(void *p); + + +#endif /*EMU_SCSI_CDROM_H*/ diff --git a/src/devices/scsi/scsi_device.c b/src/devices/scsi/scsi_device.c index 00246c3..2a709ae 100644 --- a/src/devices/scsi/scsi_device.c +++ b/src/devices/scsi/scsi_device.c @@ -8,7 +8,7 @@ * * The generic SCSI device command handler. * - * Version: @(#)scsi_device.c 1.0.7 2018/09/15 + * Version: @(#)scsi_device.c 1.0.9 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,401 +44,152 @@ #include "../disk/hdd.h" #include "scsi.h" #include "scsi_device.h" -#include "scsi_disk.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" -static const uint8_t scsi_null_device_sense[18] = { +scsi_device_t scsi_devices[SCSI_ID_MAX][SCSI_LUN_MAX]; +const uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; static uint8_t -scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) +scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb) { - uint8_t ret = SCSI_STATUS_CHECK_CONDITION; - - switch (lun_type) { - case SCSI_DISK: - scsi_disk_command(scsi_disk[id], cdb); - ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]); - break; - - case SCSI_CDROM: - cdrom_command(cdrom[id], cdb); - ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]); - break; - - case SCSI_ZIP: - zip_command(zip[id], cdb); - ret = zip_ZIP_PHASE_to_scsi(zip[id]); - break; - - default: - break; + if (dev->command && dev->err_stat_to_scsi) { + dev->command(dev->p, cdb); + return dev->err_stat_to_scsi(dev->p); } - return ret; + return SCSI_STATUS_CHECK_CONDITION; } static void -scsi_device_target_phase_callback(int lun_type, uint8_t id) +scsi_device_target_callback(scsi_device_t *dev) { - switch (lun_type) { - case SCSI_DISK: - scsi_disk_callback(scsi_disk[id]); - break; - - case SCSI_CDROM: - cdrom_phase_callback(cdrom[id]); - break; - - case SCSI_ZIP: - zip_phase_callback(zip[id]); - break; - - default: - break; - } + if (dev->callback) + dev->callback(dev->p); } static int -scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id) +scsi_device_target_err_stat_to_scsi(scsi_device_t *dev) { - uint8_t ret = SCSI_STATUS_CHECK_CONDITION; + if (dev->err_stat_to_scsi) + return dev->err_stat_to_scsi(dev->p); - switch (lun_type) { - case SCSI_DISK: - ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]); - break; - - case SCSI_CDROM: - ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]); - break; - - case SCSI_ZIP: - ret = zip_ZIP_PHASE_to_scsi(zip[id]); - break; - - default: - break; - } - - return ret; + return SCSI_STATUS_CHECK_CONDITION; } int64_t -scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_get_callback(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - int64_t ret = -1LL; - uint8_t id; + scsi_device_data_t *sdd = (scsi_device_data_t *)dev->p; - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - ret = scsi_disk[id]->callback; - break; + if (sdd) + return sdd->callback; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - ret = cdrom[id]->callback; - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - ret = zip[id]->callback; - break; - - default: - break; - } - - return ret; + return -1LL; } uint8_t * -scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_sense(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t *ret = (uint8_t *)scsi_null_device_sense; - uint8_t id; + scsi_device_data_t *sdd = (scsi_device_data_t *)dev->p; - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - ret = scsi_disk[id]->sense; - break; + if (sdd) + return sdd->sense; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - ret = cdrom[id]->sense; - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - ret = zip[id]->sense; - break; - - default: - break; - } - - return ret; + return (uint8_t *)scsi_null_device_sense; } void -scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length) +scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length); - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length); - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - zip_request_sense_for_scsi(zip[id], buffer, alloc_length); - break; - - default: - memcpy(buffer, scsi_null_device_sense, alloc_length); - break; - } + if (dev->request_sense) + dev->request_sense(dev->p, buffer, alloc_length); + else + memcpy(buffer, scsi_null_device_sense, alloc_length); } void -scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_reset(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - scsi_disk_reset(scsi_disk[id]); - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - cdrom_reset(cdrom[id]); - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - zip_reset(zip[id]); - break; - - default: - break; - } -} - - -void -scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb) -{ - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - - switch (lun_type) { - case SCSI_DISK: - *type = *rmb = 0x00; - break; - - case SCSI_CDROM: - *type = 0x05; - *rmb = 0x80; - break; - - case SCSI_ZIP: - *type = 0x00; - *rmb = 0x80; - break; - - default: - *type = *rmb = 0xff; - break; - } + if (dev->reset) + dev->reset(dev->p); } int -scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +scsi_device_present(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - int ret = 0; - uint8_t id; + if (dev->type == SCSI_NONE) + return 0; - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - ret = scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len); - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - ret = cdrom_read_capacity(cdrom[id], cdb, buffer, len); - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - ret = zip_read_capacity(zip[id], cdb, buffer, len); - break; - - default: - break; - } - - return ret; + return 1; } int -scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_valid(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - int ret = 0; + if (dev->p) + return 1; - switch (lun_type) { - case SCSI_NONE: - ret = 0; - break; - - default: - ret = 1; - break; - } - - return ret; + return 0; } int -scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_cdb_length(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - break; - - default: - break; - } - - return (id == 0xff) ? 0 : 1; -} - - -int -scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun) -{ - (void)scsi_id; - (void)scsi_lun; - /* Right now, it's 12 for all devices. */ return 12; } void -scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb) +scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - break; - - default: - SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS; - SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION; - return; + if (! dev->p) { + dev->phase = SCSI_PHASE_STATUS; + dev->status = SCSI_STATUS_CHECK_CONDITION; + return; } /* Finally, execute the SCSI command immediately and get the transfer length. */ - SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND; - SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb); + dev->phase = SCSI_PHASE_COMMAND; + dev->status = scsi_device_target_command(dev, cdb); - if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) { + if (dev->phase == SCSI_PHASE_STATUS) { /* Command completed (either OK or error) - call the phase callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); + scsi_device_target_callback(dev); } - /* If the phase is DATA IN or DATA OUT, finish this here. */ } void -scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_command_phase1(scsi_device_t *dev) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - break; - - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - break; - - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - break; - - default: - return; - } + if (! dev->p) + return; /* Call the second phase. */ - scsi_device_target_phase_callback(lun_type, id); - - SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id); + scsi_device_target_callback(dev); + dev->status = scsi_device_target_err_stat_to_scsi(dev); /* Command second phase complete - call the callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); + scsi_device_target_callback(dev); } int32_t * -scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun) +scsi_device_get_buf_len(scsi_device_t *dev) { - return &SCSIDevices[scsi_id][scsi_lun].BufferLength; + return &dev->buffer_length; } diff --git a/src/devices/scsi/scsi_device.h b/src/devices/scsi/scsi_device.h index 3c826b5..94adf4f 100644 --- a/src/devices/scsi/scsi_device.h +++ b/src/devices/scsi/scsi_device.h @@ -8,7 +8,7 @@ * * Definitions for the generic SCSI device command handler. * - * Version: @(#)scsi_device.h 1.0.3 2018/10/05 + * Version: @(#)scsi_device.h 1.0.5 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -34,8 +34,8 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef SCSI_DEVICE_H -# define SCSI_DEVICE_H +#ifndef EMU_SCSI_DEVICE_H +# define EMU_SCSI_DEVICE_H /* Configuration. */ @@ -109,25 +109,33 @@ /* Mode page codes for mode sense/set */ #define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */ +#define GPMODE_FORMAT_DEVICE_PAGE 0x03 +#define GPMODE_RIGID_DISK_PAGE 0x04 /* Rigid disk geometry page */ +#define GPMODE_FLEXIBLE_DISK_PAGE 0x05 +#define GPMODE_CACHING_PAGE 0x08 #define GPMODE_CDROM_PAGE 0x0d #define GPMODE_CDROM_AUDIO_PAGE 0x0e #define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_IOMEGA_PAGE 0x2f +#define GPMODE_UNK_VENDOR_PAGE 0x30 #define GPMODE_ALL_PAGES 0x3f /* Mode page codes for presence */ #define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL -#define GPMODEP_UNK_PAGE_02 0x0000000000000004LL -#define GPMODEP_UNK_PAGE_03 0x0000000000000008LL -#define GPMODEP_UNK_PAGE_04 0x0000000000000010LL -#define GPMODEP_UNK_PAGE_05 0x0000000000000020LL -#define GPMODEP_UNK_PAGE_08 0x0000000000000100LL +#define GPMODEP_DISCONNECT_PAGE 0x0000000000000004LL +#define GPMODEP_FORMAT_DEVICE_PAGE 0x0000000000000008LL +#define GPMODEP_RIGID_DISK_PAGE 0x0000000000000010LL +#define GPMODEP_FLEXIBLE_DISK_PAGE 0x0000000000000020LL +#define GPMODEP_CACHING_PAGE 0x0000000000000100LL #define GPMODEP_CDROM_PAGE 0x0000000000002000LL #define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL #define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL -#define GPMODEP_UNK_PAGE_2F 0x0000800000000000LL -#define GPMODEP_UNK_PAGE_30 0x0001000000000000LL +#define GPMODEP_IOMEGA_PAGE 0x0000800000000000LL +#define GPMODEP_UNK_VENDOR_PAGE 0x0001000000000000LL #define GPMODEP_ALL_PAGES 0x8000000000000000LL + /* SCSI Status Codes */ #define SCSI_STATUS_OK 0 #define SCSI_STATUS_CHECK_CONDITION 2 @@ -139,6 +147,7 @@ #define SENSE_UNIT_ATTENTION 6 /* SCSI Additional Sense Codes */ +#define ASC_NONE 0x00 #define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_NOT_READY 0x04 #define ASC_ILLEGAL_OPCODE 0x20 @@ -153,6 +162,8 @@ #define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASC_DATA_PHASE_ERROR 0x4b #define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 + +#define ASCQ_NONE 0x00 #define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 #define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 #define ASCQ_CAPACITY_DATA_CHANGED 0x09 @@ -252,12 +263,21 @@ #define BUS_IDLE (1 << 31) -#define SCSI_PHASE_DATA_OUT 0 -#define SCSI_PHASE_DATA_IN BUS_IO -#define SCSI_PHASE_COMMAND BUS_CD -#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) -#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) -#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) +#define PHASE_IDLE 0x00 +#define PHASE_COMMAND 0x01 +#define PHASE_COMPLETE 0x02 +#define PHASE_DATA_IN 0x03 +#define PHASE_DATA_IN_DMA 0x04 +#define PHASE_DATA_OUT 0x05 +#define PHASE_DATA_OUT_DMA 0x06 +#define PHASE_ERROR 0x80 + +#define SCSI_PHASE_DATA_OUT 0 +#define SCSI_PHASE_DATA_IN BUS_IO +#define SCSI_PHASE_COMMAND BUS_CD +#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) +#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) +#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) #define MODE_SELECT_PHASE_IDLE 0 #define MODE_SELECT_PHASE_HEADER 1 @@ -265,28 +285,41 @@ #define MODE_SELECT_PHASE_PAGE_HEADER 3 #define MODE_SELECT_PHASE_PAGE 4 +/* These are based on the INQUIRY values. */ +#define SCSI_NONE 0x0060 +#define SCSI_FIXED_DISK 0x0000 +#define SCSI_REMOVABLE_DISK 0x8000 +#define SCSI_REMOVABLE_CDROM 0x8005 + +#if 0 typedef struct { - int state; - int new_state; - int clear_req; - uint32_t bus_in, bus_out; - int dev_id; - - int command_pos; - uint8_t command[20]; - int data_pos; - - int change_state_delay; - int new_req_delay; + uint8_t command[20]; + int state, new_state, + clear_req, dev_id, + command_pos, data_pos, + change_state_delay, + new_req_delay; + uint32_t bus_in, bus_out; } scsi_bus_t; +#endif typedef struct { - uint8_t *CmdBuffer; - int LunType; - int32_t BufferLength; - uint8_t Status; - uint8_t Phase; + uint8_t id, lun; + uint16_t type; + + uint8_t status, phase; + + int32_t buffer_length; + uint8_t *cmd_buffer; + + void *p; + void (*command)(void *p, uint8_t *cdb); + void (*callback)(void *p); + int (*err_stat_to_scsi)(void *p); + void (*request_sense)(void *p, uint8_t *buffer, uint8_t alloc_length); + void (*reset)(void *p); + int (*read_capacity)(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len); } scsi_device_t; #pragma pack(push,1) @@ -295,15 +328,38 @@ typedef struct { } mode_sense_pages_t; #pragma pack(pop) -enum { - SCSI_NONE = 0, - SCSI_DISK, - SCSI_CDROM, - SCSI_ZIP -}; +/* This is so we can access the common elements to all SCSI device structs + without knowing the device type. */ +typedef struct { + mode_sense_pages_t ms_pages_saved; + + void *p; + + uint8_t *temp_buffer, + pad[16], /* This is atapi_cdb in ATAPI-supporting devices, + and pad in SCSI-only devices. */ + current_cdb[16], + sense[256]; + + uint8_t status, phase, + error, id, + features, pad0, + pad1, pad2; + + uint16_t request_length, max_transfer_len; + + int requested_blocks, packet_status, + total_length, do_page_save, + unit_attention; + + uint32_t sector_pos, sector_len, + packet_len, pos; + + int64_t callback; +} scsi_device_data_t; -extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; +extern scsi_device_t scsi_devices[SCSI_ID_MAX][SCSI_LUN_MAX]; extern void scsi_dev_log(int level, const char *fmt, ...); @@ -314,26 +370,18 @@ extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save extern int mode_select_terminate(int force); extern int mode_select_write(uint8_t val); -extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun); -extern void scsi_device_type_data(uint8_t id, uint8_t lun, - uint8_t *type, uint8_t *rmb); -extern int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun); -extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, - uint8_t *buffer, +extern uint8_t *scsi_device_sense(scsi_device_t *dev); +extern int64_t scsi_device_get_callback(scsi_device_t *dev); +extern void scsi_device_request_sense(scsi_device_t *dev, uint8_t *buffer, uint8_t alloc_length); -extern void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun); -extern int scsi_device_read_capacity(uint8_t id, uint8_t lun, - uint8_t *cdb, uint8_t *buffer, - uint32_t *len); -extern int scsi_device_present(uint8_t id, uint8_t lun); -extern int scsi_device_valid(uint8_t id, uint8_t lun); -extern int scsi_device_cdb_length(uint8_t id, uint8_t lun); -extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len, - uint8_t *cdb); -extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, - uint8_t *cdb); -extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun); -extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun); + +extern void scsi_device_reset(scsi_device_t *dev); +extern int scsi_device_present(scsi_device_t *dev); +extern int scsi_device_valid(scsi_device_t *dev); +extern int scsi_device_cdb_length(scsi_device_t *dev); +extern void scsi_device_command_phase0(scsi_device_t *dev, uint8_t *cdb); +extern void scsi_device_command_phase1(scsi_device_t *dev); +extern int32_t *scsi_device_get_buf_len(scsi_device_t *dev); -#endif /*SCSI_DEVICE_H*/ +#endif /*EMU_SCSI_DEVICE_H*/ diff --git a/src/devices/scsi/scsi_disk.c b/src/devices/scsi/scsi_disk.c index 5402549..a817a6e 100644 --- a/src/devices/scsi/scsi_disk.c +++ b/src/devices/scsi/scsi_disk.c @@ -8,7 +8,7 @@ * * Emulation of SCSI fixed disks. * - * Version: @(#)scsi_disk.c 1.0.13 2018/10/11 + * Version: @(#)scsi_disk.c 1.0.14 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,7 +54,6 @@ #include "../disk/hdc_ide.h" #include "scsi_device.h" #include "scsi_disk.h" -#include "../cdrom/cdrom.h" /* Bits of 'status' */ @@ -71,42 +70,18 @@ #define MAX_BLOCKS_AT_ONCE 340 - -/*FIXME: PLEASE, get rid of these, they make the code unclear. --FvK */ -#define scsi_disk_sense_error dev->sense[0] -#define scsi_disk_sense_key dev->sense[2] -#define scsi_disk_asc dev->sense[12] -#define scsi_disk_ascq dev->sense[13] +#define scsi_disk_sense_error dev->sense[0] +#define scsi_disk_sense_key dev->sense[2] +#define scsi_disk_asc dev->sense[12] +#define scsi_disk_ascq dev->sense[13] -#ifdef ENABLE_SCSI_DISK_LOG -int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; -#endif - - -scsi_disk_t *scsi_disk[HDD_NUM]; -uint8_t scsi_disks[16][8] = { - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } -}; +scsi_disk_t *scsi_disk[HDD_NUM] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -static const uint8_t scsi_disk_command_flags[0x100] = { +const uint8_t scsi_disk_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, @@ -169,40 +144,34 @@ static const uint8_t scsi_disk_command_flags[0x100] = { }; -uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_UNK_PAGE_03 | - GPMODEP_UNK_PAGE_04 | - GPMODEP_UNK_PAGE_30 | +uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_FORMAT_DEVICE_PAGE | + GPMODEP_RIGID_DISK_PAGE | + GPMODEP_UNK_VENDOR_PAGE | GPMODEP_ALL_PAGES); /* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ -static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = { -#ifdef __cplusplus - 0 -#else - { [0x03] = { 0x03, 0x16, - 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [0x04] = { 0x04, 0x16, - 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, - [0x30] = { 0xB0, 0x16, - 'V', 'A', 'R', 'C', 'e', 'm', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } - } -#endif -}; +static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = +{ { [GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [GPMODE_RIGID_DISK_PAGE ] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [GPMODE_UNK_VENDOR_PAGE ] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } +} }; static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = -{ -#ifdef __cplusplus - 0 -#else - { [0x03] = { 0x03, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - [0x04] = { 0x04, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - [0x30] = { 0xB0, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } - } +{ { [GPMODE_FORMAT_DEVICE_PAGE] = { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0 }, + [GPMODE_RIGID_DISK_PAGE ] = { GPMODE_RIGID_DISK_PAGE, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0 }, + [GPMODE_UNK_VENDOR_PAGE ] = { 0xB0, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +} }; + + +static void scsi_disk_callback(void *p); + + +#ifdef ENABLE_SCSI_DISK_LOG +int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; #endif -}; -void +static void scsi_disk_log(int level, const char *fmt, ...) { #ifdef ENABLE_SCSI_DISK_LOG @@ -218,9 +187,11 @@ scsi_disk_log(int level, const char *fmt, ...) /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int -scsi_disk_err_stat_to_scsi(scsi_disk_t *dev) +static int +scsi_disk_err_stat_to_scsi(void *p) { + scsi_disk_t *dev = (scsi_disk_t *)p; + if (dev->status & ERR_STAT) return SCSI_STATUS_CHECK_CONDITION; @@ -228,54 +199,6 @@ scsi_disk_err_stat_to_scsi(scsi_disk_t *dev) } -int -find_hdd_for_scsi_id(uint8_t id, uint8_t lun) -{ - uint8_t i; - - for (i = 0; i < HDD_NUM; i++) { - if (wcslen(hdd[i].fn) == 0) - continue; - if ((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) - continue; - if ((hdd[i].bus == HDD_BUS_SCSI) && (hdd[i].id.scsi.id == id) && (hdd[i].id.scsi.lun == lun)) - return i; - } - - return 0xff; -} - - -void -scsi_loadhd(int scsi_id, int scsi_lun, int id) -{ - if (! hdd_image_load(id)) - scsi_disks[scsi_id][scsi_lun] = 0xff; - - hdd_active(id, 0); -} - - -void -build_scsi_disk_map(void) -{ - uint8_t i, j; - - for (i = 0; i < 16; i++) - memset(scsi_disks[i], 0xff, 8); - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - scsi_disks[i][j] = find_hdd_for_scsi_id(i, j); - if (scsi_disks[i][j] != 0xff) { - if (wcslen(hdd[scsi_disks[i][j]].fn) > 0) - scsi_loadhd(i, j, scsi_disks[i][j]); - } - } - } -} - - void scsi_disk_mode_sense_load(scsi_disk_t *dev) { @@ -284,15 +207,13 @@ scsi_disk_mode_sense_load(scsi_disk_t *dev) int i; memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (scsi_disk_mode_sense_pages_default.pages[i][1] != 0) - memcpy(dev->ms_pages_saved.pages[i], - scsi_disk_mode_sense_pages_default.pages[i], + if (scsi_disk_mode_sense_pages_default.pages[i][1] != 0) { + memcpy(dev->ms_pages_saved.pages[i], scsi_disk_mode_sense_pages_default.pages[i], scsi_disk_mode_sense_pages_default.pages[i][1] + 2); + } } - - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", dev->id); + swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); memset(file_name, 0, 512 * sizeof(wchar_t)); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { @@ -309,7 +230,7 @@ scsi_disk_mode_sense_save(scsi_disk_t *dev) FILE *f; memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", dev->id); + swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); f = plat_fopen(nvr_path(file_name), L"wb"); if (f) { fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); @@ -318,9 +239,10 @@ scsi_disk_mode_sense_save(scsi_disk_t *dev) } -int -scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +static int +scsi_disk_read_capacity(void *p, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { + scsi_disk_t *dev = (scsi_disk_t *)p; int size = 0; size = hdd_image_get_last_sector(dev->id); @@ -358,13 +280,14 @@ scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint32_t -scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, uint8_t block_descriptor_len) { - uint8_t msplen, page_control = (type >> 6) & 3; + uint8_t msplen, page_control = (page >> 6) & 3; + int i = 0, j = 0; int size = 0; - type &= 0x3f; + page &= 0x3f; size = hdd_image_get_last_sector(dev->id); @@ -380,8 +303,8 @@ scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, } for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (scsi_disk_mode_sense_page_flags & (1LL << dev->current_page_code)) { + if ((page == GPMODE_ALL_PAGES) || (page == i)) { + if (scsi_disk_mode_sense_page_flags & (1LL << (uint64_t) page)) { buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); buf[pos++] = msplen; @@ -401,8 +324,8 @@ scsi_disk_command_common(scsi_disk_t *dev) { dev->status = BUSY_STAT; dev->phase = 1; - if (dev->packet_status == CDROM_PHASE_COMPLETE) { - scsi_disk_callback(dev); + if (dev->packet_status == PHASE_COMPLETE) { + scsi_disk_callback((void *) dev); dev->callback = 0LL; } else dev->callback = -1LL; /* Speed depends on SCSI controller */ @@ -412,7 +335,7 @@ scsi_disk_command_common(scsi_disk_t *dev) static void scsi_disk_command_complete(scsi_disk_t *dev) { - dev->packet_status = CDROM_PHASE_COMPLETE; + dev->packet_status = PHASE_COMPLETE; scsi_disk_command_common(dev); } @@ -421,7 +344,7 @@ scsi_disk_command_complete(scsi_disk_t *dev) static void scsi_disk_command_read_dma(scsi_disk_t *dev) { - dev->packet_status = CDROM_PHASE_DATA_IN_DMA; + dev->packet_status = PHASE_DATA_IN_DMA; scsi_disk_command_common(dev); } @@ -430,7 +353,7 @@ scsi_disk_command_read_dma(scsi_disk_t *dev) static void scsi_disk_command_write_dma(scsi_disk_t *dev) { - dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; + dev->packet_status = PHASE_DATA_OUT_DMA; scsi_disk_command_common(dev); } @@ -440,9 +363,7 @@ static void scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) { DEBUG("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, - direction, dev->request_length); - + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); if (alloc_len >= 0) { if (alloc_len < len) len = alloc_len; @@ -468,13 +389,10 @@ scsi_disk_sense_clear(scsi_disk_t *dev, int command) static void scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) { - uint8_t scsi_id = hdd[dev->id].id.scsi.id; - uint8_t scsi_lun = hdd[dev->id].id.scsi.lun; - - if (hdd[dev->id].bus != HDD_BUS_SCSI) + if (dev->drv->bus != HDD_BUS_SCSI) return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].phase = phase; } @@ -482,13 +400,13 @@ static void scsi_disk_cmd_error(scsi_disk_t *dev) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; dev->status = READY_STAT | ERR_STAT; dev->phase = 3; dev->packet_status = 0x80; dev->callback = 50 * SCSI_TIME; - DEBUG("SCSI HD %i: ERROR: %02X/%02X/%02X\n", - dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + DEBUG("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } @@ -499,6 +417,7 @@ scsi_disk_invalid_lun(scsi_disk_t *dev) scsi_disk_asc = ASC_INV_LUN; scsi_disk_ascq = 0; scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_cmd_error(dev); } @@ -509,6 +428,7 @@ scsi_disk_illegal_opcode(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_ILLEGAL_OPCODE; scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } @@ -519,6 +439,7 @@ scsi_disk_lba_out_of_range(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } @@ -529,7 +450,9 @@ scsi_disk_invalid_field(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } @@ -540,7 +463,9 @@ scsi_disk_invalid_field_pl(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } @@ -551,6 +476,7 @@ scsi_disk_data_phase_error(scsi_disk_t *dev) scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; scsi_disk_asc = ASC_DATA_PHASE_ERROR; scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } @@ -558,18 +484,15 @@ scsi_disk_data_phase_error(scsi_disk_t *dev) static int scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) { - if (((dev->request_length >> 5) & 7) != hdd[dev->id].id.scsi.lun) { - DEBUG("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); - + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { + DEBUG("SCSI DISK %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); scsi_disk_invalid_lun(dev); return 0; } if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { - DEBUG("SCSI HD %i: Attempting to execute unknown command %02X\n", - dev->id, cdb[0]); - + DEBUG("SCSI DISK %i: Attempting to execute unknown command %02X\n", dev->id, cdb[0]); scsi_disk_illegal_opcode(dev); return 0; } @@ -579,7 +502,7 @@ scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) if (cdb[0] != GPCMD_REQUEST_SENSE) scsi_disk_sense_clear(dev, cdb[0]); - DEBUG("SCSI HD %i: Continuing with command\n", dev->id); + DEBUG("SCSI DISK %i: Continuing with command\n", dev->id); return 1; } @@ -588,7 +511,7 @@ scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) static void scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) { - DBGLOG(1, "SCSI HD %i: Seek %08X\n", dev->id, pos); + DBGLOG(1, "SCSI DISK %i: Seek %08X\n", dev->id, pos); hdd_image_seek(dev->id, pos); } @@ -601,13 +524,16 @@ scsi_disk_rezero(scsi_disk_t *dev) return; dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); } -void -scsi_disk_reset(scsi_disk_t *dev) +static void +scsi_disk_reset(void *p) { + scsi_disk_t *dev = (scsi_disk_t *)p; + scsi_disk_rezero(dev); dev->status = 0; @@ -634,17 +560,18 @@ scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, buffer[0] = 0x70; - DEBUG("SCSI HD %i: Reporting sense: %02X %02X %02X\n", - dev->id, buffer[2], buffer[12], buffer[13]); + DEBUG("SCSI DISK %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); /* Clear the sense stuff as per the spec. */ scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); } -void -scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length) +static void +scsi_disk_request_sense_for_scsi(void *p, uint8_t *buffer, uint8_t alloc_length) { + scsi_disk_t *dev = (scsi_disk_t *)p; + scsi_disk_request_sense(dev, buffer, alloc_length, 0); } @@ -658,26 +585,27 @@ scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) *BufLen = MIN(*src_len, *BufLen); *src_len = *BufLen; } - - DEBUG("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); + DEBUG("SCSI DISK %i: Actual transfer length: %i\n", dev->id, *BufLen); } -void -scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) +static void +scsi_disk_command(void *p, uint8_t *cdb) { -#ifdef _LOGGING - uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; -#endif + scsi_disk_t *dev = (scsi_disk_t *)p; + uint8_t *hdbufferb; + int32_t *BufLen; int32_t len, max_len, alloc_length; int pos = 0; int idx = 0; unsigned size_idx, preamble_len; uint32_t last_sector = 0; char device_identify[9] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', ' ', 'v', '0'+EMU_VER_MAJOR, '.', '0'+EMU_VER_MINOR, '0'+EMU_VER_REV, 0 }; int block_desc = 0; - int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; + + hdbufferb = scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].cmd_buffer; + BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; last_sector = hdd_image_get_last_sector(dev->id); @@ -696,14 +624,13 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - DEBUG("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", - dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, - scsi_disk_ascq); - DEBUG("SCSI HD %i: Request length: %04X\n", - dev->id, dev->request_length); - DEBUG("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], - cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); + DEBUG("SCSI DISK %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", + dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); + DEBUG("SCSI DISK %i: Request length: %04X\n", dev->id, dev->request_length); + + DEBUG("SCSI DISK %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); } dev->sector_len = 0; @@ -741,7 +668,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) if (!len) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->packet_status = CDROM_PHASE_COMPLETE; + dev->packet_status = PHASE_COMPLETE; dev->callback = 20 * SCSI_TIME; break; } @@ -759,7 +686,6 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) case GPCMD_MECHANISM_STATUS: len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - scsi_disk_set_buf_len(dev, BufLen, &len); scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); scsi_disk_data_command_finish(dev, 8, 8, len, 0); @@ -783,22 +709,19 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) break; } - if ((dev->sector_pos > last_sector) || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + if ((dev->sector_pos > last_sector) || ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { scsi_disk_lba_out_of_range(dev); return; } if ((!dev->sector_len) || (*BufLen == 0)) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - DEBUG("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = CDROM_PHASE_COMPLETE; + DEBUG("SCSI DISK %i: All done - callback set\n", dev); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20 * SCSI_TIME; break; } - hdd_active(dev->id, 1); - max_len = dev->sector_len; dev->requested_blocks = max_len; @@ -826,19 +749,20 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - switch(cdb[0]) { + switch(cdb[0]) + { case GPCMD_VERIFY_6: case GPCMD_WRITE_6: dev->sector_len = cdb[4]; dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + DEBUG("SCSI DISK %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + DEBUG("SCSI DISK %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: @@ -856,14 +780,12 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) if ((!dev->sector_len) || (*BufLen == 0)) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - DEBUG("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = CDROM_PHASE_COMPLETE; + DEBUG("SCSI DISK %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20 * SCSI_TIME; break; } - hdd_active(dev->id, 1); - max_len = dev->sector_len; dev->requested_blocks = max_len; @@ -886,8 +808,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", - dev->id, dev->sector_len, dev->sector_pos); + DEBUG("SCSI DISK %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); if ((dev->sector_pos > last_sector) || ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { @@ -897,14 +818,12 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) if ((!dev->sector_len) || (*BufLen == 0)) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - DEBUG("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = CDROM_PHASE_COMPLETE; + DEBUG("SCSI DISK %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20 * SCSI_TIME; break; } - hdd_active(dev->id, 1); - max_len = 1; dev->requested_blocks = max_len; @@ -930,11 +849,9 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) else len = (cdb[8] | (cdb[7] << 8)); - dev->current_page_code = cdb[2] & 0x3F; - alloc_length = len; - dev->temp_buffer = (uint8_t *)mem_alloc(65536); + dev->temp_buffer = (uint8_t *) malloc(65536); memset(dev->temp_buffer, 0, 65536); if (cdb[0] == GPCMD_MODE_SENSE_6) { @@ -964,9 +881,7 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) alloc_length = len; scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - - DEBUG("SCSI HDD %i: Reading mode page: %02X...\n", - dev->id, cdb[2]); + DEBUG("SCSI DISK %i: Reading mode page: %02X...\n", dev->id, cdb[2]); scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); return; @@ -983,7 +898,6 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) scsi_disk_set_buf_len(dev, BufLen, &len); dev->total_length = len; dev->do_page_save = cdb[1] & 1; - scsi_disk_data_command_finish(dev, len, len, len, 1); return; @@ -994,15 +908,13 @@ scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) if ((!max_len) || (*BufLen == 0)) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - - DEBUG("SCSI HD %i: All done - callback set\n", dev->id); - - dev->packet_status = CDROM_PHASE_COMPLETE; + DBGLOG(1, "SCSI DISK %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; dev->callback = 20 * SCSI_TIME; break; } - dev->temp_buffer = (uint8_t *)mem_alloc(1024); + dev->temp_buffer = malloc(1024); if (cdb[1] & 1) { preamble_len = 4; @@ -1118,7 +1030,7 @@ atapi_out: break; case GPCMD_READ_CDROM_CAPACITY: - dev->temp_buffer = (uint8_t *)mem_alloc(8); + dev->temp_buffer = (uint8_t *) malloc(8); if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, (uint32_t *) &len) == 0) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); @@ -1136,16 +1048,15 @@ atapi_out: break; } - DBGLOG(1, "SCSI HD %i: Phase: %02X, request length: %i\n", - dev->id, dev->phase, dev->request_length); + DBGLOG(1, "SCSI DISK %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); } static void scsi_disk_phase_data_in(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; - int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; + uint8_t *hdbufferb = scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].cmd_buffer; + int32_t *BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; if (!*BufLen) { DEBUG("scsi_disk_phase_data_in(): Buffer length is 0\n"); @@ -1156,11 +1067,11 @@ scsi_disk_phase_data_in(scsi_disk_t *dev) switch (dev->current_cdb[0]) { case GPCMD_REQUEST_SENSE: - DEBUG("SCSI HD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen); + DEBUG("SCSI DISK %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen); scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1); break; case GPCMD_MECHANISM_STATUS: - memset(hdbufferb, 0, *BufLen); + memset(hdbufferb, 0, *BufLen); hdbufferb[5] = 1; break; case GPCMD_READ_6: @@ -1186,7 +1097,7 @@ scsi_disk_phase_data_in(scsi_disk_t *dev) hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); break; default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->current_cdb[0]); + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); break; } @@ -1197,9 +1108,9 @@ scsi_disk_phase_data_in(scsi_disk_t *dev) static void scsi_disk_phase_data_out(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; + uint8_t *hdbufferb = scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].cmd_buffer; int i; - int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; + int32_t *BufLen = &scsi_devices[dev->drv->bus_id.scsi.id][dev->drv->bus_id.scsi.lun].buffer_length; uint32_t last_sector = hdd_image_get_last_sector(dev->id); uint32_t c, h, s, last_to_write = 0; uint16_t block_desc_len, pos; @@ -1242,9 +1153,9 @@ scsi_disk_phase_data_out(scsi_disk_t *dev) hdbufferb[2] = (i >> 8) & 0xff; hdbufferb[3] = i & 0xff; } else if (dev->current_cdb[1] & 4) { - s = (i % hdd[dev->id].spt); - h = ((i - s) / hdd[dev->id].spt) % hdd[dev->id].hpc; - c = ((i - s) / hdd[dev->id].spt) / hdd[dev->id].hpc; + s = (i % dev->drv->spt); + h = ((i - s) / dev->drv->spt) % dev->drv->hpc; + c = ((i - s) / dev->drv->spt) / dev->drv->hpc; hdbufferb[0] = (c >> 16) & 0xff; hdbufferb[1] = (c >> 8) & 0xff; hdbufferb[2] = c & 0xff; @@ -1312,7 +1223,7 @@ scsi_disk_phase_data_out(scsi_disk_t *dev) scsi_disk_invalid_field_pl(dev); break; default: - fatal("SCSI HD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); + fatal("SCSI DISK %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); break; } @@ -1321,39 +1232,39 @@ scsi_disk_phase_data_out(scsi_disk_t *dev) /* If the result is 1, issue an IRQ, otherwise not. */ -void -scsi_disk_callback(scsi_disk_t *dev) +static void +scsi_disk_callback(void *p) { + scsi_disk_t *dev = (scsi_disk_t *)p; + switch(dev->packet_status) { - case CDROM_PHASE_IDLE: - DEBUG("SCSI HD %i: PHASE_IDLE\n", dev->id); + case PHASE_IDLE: + DEBUG("SCSI DISK %i: PHASE_IDLE\n", dev->id); dev->phase = 1; dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - hdd_active(dev->id, 0); return; - case CDROM_PHASE_COMPLETE: - DEBUG("SCSI HD %i: PHASE_COMPLETE\n", dev->id); + case PHASE_COMPLETE: + DEBUG("SCSI DISK %i: PHASE_COMPLETE\n", dev->id); dev->status = READY_STAT; dev->phase = 3; dev->packet_status = 0xFF; - hdd_active(dev->id, 0); return; - case CDROM_PHASE_DATA_OUT_DMA: - DEBUG("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id); + case PHASE_DATA_OUT_DMA: + DEBUG("SCSI DISK %i: PHASE_DATA_OUT_DMA\n", dev->id); scsi_disk_phase_data_out(dev); - dev->packet_status = CDROM_PHASE_COMPLETE; + dev->packet_status = PHASE_COMPLETE; dev->status = READY_STAT; dev->phase = 3; return; - case CDROM_PHASE_DATA_IN_DMA: - DEBUG("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id); + case PHASE_DATA_IN_DMA: + DEBUG("SCSI DISK %i: PHASE_DATA_IN_DMA\n", dev->id); scsi_disk_phase_data_in(dev); - dev->packet_status = CDROM_PHASE_COMPLETE; + dev->packet_status = PHASE_COMPLETE; dev->status = READY_STAT; dev->phase = 3; return; - case CDROM_PHASE_ERROR: - DEBUG("SCSI HD %i: PHASE_ERROR\n", dev->id); + case PHASE_ERROR: + DEBUG("SCSI DISK %i: PHASE_ERROR\n", dev->id); dev->status = READY_STAT | ERR_STAT; dev->phase = 3; return; @@ -1374,19 +1285,49 @@ void scsi_disk_hard_reset(void) { int c; + scsi_device_t *sd; for (c = 0; c < HDD_NUM; c++) { if (hdd[c].bus == HDD_BUS_SCSI) { DEBUG("SCSI disk hard_reset drive=%d\n", c); - if (scsi_disk[c] == NULL) { + /* Make sure to ignore any SCSI disk that has an out of range ID. */ + if (hdd[c].bus_id.scsi.id > SCSI_ID_MAX) + continue; + if (hdd[c].bus_id.scsi.lun > SCSI_LUN_MAX) + continue; + + /* Make sure to ignore any SCSI disk whose image file name is empty. */ + if (wcslen(hdd[c].fn) == 0) + continue; + + /* Make sure to ignore any SCSI disk whose image fails to load. */ + if (! hdd_image_load(c)) + continue; + + if (! scsi_disk[c]) { scsi_disk[c] = (scsi_disk_t *)mem_alloc(sizeof(scsi_disk_t)); memset(scsi_disk[c], 0, sizeof(scsi_disk_t)); } + /* SCSI disk, attach to the SCSI bus. */ + sd = &scsi_devices[hdd[c].bus_id.scsi.id][hdd[c].bus_id.scsi.lun]; + + sd->p = scsi_disk[c]; + sd->command = scsi_disk_command; + sd->callback = scsi_disk_callback; + sd->err_stat_to_scsi = scsi_disk_err_stat_to_scsi; + sd->request_sense = scsi_disk_request_sense_for_scsi; + sd->reset = scsi_disk_reset; + sd->read_capacity = scsi_disk_read_capacity; + sd->type = SCSI_FIXED_DISK; + scsi_disk[c]->id = c; scsi_disk[c]->drv = &hdd[c]; + scsi_disk_mode_sense_load(scsi_disk[c]); + + DEBUG("SCSI disk %i attached to ID %i LUN %i\n", c, hdd[c].bus_id.scsi.id, hdd[c].bus_id.scsi.lun); } } } @@ -1401,11 +1342,10 @@ scsi_disk_close(void) for (c = 0; c < HDD_NUM; c++) { dev = scsi_disk[c]; - if (dev != NULL) { + if (dev) { hdd_image_close(c); free(scsi_disk[c]); - scsi_disk[c] = NULL; } } diff --git a/src/devices/scsi/scsi_disk.h b/src/devices/scsi/scsi_disk.h index 5fee188..d9ad9ac 100644 --- a/src/devices/scsi/scsi_disk.h +++ b/src/devices/scsi/scsi_disk.h @@ -8,7 +8,7 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.h 1.0.3 2018/09/19 + * Version: @(#)scsi_disk.h 1.0.4 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -34,8 +34,8 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef SCSI_DISK_H -# define SCSI_DISK_H +#ifndef EMU_SCSI_DISK_H +# define EMU_SCSI_DISK_H typedef struct { @@ -43,30 +43,31 @@ typedef struct { hard_disk_t *drv; - /* Stuff for SCSI hard disks. */ - uint8_t status, phase, - error, id, + uint8_t *temp_buffer, + pad[16], /* This is atapi_cdb in ATAPI-supporting devices, + and pad in SCSI-only devices. */ current_cdb[16], sense[256]; - uint16_t request_length; + uint8_t status, phase, + error, id, + pad0, pad1, + pad2, pad3; - int requested_blocks, block_total, - packet_status, callback, - block_descriptor_len, - total_length, do_page_save; + uint16_t request_length, pad4; + + int requested_blocks, packet_status, + total_length, do_page_save, + unit_attention; uint32_t sector_pos, sector_len, - packet_len; + packet_len, pos; - uint64_t current_page_code; - - uint8_t *temp_buffer; + int64_t callback; } scsi_disk_t; extern scsi_disk_t *scsi_disk[HDD_NUM]; -extern uint8_t scsi_disks[16][8]; #ifdef USE_REMOVABLE_DISK @@ -79,20 +80,6 @@ extern void scsi_disk_log(int level, const char *fmt, ...); extern void scsi_disk_global_init(void); extern void scsi_disk_hard_reset(void); extern void scsi_disk_close(void); -extern void scsi_loadhd(int scsi_id, int scsi_lun, int id); - -extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, - uint8_t *buffer, uint32_t *len); -extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev); -extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev); -extern int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern void build_scsi_disk_map(void); -extern void scsi_disk_reset(scsi_disk_t *dev); -extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, - uint8_t *buffer, - uint8_t alloc_length); -extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb); -extern void scsi_disk_callback(scsi_disk_t *dev); -#endif /*SCSI_DISK_H*/ +#endif /*EMU_SCSI_DISK_H*/ diff --git a/src/devices/scsi/scsi_ncr5380.c b/src/devices/scsi/scsi_ncr5380.c index 671628d..e731c58 100644 --- a/src/devices/scsi/scsi_ncr5380.c +++ b/src/devices/scsi/scsi_ncr5380.c @@ -11,7 +11,7 @@ * * NOTE: This code now only supports targets at LUN=0 !! * - * Version: @(#)scsi_ncr5380.c 1.0.10 2018/10/11 + * Version: @(#)scsi_ncr5380.c 1.0.11 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -280,19 +280,19 @@ ncr_wait_process(ncr5380_t *ncr_dev) if (ncr->wait_data) { ncr->wait_data--; if (! ncr->wait_data) { - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + dev = &scsi_devices[ncr->target_id][ncr->target_lun]; SET_BUS_STATE(ncr, ncr->new_phase); if (ncr->new_phase == SCSI_PHASE_DATA_IN) { DEBUG("Data In bus phase\n"); - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->tx_data = dev->cmd_buffer[ncr->data_pos++]; ncr->state = STATE_DATAIN; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; } else if (ncr->new_phase == SCSI_PHASE_STATUS) { DEBUG("Status bus phase\n"); ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; } else if (ncr->new_phase == SCSI_PHASE_MESSAGE_IN) { DEBUG("Message In bus phase\n"); ncr->state = STATE_MESSAGEIN; @@ -325,8 +325,8 @@ ncr_callback(void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; - int c = 0; + scsi_device_t *dev = &scsi_devices[ncr->target_id][ncr->target_lun]; + int req_len, c = 0; int64_t p; uint8_t temp, data; @@ -337,7 +337,7 @@ ncr_callback(void *priv) if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE)) ncr_dev->timer_period = (int64_t) ncr_dev->period; else - ncr_dev->timer_period += 10LL * TIMER_USEC; + ncr_dev->timer_period += 40LL * TIMER_USEC; if (ncr->dma_mode == DMA_IDLE) { ncr->bus_host = get_bus_host(ncr); @@ -360,7 +360,7 @@ ncr_callback(void *priv) /*Once the device has been found and selected, mark it as busy*/ if ((ncr->target_id != -1) && - scsi_device_present(ncr->target_id, ncr->target_lun)) { + scsi_device_present(&scsi_devices[ncr->target_id][ncr->target_lun])) { ncr->cur_bus |= BUS_BSY; DEBUG("DEBUG: device found at ID %i\n", ncr->target_id); DEBUG("NCR: current Bus BSY=%02x\n", ncr->cur_bus); @@ -394,35 +394,36 @@ ncr_callback(void *priv) /*Reset data position to default*/ ncr->data_pos = 0; - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + dev = &scsi_devices[ncr->target_id][ncr->target_lun]; - DEBUG("NCR: SCSI command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status); + DEBUG("NCR: SCSI command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); - dev->BufferLength = -1; + dev->buffer_length = -1; /*Now, execute the given SCSI command*/ - scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command); + scsi_device_command_phase0(dev, ncr->command); - DEBUG("NCR: SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase); + DEBUG("NCR: SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase); - if (dev->Status != SCSI_STATUS_OK) { + if (dev->status != SCSI_STATUS_OK) { ncr->new_phase = SCSI_PHASE_STATUS; ncr->wait_data = 4; return; } /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ - if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) { - dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); + if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { + dev->cmd_buffer = (uint8_t *)mem_alloc(dev->buffer_length); - p = scsi_device_get_callback(ncr->target_id, ncr->target_lun); + p = scsi_device_get_callback(dev); + req_len = MIN(64, dev->buffer_length); if (p <= 0LL) - ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, dev->BufferLength)); + ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) req_len); else - ncr_dev->period = (p / ((double) dev->BufferLength)) * ((double) MIN(64, dev->BufferLength)); + ncr_dev->period = (p / ((double) dev->buffer_length)) * ((double) req_len); } - if (dev->Phase == SCSI_PHASE_DATA_OUT) { + if (dev->phase == SCSI_PHASE_DATA_OUT) { /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ DEBUG("NCR: next state is data out\n"); ncr->new_phase = SCSI_PHASE_DATA_OUT; @@ -430,23 +431,23 @@ ncr_callback(void *priv) ncr->clear_req = 4; } else { /* Other command - execute immediately. */ - ncr->new_phase = dev->Phase; + ncr->new_phase = dev->phase; if (ncr->new_phase == SCSI_PHASE_DATA_IN) - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + scsi_device_command_phase1(dev); ncr->wait_data = 4; } } } } else if (ncr->state == STATE_DATAIN) { - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + dev = &scsi_devices[ncr->target_id][ncr->target_lun]; DEBUG("NCR: Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); if (ncr->bus_host & BUS_ACK) { - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (ncr->data_pos >= dev->buffer_length) { + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -454,7 +455,7 @@ ncr_callback(void *priv) ncr->wait_data = 4; ncr->wait_complete = 8; } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->tx_data = dev->cmd_buffer[ncr->data_pos++]; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; ncr->clear_req = 3; ncr->cur_bus &= ~BUS_REQ; @@ -462,18 +463,18 @@ ncr_callback(void *priv) } } } else if (ncr->state == STATE_DATAOUT) { - dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + dev = &scsi_devices[ncr->target_id][ncr->target_lun]; DEBUG("NCR: Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); if (ncr->bus_host & BUS_ACK) { - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + if (ncr->data_pos >= dev->buffer_length) { + scsi_device_command_phase1(dev); - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -524,10 +525,10 @@ ncr_callback(void *priv) temp = BUS_GETDATA(ncr->bus_host); ncr->bus_host = get_bus_host(ncr); - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (ncr->data_pos >= dev->buffer_length) { + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -535,7 +536,7 @@ ncr_callback(void *priv) ncr->wait_data = 4; ncr->wait_complete = 8; } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->tx_data = dev->cmd_buffer[ncr->data_pos++]; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; ncr->clear_req = 3; ncr->cur_bus &= ~BUS_REQ; @@ -590,14 +591,14 @@ ncr_callback(void *priv) ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; ncr->bus_host |= BUS_SETDATA(data); - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + if (ncr->data_pos >= dev->buffer_length) { + scsi_device_command_phase1(dev); - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -647,10 +648,10 @@ ncr_callback(void *priv) temp = BUS_GETDATA(ncr->bus_host); ncr->bus_host = get_bus_host(ncr); - if (ncr->data_pos >= dev->BufferLength) { - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (ncr->data_pos >= dev->buffer_length) { + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -658,7 +659,7 @@ ncr_callback(void *priv) ncr->wait_data = 4; ncr->wait_complete = 8; } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->tx_data = dev->cmd_buffer[ncr->data_pos++]; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; ncr->clear_req = 3; ncr->cur_bus &= ~BUS_REQ; @@ -699,14 +700,14 @@ ncr_callback(void *priv) ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; ncr->bus_host |= BUS_SETDATA(data); - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + dev->cmd_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + if (ncr->data_pos >= dev->buffer_length) { + scsi_device_command_phase1(dev); - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } ncr->cur_bus &= ~BUS_REQ; @@ -1217,7 +1218,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + scsi_device_t *dev = &scsi_devices[ncr->target_id][ncr->target_lun]; DBGLOG(2, "SCSI-AT write=0x%03x, val=%02x\n", port, val); @@ -1263,7 +1264,7 @@ scsiat_out(uint16_t port, uint8_t val, void *priv) if (ncr->unk_08 & 0x01) { ncr_dev->block_count_loaded = 1; - ncr_dev->block_count = dev->BufferLength / 128; + ncr_dev->block_count = dev->buffer_length / 128; } break; diff --git a/src/devices/scsi/scsi_ncr53c810.c b/src/devices/scsi/scsi_ncr53c810.c index 15485de..f330060 100644 --- a/src/devices/scsi/scsi_ncr53c810.c +++ b/src/devices/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.10 2018/09/22 + * Version: @(#)scsi_ncr53c810.c 1.0.11 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -191,14 +191,6 @@ #define NCR_BUF_SIZE 4096 -typedef struct ncr53c810_request { - uint32_t tag; - uint32_t dma_len; - uint8_t *dma_buf; - uint32_t pending; - int out; -} ncr53c810_request; - typedef enum { SCSI_STATE_SEND_COMMAND, SCSI_STATE_READ_DATA, @@ -208,6 +200,15 @@ typedef enum { SCSI_STATE_WRITE_MESSAGE } scsi_state_t; + +typedef struct { + uint32_t tag; + uint32_t dma_len; + uint8_t *dma_buf; + uint32_t pending; + int out; +} ncr53c810_request_t; + typedef struct { uint8_t pci_slot; int has_bios; @@ -238,7 +239,7 @@ typedef struct { uint8_t current_lun; uint8_t select_id; int command_complete; - ncr53c810_request *current; + ncr53c810_request_t *current; int irq; @@ -397,9 +398,10 @@ ncr53c810_soft_reset(ncr53c810_t *dev) dev->gpreg0 = 0; dev->sstop = 1; - for (i = 0; i < 16; i++) { + /* Narrow-SCSI, so 8 targets with 8 lun's each. */ + for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) - scsi_device_reset(i, j); + scsi_device_reset(&scsi_devices[i][j]); } } @@ -455,8 +457,8 @@ read_dword(ncr53c810_t *dev, uint32_t addr) } -static -void do_irq(ncr53c810_t *dev, int level) +static void +do_irq(ncr53c810_t *dev, int level) { if (level) { pci_set_irq(dev->pci_slot, PCI_INTA); @@ -609,12 +611,11 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) { uint32_t addr, tdbc; int32_t count; - scsi_device_t *sd; - sd = &SCSIDevices[id][dev->current_lun]; + sd = &scsi_devices[id][dev->current_lun]; - if ((!scsi_device_present(id, dev->current_lun))) { + if (! scsi_device_present(sd)) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); return; } @@ -625,7 +626,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) return; } - /* Make sure count is never bigger than BufferLength. */ + /* Make sure count is never bigger than buffer_length. */ count = tdbc = dev->dbc; if (count > dev->temp_buf_len) count = dev->temp_buf_len; @@ -637,13 +638,13 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) dev->dbc -= count; if (out) - ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); + ncr53c810_read(dev, addr, sd->cmd_buffer + dev->buffer_pos, count); else { if (!dev->buffer_pos) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(dev->current->tag, dev->current_lun); + scsi_device_command_phase1(sd); } - ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); + ncr53c810_write(dev, addr, sd->cmd_buffer + dev->buffer_pos, count); } dev->temp_buf_len -= count; @@ -652,13 +653,13 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) if (dev->temp_buf_len <= 0) { if (out) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(id, dev->current_lun); + scsi_device_command_phase1(sd); } - if (sd->CmdBuffer != NULL) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; + if (sd->cmd_buffer != NULL) { + free(sd->cmd_buffer); + sd->cmd_buffer = NULL; } - ncr53c810_command_complete(dev, sd->Status); + ncr53c810_command_complete(dev, sd->status); } else { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); dev->sstop = 0; @@ -696,56 +697,56 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) dev->sfbr = buf[0]; dev->command_complete = 0; - sd = &SCSIDevices[id][dev->current_lun]; - if (!scsi_device_present(id, dev->current_lun)) { + sd = &scsi_devices[id][dev->current_lun]; + if (! scsi_device_present(sd)) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); ncr53c810_bad_selection(dev, id); return(0); } - dev->current = (ncr53c810_request*)mem_alloc(sizeof(ncr53c810_request)); + dev->current = (ncr53c810_request_t *)mem_alloc(sizeof(ncr53c810_request_t)); dev->current->tag = id; - sd->BufferLength = -1; + sd->buffer_length = -1; DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); dev->last_command = buf[0]; - scsi_device_command_phase0(dev->current->tag, dev->current_lun, buf); + scsi_device_command_phase0(sd, buf); dev->hba_private = (void *)dev->current; dev->waiting = 0; dev->buffer_pos = 0; - dev->temp_buf_len = sd->BufferLength; + dev->temp_buf_len = sd->buffer_length; - if (sd->BufferLength > 0) { - sd->CmdBuffer = (uint8_t *)mem_alloc(sd->BufferLength); - dev->current->dma_len = sd->BufferLength; + if (sd->buffer_length > 0) { + sd->cmd_buffer = (uint8_t *)mem_alloc(sd->buffer_length); + dev->current->dma_len = sd->buffer_length; } - if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { + if ((sd->phase == SCSI_PHASE_DATA_IN) && (sd->buffer_length > 0)) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DI); - p = scsi_device_get_callback(dev->current->tag, dev->current_lun); + p = scsi_device_get_callback(sd); if (p <= 0LL) { - period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ + period = ((double) sd->buffer_length) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ dev->timer_period += (int64_t) period; } else dev->timer_period += p; return(1); - } else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { + } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && (sd->buffer_length > 0)) { DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DO); - p = scsi_device_get_callback(dev->current->tag, dev->current_lun); + p = scsi_device_get_callback(sd); if (p <= 0LL) { - period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ + period = ((double) sd->buffer_length) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ dev->timer_period += (int64_t) period; } else dev->timer_period += p; return(1); } else { - ncr53c810_command_complete(dev, sd->Status); + ncr53c810_command_complete(dev, sd->status); return(0); } } @@ -755,6 +756,7 @@ static void ncr53c810_do_status(ncr53c810_t *dev) { uint8_t status; + DEBUG("Get status len=%d status=%d\n", dev->dbc, dev->status); if (dev->dbc != 1) { DEBUG("Bad Status move\n"); @@ -853,7 +855,7 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) DEBUG("MSG out len=%d\n", dev->dbc); - sd = &SCSIDevices[id][dev->current_lun]; + sd = &scsi_devices[id][dev->current_lun]; #ifdef _LOGGING current_tag = id; @@ -906,9 +908,9 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) case 0x0d: /* The ABORT TAG message clears the current I/O process only. */ DEBUG("MSG: ABORT TAG tag=0x%x\n", current_tag); - if (sd->CmdBuffer) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; + if (sd->cmd_buffer) { + free(sd->cmd_buffer); + sd->cmd_buffer = NULL; } ncr53c810_disconnect(dev); break; @@ -929,9 +931,9 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) DEBUG("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); /* clear the current I/O process */ - if (sd->CmdBuffer) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; + if (sd->cmd_buffer) { + free(sd->cmd_buffer); + sd->cmd_buffer = NULL; } ncr53c810_disconnect(dev); break; @@ -953,8 +955,8 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) static void ncr53c810_memcpy(ncr53c810_t *dev, uint32_t dest, uint32_t src, int count) { - int n; uint8_t buf[NCR_BUF_SIZE]; + int n; DEBUG("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); while (count) { @@ -1103,7 +1105,7 @@ again: } dev->sstat0 |= NCR_SSTAT0_WOA; dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (!scsi_device_present(id, 0)) { + if (! scsi_device_present(&scsi_devices[id][0])) { ncr53c810_bad_selection(dev, id); break; } diff --git a/src/devices/scsi/scsi_x54x.c b/src/devices/scsi/scsi_x54x.c index 35a8f1d..cf12be6 100644 --- a/src/devices/scsi/scsi_x54x.c +++ b/src/devices/scsi/scsi_x54x.c @@ -12,7 +12,7 @@ * * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.c 1.0.12 2018/10/05 + * Version: @(#)scsi_x54x.c 1.0.14 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -149,39 +149,56 @@ clear_irq(x54x_t *dev) static void target_check(uint8_t id, uint8_t lun) { - if (! scsi_device_valid(id, lun)) - fatal("BIOS INT13 device on ID %02i:%02i has disappeared\n", id, lun); + if (! scsi_device_valid(&scsi_devices[id][lun])) + fatal("BIOS INT13 device on ID %i:%i has disappeared\n", id, lun); } static uint8_t completion_code(uint8_t *sense) { - switch (sense[12]) { - case 0x00: - return(0x00); + uint8_t ret = 0xff; - case 0x20: - return(0x01); + switch (sense[12]) { + case ASC_NONE: + ret = 0x00; + break; + + case ASC_ILLEGAL_OPCODE: + case ASC_INV_FIELD_IN_CMD_PACKET: + case ASC_INV_FIELD_IN_PARAMETER_LIST: + case ASC_DATA_PHASE_ERROR: + ret = 0x01; + break; case 0x12: - case 0x21: - return(0x02); + case ASC_LBA_OUT_OF_RANGE: + ret = 0x02; + break; - case 0x27: - return(0x03); + case ASC_WRITE_PROTECTED: + ret = 0x03; + break; case 0x14: case 0x16: - return(0x04); + ret = 0x04; + break; + + case ASC_INCOMPATIBLE_FORMAT: + case ASC_ILLEGAL_MODE_FOR_THIS_TRACK: + ret = 0x0c; + break; case 0x10: case 0x11: - return(0x10); + ret = 0x10; + break; case 0x17: case 0x18: - return(0x11); + ret = 0x11; + break; case 0x01: case 0x03: @@ -203,71 +220,180 @@ completion_code(uint8_t *sense) case 0x47: case 0x48: case 0x49: - return(0x20); + ret = 0x20; + break; case 0x15: case 0x02: - return(0x40); + ret = 0x40; + break; - case 0x04: - case 0x28: + case 0x25: + ret = 0x80; + break; + + case ASC_NOT_READY: + case ASC_MEDIUM_MAY_HAVE_CHANGED: case 0x29: - case 0x2a: - return(0xaa); - - default: + case ASC_CAPACITY_DATA_CHANGED: + case ASC_MEDIUM_NOT_PRESENT: + ret = 0xaa; break; }; - return(0xff); + return(ret); +} + + + +static uint8_t +x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, uint32_t addr) +{ + dev->buffer_length = -1; + + scsi_device_command_phase0(dev, cdb); + + if (dev->phase == SCSI_PHASE_STATUS) + return(completion_code(scsi_device_sense(dev))); + + dev->cmd_buffer = (uint8_t *)malloc(dev->buffer_length); + if (dev->phase == SCSI_PHASE_DATA_IN) { + scsi_device_command_phase1(dev); + if (len > 0) { + if (buf) + memcpy(buf, dev->cmd_buffer, dev->buffer_length); + else + DMAPageWrite(addr, dev->cmd_buffer, dev->buffer_length); + } + } else if (dev->phase == SCSI_PHASE_DATA_OUT) { + if (len > 0) { + if (buf) + memcpy(dev->cmd_buffer, buf, dev->buffer_length); + else + DMAPageRead(addr, dev->cmd_buffer, dev->buffer_length); + } + scsi_device_command_phase1(dev); + } + + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; + } + + return(completion_code(scsi_device_sense(dev))); } static uint8_t -x54x_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) +x54x_bios_read_capacity(scsi_device_t *sd, uint8_t *buf) { - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; + uint8_t *cdb; + uint8_t ret; - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); - if (ret == 0) return(sc); + cdb = (uint8_t *)mem_alloc(12); + memset(cdb, 0, 12); + cdb[0] = GPCMD_READ_CDROM_CAPACITY; + + memset(buf, 0, 8); + + ret = x54x_bios_scsi_command(sd, cdb, buf, 8, 0); + + free(cdb); + + return(ret); +} + + +static uint8_t +x54x_bios_inquiry(scsi_device_t *sd, uint8_t *buf) +{ + uint8_t *cdb; + uint8_t ret; + + cdb = (uint8_t *) malloc(12); + memset(cdb, 0, 12); + cdb[0] = GPCMD_INQUIRY; + cdb[4] = 36; + + memset(buf, 0, 36); + + ret = x54x_bios_scsi_command(sd, cdb, buf, 36, 0); + + free(cdb); + + return(ret); +} + + +static uint8_t +x54x_bios_command_08(scsi_device_t *sd, uint8_t *buffer) +{ + uint8_t *rcbuf; + uint8_t ret; + int i; memset(buffer, 0x00, 6); - for (i=0; i<4; i++) + + rcbuf = (uint8_t *)mem_alloc(8); + + ret = x54x_bios_read_capacity(sd, rcbuf); + if (ret) { + free(rcbuf); + return(ret); + } + + memset(buffer, 0x00, 6); + + for (i = 0; i < 4; i++) buffer[i] = rcbuf[i]; - for (i=4; i<6; i++) + for (i = 4; i < 6; i++) buffer[i] = rcbuf[(i + 2) ^ 1]; DEBUG("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + free(rcbuf); + return(0); } static int -x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) +x54x_bios_command_15(scsi_device_t *sd, uint8_t *buffer) { - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; - - ret = scsi_device_read_capacity(id, lun, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id, lun)); + uint8_t *inqbuf, *rcbuf; + uint8_t ret; + int i; memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = (ret == 0) ? 0 : rcbuf[i]; - scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5])); + inqbuf = (uint8_t *)mem_alloc(36); + ret = x54x_bios_inquiry(sd, inqbuf); + if (ret) { + free(inqbuf); + return(ret); + } + + buffer[4] = inqbuf[0]; + buffer[5] = inqbuf[1]; + + rcbuf = (uint8_t *)mem_alloc(8); + ret = x54x_bios_read_capacity(sd, rcbuf); + if (ret) { + free(rcbuf); + free(inqbuf); + return(ret); + } + + for (i = 0; i < 4; i++) + buffer[i] = rcbuf[i]; DEBUG("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - return(sc); + free(rcbuf); + free(inqbuf); + + return(0); } @@ -275,12 +401,18 @@ x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) static uint8_t x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) { - uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; - scsi_device_t *dev; - uint32_t dma_address; + const int bios_cmd_to_scsi[18] = { + 0, 0, GPCMD_READ_10, GPCMD_WRITE_10, GPCMD_VERIFY_10, 0, 0, + GPCMD_FORMAT_UNIT, 0, 0, 0, 0, GPCMD_SEEK_10, 0, 0, 0, + GPCMD_TEST_UNIT_READY, GPCMD_REZERO_UNIT + }; + uint8_t cdb[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t *buf; + scsi_device_t *dev = NULL; + uint32_t dma_address = 0; uint32_t lba; int sector_len = cmd->secount; - uint8_t ret; + uint8_t ret = 0x00; if (islba) lba = lba32_blk(cmd); @@ -290,45 +422,45 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) DEBUG("BIOS Command = 0x%02X\n", cmd->command); if ((cmd->id > max_id) || (cmd->lun > 7)) { - DEBUG("BIOS Target ID %i or LUN %i are above maximum\n", - cmd->id, cmd->lun); - return(0x80); + DEBUG("BIOS target %i or LUN %i are above maximum\n", cmd->id, cmd->lun); + ret = 0x80; } if (cmd->lun) { - DEBUG("BIOS Target LUN is not 0\n"); - return(0x80); + DEBUG("BIOS target LUN is not 0\n"); + ret = 0x80; } - /* Get pointer to selected device. */ - dev = &SCSIDevices[cmd->id][cmd->lun]; - dev->BufferLength = 0; + if (! ret) { + /* Get pointer to selected device. */ + dev = &scsi_devices[cmd->id][cmd->lun]; + dev->buffer_length = 0; - if (! scsi_device_present(cmd->id, cmd->lun)) { - DEBUG("BIOS Target ID %i and LUN %i have no device attached\n", - cmd->id, cmd->lun); - return(0x80); + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; + } + + if (! scsi_device_present(dev)) { + DEBUG("BIOS Target ID %i has no device attached\n", cmd->id); + ret = 0x80; + } else { + if ((dev->type == SCSI_REMOVABLE_CDROM) && !x54x->cdrom_boot) { + DEBUG("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id); + return(0x80); + } else { + dma_address = ADDR_TO_U32(cmd->dma_address); + + DEBUG("BIOS Data Buffer write: length %d, pointer 0x%04X\n", + sector_len, dma_address); + } + } } - if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) { - DEBUG("BIOS Target ID %i and LUN %i is CD-ROM on unsupported BIOS\n", - cmd->id, cmd->lun); - return(0x80); - } - - dma_address = ADDR_TO_U32(cmd->dma_address); - - DEBUG("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - sector_len, dma_address); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - switch(cmd->command) { + if (! ret) switch(cmd->command) { case 0x00: /* Reset Disk System, in practice it's a nop */ - return(0); + ret = 0x00; + break; case 0x01: /* Read Status of Last Operation */ target_check(cmd->id, cmd->lun); @@ -338,227 +470,108 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) * length for SCSI sense, and no command-specific * indication is given. */ - dev->BufferLength = 14; - dev->CmdBuffer = (uint8_t *)mem_alloc(14); - memset(dev->CmdBuffer, 0x00, 14); + dev->buffer_length = 14; + dev->cmd_buffer = (uint8_t *)mem_alloc(dev->buffer_length); + memset(dev->cmd_buffer, 0x00, dev->buffer_length); if (sector_len > 0) { DEBUG("BIOS DMA: Reading 14 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - scsi_device_sense(cmd->id, cmd->lun), 14); + DMAPageWrite(dma_address, scsi_device_sense(dev), 14); } - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; + if (dev && (dev->cmd_buffer != NULL)) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; } - return(0); + break; case 0x02: /* Read Desired Sectors to Memory */ - target_check(cmd->id, cmd->lun); - - dev->BufferLength = -1; - - cdb[0] = GPCMD_READ_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; - DBGLOG(1, "BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - if (dev->Phase == SCSI_PHASE_STATUS) - goto skip_read_phase1; - - dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); - - scsi_device_command_phase1(cmd->id, cmd->lun); - if (sector_len > 0) { - DEBUG("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, dev->BufferLength); - } - -skip_read_phase1: - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - case 0x03: /* Write Desired Sectors from Memory */ - target_check(cmd->id, cmd->lun); - - dev->BufferLength = -1; - - cdb[0] = GPCMD_WRITE_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; - DBGLOG(1, "BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - if (dev->Phase == SCSI_PHASE_STATUS) - goto skip_write_phase1; - - dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); - - if (sector_len > 0) { - DEBUG("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); - DMAPageRead(dma_address, - dev->CmdBuffer, dev->BufferLength); - } - - scsi_device_command_phase1(cmd->id, cmd->lun); - -skip_write_phase1: - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - case 0x04: /* Verify Desired Sectors */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_VERIFY_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x05: /* Format Track, invalid since SCSI has no tracks */ -//FIXME: add a longer delay here --FvK - return(1); - - case 0x06: /* Identify SCSI Devices, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x07: /* Format Unit */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_FORMAT_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x08: /* Read Drive Parameters */ - target_check(cmd->id, cmd->lun); - - dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); - memset(dev->CmdBuffer, 0x00, dev->BufferLength); - - ret = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer); - - DEBUG("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, 4 /* dev->BufferLength */); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); - - case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - case 0x0c: /* Seek */ target_check(cmd->id, cmd->lun); - cdb[0] = GPCMD_SEEK_10; + cdb[0] = bios_cmd_to_scsi[cmd->command]; cdb[1] = (cmd->lun & 7) << 5; cdb[2] = (lba >> 24) & 0xff; cdb[3] = (lba >> 16) & 0xff; cdb[4] = (lba >> 8) & 0xff; cdb[5] = lba & 0xff; + if (cmd->command != 0x0c) + cdb[8] = sector_len; + DBGLOG(1, "BIOS CMD(READ/WRITE/VERIFY, %08lx, %d)\n", + lba, cmd->secount); - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - return((dev->Status == SCSI_STATUS_OK) ? 1 : 0); - - case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x10: /* Test Drive Ready */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_TEST_UNIT_READY; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x11: /* Recalibrate */ - target_check(cmd->id, cmd->lun); - - cdb[0] = GPCMD_REZERO_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cmd->lun, cdb); - - return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); - - case 0x14: /* Controller Diagnostic */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x15: /* Read DASD Type */ - target_check(cmd->id, cmd->lun); - - dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); - memset(dev->CmdBuffer, 0x00, dev->BufferLength); - - ret = x54x_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer); - - DEBUG("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, 4 /* dev->BufferLength */); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); + ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address); + if (cmd->command == 0x0c) + ret = !!ret; + break; default: DEBUG("BIOS: Unimplemented command: %02X\n", cmd->command); - return(1); + /*FALLTHROUGH*/ + + case 0x05: /* Format Track, invalid since SCSI has no tracks */ + case 0x0a: /* ???? */ + case 0x0b: /* ???? */ + case 0x12: /* ???? */ + case 0x13: /* ???? */ +//FIXME: add a longer delay here --FvK + ret = 0x01; + break; + + case 0x06: /* Identify SCSI Devices, in practice it's a nop */ + case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ + case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ + case 0x0e: /* Read Sector Buffer */ + case 0x0f: /* Write Sector Buffer */ + case 0x14: /* Controller Diagnostic */ +//FIXME: add a longer delay here --FvK + ret = 0x80; + break; + + case 0x07: /* Format Unit */ + case 0x10: /* Test Drive Ready */ + case 0x11: /* Recalibrate */ + target_check(cmd->id, cmd->lun); + + cdb[0] = cdb[0] = bios_cmd_to_scsi[cmd->command]; + cdb[1] = (cmd->lun & 7) << 5; + + ret = x54x_bios_scsi_command(dev, cdb, NULL, sector_len, dma_address); + break; + + case 0x08: /* Read Drive Parameters */ + case 0x15: /* Read DASD Type */ + target_check(cmd->id, cmd->lun); + + dev->buffer_length = 6; + dev->cmd_buffer = (uint8_t *)mem_alloc(dev->buffer_length); + memset(dev->cmd_buffer, 0x00, dev->buffer_length); + + buf = (uint8_t *) malloc(6); + if (cmd->command == 0x08) + ret = x54x_bios_command_08(dev, buf); + else + ret = x54x_bios_command_15(dev, buf); + + DEBUG("BIOS DMA: Reading 4 bytes at %08X\n", dma_address); + DMAPageWrite(dma_address, buf, 4); + free(buf); + + if (dev->cmd_buffer != NULL) { + free(dev->cmd_buffer); + dev->cmd_buffer = NULL; + } + + break; } - DEBUG("BIOS Request complete\n"); + DEBUG("BIOS Request %02X complete: %02X\n", cmd->command, ret); + + return(ret); } @@ -753,7 +766,7 @@ x54x_set_residue(Req_t *req, int32_t TransferLength) { uint32_t Residue = 0; addr24 Residue24; - int32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + int32_t BufLen = scsi_devices[req->TargetID][req->LUN].buffer_length; if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { @@ -784,12 +797,16 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t Address, i = 0; - uint32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; + uint32_t BufLen; uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); int sg_pos = 0; SGE32 SGBuffer; uint32_t DataToTransfer = 0; + scsi_device_t *sd; + + sd = &scsi_devices[req->TargetID][req->LUN]; + BufLen = sd->buffer_length; if (Is24bit) { DataPointer = ADDR_TO_U32(req->CmdBlock.old_fmt.DataPointer); @@ -816,11 +833,11 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) if (read_from_host && DataToTransfer) { DEBUG("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageRead(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + DMAPageRead(Address, &sd->cmd_buffer[sg_pos], DataToTransfer); } else if (write_to_host && DataToTransfer) { DEBUG("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageWrite(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); + DMAPageWrite(Address, &sd->cmd_buffer[sg_pos], DataToTransfer); } else DEBUG("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); @@ -842,9 +859,9 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { if (read_from_host) - DMAPageRead(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, (int)DataLength)); + DMAPageRead(Address, sd->cmd_buffer, MIN(BufLen, (int)DataLength)); else if (write_to_host) - DMAPageWrite(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, (int)DataLength)); + DMAPageWrite(Address, sd->cmd_buffer, MIN(BufLen, (int)DataLength)); } } } @@ -852,25 +869,25 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) void -x54x_buf_alloc(uint8_t id, uint8_t lun, int length) +x54x_buf_alloc(scsi_device_t *sd, int length) { - if (SCSIDevices[id][lun].CmdBuffer != NULL) { - free(SCSIDevices[id][lun].CmdBuffer); - SCSIDevices[id][lun].CmdBuffer = NULL; + if (sd->cmd_buffer != NULL) { + free(sd->cmd_buffer); + sd->cmd_buffer = NULL; } DEBUG("Allocating data buffer (%i bytes)\n", length); - SCSIDevices[id][lun].CmdBuffer = (uint8_t *)mem_alloc(length); - memset(SCSIDevices[id][lun].CmdBuffer, 0, length); + sd->cmd_buffer = (uint8_t *)mem_alloc(length); + memset(sd->cmd_buffer, 0, length); } void -x54x_buf_free(uint8_t id, uint8_t lun) +x54x_buf_free(scsi_device_t *sd) { - if (SCSIDevices[id][lun].CmdBuffer != NULL) { - free(SCSIDevices[id][lun].CmdBuffer); - SCSIDevices[id][lun].CmdBuffer = NULL; + if (sd->cmd_buffer != NULL) { + free(sd->cmd_buffer); + sd->cmd_buffer = NULL; } } @@ -895,6 +912,7 @@ uint32_t SenseBufferPointer(Req_t *req) { uint32_t SenseBufferAddress; + if (req->Is24bit) { SenseBufferAddress = req->CCBPointer; SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; @@ -914,7 +932,7 @@ SenseBufferFree(Req_t *req, int Copy) uint8_t temp_sense[256]; if (SenseLength && Copy) { - scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength); + scsi_device_request_sense(&scsi_devices[req->TargetID][req->LUN], temp_sense, SenseLength); /* * The sense address, in 32-bit mode, is located in the @@ -939,30 +957,26 @@ static void x54x_scsi_cmd(x54x_t *dev) { Req_t *req = &dev->Req; - uint8_t id, lun; + uint8_t phase, bit24 = !!req->Is24bit; + uint32_t i, SenseBufferAddress; + int target_data_len, target_cdb_len = 12; uint8_t temp_cdb[12]; - uint32_t i; - int target_cdb_len = 12; - int target_data_len; - uint8_t bit24 = !!req->Is24bit; int32_t *BufLen; - uint8_t phase; - uint32_t SenseBufferAddress; int64_t p; + scsi_device_t *sd; - id = req->TargetID; - lun = req->LUN; + sd = &scsi_devices[req->TargetID][req->LUN]; target_cdb_len = 12; target_data_len = x54x_get_length(req, bit24); - if (!scsi_device_valid(id, lun)) - fatal("SCSI target on %02i:%02i has disappeared\n", id, lun); + if (! scsi_device_valid(sd)) + fatal("SCSI target on %i:%i has disappeared\n", req->TargetID, req->LUN); DEBUG("target_data_len = %i\n", target_data_len); - DEBUG("SCSI command being executed on ID %i, LUN %i\n", id, lun); + DEBUG("SCSI command being executed on ID %i:%i\n", req->TargetID, req->LUN); DEBUG("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); - for (i=1; iCmdBlock.common.CdbLength; i++) + for (i = 1; i < req->CmdBlock.common.CdbLength; i++) DEBUG("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); memset(temp_cdb, 0x00, target_cdb_len); @@ -977,14 +991,14 @@ x54x_scsi_cmd(x54x_t *dev) dev->Residue = 0; - BufLen = scsi_device_get_buf_len(id, lun); + BufLen = scsi_device_get_buf_len(sd); *BufLen = target_data_len; - DEBUG("Command buffer: %08X\n", SCSIDevices[id][lun].CmdBuffer); + DEBUG("Command buffer: %08X\n", sd->cmd_buffer); - scsi_device_command_phase0(id, lun, temp_cdb); + scsi_device_command_phase0(sd, temp_cdb); - phase = SCSIDevices[id][lun].Phase; + phase = sd->phase; DEBUG("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); @@ -992,47 +1006,46 @@ x54x_scsi_cmd(x54x_t *dev) if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { /* Request sense in non-data mode - sense goes to sense buffer. */ *BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - x54x_buf_alloc(id, lun, *BufLen); - scsi_device_command_phase1(id, lun); - if ((SCSIDevices[id][lun].Status != SCSI_STATUS_OK) && (*BufLen > 0)) { + x54x_buf_alloc(sd, *BufLen); + scsi_device_command_phase1(sd); + if ((sd->status != SCSI_STATUS_OK) && (*BufLen > 0)) { SenseBufferAddress = SenseBufferPointer(req); - DMAPageWrite(SenseBufferAddress, SCSIDevices[id][lun].CmdBuffer, *BufLen); + DMAPageWrite(SenseBufferAddress, sd->cmd_buffer, *BufLen); x54x_add_to_period(*BufLen); } } else { - p = scsi_device_get_callback(id, lun); + p = scsi_device_get_callback(sd); if (p <= 0LL) x54x_add_to_period(*BufLen); else dev->media_period += p; - x54x_buf_alloc(id, lun, MIN(target_data_len, *BufLen)); + x54x_buf_alloc(sd, MIN(target_data_len, *BufLen)); if (phase == SCSI_PHASE_DATA_OUT) x54x_buf_dma_transfer(req, bit24, target_data_len, 1); - scsi_device_command_phase1(id, lun); + scsi_device_command_phase1(sd); if (phase == SCSI_PHASE_DATA_IN) x54x_buf_dma_transfer(req, bit24, target_data_len, 0); - SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK)); + SenseBufferFree(req, (sd->status != SCSI_STATUS_OK)); } } else - SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK)); + SenseBufferFree(req, (sd->status != SCSI_STATUS_OK)); x54x_set_residue(req, target_data_len); - x54x_buf_free(id, lun); + x54x_buf_free(sd); DEBUG("Request complete\n"); - if (SCSIDevices[id][lun].Status == SCSI_STATUS_OK) { + if (sd->status == SCSI_STATUS_OK) { x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - } else if (SCSIDevices[id][lun].Status == SCSI_STATUS_CHECK_CONDITION) { + } else if (sd->status == SCSI_STATUS_CHECK_CONDITION) { x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); } - DEBUG("SCSIDevices[%02i][%02i].Status = %02X\n", - id, lun, SCSIDevices[id][lun].Status); + DEBUG("scsi_devices[%i][%i].status = %02X\n", req->TargetID, req->LUN, sd->status); } @@ -1050,7 +1063,7 @@ static void x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { Req_t *req = &dev->Req; - uint8_t id, lun; + scsi_device_t *sd; /* Fetch data from the Command Control Block. */ DMAPageRead(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32)); @@ -1061,30 +1074,29 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) req->TargetID = dev->Mbx24bit ? req->CmdBlock.old_fmt.Id : req->CmdBlock.new_fmt.Id; req->LUN = dev->Mbx24bit ? req->CmdBlock.old_fmt.Lun : req->CmdBlock.new_fmt.Lun; - id = req->TargetID; - lun = req->LUN; - if ((id > dev->max_id) || (lun > 7)) { - DEBUG("SCSI Target ID %i or LUN %i is not valid\n",id,lun); + if ((req->TargetID > dev->max_id) || (req->LUN > 7)) { + DEBUG("SCSI Target ID %i or LUN %i is not valid\n", req->TargetID, req->LUN); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } + sd = &scsi_devices[req->TargetID][req->LUN]; - DEBUG("Scanning SCSI Target ID %i\n", id); + DEBUG("Scanning SCSI Target ID %i\n", req->TargetID); - SCSIDevices[id][lun].Status = SCSI_STATUS_OK; + sd->status = SCSI_STATUS_OK; /* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */ - if (! scsi_device_present(id, 0)) { - DEBUG("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); + if (! scsi_device_present(sd)) { + DEBUG("SCSI Target ID %i and LUN %i have no device attached\n", req->TargetID, req->LUN); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); } else { - DEBUG("SCSI Target ID %i detected and working\n", id); + DEBUG("SCSI Target ID %i detected and working\n", req->TargetID); DEBUG("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); DEBUG("CDB Length %i\n", req->CmdBlock.common.CdbLength); DEBUG("CCB Opcode %x\n", req->CmdBlock.common.Opcode); @@ -1101,7 +1113,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) if (req->CmdBlock.common.Opcode == 0x81) { DEBUG("Bus reset opcode\n"); - scsi_device_reset(id, lun); + scsi_device_reset(sd); x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); @@ -1436,9 +1448,9 @@ x54x_reset(x54x_t *dev) dev->MailboxOutPosCur = 0; /* Reset all devices on controller reset. */ - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) - scsi_device_reset(i, j); + for (i = 0; i < SCSI_ID_MAX; i++) { + for (j = 0; j < SCSI_LUN_MAX; j++) + scsi_device_reset(&scsi_devices[i][j]); } if (dev->ven_reset) @@ -1495,9 +1507,9 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (val & CTRL_SCRST) { /* Reset all devices on SCSI bus reset. */ - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) - scsi_device_reset(i, j); + for (i = 0; i < SCSI_ID_MAX; i++) { + for (j = 0; j < SCSI_LUN_MAX; j++) + scsi_device_reset(&scsi_devices[i][j]); } } @@ -1668,14 +1680,14 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (dev->ven_get_host_id) host_id = dev->ven_get_host_id(dev); - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) { dev->DataBuf[i] = 0x00; /* Skip the HA .. */ if (i == host_id) continue; - for (j=0; jDataBuf[i] |= (1< * Miran Grca, @@ -541,8 +541,8 @@ typedef struct { extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); -extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length); -extern void x54x_buf_free(uint8_t id, uint8_t lun); +extern void x54x_buf_alloc(scsi_device_t *sd, int length); +extern void x54x_buf_free(scsi_device_t *sd); extern uint8_t x54x_mbo_process(x54x_t *dev); extern void x54x_wait_for_poll(void); extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len); diff --git a/src/devices/sound/midi.c b/src/devices/sound/midi.c index 346be53..880d6f0 100644 --- a/src/devices/sound/midi.c +++ b/src/devices/sound/midi.c @@ -8,7 +8,7 @@ * * MIDI support module, main file. * - * Version: @(#)midi.c 1.0.7 2018/09/22 + * Version: @(#)midi.c 1.0.8 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -222,7 +222,14 @@ void midi_close(void) { if (midi != NULL) { +#if 0 + /* is a const device .. */ + if (midi->device) + free(midi->device); +#endif + free(midi); + midi = NULL; } } diff --git a/src/devices/sound/midi_fluidsynth.c b/src/devices/sound/midi_fluidsynth.c index 981d106..62ad20d 100644 --- a/src/devices/sound/midi_fluidsynth.c +++ b/src/devices/sound/midi_fluidsynth.c @@ -17,7 +17,7 @@ * website (for 32bit and 64bit Windows) are working, and * need no additional support files other than sound fonts. * - * Version: @(#)midi_fluidsynth.c 1.0.12 2018/10/05 + * Version: @(#)midi_fluidsynth.c 1.0.13 2018/10/14 * * Code borrowed from scummvm. * @@ -90,7 +90,6 @@ static int (*f_fluid_synth_sysex)(fluid_synth_t *synth, const char *data, int le static int (*f_fluid_synth_pitch_bend)(fluid_synth_t *synth, int chan, int val); static int (*f_fluid_synth_program_change)(fluid_synth_t *synth, int chan, int program); static int (*f_fluid_synth_sfload)(fluid_synth_t *synth, const char *filename, int reset_presets); -static int (*f_fluid_synth_sfunload)(fluid_synth_t *synth, unsigned int id, int reset_presets); static int (*f_fluid_synth_set_interp_method)(fluid_synth_t *synth, int chan, int interp_method); static void (*f_fluid_synth_set_reverb)(fluid_synth_t *synth, double roomsize, double damping, double width, double level); static void (*f_fluid_synth_set_reverb_on)(fluid_synth_t *synth, int on); @@ -114,7 +113,6 @@ static dllimp_t fluidsynth_imports[] = { { "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend }, { "fluid_synth_program_change", &f_fluid_synth_program_change }, { "fluid_synth_sfload", &f_fluid_synth_sfload }, - { "fluid_synth_sfunload", &f_fluid_synth_sfunload }, { "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method}, { "fluid_synth_set_reverb", &f_fluid_synth_set_reverb }, { "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on }, @@ -128,17 +126,19 @@ static dllimp_t fluidsynth_imports[] = { typedef struct fluidsynth { - fluid_settings_t* settings; - fluid_synth_t* synth; - int samplerate; - int sound_font; + fluid_settings_t *settings; + fluid_synth_t *synth; + int samplerate; + int sound_font; - thread_t* thread_h; - event_t* event; - int buf_size; - float* buffer; - int16_t* buffer_int16; - int midi_pos; + thread_t *thread_h; + event_t *event, *start_event; + + int buf_size; + float *buffer; + int16_t *buffer_int16; + int midi_pos; + volatile int on; } fluidsynth_t; @@ -172,8 +172,12 @@ fluidsynth_thread(void *param) int buf_pos = 0; int buf_size = data->buf_size / BUFFER_SEGMENTS; - while (1) { + thread_set_event(data->start_event); + + while (data->on) { thread_wait_event(data->event, -1); + thread_reset_event(data->event); + if (sound_is_float) { float *buf = (float*)((uint8_t*)data->buffer + buf_pos); memset(buf, 0, buf_size); @@ -276,7 +280,8 @@ fluidsynth_sysex(uint8_t *data, unsigned int len) static void * fluidsynth_init(const device_t *info) { - fluidsynth_t* data = &fsdev; + fluidsynth_t *data = &fsdev; + midi_device_t* dev; memset(data, 0x00, sizeof(fluidsynth_t)); @@ -346,15 +351,13 @@ fluidsynth_init(const device_t *info) data->buffer = NULL; data->buffer_int16 = (int16_t *)mem_alloc(data->buf_size); } - data->event = thread_create_event(); - data->thread_h = thread_create(fluidsynth_thread, data); openal_set_midi(data->samplerate, data->buf_size); DEBUG("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", f_fluid_version_str(), data->samplerate, data->buf_size); - midi_device_t *dev = (midi_device_t *)mem_alloc(sizeof(midi_device_t)); + dev = (midi_device_t *)mem_alloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); dev->play_msg = fluidsynth_msg; @@ -363,6 +366,16 @@ fluidsynth_init(const device_t *info) midi_init(dev); + data->on = 1; + + data->start_event = thread_create_event(); + data->event = thread_create_event(); + + data->thread_h = thread_create(fluidsynth_thread, data); + + thread_wait_event(data->start_event, -1); + thread_reset_event(data->start_event); + return(dev); } @@ -375,10 +388,9 @@ fluidsynth_close(void* priv) fluidsynth_t* data = &fsdev; - if (data->sound_font != -1) { - f_fluid_synth_sfunload(data->synth, data->sound_font, 1); - data->sound_font = -1; - } + data->on = 0; + thread_set_event(data->event); + thread_wait(data->thread_h, -1); if (data->synth) { f_delete_fluid_synth(data->synth); @@ -390,8 +402,6 @@ fluidsynth_close(void* priv) data->settings = NULL; } - midi_close(); - if (data->buffer) { free(data->buffer); data->buffer = NULL; diff --git a/src/devices/sound/midi_mt32.c b/src/devices/sound/midi_mt32.c index a23ef40..6f71340 100644 --- a/src/devices/sound/midi_mt32.c +++ b/src/devices/sound/midi_mt32.c @@ -8,7 +8,7 @@ * * Interface to the MuNT32 MIDI synthesizer. * - * Version: @(#)midi_mt32.c 1.0.5 2018/10/05 + * Version: @(#)midi_mt32.c 1.0.6 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -102,6 +102,8 @@ static const mt32emu_report_handler_i_v0 handler_v0 = { static thread_t *thread_h = NULL; static event_t *event = NULL; +static event_t *start_event = NULL; +static volatile int mt32_on = 0; static uint32_t samplerate = 44100; static int buf_size = 0; static float* buffer = NULL; @@ -178,12 +180,16 @@ mt32_thread(void *param) { int buf_pos = 0; int bsize = buf_size / BUFFER_SEGMENTS; + float *buf; + int16_t *buf16; - while (1) { + thread_set_event(start_event); + while (mt32_on) { thread_wait_event(event, -1); + thread_reset_event(event); if (sound_is_float) { - float *buf = (float *) ((uint8_t*)buffer + buf_pos); + buf = (float *) ((uint8_t*)buffer + buf_pos); memset(buf, 0, bsize); mt32_stream(buf, bsize / (2 * sizeof(float))); @@ -194,10 +200,10 @@ mt32_thread(void *param) buf_pos = 0; } } else { - int16_t *buf = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos); + buf16 = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos); - memset(buf, 0, bsize); - mt32_stream_int16(buf, bsize / (2 * sizeof(int16_t))); + memset(buf16, 0, bsize); + mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t))); buf_pos += bsize; if (buf_pos >= buf_size) { if (soundon) @@ -242,8 +248,6 @@ mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) return 0; - event = thread_create_event(); - thread_h = thread_create(mt32_thread, 0); samplerate = mt32emu_get_actual_stereo_output_samplerate(context); /* buf_size = samplerate/RENDER_RATE*2; */ @@ -281,6 +285,15 @@ mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) midi_init(dev); + mt32_on = 1; + + start_event = thread_create_event(); + event = thread_create_event(); + thread_h = thread_create(mt32_thread, 0); + + thread_wait_event(start_event, -1); + thread_reset_event(start_event); + return dev; } @@ -304,11 +317,12 @@ mt32_close(void *priv) { if (priv == NULL) return; - if (thread_h) - thread_kill(thread_h); - if (event) - thread_destroy_event(event); + mt32_on = 0; + thread_set_event(event); + thread_wait(thread_h, -1); + event = NULL; + start_event = NULL; thread_h = NULL; if (context) { @@ -324,10 +338,6 @@ mt32_close(void *priv) if (buffer_int16) free(buffer_int16); buffer_int16 = NULL; - - midi_close(); - - free((midi_device_t*)priv); } diff --git a/src/devices/sound/sound.c b/src/devices/sound/sound.c index 17626b9..9c2119c 100644 --- a/src/devices/sound/sound.c +++ b/src/devices/sound/sound.c @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.12 2018/10/05 + * Version: @(#)sound.c 1.0.13 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,7 +48,6 @@ #include "../../timer.h" #include "../../device.h" #include "../../plat.h" -#include "../scsi/scsi_device.h" #include "../cdrom/cdrom.h" #include "sound.h" #include "midi.h" @@ -105,7 +104,7 @@ cd_thread(void *param) float cd_buffer_temp2[2] = {0.0, 0.0}; int32_t audio_vol_l; int32_t audio_vol_r; - int channel_select[2]; + int ch_sel[2]; int c, i, r, has_audio; thread_set_event(cd_start_event); @@ -129,22 +128,32 @@ cd_thread(void *param) for (i = 0; i < CDROM_NUM; i++) { has_audio = 0; - if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || - !cdrom[i] || !cdrom[i]->handler) continue; + if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || !cdrom[i].ops) continue; - if (cdrom[i]->handler->audio_callback) { - r = cdrom[i]->handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); - has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on/* && r*/); + if (cdrom[i].ops->audio_callback) { + r = cdrom[i].ops->audio_callback(&cdrom[i], cd_buffer[i], CD_BUFLEN*2); + has_audio = (cdrom[i].bus_type && cdrom[i].sound_on/* && r*/); } else continue; if (soundon && has_audio) { - audio_vol_l = cdrom_mode_sense_get_volume(cdrom[i], 0); - audio_vol_r = cdrom_mode_sense_get_volume(cdrom[i], 1); + if (cdrom[i].get_volume) { + audio_vol_l = cdrom[i].get_volume(cdrom[i].p, 0); + audio_vol_r = cdrom[i].get_volume(cdrom[i].p, 1); + } else { + audio_vol_l = 255; + audio_vol_r = 255; + } - channel_select[0] = cdrom_mode_sense_get_channel(cdrom[i], 0); - channel_select[1] = cdrom_mode_sense_get_channel(cdrom[i], 1); - if (!r) { + if (cdrom[i].get_channel) { + ch_sel[0] = cdrom[i].get_channel(cdrom[i].p, 0); + ch_sel[1] = cdrom[i].get_channel(cdrom[i].p, 1); + } else { + ch_sel[0] = 1; + ch_sel[1] = 2; + } + + if (! r) { for (c = 0; c < CD_BUFLEN*2; c += 2) { if (sound_is_float) { cd_out_buffer[c] += 0.0; @@ -170,13 +179,13 @@ cd_thread(void *param) /*Apply ATAPI channel select*/ cd_buffer_temp2[0] = cd_buffer_temp2[1] = 0.0; - if (channel_select[0] & 1) + if (ch_sel[0] & 1) cd_buffer_temp2[0] += cd_buffer_temp[0]; - if (channel_select[0] & 2) + if (ch_sel[0] & 2) cd_buffer_temp2[1] += cd_buffer_temp[0]; - if (channel_select[1] & 1) + if (ch_sel[1] & 1) cd_buffer_temp2[0] += cd_buffer_temp[1]; - if (channel_select[1] & 2) + if (ch_sel[1] & 2) cd_buffer_temp2[1] += cd_buffer_temp[1]; /*Apply sound card CD volume*/ @@ -340,8 +349,8 @@ sound_reset(void) sound_cd_set_volume(65535, 65535); for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop) - cdrom[i]->handler->audio_stop(i); + if (cdrom[i].ops && cdrom[i].ops->audio_stop) + cdrom[i].ops->audio_stop(&cdrom[i]); } /* Initialize the PC Speaker device. */ @@ -380,7 +389,7 @@ sound_init(void) /* Set up the CD-AUDIO thread. */ drives = 0; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i] && (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)) + if (cdrom[i].bus_type != CDROM_BUS_DISABLED) drives++; } @@ -427,9 +436,9 @@ sound_cd_stop(void) int i; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop) - cdrom[i]->handler->audio_stop(i); - if ((cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) && cdrom[i]) + if (cdrom[i].ops && cdrom[i].ops->audio_stop) + cdrom[i].ops->audio_stop(&cdrom[i]); + if (cdrom[i].bus_type != CDROM_BUS_DISABLED) drives++; } if (drives && !cd_thread_enable) { diff --git a/src/devices/system/intel_piix.c b/src/devices/system/intel_piix.c index 5a4bf68..d351535 100644 --- a/src/devices/system/intel_piix.c +++ b/src/devices/system/intel_piix.c @@ -12,7 +12,7 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.7 2018/10/05 + * Version: @(#)intel_piix.c 1.0.8 2018/10/14 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,8 +52,9 @@ #include "../input/keyboard.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "../scsi/scsi_device.h" #include "../cdrom/cdrom.h" +#include "../scsi/scsi_device.h" +#include "../scsi/scsi_cdrom.h" #include "../disk/zip.h" #include "pci.h" #include "dma.h" @@ -824,11 +825,13 @@ piix_reset(void *p) { int i; + //FIXME: cdrom_reset_bus(CDROM_BUS_ATAPI); --FvK for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) - cdrom_reset(cdrom[i]); + if (cdrom[i].bus_type == CDROM_BUS_ATAPI) + scsi_cdrom_reset(scsi_cdrom[i]); } + //FIXME: zip_reset_bus(ZIP_BUS_ATAPI); --FvK for (i = 0; i < ZIP_NUM; i++) { if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) zip_reset(zip[i]); diff --git a/src/devices/video/vid_hercules.c b/src/devices/video/vid_hercules.c index f22c786..134f90a 100644 --- a/src/devices/video/vid_hercules.c +++ b/src/devices/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.7 2018/09/22 + * Version: @(#)vid_hercules.c 1.0.8 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -448,7 +448,12 @@ hercules_close(void *priv) { hercules_t *dev = (hercules_t *)priv; - free(dev->vram); + if (! dev) + return; + + if (dev->vram) + free(dev->vram); + free(dev); } diff --git a/src/devices/video/vid_herculesplus.c b/src/devices/video/vid_herculesplus.c index 153de5a..6c7e483 100644 --- a/src/devices/video/vid_herculesplus.c +++ b/src/devices/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_hercules_plus.c 1.0.9 2018/09/22 + * Version: @(#)vid_hercules_plus.c 1.0.10 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -671,7 +671,12 @@ herculesplus_close(void *priv) { herculesplus_t *dev = (herculesplus_t *)priv; - free(dev->vram); + if (! dev) + return; + + if (dev->vram) + free(dev->vram); + free(dev); } diff --git a/src/devices/video/vid_incolor.c b/src/devices/video/vid_incolor.c index 8369628..ecbe9a1 100644 --- a/src/devices/video/vid_incolor.c +++ b/src/devices/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.9 2018/09/22 + * Version: @(#)vid_incolor.c 1.0.10 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1079,7 +1079,12 @@ incolor_close(void *priv) { incolor_t *dev = (incolor_t *)priv; - free(dev->vram); + if (! dev) + return; + + if (dev->vram) + free(dev->vram); + free(dev); } diff --git a/src/machines/m_at_headland.c b/src/machines/m_at_headland.c index 16f419b..81e0c51 100644 --- a/src/machines/m_at_headland.c +++ b/src/machines/m_at_headland.c @@ -98,10 +98,9 @@ static const int mem_conf_cr1[41] = { 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40 }; -static const video_timings_t oti067_timing = {VID_ISA,6,8,16,6,8,16}; -static uint32_t +static uint32_t get_addr(headland_t *dev, uint32_t addr, uint16_t *mr) { if (mr && (dev->cr[0] & 2) && (*mr & 0x200)) { @@ -121,7 +120,7 @@ get_addr(headland_t *dev, uint32_t addr, uint16_t *mr) } else if (dev->cr[0] & 0x80) addr |= (*mr & 0x100) ? ((*mr & 0x80) + 0x400) << 12 : (*mr & 0xE0) << 14; else - addr |= (*mr & 0x100) ? ((*mr & 0xE0) + 0x40) << 14 : (*mr & 0x80) << 12; + addr |= (*mr & 0x100) ? ((*mr & 0xE0) + 0x40) << 14 : (*mr & 0x80) << 12; } else { if ((dev->cr[4] & 0x80) && (dev->cr[6] & 1)) { if (dev->cr[0] & 0x80) { @@ -142,7 +141,7 @@ get_addr(headland_t *dev, uint32_t addr, uint16_t *mr) } -static void +static void set_global_EMS_state(headland_t *dev, int state) { uint32_t base_addr, virt_addr; @@ -175,7 +174,7 @@ set_global_EMS_state(headland_t *dev, int state) } -static void +static void memmap_state_update(headland_t *dev) { uint32_t addr; @@ -208,7 +207,7 @@ memmap_state_update(headland_t *dev) } -static void +static void hl_write(uint16_t addr, uint8_t val, void *priv) { headland_t *dev = (headland_t *)priv; @@ -334,7 +333,7 @@ hl_write(uint16_t addr, uint8_t val, void *priv) } -static void +static void hl_writew(uint16_t addr, uint16_t val, void *priv) { headland_t *dev = (headland_t *)priv; @@ -443,7 +442,7 @@ hl_read(uint16_t addr, void *priv) } -static uint16_t +static uint16_t hl_readw(uint16_t addr, void *priv) { headland_t *dev = (headland_t *)priv; @@ -464,7 +463,7 @@ hl_readw(uint16_t addr, void *priv) } -static uint8_t +static uint8_t mem_read_b(uint32_t addr, void *priv) { mem_map_t *map = (mem_map_t *)priv; @@ -480,7 +479,7 @@ mem_read_b(uint32_t addr, void *priv) } -static uint16_t +static uint16_t mem_read_w(uint32_t addr, void *priv) { mem_map_t *map = (mem_map_t *)priv; @@ -496,7 +495,7 @@ mem_read_w(uint32_t addr, void *priv) } -static uint32_t +static uint32_t mem_read_l(uint32_t addr, void *priv) { mem_map_t *map = (mem_map_t *)priv; @@ -525,7 +524,7 @@ mem_write_b(uint32_t addr, uint8_t val, void *priv) } -static void +static void mem_write_w(uint32_t addr, uint16_t val, void *priv) { mem_map_t *map = (mem_map_t *)priv; @@ -538,7 +537,7 @@ mem_write_w(uint32_t addr, uint16_t val, void *priv) } -static void +static void mem_write_l(uint32_t addr, uint32_t val, void *priv) { mem_map_t *map = (mem_map_t *)priv; @@ -551,7 +550,7 @@ mem_write_l(uint32_t addr, uint32_t val, void *priv) } -static void +static void headland_init(headland_t *dev, int ht386) { int i; diff --git a/src/machines/m_ps1_hdc.c b/src/machines/m_ps1_hdc.c index 430f032..695605f 100644 --- a/src/machines/m_ps1_hdc.c +++ b/src/machines/m_ps1_hdc.c @@ -43,7 +43,7 @@ * Type table with the main code, so the user can only select * items from that list... * - * Version: @(#)m_ps1_hdc.c 1.0.8 2018/10/05 + * Version: @(#)m_ps1_hdc.c 1.0.9 2018/10/15 * * Author: Fred N. van Kempen, * @@ -1401,8 +1401,8 @@ ps1_hdc_init(const device_t *info) /* Load any disks for this device class. */ c = 0; for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_IDE) && (hdd[i].id.ide_channel < PS1_HDD_NUM)) { - drive = &dev->drives[hdd[i].id.ide_channel]; + if ((hdd[i].bus == HDD_BUS_IDE) && (hdd[i].bus_id.ide_channel < PS1_HDD_NUM)) { + drive = &dev->drives[hdd[i].bus_id.ide_channel]; if (! hdd_image_load(i)) { drive->present = 0; @@ -1425,7 +1425,7 @@ ps1_hdc_init(const device_t *info) drive->present = 1; INFO("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", - hdd[i].id.ide_channel, drive->type, + hdd[i].bus_id.ide_channel, drive->type, drive->tracks, drive->hpc, drive->spt, i); if (++c > PS1_HDD_NUM) break; diff --git a/src/mem.c b/src/mem.c index 7fc35ff..d51fdf0 100644 --- a/src/mem.c +++ b/src/mem.c @@ -8,7 +8,7 @@ * * Memory handling and MMU. * - * Version: @(#)mem.c 1.0.21 2018/10/05 + * Version: @(#)mem.c 1.0.22 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1213,13 +1213,21 @@ mem_write_nulll(uint32_t addr, uint32_t val, void *p) void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { + uint32_t cur_addr; + start_addr &= ~PAGE_MASK_MASK; end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + /* + * Do nothing if the pages array is empty or DMA reads/writes + * to/from PCI device memory addresses may crash the emulator. + */ + cur_addr = (start_addr >> 12); + if (cur_addr < pages_sz) + pages[cur_addr].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; } } @@ -1649,7 +1657,17 @@ mem_reset(void) } } else { /* 8088/86; maximum address space is 1MB. */ +#if 1 + /* + * According to the 86Box folks, the Toshiba T1200 can + * take up to 2 MB of RAM. Weird, since it uses a 8086, + * which cannot address that much other than using it + * as "hard ram", aka battery-backed EMS memory. --FvK + */ + m = 512; +#else m = 256; +#endif } /* diff --git a/src/pc.c b/src/pc.c index 766290a..50656b7 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.55 2018/10/07 + * Version: @(#)pc.c 1.0.57 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -888,14 +888,6 @@ pc_init(void) floppy_init(); //FIXME: fdd_init() now? #endif - /* FIXME: should be disk_init() */ - cdrom_hard_reset(); - zip_hard_reset(); - - /* FIXME: should be scsi_init() */ - scsi_disk_hard_reset(); - scsi_card_init(); - pc_full_speed(); shadowbios = 0; @@ -964,6 +956,10 @@ pc_reset_hard_close(void) cdrom_close(); + zip_close(); + + scsi_disk_close(); + #if 0 sound_close(); #endif @@ -990,10 +986,6 @@ pc_reset_hard_init(void) parallel_reset(); serial_reset(); - /* FIXME: these, should be in disk_reset(). */ - cdrom_hard_reset(); - zip_hard_reset(); - /* * Reset the actual machine and its basic modules. * @@ -1036,6 +1028,10 @@ pc_reset_hard_init(void) /* Reset and reconfigure the SCSI layer. */ scsi_card_init(); + cdrom_hard_reset(); + zip_hard_reset(); + scsi_disk_hard_reset(); + /* Reset and reconfigure the Network Card layer. */ network_reset(); diff --git a/src/ui/ui_cdrom.c b/src/ui/ui_cdrom.c index 946205d..0350cdc 100644 --- a/src/ui/ui_cdrom.c +++ b/src/ui/ui_cdrom.c @@ -8,7 +8,7 @@ * * Handle the UI part of CD-ROM/ZIP/DISK media changes. * - * Version: @(#)ui_cdrom.c 1.0.3 2018/10/05 + * Version: @(#)ui_cdrom.c 1.0.4 2018/10/15 * * Author: Fred N. van Kempen, * @@ -58,8 +58,6 @@ #include "../devices/scsi/scsi_disk.h" #include "../devices/disk/zip.h" #include "../devices/cdrom/cdrom.h" -#include "../devices/cdrom/cdrom_image.h" -#include "../devices/cdrom/cdrom_null.h" #include "ui.h" @@ -88,43 +86,14 @@ ui_floppy_mount(uint8_t drive, int part, int8_t wp, const wchar_t *fn) void ui_cdrom_eject(uint8_t id) { - if (cdrom_drives[id].host_drive == 0) { - /* Switch from empty to empty. Do nothing. */ - return; - } - - if ((cdrom_drives[id].host_drive >= 'A') && - (cdrom_drives[id].host_drive <= 'Z')) { - ui_sb_menu_set_item(SB_CDROM | id, - IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 0); - } - - if (cdrom_image[id].prev_image_path) { - free(cdrom_image[id].prev_image_path); - cdrom_image[id].prev_image_path = NULL; - } - - if (cdrom_drives[id].host_drive == 200) { - cdrom_image[id].prev_image_path = (wchar_t *)mem_alloc(1024); - wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); - } - - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom[id]->handler->exit(id); - cdrom_close_handler(id); - memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); - cdrom_null_open(id); - - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(cdrom[id]); - } + /* Actually eject the media, if any. */ + cdrom_eject(id); + /* Now update the UI. */ ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); - cdrom_drives[id].host_drive = 0; ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); - ui_sb_icon_state(SB_CDROM|id, 1); ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 1); + ui_sb_icon_state(SB_CDROM|id, 1); ui_sb_tip_update(SB_CDROM|id); config_save(); @@ -134,60 +103,31 @@ ui_cdrom_eject(uint8_t id) void ui_cdrom_reload(uint8_t id) { -#ifdef USE_CDROM_IOCTL - int new_cdrom_drive; -#endif + cdrom_t *dev = &cdrom[id]; - if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || - (cdrom_drives[id].prev_host_drive == 0) || - (cdrom_drives[id].host_drive != 0)) { - /* Switch from empty to empty. Do nothing. */ - return; - } + /* Actually reload the media, if any. */ + cdrom_reload(id); - cdrom_close_handler(id); - memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); - - if (cdrom_drives[id].prev_host_drive == 200) { - /* Reload a previous image. */ - wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); - free(cdrom_image[id].prev_image_path); - cdrom_image[id].prev_image_path = NULL; - image_open(id, cdrom_image[id].image_path); - - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(cdrom[id]); - } - - if (wcslen(cdrom_image[id].image_path) == 0) { + /* Now update the UI. */ + switch (dev->host_drive) { + case 0: /* no media */ ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); - cdrom_drives[id].host_drive = 0; ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); - ui_sb_icon_state(SB_CDROM|id, 1); - } else { + break; + + case 200: /* image mounted */ ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); - cdrom_drives[id].host_drive = 200; ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 1); - ui_sb_icon_state(SB_CDROM|id, 0); - } -#ifdef USE_CDROM_IOCTL - } else { - /* Reload the previous host drive. */ - new_cdrom_drive = cdrom_drives[id].prev_host_drive; - ioctl_open(id, new_cdrom_drive); - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); - cdrom_drives[id].host_drive = new_cdrom_drive; - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 1); - ui_sb_icon_state(SB_CDROM|id, 0); -#endif + break; + + default: /* host drive mounted */ + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((dev->host_drive - 'A') << 3), 1); + break; } ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 0); + ui_sb_icon_state(SB_CDROM|id, 0); ui_sb_tip_update(SB_CDROM|id); config_save(); diff --git a/src/ui/ui_stbar.c b/src/ui/ui_stbar.c index f3560ac..e4af1a7 100644 --- a/src/ui/ui_stbar.c +++ b/src/ui/ui_stbar.c @@ -8,7 +8,7 @@ * * Common UI support functions for the Status Bar module. * - * Version: @(#)ui_stbar.c 1.0.10 2018/10/05 + * Version: @(#)ui_stbar.c 1.0.11 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -234,20 +234,20 @@ ui_sb_tip_update(uint8_t tag) case SB_CDROM: drive = ptr->tag & 0x0f; - bus = cdrom_drives[drive].bus_type; + bus = cdrom[drive].bus_type; id = IDS_3580 + (bus - 1); wcscpy(temp, get_string(id)); - str = cdrom_image[drive].image_path; + str = cdrom[drive].image_path; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ - if (cdrom_drives[drive].host_drive == 200) { + if (cdrom[drive].host_drive == 200) { swprintf(tip, sizeof_w(tip), get_string(IDS_3920), drive+1, temp, str); - } else if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { + } else if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { swprintf(temp, sizeof_w(temp), get_string(IDS_3901), - cdrom_drives[drive].host_drive & ~0x20); + cdrom[drive].host_drive & ~0x20); swprintf(tip, sizeof_w(tip), get_string(IDS_3920), drive+1, get_string(id), temp); @@ -259,7 +259,7 @@ ui_sb_tip_update(uint8_t tag) case SB_ZIP: drive = ptr->tag & 0x0f; - bus = cdrom_drives[drive].bus_type; + bus = zip_drives[drive].bus_type; id = IDS_3580 + (bus - 1); wcscpy(temp, get_string(id)); type = zip_drives[drive].is_250 ? 250 : 100; @@ -361,17 +361,17 @@ menu_cdrom(int part, int drive) sb_menu_add_item(part, IDM_CDROM_EMPTY | drive, get_string(IDS_3906)); if (host_cdrom_drive_available_num == 0) { - if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { - cdrom_drives[drive].host_drive = 0; + if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { + cdrom[drive].host_drive = 0; } goto check_items; } else { - if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { - if (! host_cdrom_drive_available[cdrom_drives[drive].host_drive - 'A']) { - cdrom_drives[drive].host_drive = 0; + if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { + if (! host_cdrom_drive_available[cdrom[drive].host_drive - 'A']) { + cdrom[drive].host_drive = 0; } } } @@ -385,18 +385,18 @@ menu_cdrom(int part, int drive) } check_items: - if (! cdrom_drives[drive].sound_on) + if (! cdrom[drive].sound_on) sb_menu_set_item(part, IDM_CDROM_MUTE | drive, 1); - if (cdrom_drives[drive].host_drive == 200) + if (cdrom[drive].host_drive == 200) sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 1); else - if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { + if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | - ((cdrom_drives[drive].host_drive - 'A') << 3), 1); + ((cdrom[drive].host_drive - 'A') << 3), 1); } else { - cdrom_drives[drive].host_drive = 0; + cdrom[drive].host_drive = 0; sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 1); } } @@ -479,16 +479,16 @@ ui_sb_reset(void) for (drive = 0; drive < CDROM_NUM; drive++) { /* Could be Internal or External IDE.. */ - if ((cdrom_drives[drive].bus_type == CDROM_BUS_ATAPI) && + if ((cdrom[drive].bus_type == CDROM_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { continue; } - if ((cdrom_drives[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) { + if ((cdrom[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) { continue; } - if (cdrom_drives[drive].bus_type != CDROM_BUS_DISABLED) + if (cdrom[drive].bus_type != CDROM_BUS_DISABLED) sb_nparts++; } @@ -563,15 +563,15 @@ ui_sb_reset(void) for (drive = 0; drive < CDROM_NUM; drive++) { /* Could be Internal or External IDE.. */ - if ((cdrom_drives[drive].bus_type == CDROM_BUS_ATAPI) && + if ((cdrom[drive].bus_type == CDROM_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3))) { continue; } - if ((cdrom_drives[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) + if ((cdrom[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) continue; - if (cdrom_drives[drive].bus_type != CDROM_BUS_DISABLED) { + if (cdrom[drive].bus_type != CDROM_BUS_DISABLED) { ptr = &sb_parts[sb_nparts++]; ptr->width = SB_ICON_WIDTH; ptr->tag = SB_CDROM | drive; @@ -660,9 +660,9 @@ ui_sb_reset(void) case SB_CDROM: /* CD-ROM */ drive = ptr->tag & 0x0f; - if (cdrom_drives[drive].host_drive == 200) { - ptr->flags = (wcslen(cdrom_image[drive].image_path) == 0) ? ICON_EMPTY : 0; - } else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { + if (cdrom[drive].host_drive == 200) { + ptr->flags = (wcslen(cdrom[drive].image_path) == 0) ? ICON_EMPTY : 0; + } else if ((cdrom[drive].host_drive >= 'A') && (cdrom[drive].host_drive <= 'Z')) { ptr->flags = 0; } else { ptr->flags = ICON_EMPTY; @@ -797,9 +797,9 @@ ui_sb_menu_command(int idm, uint8_t tag) part = find_tag(SB_CDROM | drive); if (part == -1) break; - cdrom_drives[drive].sound_on ^= 1; + cdrom[drive].sound_on ^= 1; sb_menu_set_item(part, IDM_CDROM_MUTE | drive, - cdrom_drives[drive].sound_on); + cdrom[drive].sound_on); config_save(); sound_cd_stop(); break; @@ -820,37 +820,37 @@ ui_sb_menu_command(int idm, uint8_t tag) if (part == -1) break; /* Browse for a new image to use. */ - str = cdrom_image[drive].image_path; + str = cdrom[drive].image_path; if (! dlg_file(get_string(IDS_3922), str, temp, DLG_FILE_LOAD|DLG_FILE_RO)) break; /* Save current drive/pathname for later re-use. */ - cdrom_drives[drive].prev_host_drive = cdrom_drives[drive].host_drive; - if (! cdrom_image[drive].prev_image_path) - cdrom_image[drive].prev_image_path = (wchar_t *)mem_alloc(1024); - wcscpy(cdrom_image[drive].prev_image_path, str); + cdrom[drive].prev_host_drive = cdrom[drive].host_drive; + if (! cdrom[drive].prev_image_path) + cdrom[drive].prev_image_path = (wchar_t *)mem_alloc(1024); + wcscpy(cdrom[drive].prev_image_path, str); /* Close the current drive/pathname. */ - cdrom[drive]->handler->exit(drive); + cdrom[drive].ops->exit(&cdrom[drive]); cdrom_close_handler(drive); - memset(cdrom_image[drive].image_path, 0, sizeof(cdrom_image[drive].image_path)); + memset(cdrom[drive].image_path, 0, sizeof(cdrom[drive].image_path)); /* Now open new image. */ - image_open(drive, temp); + cdrom_image_open(&cdrom[drive], temp); /* Signal media change to the emulated machine. */ - cdrom_insert(cdrom[drive]); + cdrom_insert(drive); /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); - if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { + if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { sb_menu_set_item(part, - IDM_CDROM_HOST_DRIVE | drive | ((cdrom_drives[drive].host_drive - 'A') << 3), + IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), 0); } - cdrom_drives[drive].host_drive = (wcslen(cdrom_image[drive].image_path) == 0) ? 0 : 200; - if (cdrom_drives[drive].host_drive == 200) { + cdrom[drive].host_drive = (wcslen(cdrom[drive].image_path) == 0) ? 0 : 200; + if (cdrom[drive].host_drive == 200) { sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 1); ui_sb_icon_state(SB_CDROM | drive, 0); } else { @@ -870,33 +870,33 @@ ui_sb_menu_command(int idm, uint8_t tag) if (part == -1) break; new_cdrom_drive = i; - if (cdrom_drives[drive].host_drive == new_cdrom_drive) { + if (cdrom[drive].host_drive == new_cdrom_drive) { /* Switching to the same drive. Do nothing. */ break; } - cdrom_drives[drive].prev_host_drive = cdrom_drives[drive].host_drive; + cdrom[drive].prev_host_drive = cdrom[drive].host_drive; /* Close the current drive/pathname. */ - cdrom[drive]->handler->exit(drive); + cdrom[drive].ops->exit(&cdrom[drive]); cdrom_close_handler(drive); - memset(cdrom_image[drive].image_path, 0, sizeof(cdrom_image[drive].image_path)); + memset(cdrom[drive].image_path, 0, sizeof(cdrom[drive].image_path)); #ifdef USE_CDROM_IOCTL ioctl_open(drive, new_cdrom_drive); #endif /* Signal media change to the emulated machine. */ - cdrom_insert(cdrom[drive]); + cdrom_insert(drive); /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); - if ((cdrom_drives[drive].host_drive >= 'A') && - (cdrom_drives[drive].host_drive <= 'Z')) { - sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom_drives[drive].host_drive - 'A') << 3), 0); + if ((cdrom[drive].host_drive >= 'A') && + (cdrom[drive].host_drive <= 'Z')) { + sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), 0); } + cdrom[drive].host_drive = new_cdrom_drive; sb_menu_set_item(part, IDM_CDROM_IMAGE | drive, 0); - cdrom_drives[drive].host_drive = new_cdrom_drive; - sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom_drives[drive].host_drive - 'A') << 3), 1); + sb_menu_set_item(part, IDM_CDROM_HOST_DRIVE | drive | ((cdrom[drive].host_drive - 'A') << 3), 1); sb_menu_enable_item(part, IDM_CDROM_RELOAD | drive, 0); ui_sb_icon_state(SB_CDROM | drive, 0); ui_sb_tip_update(SB_CDROM | drive); diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 98eba4c..aeacb83 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.60 2018/10/06 +# Version: @(#)Makefile.mingw 1.0.61 2018/10/14 # # Author: Fred N. van Kempen, # @@ -652,10 +652,8 @@ USBOBJ := usb.o endif SCSIOBJ := scsi.o \ - scsi_device.o \ - scsi_disk.o \ - scsi_x54x.o \ - scsi_aha154x.o scsi_buslogic.o \ + scsi_device.o scsi_disk.o scsi_cdrom.o \ + scsi_x54x.o scsi_aha154x.o scsi_buslogic.o \ scsi_ncr5380.o scsi_ncr53c810.o NETOBJ := network.o \ diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index 41f5c93..08762aa 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.46 2018/10/05 +# Version: @(#)Makefile.VC 1.0.47 2018/10/14 # # Author: Fred N. van Kempen, # @@ -619,10 +619,8 @@ USBOBJ := usb.obj endif SCSIOBJ := scsi.obj \ - scsi_device.obj \ - scsi_disk.obj \ - scsi_x54x.obj \ - scsi_aha154x.obj scsi_buslogic.obj \ + scsi_device.obj scsi_disk.obj scsi_cdrom.obj \ + scsi_x54x.obj scsi_aha154x.obj scsi_buslogic.obj \ scsi_ncr5380.obj scsi_ncr53c810.obj NETOBJ := network.obj \ diff --git a/src/win/win.h b/src/win/win.h index 7f974a2..a48f03a 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -10,7 +10,7 @@ * only things used globally within the Windows platform; the * generic platform defintions are in the plat.h file. * - * Version: @(#)win.h 1.0.19 2018/10/01 + * Version: @(#)win.h 1.0.21 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -66,6 +66,9 @@ #define WM_RESET_D3D WM_USER+2 #define WM_SAVE_CFG WM_USER+3 #define WM_SHOW_CFG WM_USER+4 +#define WM_HARD_RESET WM_USER+5 +#define WM_SHUTDOWN WM_USER+6 +#define WM_CTRLALTDEL WM_USER+7 /* Status bar definitions. */ diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 717f916..d6dfd57 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -1340,10 +1340,8 @@ ioctl_hopen(uint8_t id) int -ioctl_open(uint8_t id, char d) +ioctl_open(cdrom_t *dev, char d) { - cdrom_t *dev = cdrom[id]; - sprintf(cdrom_ioctl[id].ioctl_path,"\\\\.\\%c:",d); pclog("IOCTL path: %s\n", cdrom_ioctl[id].ioctl_path); dev->disc_changed = 1; @@ -1365,7 +1363,7 @@ ioctl_open(uint8_t id, char d) void -ioctl_close(uint8_t id) +ioctl_close(cdrom_t *dev) { if (cdrom_ioctl_windows[id].is_playing) return; @@ -1377,10 +1375,8 @@ ioctl_close(uint8_t id) static void -ioctl_exit(uint8_t id) +ioctl_exit(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - cdrom_ioctl_windows[id].is_playing = 0; ioctl_stop(id); @@ -1389,7 +1385,7 @@ ioctl_exit(uint8_t id) } -static CDROM ioctl_cdrom = { +static cdrom_ops_t cdrom_ioctl_ops = { ioctl_ready, ioctl_medium_changed, ioctl_media_type_id, diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 29ac6ad..6752f44 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings.c 1.0.34 2018/10/05 + * Version: @(#)win_settings.c 1.0.35 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -129,7 +129,7 @@ static int temp_fdd_types[FDD_NUM], static hard_disk_t temp_hdd[HDD_NUM]; /* Other removable devices category. */ -static cdrom_drive_t temp_cdrom_drives[CDROM_NUM]; +static cdrom_t temp_cdrom_drives[CDROM_NUM]; static zip_drive_t temp_zip_drives[ZIP_NUM]; @@ -242,7 +242,7 @@ settings_init(void) memcpy(temp_hdd, hdd, HDD_NUM * sizeof(hard_disk_t)); /* Other removable devices category */ - memcpy(temp_cdrom_drives, cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + memcpy(temp_cdrom_drives, cdrom, CDROM_NUM * sizeof(cdrom_t)); memcpy(temp_zip_drives, zip_drives, ZIP_NUM * sizeof(zip_drive_t)); temp_deviceconfig = 0; @@ -319,7 +319,7 @@ settings_changed(void) } /* Other removable devices category */ - i = i || memcmp(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + i = i || memcmp(cdrom, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_t)); i = i || memcmp(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); i = i || !!temp_deviceconfig; @@ -423,7 +423,7 @@ settings_save(void) } /* Removable devices category */ - memcpy(cdrom_drives, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_drive_t)); + memcpy(cdrom, temp_cdrom_drives, CDROM_NUM * sizeof(cdrom_t)); memcpy(zip_drives, temp_zip_drives, ZIP_NUM * sizeof(zip_drive_t)); /* Mark configuration as changed. */ diff --git a/src/win/win_settings_disk.h b/src/win/win_settings_disk.h index 1cca1e1..0756c86 100644 --- a/src/win/win_settings_disk.h +++ b/src/win/win_settings_disk.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_disk.h 1.0.15 2018/10/07 + * Version: @(#)win_settings_disk.h 1.0.16 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -75,13 +75,13 @@ disk_track_init(void) for (i = 0; i < HDD_NUM; i++) { if (hdd[i].bus == HDD_BUS_ST506) - st506_tracking |= (1ULL << (hdd[i].id.st506_channel << 3)); + st506_tracking |= (1ULL << (hdd[i].bus_id.st506_channel << 3)); else if (hdd[i].bus == HDD_BUS_ESDI) - esdi_tracking |= (1ULL << (hdd[i].id.esdi_channel << 3)); + esdi_tracking |= (1ULL << (hdd[i].bus_id.esdi_channel << 3)); else if (hdd[i].bus == HDD_BUS_IDE) - ide_tracking |= (1ULL << (hdd[i].id.ide_channel << 3)); + ide_tracking |= (1ULL << (hdd[i].bus_id.ide_channel << 3)); else if (hdd[i].bus == HDD_BUS_SCSI) - scsi_tracking[hdd[i].id.scsi.id] |= (1ULL << (hdd[i].id.scsi.lun << 3)); + scsi_tracking[hdd[i].bus_id.scsi.id] |= (1ULL << (hdd[i].bus_id.scsi.lun << 3)); } } @@ -302,8 +302,8 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - temp_hdd[hdlv_current_sel].id.st506_channel = next_free_binary_channel(&st506_tracking); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.st506_channel : temp_hdd[hdlv_current_sel].id.st506_channel, 0); + temp_hdd[hdlv_current_sel].bus_id.st506_channel = next_free_binary_channel(&st506_tracking); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.bus_id.st506_channel : temp_hdd[hdlv_current_sel].bus_id.st506_channel, 0); break; case HDD_BUS_ESDI: /* ESDI */ @@ -315,8 +315,8 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - temp_hdd[hdlv_current_sel].id.esdi_channel = next_free_binary_channel(&esdi_tracking); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.esdi_channel : temp_hdd[hdlv_current_sel].id.esdi_channel, 0); + temp_hdd[hdlv_current_sel].bus_id.esdi_channel = next_free_binary_channel(&esdi_tracking); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.bus_id.esdi_channel : temp_hdd[hdlv_current_sel].bus_id.esdi_channel, 0); break; case HDD_BUS_IDE: /* IDE */ @@ -328,8 +328,8 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - temp_hdd[hdlv_current_sel].id.ide_channel = next_free_ide_channel(); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.ide_channel : temp_hdd[hdlv_current_sel].id.ide_channel, 0); + temp_hdd[hdlv_current_sel].bus_id.ide_channel = next_free_ide_channel(); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.bus_id.ide_channel : temp_hdd[hdlv_current_sel].bus_id.ide_channel, 0); break; case HDD_BUS_SCSI: /* SCSI */ @@ -341,17 +341,17 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) EnableWindow(h, TRUE); if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_hdd[hdlv_current_sel].id.scsi.id, (uint8_t *) &temp_hdd[hdlv_current_sel].id.scsi.lun); + next_free_scsi_id_and_lun((uint8_t *) &temp_hdd[hdlv_current_sel].bus_id.scsi.id, (uint8_t *) &temp_hdd[hdlv_current_sel].bus_id.scsi.lun); h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.scsi.id : temp_hdd[hdlv_current_sel].id.scsi.id, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.bus_id.scsi.id : temp_hdd[hdlv_current_sel].bus_id.scsi.id, 0); h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); - SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.scsi.lun : temp_hdd[hdlv_current_sel].id.scsi.lun, 0); + SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.bus_id.scsi.lun : temp_hdd[hdlv_current_sel].bus_id.scsi.lun, 0); break; case HDD_BUS_USB: /* USB */ @@ -458,29 +458,29 @@ disk_update_item(HWND hwndList, int i, int column) case HDD_BUS_ST506: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.st506_channel >> 1, - temp_hdd[i].id.st506_channel & 1); + temp_hdd[i].bus_id.st506_channel >> 1, + temp_hdd[i].bus_id.st506_channel & 1); break; case HDD_BUS_ESDI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.esdi_channel >> 1, - temp_hdd[i].id.esdi_channel & 1); + temp_hdd[i].bus_id.esdi_channel >> 1, + temp_hdd[i].bus_id.esdi_channel & 1); break; case HDD_BUS_IDE: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.ide_channel >> 1, - temp_hdd[i].id.ide_channel & 1); + temp_hdd[i].bus_id.ide_channel >> 1, + temp_hdd[i].bus_id.ide_channel & 1); break; case HDD_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.scsi.id, - temp_hdd[i].id.scsi.lun); + temp_hdd[i].bus_id.scsi.id, + temp_hdd[i].bus_id.scsi.lun); break; case HDD_BUS_USB: @@ -549,29 +549,29 @@ disk_recalc_list(HWND hwndList) case HDD_BUS_ST506: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.st506_channel >> 1, - temp_hdd[i].id.st506_channel & 1); + temp_hdd[i].bus_id.st506_channel >> 1, + temp_hdd[i].bus_id.st506_channel & 1); break; case HDD_BUS_ESDI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.esdi_channel >> 1, - temp_hdd[i].id.esdi_channel & 1); + temp_hdd[i].bus_id.esdi_channel >> 1, + temp_hdd[i].bus_id.esdi_channel & 1); break; case HDD_BUS_IDE: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.ide_channel >> 1, - temp_hdd[i].id.ide_channel & 1); + temp_hdd[i].bus_id.ide_channel >> 1, + temp_hdd[i].bus_id.ide_channel & 1); break; case HDD_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", hdd_bus_to_ids(temp_hdd[i].bus), - temp_hdd[i].id.scsi.id, - temp_hdd[i].id.scsi.lun); + temp_hdd[i].bus_id.scsi.id, + temp_hdd[i].bus_id.scsi.lun); break; case HDD_BUS_USB: @@ -909,11 +909,11 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); SendMessage(h, CB_SETCURSEL, channel, 0); - new_hdd.id.st506_channel = next_free_binary_channel(&st506_tracking); - new_hdd.id.esdi_channel = next_free_binary_channel(&esdi_tracking); - new_hdd.id.ide_channel = channel; - new_hdd.id.scsi.id = id; - new_hdd.id.scsi.lun = lun; + new_hdd.bus_id.st506_channel = next_free_binary_channel(&st506_tracking); + new_hdd.bus_id.esdi_channel = next_free_binary_channel(&esdi_tracking); + new_hdd.bus_id.ide_channel = channel; + new_hdd.bus_id.scsi.id = id; + new_hdd.bus_id.scsi.lun = lun; #ifdef USE_REMOVABLE_DISK } #endif @@ -979,24 +979,24 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch(hdd_ptr->bus) { case HDD_BUS_ST506: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdd_ptr->id.st506_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + hdd_ptr->bus_id.st506_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; case HDD_BUS_ESDI: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); - hdd_ptr->id.esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + hdd_ptr->bus_id.esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; case HDD_BUS_IDE: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); - hdd_ptr->id.ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + hdd_ptr->bus_id.ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; case HDD_BUS_SCSI: h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); - hdd_ptr->id.scsi.id = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + hdd_ptr->bus_id.scsi.id = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); - hdd_ptr->id.scsi.lun = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + hdd_ptr->bus_id.scsi.lun = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; case HDD_BUS_USB: @@ -1524,19 +1524,19 @@ disk_track(uint8_t id) { switch(temp_hdd[id].bus) { case HDD_BUS_ST506: - st506_tracking |= (1ULL << (temp_hdd[id].id.st506_channel << 3)); + st506_tracking |= (1ULL << (temp_hdd[id].bus_id.st506_channel << 3)); break; case HDD_BUS_ESDI: - esdi_tracking |= (1ULL << (temp_hdd[id].id.esdi_channel << 3)); + esdi_tracking |= (1ULL << (temp_hdd[id].bus_id.esdi_channel << 3)); break; case HDD_BUS_IDE: - ide_tracking |= (1ULL << (temp_hdd[id].id.ide_channel << 3)); + ide_tracking |= (1ULL << (temp_hdd[id].bus_id.ide_channel << 3)); break; case HDD_BUS_SCSI: - scsi_tracking[temp_hdd[id].id.scsi.id] |= (1ULL << (temp_hdd[id].id.scsi.lun << 3)); + scsi_tracking[temp_hdd[id].bus_id.scsi.id] |= (1ULL << (temp_hdd[id].bus_id.scsi.lun << 3)); break; } } @@ -1547,19 +1547,19 @@ disk_untrack(uint8_t id) { switch(temp_hdd[id].bus) { case HDD_BUS_ST506: - st506_tracking &= ~(1 << (temp_hdd[id].id.st506_channel << 3)); + st506_tracking &= ~(1 << (temp_hdd[id].bus_id.st506_channel << 3)); break; case HDD_BUS_ESDI: - esdi_tracking &= ~(1 << (temp_hdd[id].id.esdi_channel << 3)); + esdi_tracking &= ~(1 << (temp_hdd[id].bus_id.esdi_channel << 3)); break; case HDD_BUS_IDE: - ide_tracking &= ~(1 << (temp_hdd[id].id.ide_channel << 3)); + ide_tracking &= ~(1 << (temp_hdd[id].bus_id.ide_channel << 3)); break; case HDD_BUS_SCSI: - scsi_tracking[temp_hdd[id].id.scsi.id] &= ~(1 << (temp_hdd[id].id.scsi.lun << 3)); + scsi_tracking[temp_hdd[id].bus_id.scsi.id] &= ~(1 << (temp_hdd[id].bus_id.scsi.lun << 3)); break; } } @@ -1679,9 +1679,9 @@ hd_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); disk_untrack(hdlv_current_sel); if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_ST506) - temp_hdd[hdlv_current_sel].id.st506_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + temp_hdd[hdlv_current_sel].bus_id.st506_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; else if (temp_hdd[hdlv_current_sel].bus == HDD_BUS_ESDI) - temp_hdd[hdlv_current_sel].id.esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + temp_hdd[hdlv_current_sel].bus_id.esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; disk_track(hdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); disk_update_item(h, hdlv_current_sel, 0); @@ -1695,7 +1695,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].id.ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + temp_hdd[hdlv_current_sel].bus_id.ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; disk_track(hdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); disk_update_item(h, hdlv_current_sel, 0); @@ -1709,7 +1709,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].id.scsi.id = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + temp_hdd[hdlv_current_sel].bus_id.scsi.id = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; disk_track(hdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); disk_update_item(h, hdlv_current_sel, 0); @@ -1723,7 +1723,7 @@ hd_bus_skip: ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].id.scsi.lun = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + temp_hdd[hdlv_current_sel].bus_id.scsi.lun = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; disk_track(hdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); disk_update_item(h, hdlv_current_sel, 0); diff --git a/src/win/win_settings_remov.h b/src/win/win_settings_remov.h index 6bbabff..895f5c6 100644 --- a/src/win/win_settings_remov.h +++ b/src/win/win_settings_remov.h @@ -8,7 +8,7 @@ * * Implementation of the "Removable Devices" dialog. * - * Version: @(#)win_settings_remov.h 1.0.8 2018/09/19 + * Version: @(#)win_settings_remov.h 1.0.9 2018/10/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,10 +54,10 @@ cdrom_track_init(void) int i; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) - ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); - else if (cdrom_drives[i].bus_type == CDROM_BUS_SCSI) - scsi_tracking[cdrom_drives[i].scsi_device_id] |= (2 << (cdrom_drives[i].scsi_device_lun << 3)); + if (cdrom[i].bus_type == CDROM_BUS_ATAPI) + ide_tracking |= (2 << (cdrom[i].bus_id.ide_channel << 3)); + else if (cdrom[i].bus_type == CDROM_BUS_SCSI) + scsi_tracking[cdrom[i].bus_id.scsi.id] |= (2 << (cdrom[i].bus_id.scsi.lun << 3)); } } @@ -131,8 +131,8 @@ cdrom_recalc_list(HWND hwndList) case CDROM_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), - temp_cdrom_drives[i].ide_channel >> 1, - temp_cdrom_drives[i].ide_channel & 1); + temp_cdrom_drives[i].bus_id.ide_channel >> 1, + temp_cdrom_drives[i].bus_id.ide_channel & 1); lvI.pszText = temp; lvI.iImage = 1; break; @@ -140,8 +140,8 @@ cdrom_recalc_list(HWND hwndList) case CDROM_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", get_string(combo_to_string(fsid)), - temp_cdrom_drives[i].scsi_device_id, - temp_cdrom_drives[i].scsi_device_lun); + temp_cdrom_drives[i].bus_id.scsi.id, + temp_cdrom_drives[i].bus_id.scsi.lun); lvI.pszText = temp; lvI.iImage = 1; break; @@ -236,8 +236,8 @@ cdrom_update_item(HWND hwndList, int i) case CDROM_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), - temp_cdrom_drives[i].ide_channel >> 1, - temp_cdrom_drives[i].ide_channel & 1); + temp_cdrom_drives[i].bus_id.ide_channel >> 1, + temp_cdrom_drives[i].bus_id.ide_channel & 1); lvI.pszText = temp; lvI.iImage = 1; break; @@ -245,8 +245,8 @@ cdrom_update_item(HWND hwndList, int i) case CDROM_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", get_string(combo_to_string(fsid)), - temp_cdrom_drives[i].scsi_device_id, - temp_cdrom_drives[i].scsi_device_lun); + temp_cdrom_drives[i].bus_id.scsi.id, + temp_cdrom_drives[i].bus_id.scsi.lun); lvI.pszText = temp; lvI.iImage = 1; break; @@ -343,13 +343,13 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - temp_cdrom_drives[cdlv_current_sel].ide_channel = next_free_ide_channel(); + temp_cdrom_drives[cdlv_current_sel].bus_id.ide_channel = next_free_ide_channel(); h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_cdrom_drives[cdlv_current_sel].ide_channel, 0); + temp_cdrom_drives[cdlv_current_sel].bus_id.ide_channel, 0); break; case CDROM_BUS_SCSI: @@ -360,19 +360,19 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_cdrom_drives[cdlv_current_sel].scsi_device_id, (uint8_t *) &temp_cdrom_drives[cdlv_current_sel].scsi_device_lun); + next_free_scsi_id_and_lun((uint8_t *) &temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.id, (uint8_t *) &temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.lun); h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_cdrom_drives[cdlv_current_sel].scsi_device_id, 0); + temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.id, 0); h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_cdrom_drives[cdlv_current_sel].scsi_device_lun, 0); + temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.lun, 0); break; } } @@ -382,9 +382,9 @@ static void cdrom_track(uint8_t id) { if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) - ide_tracking |= (2 << (temp_cdrom_drives[id].ide_channel << 3)); + ide_tracking |= (2 << (temp_cdrom_drives[id].bus_id.ide_channel << 3)); else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom_drives[id].scsi_device_id] |= (1ULL << temp_cdrom_drives[id].scsi_device_lun); + scsi_tracking[temp_cdrom_drives[id].bus_id.scsi.id] |= (1ULL << temp_cdrom_drives[id].bus_id.scsi.lun); } @@ -392,9 +392,9 @@ static void cdrom_untrack(uint8_t id) { if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) - ide_tracking &= ~(2 << (temp_cdrom_drives[id].ide_channel << 3)); + ide_tracking &= ~(2 << (temp_cdrom_drives[id].bus_id.ide_channel << 3)); else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - scsi_tracking[temp_cdrom_drives[id].scsi_device_id] &= ~(1ULL << temp_cdrom_drives[id].scsi_device_lun); + scsi_tracking[temp_cdrom_drives[id].bus_id.scsi.id] &= ~(1ULL << temp_cdrom_drives[id].bus_id.scsi.lun); } @@ -417,9 +417,9 @@ zip_track_init(void) for (i = 0; i < ZIP_NUM; i++) { if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) - ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); + ide_tracking |= (4 << (zip_drives[i].bus_id.ide_channel << 3)); else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) - scsi_tracking[zip_drives[i].scsi_device_id] |= (4 << (zip_drives[i].scsi_device_lun << 3)); + scsi_tracking[zip_drives[i].bus_id.scsi.id] |= (4 << (zip_drives[i].bus_id.scsi.lun << 3)); } } @@ -470,8 +470,8 @@ zip_recalc_list(HWND hwndList) case ZIP_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), - temp_zip_drives[i].ide_channel >> 1, - temp_zip_drives[i].ide_channel & 1); + temp_zip_drives[i].bus_id.ide_channel >> 1, + temp_zip_drives[i].bus_id.ide_channel & 1); lvI.pszText = temp; lvI.iImage = 1; break; @@ -479,8 +479,8 @@ zip_recalc_list(HWND hwndList) case ZIP_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", get_string(combo_to_string(fsid)), - temp_zip_drives[i].scsi_device_id, - temp_zip_drives[i].scsi_device_lun); + temp_zip_drives[i].bus_id.scsi.id, + temp_zip_drives[i].bus_id.scsi.lun); lvI.pszText = temp; lvI.iImage = 1; break; @@ -569,8 +569,8 @@ zip_update_item(HWND hwndList, int i) case ZIP_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), - temp_zip_drives[i].ide_channel >> 1, - temp_zip_drives[i].ide_channel & 1); + temp_zip_drives[i].bus_id.ide_channel >> 1, + temp_zip_drives[i].bus_id.ide_channel & 1); lvI.pszText = temp; lvI.iImage = 1; break; @@ -578,8 +578,8 @@ zip_update_item(HWND hwndList, int i) case ZIP_BUS_SCSI: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", get_string(combo_to_string(fsid)), - temp_zip_drives[i].scsi_device_id, - temp_zip_drives[i].scsi_device_lun); + temp_zip_drives[i].bus_id.scsi.id, + temp_zip_drives[i].bus_id.scsi.lun); lvI.pszText = temp; lvI.iImage = 1; break; @@ -653,13 +653,13 @@ zip_recalc_location_controls(HWND hdlg, int assign_id) EnableWindow(h, TRUE); if (assign_id) - temp_zip_drives[zdlv_current_sel].ide_channel = next_free_ide_channel(); + temp_zip_drives[zdlv_current_sel].bus_id.ide_channel = next_free_ide_channel(); h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_zip_drives[zdlv_current_sel].ide_channel, 0); + temp_zip_drives[zdlv_current_sel].bus_id.ide_channel, 0); break; case ZIP_BUS_SCSI: @@ -670,19 +670,19 @@ zip_recalc_location_controls(HWND hdlg, int assign_id) ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); if (assign_id) - next_free_scsi_id_and_lun((uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_id, (uint8_t *) &temp_zip_drives[zdlv_current_sel].scsi_device_lun); + next_free_scsi_id_and_lun((uint8_t *) &temp_zip_drives[zdlv_current_sel].bus_id.scsi.id, (uint8_t *) &temp_zip_drives[zdlv_current_sel].bus_id.scsi.lun); h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_zip_drives[zdlv_current_sel].scsi_device_id, 0); + temp_zip_drives[zdlv_current_sel].bus_id.scsi.id, 0); h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, - temp_zip_drives[zdlv_current_sel].scsi_device_lun, 0); + temp_zip_drives[zdlv_current_sel].bus_id.scsi.lun, 0); break; } } @@ -692,9 +692,9 @@ static void zip_track(uint8_t id) { if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) - ide_tracking |= (1ULL << temp_zip_drives[id].ide_channel); + ide_tracking |= (1ULL << temp_zip_drives[id].bus_id.ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id] |= (1ULL << temp_zip_drives[id].scsi_device_lun); + scsi_tracking[temp_zip_drives[id].bus_id.scsi.id] |= (1ULL << temp_zip_drives[id].bus_id.scsi.lun); } @@ -702,9 +702,9 @@ static void zip_untrack(uint8_t id) { if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) - ide_tracking &= ~(1ULL << temp_zip_drives[id].ide_channel); + ide_tracking &= ~(1ULL << temp_zip_drives[id].bus_id.ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) - scsi_tracking[temp_zip_drives[id].scsi_device_id] &= ~(1ULL << temp_zip_drives[id].scsi_device_lun); + scsi_tracking[temp_zip_drives[id].bus_id.scsi.id] &= ~(1ULL << temp_zip_drives[id].bus_id.scsi.lun); } @@ -846,7 +846,7 @@ cdrom_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); cdrom_untrack(cdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_cdrom_drives[cdlv_current_sel].scsi_device_id = (uint8_t)b; + temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.id = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -861,7 +861,7 @@ cdrom_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); cdrom_untrack(cdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_cdrom_drives[cdlv_current_sel].scsi_device_lun = (uint8_t)b; + temp_cdrom_drives[cdlv_current_sel].bus_id.scsi.lun = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -876,7 +876,7 @@ cdrom_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); cdrom_untrack(cdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_cdrom_drives[cdlv_current_sel].ide_channel = (uint8_t)b; + temp_cdrom_drives[cdlv_current_sel].bus_id.ide_channel = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -924,7 +924,7 @@ zip_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); zip_untrack(zdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_zip_drives[zdlv_current_sel].scsi_device_id = (uint8_t)b; + temp_zip_drives[zdlv_current_sel].bus_id.scsi.id = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); @@ -939,7 +939,7 @@ zip_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); zip_untrack(zdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_zip_drives[zdlv_current_sel].scsi_device_lun = (uint8_t)b; + temp_zip_drives[zdlv_current_sel].bus_id.scsi.lun = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); @@ -954,7 +954,7 @@ zip_bus_skip: h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); zip_untrack(zdlv_current_sel); b = SendMessage(h, CB_GETCURSEL, 0, 0); - temp_zip_drives[zdlv_current_sel].ide_channel = (uint8_t)b; + temp_zip_drives[zdlv_current_sel].bus_id.ide_channel = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 5f5c271..4af0869 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * Implement the user Interface module. * - * Version: @(#)win_ui.c 1.0.27 2018/10/07 + * Version: @(#)win_ui.c 1.0.29 2018/10/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -474,6 +474,18 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) menu_set_item(IDM_PAUSE, dopause); break; + case WM_HARD_RESET: + pc_reset(1); + break; + + case WM_CTRLALTDEL: + pc_reset(0); + break; + + case WM_SHUTDOWN: + PostQuitMessage(0); + break; + case WM_SYSCOMMAND: /* * Disable ALT key *ALWAYS*,