Added the IBM 5161 ISA expansion for PC and XT;

Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g  / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
This commit is contained in:
OBattler
2019-09-20 14:02:30 +02:00
parent b06296bbf6
commit 552a87ea3d
524 changed files with 129555 additions and 21862 deletions

View File

@@ -9,11 +9,11 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)scsi_cdrom.c 1.0.69 2018/11/11
* Version: @(#)scsi_cdrom.c 1.0.70 2019/03/11
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2016-2019 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
@@ -83,7 +83,8 @@ const uint8_t scsi_cdrom_command_flags[0x100] =
IMPLEMENTED | CHECK_READY, /* 0x1E */
0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */
IMPLEMENTED | CHECK_READY, /* 0x25 */
0, 0, /* 0x26-0x27 */
0 /*IMPLEMENTED | CHECK_READY | SCSI_ONLY*/,
0, /* 0x26-0x27 */
IMPLEMENTED | CHECK_READY, /* 0x28 */
0, 0, /* 0x29-0x2A */
IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */
@@ -139,9 +140,12 @@ const uint8_t scsi_cdrom_command_flags[0x100] =
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, /* 0xC0 */
0, /* 0xC1 */
IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */
0, 0, 0, /* 0xC3-0xC5 */
IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC6 */
0, 0, 0, 0, 0, 0, /* 0xC7-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 */
@@ -331,7 +335,7 @@ scsi_cdrom_log(const char *format, ...)
static void
scsi_cdrom_set_callback(scsi_cdrom_t *dev)
{
if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI))
if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI && dev->drv->bus_type != CDROM_BUS_SCSI_CHINON))
ide_set_callback(dev->drv->ide_channel >> 1, dev->callback);
}
@@ -370,7 +374,7 @@ scsi_cdrom_init(scsi_cdrom_t *dev)
static int
scsi_cdrom_current_mode(scsi_cdrom_t *dev)
{
if (dev->drv->bus_type == CDROM_BUS_SCSI)
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
return 2;
else if (dev->drv->bus_type == CDROM_BUS_ATAPI) {
scsi_cdrom_log("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id,
@@ -444,7 +448,7 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev)
memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, sizeof(mode_sense_pages_t));
memset(file_name, 0, 512 * sizeof(wchar_t));
if (dev->drv->bus_type == CDROM_BUS_SCSI)
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
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);
@@ -604,8 +608,8 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len)
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 */
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
dev->callback = -1.0; /* Speed depends on SCSI controller */
return 0.0;
} else {
/* TODO: Get the actual selected speed from IDE. */
@@ -621,17 +625,16 @@ 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;
dev->callback = 0;
scsi_cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed);
if (dev->packet_status == PHASE_COMPLETE)
dev->callback = 0LL;
dev->callback = 0;
else {
switch(dev->current_cdb[0]) {
case GPCMD_REZERO_UNIT:
@@ -640,9 +643,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
/* Seek time is in us. */
period = cdrom_seek_time(dev->drv);
scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n",
dev->id, (int64_t) period);
period = period * ((double) TIMER_USEC);
dev->callback += ((int64_t) period);
dev->id, (uint64_t) period);
dev->callback += period;
scsi_cdrom_set_callback(dev);
return;
case 0x08:
@@ -651,9 +653,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
/* Seek time is in us. */
period = cdrom_seek_time(dev->drv);
scsi_cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n",
dev->id, (int64_t) period);
period = period * ((double) TIMER_USEC);
dev->callback += ((int64_t) period);
dev->id, (uint64_t) period);
dev->callback += period;
/*FALLTHROUGH*/
case 0x25:
case 0x42:
@@ -666,7 +667,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
case 0xb9:
case 0xbe:
if (dev->current_cdb[0] == 0x42)
dev->callback += 200LL * CDROM_TIME;
dev->callback += 200.0 * CDROM_TIME;
/* Account for seek time. */
bytes_per_second = 176.0 * 1024.0;
bytes_per_second *= (double) dev->drv->cur_speed;
@@ -674,18 +675,17 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev)
default:
bytes_per_second = scsi_cdrom_bus_speed(dev);
if (bytes_per_second == 0.0) {
dev->callback = -1LL; /* Speed depends on SCSI controller */
dev->callback = -1; /* Speed depends on SCSI controller */
return;
}
break;
}
period = 1000000.0 / bytes_per_second;
scsi_cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period);
scsi_cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period);
period = period * (double) (dev->packet_len);
scsi_cdrom_log("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_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period);
dev->callback += period;
}
scsi_cdrom_set_callback(dev);
}
@@ -745,13 +745,13 @@ static void scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block
len = alloc_len;
}
if ((len == 0) || (scsi_cdrom_current_mode(dev) == 0)) {
if (dev->drv->bus_type != CDROM_BUS_SCSI)
if (dev->drv->bus_type != CDROM_BUS_SCSI && dev->drv->bus_type != CDROM_BUS_SCSI_CHINON)
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)
if (dev->drv->bus_type != CDROM_BUS_SCSI && dev->drv->bus_type != CDROM_BUS_SCSI_CHINON)
dev->packet_len = alloc_len;
if (direction == 0)
@@ -784,7 +784,7 @@ scsi_cdrom_set_phase(scsi_cdrom_t *dev, uint8_t phase)
{
uint8_t scsi_id = dev->drv->scsi_device_id;
if (dev->drv->bus_type != CDROM_BUS_SCSI)
if (dev->drv->bus_type != CDROM_BUS_SCSI && dev->drv->bus_type != CDROM_BUS_SCSI_CHINON)
return;
scsi_devices[scsi_id].phase = phase;
@@ -802,7 +802,7 @@ scsi_cdrom_cmd_error(scsi_cdrom_t *dev)
dev->phase = 3;
dev->pos = 0;
dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * CDROM_TIME;
dev->callback = 50.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq);
}
@@ -819,7 +819,7 @@ scsi_cdrom_unit_attention(scsi_cdrom_t *dev)
dev->phase = 3;
dev->pos = 0;
dev->packet_status = PHASE_ERROR;
dev->callback = 50LL * CDROM_TIME;
dev->callback = 50.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_log("CD-ROM %i: UNIT ATTENTION\n", dev->id);
}
@@ -948,63 +948,6 @@ scsi_cdrom_data_phase_error(scsi_cdrom_t *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)
{
@@ -1023,15 +966,20 @@ scsi_cdrom_read_data(scsi_cdrom_t *dev, int msf, int type, int flags, int32_t *l
scsi_cdrom_log("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;
return -1;
}
/* FIXME: Temporarily disabled this because the Triones ATAPI DMA driver seems to
always request a 4-sector read but sets the DMA bus master to transfer less
data than that. */
#if 0
if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) {
scsi_cdrom_log("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;
return -1;
}
#endif
dev->old_len = 0;
*len = 0;
@@ -1079,13 +1027,13 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev, int32_t *len, int first_batch)
scsi_cdrom_log("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);
scsi_cdrom_log("Read %i bytes of blocks...\n", *len);
if (!ret || ((dev->old_len != *len) && !first_batch)) {
if (ret == -1)
return 0;
else if (!ret || ((dev->old_len != *len) && !first_batch)) {
if ((dev->old_len != *len) && !first_batch)
scsi_cdrom_illegal_mode(dev);
@@ -1234,7 +1182,7 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb)
{
int ready = 0;
if (dev->drv->bus_type == CDROM_BUS_SCSI) {
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) {
scsi_cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n",
dev->id, ((dev->request_length >> 5) & 7));
@@ -1245,7 +1193,7 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb)
if (!(scsi_cdrom_command_flags[cdb[0]] & IMPLEMENTED)) {
scsi_cdrom_log("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");
(dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) ? "SCSI" : "ATAPI");
scsi_cdrom_illegal_opcode(dev);
return 0;
@@ -1257,7 +1205,7 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb)
return 0;
}
if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) {
if ((dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) && (scsi_cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) {
scsi_cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]);
scsi_cdrom_illegal_opcode(dev);
return 0;
@@ -1340,7 +1288,7 @@ scsi_cdrom_reset(scsi_common_t *sc)
scsi_cdrom_rezero(dev);
dev->status = 0;
dev->callback = 0LL;
dev->callback = 0.0;
scsi_cdrom_set_callback(dev);
dev->phase = 1;
dev->request_length = 0xEB14;
@@ -1365,16 +1313,14 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt
buffer[12]=ASC_AUDIO_PLAY_OPERATION;
buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED;
} else if ((scsi_cdrom_sense_key == 0) && ((dev->drv->cd_status == CD_STATUS_PAUSED) ||
(dev->drv->cd_status >= CD_STATUS_PLAYING))) {
((dev->drv->cd_status >= CD_STATUS_PLAYING) && (dev->drv->cd_status != CD_STATUS_STOPPED)))) {
buffer[2]=SENSE_ILLEGAL_REQUEST;
buffer[12]=ASC_AUDIO_PLAY_OPERATION;
buffer[13]=(dev->drv->cd_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;
}
} 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;
}
scsi_cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]);
@@ -1413,7 +1359,7 @@ scsi_cdrom_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t al
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 (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
if (*BufLen == -1)
*BufLen = *src_len;
else {
@@ -1447,11 +1393,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
int real_pos, track = 0;
char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 };
char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
int32_t blen = 0, *BufLen;
char device_identify_chinon[9] = { 'C', 'D', 'S', '-', '4', '3', '1', ' ', 0 };
char device_identify_ex_chinon[15] = { 'C', 'D', 'S', '-', '4', '3', '1', ' ', ' ', 'H', '4', '2', ' ', ' ', 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) {
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
BufLen = &scsi_devices[dev->drv->scsi_device_id].buffer_length;
dev->status &= ~ERR_STAT;
} else {
@@ -1468,6 +1416,9 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
device_identify_ex[10] = EMU_VERSION[0];
device_identify_ex[12] = EMU_VERSION[2];
device_identify_ex[13] = EMU_VERSION[3];
device_identify_chinon[7] = dev->id + 0x30;
device_identify_ex_chinon[7] = dev->id + 0x30;
memcpy(dev->current_cdb, cdb, 12);
@@ -1513,7 +1464,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
if (!max_len) {
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * CDROM_TIME;
dev->callback = 20.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
break;
}
@@ -1598,6 +1549,8 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
switch(cdb[0]) {
case GPCMD_READ_6:
dev->sector_len = cdb[4];
if (dev->sector_len == 0)
dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */
dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]);
msf = 0;
break;
@@ -1638,7 +1591,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
/* scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); */
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * CDROM_TIME;
dev->callback = 20.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
break;
}
@@ -1657,7 +1610,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
if (ret <= 0) {
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20LL * CDROM_TIME;
dev->callback = 20.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_buf_free(dev);
return;
@@ -1708,7 +1661,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
case GPCMD_MODE_SENSE_10:
scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN);
if (dev->drv->bus_type == CDROM_BUS_SCSI)
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
else
block_desc = 0;
@@ -1855,7 +1808,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */
b[3] = 8;
if (dev->drv->bus_type == CDROM_BUS_SCSI)
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
b[7] = 1;
else
b[7] = 2;
@@ -1997,16 +1950,16 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
memset(dev->buffer, 0, 36);
dev->buffer[0] = 0;
dev->buffer[1] = 34;
dev->buffer[2] = 1; /* track number (LSB) */
dev->buffer[3] = 1; /* session number (LSB) */
dev->buffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
dev->buffer[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 */
dev->buffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
dev->buffer[2] = 1; /* track number (LSB) */
dev->buffer[3] = 1; /* session number (LSB) */
dev->buffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
dev->buffer[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 */
dev->buffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
dev->buffer[24] = (dev->drv->cdrom_capacity >> 24) & 0xff; /* track size */
dev->buffer[25] = (dev->drv->cdrom_capacity >> 16) & 0xff; /* track size */
dev->buffer[26] = (dev->drv->cdrom_capacity >> 8) & 0xff; /* track size */
dev->buffer[27] = dev->drv->cdrom_capacity & 0xff; /* track size */
dev->buffer[24] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff; /* track size */
dev->buffer[25] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff; /* track size */
dev->buffer[26] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff; /* track size */
dev->buffer[27] = (dev->drv->cdrom_capacity - 1) & 0xff; /* track size */
if (len > max_len) {
len = max_len;
@@ -2101,9 +2054,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
return;
}
switch(cdb[3]) {
if (!(cdb[2] & 0x40))
alloc_length = 4;
else switch(cdb[3]) {
case 0:
alloc_length = 4;
/* SCSI-2: Q-type subchannel, ATAPI: reserved */
alloc_length = (dev->drv->bus_type == CDROM_BUS_SCSI ||
dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) ? 48 : 4;
break;
case 1:
alloc_length = 16;
@@ -2113,36 +2070,38 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
break;
}
len = alloc_length;
memset(dev->buffer, 0, 24);
pos = 0;
dev->buffer[pos++] = 0;
dev->buffer[pos++] = 0; /*Audio status*/
dev->buffer[pos++] = 0; dev->buffer[pos++] = 0; /*Subchannel length*/
dev->buffer[pos++] = cdb[3] & 3; /*Format code*/
if (cdb[3] == 1) {
dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[5], msf);
/* Mode 0 = Q subchannel mode, first 16 bytes are indentical to mode 1 (current position),
the rest are stuff like ISRC etc., which can be all zeroes. */
if ((cdb[3] <= 3) && (alloc_length != 4)) {
dev->buffer[pos++] = cdb[3]; /*Format code*/
dev->buffer[1] = cdrom_get_current_subchannel(dev->drv, &dev->buffer[4], msf);
dev->buffer[2] = alloc_length - 4;
switch(dev->drv->cd_status) {
case CD_STATUS_PLAYING:
dev->buffer[1] = 0x11;
break;
case CD_STATUS_PAUSED:
dev->buffer[1] = 0x12;
dev->buffer[1] = dev->drv->bus_type == CDROM_BUS_SCSI_CHINON ? 0x15 : 0x12;
break;
case CD_STATUS_DATA_ONLY:
dev->buffer[1] = 0x15;
dev->buffer[1] = dev->drv->bus_type == CDROM_BUS_SCSI_CHINON ? 0x00 : 0x15;
break;
default:
dev->buffer[1] = 0x13;
dev->buffer[1] = dev->drv->bus_type == CDROM_BUS_SCSI_CHINON ? 0x00 : 0x13;
break;
}
scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[1]);
}
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);
@@ -2182,6 +2141,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
}
break;
case GPCMD_CHINON_STOP:
case 0x26:
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
scsi_cdrom_stop(sc);
scsi_cdrom_command_complete(dev);
break;
case GPCMD_START_STOP_UNIT:
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
@@ -2205,6 +2171,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
scsi_cdrom_command_complete(dev);
break;
case GPCMD_CHINON_EJECT:
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
scsi_cdrom_stop(sc);
cdrom_eject(dev->id);
scsi_cdrom_command_complete(dev);
break;
case GPCMD_INQUIRY:
scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN);
@@ -2249,9 +2222,16 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
dev->buffer[idx++] = 0x01;
dev->buffer[idx++] = 0x00;
dev->buffer[idx++] = 68;
ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */
if (dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
ide_padstr8(dev->buffer + idx, 8, "CHINON"); /* Vendor */
else
ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */
idx += 8;
ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */
if (dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
ide_padstr8(dev->buffer + idx, 40, device_identify_ex_chinon); /* Product */
else
ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */
idx += 40;
ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */
idx += 20;
@@ -2269,17 +2249,33 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
memset(dev->buffer, 0, 8);
dev->buffer[0] = 5; /*CD-ROM*/
dev->buffer[1] = 0x80; /*Removable*/
dev->buffer[2] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/
dev->buffer[3] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x21;
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
dev->buffer[2] = 0x02;
dev->buffer[3] = 0x02;
}
else {
dev->buffer[2] = 0x00;
dev->buffer[3] = 0x21;
}
dev->buffer[4] = 31;
if (dev->drv->bus_type == CDROM_BUS_SCSI) {
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
dev->buffer[6] = 1; /* 16-bit transfers supported */
dev->buffer[7] = 0x20; /* Wide bus supported */
}
ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */
ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */
ide_padstr8(dev->buffer + 32, 4, EMU_VERSION); /* Revision */
if (dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
ide_padstr8(dev->buffer + 8, 8, "CHINON"); /* Vendor */
ide_padstr8(dev->buffer + 16, 16, device_identify_chinon); /* Product */
ide_padstr8(dev->buffer + 32, 4, "H42 "); /* Revision */
}
else {
ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */
ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */
ide_padstr8(dev->buffer + 32, 4, EMU_VERSION); /* Revision */
}
idx = 36;
if (max_len == 96) {
@@ -2334,10 +2330,10 @@ atapi_out:
/* IMPORTANT: What's returned is the last LBA block. */
memset(dev->buffer, 0, 8);
dev->buffer[0] = (dev->drv->cdrom_capacity >> 24) & 0xff;
dev->buffer[1] = (dev->drv->cdrom_capacity >> 16) & 0xff;
dev->buffer[2] = (dev->drv->cdrom_capacity >> 8) & 0xff;
dev->buffer[3] = dev->drv->cdrom_capacity & 0xff;
dev->buffer[0] = ((dev->drv->cdrom_capacity - 1) >> 24) & 0xff;
dev->buffer[1] = ((dev->drv->cdrom_capacity - 1) >> 16) & 0xff;
dev->buffer[2] = ((dev->drv->cdrom_capacity - 1) >> 8) & 0xff;
dev->buffer[3] = (dev->drv->cdrom_capacity - 1) & 0xff;
dev->buffer[6] = 8;
len = 8;
@@ -2399,7 +2395,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc)
else
hdr_len = 4;
if (dev->drv->bus_type == CDROM_BUS_SCSI) {
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON) {
if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) {
block_desc_len = dev->buffer[2];
block_desc_len <<= 8;
@@ -2446,7 +2442,7 @@ scsi_cdrom_phase_data_out(scsi_common_t *sc)
pos += page_len;
if (dev->drv->bus_type == CDROM_BUS_SCSI)
if (dev->drv->bus_type == CDROM_BUS_SCSI || dev->drv->bus_type == CDROM_BUS_SCSI_CHINON)
val = scsi_cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80;
else
val = scsi_cdrom_mode_sense_pages_default.pages[page][0] & 0x80;
@@ -2576,7 +2572,7 @@ scsi_cdrom_drive_reset(int c)
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->scsi_device_id > SCSI_ID_MAX))
if ((drv->bus_type == CDROM_BUS_SCSI || drv->bus_type == CDROM_BUS_SCSI_CHINON) && (drv->scsi_device_id > SCSI_ID_MAX))
return;
/* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */
@@ -2599,7 +2595,7 @@ scsi_cdrom_drive_reset(int c)
scsi_cdrom_init(dev);
if (drv->bus_type == CDROM_BUS_SCSI) {
if (drv->bus_type == CDROM_BUS_SCSI || drv->bus_type == CDROM_BUS_SCSI_CHINON) {
/* SCSI CD-ROM, attach to the SCSI bus. */
sd = &scsi_devices[drv->scsi_device_id];
@@ -2614,7 +2610,7 @@ scsi_cdrom_drive_reset(int c)
scsi_cdrom_log("SCSI CD-ROM drive %i attached to SCSI ID %i\n", c, cdrom[c].scsi_device_id);
} else if (drv->bus_type == CDROM_BUS_ATAPI) {
/* ATAPI CD-ROM, attach to the IDE bus. */
id = ide_drives[drv->ide_channel];
id = ide_get_drive(drv->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. */