The AHA/BusLogic reset controllers' BIOS commands now return 0x80 (no device present error) for CD-ROM drives if the device is market as not supporting CD-ROM boot, fixes sending of WRITE (10) to CD-ROM drives followed by hang;

The CD-ROM and SCSI disk REQUEST SENSE commands no longer incorrectly set the phase to status;
REQUEST SENSE with non-data direction control byte is now treated as a request to send sense bytes from the command directly to the sense buffer;
SCSI and SLiRP threads now terminate themselves again when out of the while loop;
SCSI and SLiRP mutexes are now closed when the threads terminate themselves;
Fixed a bug causing the "Press F12+F8 or middle mouse button to release" string on the title bar to get corrupt.
This commit is contained in:
OBattler
2017-10-14 18:52:25 +02:00
parent 6eb9404d04
commit 7581474aab
8 changed files with 90 additions and 32 deletions

View File

@@ -2197,14 +2197,12 @@ void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
if ((cdrom_sense_key > 0) && ((cdrom[id].cd_status < CD_STATUS_PLAYING) || (cdrom[id].cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(id))
{
SCSIPhase = SCSI_PHASE_STATUS;
buffer[2]=SENSE_ILLEGAL_REQUEST;
buffer[12]=ASC_AUDIO_PLAY_OPERATION;
buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED;
}
else if ((cdrom_sense_key == 0) && (cdrom[id].cd_status >= CD_STATUS_PLAYING) && (cdrom[id].cd_status != CD_STATUS_STOPPED))
{
SCSIPhase = SCSI_PHASE_STATUS;
buffer[2]=SENSE_ILLEGAL_REQUEST;
buffer[12]=ASC_AUDIO_PLAY_OPERATION;
buffer[13]=(cdrom[id].cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED;
@@ -2213,7 +2211,6 @@ void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
{
if (cdrom[id].unit_attention && (cdrom_sense_key == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
buffer[2]=SENSE_UNIT_ATTENTION;
buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
buffer[13]=0;

View File

@@ -147,6 +147,8 @@ poll_thread(void *arg)
thread_destroy_event(evt);
evt = poll_tid = NULL;
thread_close_mutex(slirpMutex);
pclog("SLiRP: polling stopped.\n");
}

View File

@@ -753,7 +753,7 @@ pc_run(void)
mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1);
mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu].name,
strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu].name)+1);
swprintf(s, 100, L"%s v%s - %i%% - %s - %s - %s",
swprintf(s, 200, L"%ls v%ls - %i%% - %ls - %ls - %ls",
EMU_NAME_W, EMU_VERSION_W, fps, wmachine, wcpu,
(!mousecapture) ? plat_get_string(IDS_2077)
: ((mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)));

View File

@@ -225,7 +225,7 @@ aha_get_host_id(void *p)
{
x54x_t *dev = (x54x_t *)p;
return dev->nvr[0] & 3;
return dev->nvr[0] & 0x07;
}
@@ -234,7 +234,7 @@ aha_get_irq(void *p)
{
x54x_t *dev = (x54x_t *)p;
return (dev->nvr[1] & 0x0F) + 9;
return (dev->nvr[1] & 0x07) + 9;
}
@@ -243,7 +243,7 @@ aha_get_dma(void *p)
{
x54x_t *dev = (x54x_t *)p;
return (dev->nvr[1] & 0xF0) >> 4;
return (dev->nvr[1] >> 4) & 0x07;
}
@@ -628,9 +628,9 @@ aha_setbios(x54x_t *dev)
if (dev->bios_path == NULL) return;
/* Open the BIOS image file and make sure it exists. */
pclog("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path);
aha_log("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path);
if ((f = rom_fopen(dev->bios_path, L"rb")) == NULL) {
pclog("%s: BIOS ROM not found!\n", dev->name);
aha_log("%s: BIOS ROM not found!\n", dev->name);
return;
}
@@ -657,7 +657,7 @@ aha_setbios(x54x_t *dev)
dev->rom2 = NULL;
}
if (temp != 0) {
pclog("%s: BIOS ROM size invalid!\n", dev->name);
aha_log("%s: BIOS ROM size invalid!\n", dev->name);
free(dev->rom1);
if (dev->rom2 != NULL)
free(dev->rom2);
@@ -678,7 +678,7 @@ aha_setbios(x54x_t *dev)
if (temp <= 0x2000)
size = 0x2000;
mask = (size - 1);
pclog("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n",
aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n",
dev->name, dev->rom_addr, size, mask);
/* Initialize the ROM entry for this BIOS. */
@@ -711,7 +711,7 @@ aha_setbios(x54x_t *dev)
for (i=0; i<8; i++)
if (aha_ports[i] == dev->Base) break;
if (i == 8) {
pclog("%s: invalid I/O address %04x selected!\n",
aha_log("%s: invalid I/O address %04x selected!\n",
dev->name, dev->Base);
return;
}
@@ -791,6 +791,7 @@ aha_init(device_t *info)
dev->reset_duration = AHA_RESET_DURATION_US;
dev->max_id = 7;
dev->int_geom_writable = 0;
dev->cdrom_boot = 0;
dev->ven_thread = aha_thread;
dev->ven_cmd_is_fast = aha_cmd_is_fast;
@@ -845,6 +846,7 @@ aha_init(device_t *info)
dev->rom_shramsz = 128; /* size of shadow RAM */
dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */
dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */
dev->cdrom_boot = 1;
dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */
dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */
dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */

View File

@@ -1303,6 +1303,7 @@ buslogic_init(device_t *info)
dev->reset_duration = BUSLOGIC_RESET_DURATION_US;
dev->max_id = 7;
dev->int_geom_writable = 1;
dev->cdrom_boot = 0;
bl->chip = info->local;
bl->PCIBase = 0;
@@ -1375,6 +1376,7 @@ buslogic_init(device_t *info)
scam_rom_name = L"roms/scsi/buslogic/BT-958D_SCAM.rom";
scam_rom_size = 0x0200;
dev->fw_rev = "AA507B";
dev->cdrom_boot = 1;
break;
}

View File

@@ -1326,7 +1326,6 @@ void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
if (shdc[id].unit_attention && (scsi_hd_sense_key == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
buffer[2]=SENSE_UNIT_ATTENTION;
buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
buffer[13]=0x00;

View File

@@ -352,7 +352,7 @@ x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer)
/* This returns the completion code. */
static uint8_t
x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
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;
@@ -385,6 +385,12 @@ x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
return(0x80);
}
if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) {
x54x_log("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);
x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n",
@@ -451,6 +457,10 @@ x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
#endif
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (SCSIPhase == SCSI_PHASE_STATUS)
goto skip_read_phase1;
scsi_device_command_phase1(cmd->id, cmd->lun);
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
@@ -459,6 +469,7 @@ x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
(char *)dev->CmdBuffer, dev->BufferLength);
}
skip_read_phase1:
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
@@ -487,6 +498,9 @@ x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (SCSIPhase == SCSI_PHASE_STATUS)
goto skip_write_phase1;
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading %i bytes at %08X\n",
dev->BufferLength, dma_address);
@@ -496,6 +510,7 @@ x54x_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
scsi_device_command_phase1(cmd->id, cmd->lun);
skip_write_phase1:
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
dev->CmdBuffer = NULL;
@@ -957,6 +972,21 @@ ConvertSenseLength(uint8_t RequestSenseLength)
}
uint32_t
SenseBufferPointer(Req_t *req)
{
uint32_t SenseBufferAddress;
if (req->Is24bit) {
SenseBufferAddress = req->CCBPointer;
SenseBufferAddress += req->CmdBlock.common.CdbLength + 18;
} else {
SenseBufferAddress = req->CmdBlock.new.SensePointer;
}
return SenseBufferAddress;
}
static void
SenseBufferFree(Req_t *req, int Copy)
{
@@ -972,12 +1002,7 @@ SenseBufferFree(Req_t *req, int Copy)
* Sense Pointer of the CCB, but in 24-bit mode, it is
* located at the end of the Command Descriptor Block.
*/
if (req->Is24bit) {
SenseBufferAddress = req->CCBPointer;
SenseBufferAddress += req->CmdBlock.common.CdbLength + 18;
} else {
SenseBufferAddress = req->CmdBlock.new.SensePointer;
}
SenseBufferAddress = SenseBufferPointer(req);
x54x_log("Request Sense address: %02X\n", SenseBufferAddress);
@@ -1002,6 +1027,7 @@ x54x_scsi_cmd(x54x_t *dev)
uint8_t bit24 = !!req->Is24bit;
int32_t *BufLen;
uint8_t phase;
uint32_t SenseBufferAddress;
id = req->TargetID;
lun = req->LUN;
@@ -1039,21 +1065,34 @@ x54x_scsi_cmd(x54x_t *dev)
phase = SCSIPhase;
x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03));
if (phase != SCSI_PHASE_STATUS) {
x54x_buf_alloc(id, lun, 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);
if (phase == SCSI_PHASE_DATA_IN)
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
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 ((SCSIStatus != SCSI_STATUS_OK) && (*BufLen > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, (char *)SCSIDevices[id][lun].CmdBuffer, *BufLen);
}
} else {
x54x_buf_alloc(id, lun, 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);
if (phase == SCSI_PHASE_DATA_IN)
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK));
}
}
x54x_set_residue(req, target_data_len);
x54x_buf_free(id, lun);
SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK));
x54x_log("Request complete\n");
if (SCSIStatus == SCSI_STATUS_OK) {
@@ -1314,6 +1353,23 @@ x54x_cmd_thread(void *priv)
endscsi();
}
if (poll_tid) {
thread_kill(poll_tid);
poll_tid = NULL;
}
if (poll_complete) {
thread_destroy_event(poll_complete);
poll_complete = NULL;
}
if (evt) {
thread_destroy_event(evt);
evt = NULL;
}
scsi_mutex_close();
x54x_log("%s: Callback: polling stopped.\n", dev->name);
}
@@ -1572,7 +1628,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
cmd->u.chs.head,
cmd->u.chs.sec);
}
dev->DataBuf[0] = x54x_bios_command(dev->max_id, cmd, (dev->bus & DEVICE_MCA)?1:0);
dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, (dev->bus & DEVICE_MCA)?1:0);
x54x_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]);
dev->DataReplyLeft = 1;
break;
@@ -1636,7 +1692,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
case CMD_RETCONF: /* return Configuration */
if (dev->ven_get_dma)
dev->DataBuf[0] = dev->ven_get_dma(dev);
dev->DataBuf[0] = (1<<dev->ven_get_dma(dev));
else
dev->DataBuf[0] = (1<<dev->DmaChannel);

View File

@@ -419,14 +419,14 @@ typedef struct {
uint8_t bus; /* Basically a copy of device flags */
uint8_t setup_info_len;
uint8_t max_id;
uint8_t pci_slot;
uint32_t reset_duration;
uint8_t pci_slot;
mem_mapping_t mmio_mapping;
uint8_t int_geom_writable;
uint8_t cdrom_boot;
/* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */
void *ven_data;