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:
@@ -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;
|
||||
|
@@ -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");
|
||||
}
|
||||
|
||||
|
2
src/pc.c
2
src/pc.c
@@ -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)));
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user