Realistic CD-ROM timings on ATAPI PIO, ATAPI DMA, SCSI NCR 53c810, and SCSI Adaptec/Buslogic;

Added ability to select emulated CD-ROM drive speed;
The Adaptec and BusLogic SCSI controllers are no longer threaded;
Two fixes in video/vid_s3.c.
This commit is contained in:
OBattler
2018-03-07 20:06:08 +01:00
parent 84fa69c4a6
commit 16c722b32f
18 changed files with 382 additions and 268 deletions

View File

@@ -10,7 +10,7 @@
* made by Adaptec, Inc. These controllers were designed for
* the ISA bus.
*
* Version: @(#)scsi_aha154x.c 1.0.38 2018/02/19
* Version: @(#)scsi_aha154x.c 1.0.39 2018/03/07
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Original Buslogic version by SA1988 and Miran Grca.
@@ -267,10 +267,7 @@ aha_fast_cmds(void *p, uint8_t cmd)
x54x_t *dev = (x54x_t *)p;
if (cmd == CMD_BIOS_SCSI) {
x54x_busy(1);
dev->BIOSMailboxReq++;
x54x_set_wait_event();
x54x_busy(0);
return 1;
}
@@ -362,7 +359,6 @@ aha_cmds(void *p)
case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */
/* Sent by CF BIOS. */
x54x_busy(1);
dev->Mbx24bit = 1;
mbi = (MailboxInit_t *)dev->CmdBuf;
@@ -378,7 +374,6 @@ aha_cmds(void *p)
dev->Status &= ~STAT_INIT;
dev->DataReplyLeft = 0;
x54x_busy(0);
break;
case CMD_MEMORY_MAP_1: /* AHA memory mapper */
@@ -467,16 +462,12 @@ aha_do_bios_mail(x54x_t *dev)
static void
aha_thread(void *p)
aha_callback(void *p)
{
x54x_t *dev = (x54x_t *)p;
if (dev->BIOSMailboxInit && dev->BIOSMailboxReq)
{
x54x_wait_for_poll();
aha_do_bios_mail(dev);
}
}
@@ -768,7 +759,7 @@ aha_init(device_t *info)
dev->bit32 = 0;
dev->lba_bios = 0;
dev->ven_thread = aha_thread;
dev->ven_callback = aha_callback;
dev->ven_cmd_is_fast = aha_cmd_is_fast;
dev->ven_fast_cmds = aha_fast_cmds;
dev->get_ven_param_len = aha_param_len;
@@ -797,6 +788,7 @@ aha_init(device_t *info)
dev->HostID = device_get_config_int("hostid");
dev->rom_shram = 0x3F80; /* shadow RAM address base */
dev->rom_shramsz = 128; /* size of shadow RAM */
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
case AHA_154xC:
@@ -811,6 +803,7 @@ aha_init(device_t *info)
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 */
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
case AHA_154xCF:
@@ -826,6 +819,7 @@ aha_init(device_t *info)
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 */
dev->ha_bps = 10000000.0; /* fast SCSI */
break;
case AHA_154xCP:
@@ -840,6 +834,7 @@ aha_init(device_t *info)
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 */
dev->ha_bps = 10000000.0; /* fast SCSI */
break;
case AHA_1640:
@@ -853,6 +848,7 @@ aha_init(device_t *info)
dev->pos_regs[0] = 0x1F; /* MCA board ID */
dev->pos_regs[1] = 0x0F;
mca_add(aha_mca_read, aha_mca_write, dev);
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
}

View File

@@ -11,14 +11,14 @@
* 1 - BT-545S ISA;
* 2 - BT-958D PCI
*
* Version: @(#)scsi_buslogic.c 1.0.34 2018/01/06
* Version: @(#)scsi_buslogic.c 1.0.35 2018/03/07
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -719,7 +719,6 @@ buslogic_cmds(void *p)
dev->IrqEnabled = 1;
return 1;
case 0x81:
x54x_busy(1);
dev->Mbx24bit = 0;
MailboxInitE = (MailboxInitExtended_t *)dev->CmdBuf;
@@ -736,7 +735,6 @@ buslogic_cmds(void *p)
dev->Status &= ~STAT_INIT;
dev->DataReplyLeft = 0;
x54x_busy(0);
break;
case 0x83:
if (dev->CmdParam == 12) {
@@ -1528,6 +1526,7 @@ buslogic_init(device_t *info)
has_autoscsi_rom = 0;
has_scam_rom = 0;
dev->fw_rev = "AA335";
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
case CHIP_BUSLOGIC_ISA:
default:
@@ -1540,6 +1539,7 @@ buslogic_init(device_t *info)
autoscsi_rom_size = 0x4000;
has_scam_rom = 0;
dev->fw_rev = "AA421E";
dev->ha_bps = 10000000.0; /* fast SCSI */
break;
case CHIP_BUSLOGIC_MCA:
strcpy(dev->name, "BT-640A");
@@ -1553,6 +1553,7 @@ buslogic_init(device_t *info)
dev->pos_regs[0] = 0x08; /* MCA board ID */
dev->pos_regs[1] = 0x07;
mca_add(buslogic_mca_read, buslogic_mca_write, dev);
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
case CHIP_BUSLOGIC_VLB:
strcpy(dev->name, "BT-445S");
@@ -1565,6 +1566,7 @@ buslogic_init(device_t *info)
has_scam_rom = 0;
dev->fw_rev = "AA421E";
dev->bit32 = 1;
dev->ha_bps = 10000000.0; /* fast SCSI */
break;
case CHIP_BUSLOGIC_PCI:
strcpy(dev->name, "BT-958D");
@@ -1580,6 +1582,7 @@ buslogic_init(device_t *info)
dev->fw_rev = "AA507B";
dev->cdrom_boot = 1;
dev->bit32 = 1;
dev->ha_bps = 20000000.0; /* ultra SCSI */
break;
}

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.13 2018/03/06
* Version: @(#)scsi_device.c 1.0.14 2018/03/07
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -119,6 +119,33 @@ static void scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t c
}
int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
uint8_t id = 0;
switch (lun_type)
{
case SCSI_DISK:
id = scsi_hard_disks[scsi_id][scsi_lun];
return shdc[id].callback;
break;
case SCSI_CDROM:
id = scsi_cdrom_drives[scsi_id][scsi_lun];
return cdrom[id].callback;
break;
case SCSI_ZIP:
id = scsi_zip_drives[scsi_id][scsi_lun];
return zip[id].callback;
break;
default:
return -1LL;
break;
}
}
uint8_t *scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;

View File

@@ -8,7 +8,7 @@
*
* Definitions for the generic SCSI device command handler.
*
* Version: @(#)scsi_device.h 1.0.5 2018/02/17
* Version: @(#)scsi_device.h 1.0.6 2018/03/07
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -35,6 +35,7 @@ typedef struct
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,
uint8_t alloc_length);

View File

@@ -6,11 +6,11 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.c 1.0.16 2018/01/25
* Version: @(#)scsi_disk.c 1.0.17 2018/03/07
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2018 Miran Grca.
* Copyright 2017,2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
@@ -459,14 +459,11 @@ static void scsi_hd_command_common(uint8_t id)
shdc[id].status = BUSY_STAT;
shdc[id].phase = 1;
shdc[id].pos = 0;
if (shdc[id].packet_status == CDROM_PHASE_COMPLETE)
{
shdc[id].callback = 20 * SCSI_TIME;
}
else
{
shdc[id].callback = 60 * SCSI_TIME;
}
if (shdc[id].packet_status == CDROM_PHASE_COMPLETE) {
scsi_hd_callback(id);
shdc[id].callback = 0LL;
} else
shdc[id].callback = -1LL; /* Speed depends on SCSI controller */
}

View File

@@ -9,15 +9,15 @@
* Implementation of the NCR 5380 series of SCSI Host Adapters
* made by NCR. These controllers were designed for the ISA bus.
*
* Version: @(#)scsi_ncr5380.c 1.0.10 2018/01/26
* Version: @(#)scsi_ncr5380.c 1.0.11 2018/03/07
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2017-2018 Sarah Walker.
* Copyright 2017-2018 TheCollector1995.
* Copyright 2018 Fred N. van Kempen.
* Copyright 2017,2018 Sarah Walker.
* Copyright 2017,2018 TheCollector1995.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -390,7 +390,7 @@ dma_callback(void *priv)
int bytes_transferred = 0;
int c;
scsi->dma_timer += POLL_TIME_US;
scsi->dma_timer += POLL_TIME_US * TIMER_USEC;
switch (scsi->ncr.dma_mode) {
case DMA_SEND:

View File

@@ -10,7 +10,7 @@
* NCR and later Symbios and LSI. This controller was designed
* for the PCI bus.
*
* Version: @(#)scsi_ncr53c810.c 1.0.6 2018/01/06
* Version: @(#)scsi_ncr53c810.c 1.0.7 2018/03/07
*
* Authors: Paul Brook (QEMU)
* Artyom Tarasenko (QEMU)
@@ -19,8 +19,9 @@
*
* Copyright 2006-2018 Paul Brook.
* Copyright 2009-2018 Artyom Tarasenko.
* Copyright 2018 Miran Grca.
* Copyright 2017,2018 Miran Grca.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -268,6 +269,9 @@ typedef struct {
uint8_t regop;
uint32_t adder;
int64_t timer_period;
int64_t timer_enabled;
} ncr53c810_t;
@@ -326,6 +330,8 @@ static void
ncr53c810_soft_reset(ncr53c810_t *dev)
{
ncr53c810_log("LSI Reset\n");
dev->timer_period = dev->timer_enabled = 0;
dev->carry = 0;
dev->msg_action = 0;
@@ -496,6 +502,7 @@ ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1)
if ((dev->sist0 & mask0) || (dev->sist1 & mask1)) {
ncr53c810_log("NCR 810: IRQ-mandated stop\n");
dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
}
ncr53c810_update_irq(dev);
}
@@ -509,6 +516,7 @@ ncr53c810_script_dma_interrupt(ncr53c810_t *dev, int stat)
dev->dstat |= stat;
ncr53c810_update_irq(dev);
dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
}
@@ -526,6 +534,7 @@ ncr53c810_bad_phase(ncr53c810_t *dev, int out, int new_phase)
ncr53c810_log("Phase mismatch interrupt\n");
ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0);
dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
ncr53c810_set_phase(dev, new_phase);
}
@@ -650,6 +659,8 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
scsi_device_t *sd;
uint8_t buf[12];
double period;
memset(buf, 0, 12);
DMAPageRead(dev->dnad, buf, MIN(12, dev->dbc));
if (dev->dbc > 12) {
@@ -690,9 +701,19 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DI);
dev->timer_period = scsi_device_get_callback(dev->current->tag, dev->current_lun);
if (dev->timer_period <= 0LL) {
period = ((double) sd->BufferLength) * 0.2 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period = (int64_t) period;
}
} else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DO);
dev->timer_period = scsi_device_get_callback(dev->current->tag, dev->current_lun);
if (dev->timer_period <= 0LL) {
period = ((double) sd->BufferLength) * 0.2 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period = (int64_t) period;
}
} else
ncr53c810_command_complete(dev, sd->Status);
}
@@ -907,7 +928,7 @@ ncr53c810_memcpy(ncr53c810_t *dev, uint32_t dest, uint32_t src, int count)
static void
ncr53c810_execute_script(ncr53c810_t *dev)
ncr53c810_process_script(ncr53c810_t *dev)
{
uint32_t insn, addr, id, buf[2], dest;
int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i;
@@ -936,6 +957,7 @@ again:
if (dev->sist1 & NCR_SIST1_STO) {
ncr53c810_log("Delayed select timeout\n");
dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
break;
}
ncr53c810_log("Block Move DBC=%d\n", dev->dbc);
@@ -981,7 +1003,9 @@ again:
case PHASE_CMD:
ncr53c810_log("Command Phase\n");
ncr53c810_do_command(dev, dev->sdid);
break;
dev->dfifo = dev->dbc & 0xff;
dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3);
return;
case PHASE_ST:
ncr53c810_log("Status Phase\n");
ncr53c810_do_status(dev);
@@ -1153,6 +1177,7 @@ again:
if (dev->sist1 & NCR_SIST1_STO) {
ncr53c810_log("Delayed select timeout\n");
dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
break;
}
cond = jmp = (insn & (1 << 19)) != 0;
@@ -1262,7 +1287,8 @@ again:
ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI);
} else {
ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n");
goto again;
if (insn_processed < 100)
goto again;
}
} else {
if (dev->sstop)
@@ -1271,10 +1297,41 @@ again:
ncr53c810_log("NCR 810: SCRIPTS: Waiting\n");
}
return;
ncr53c810_log("SCRIPTS execution stopped\n");
}
static void
ncr53c810_execute_script(ncr53c810_t *dev)
{
dev->timer_period = 10LL * TIMER_USEC;
dev->timer_enabled = 1;
}
static void
ncr53c810_callback(void *p)
{
ncr53c810_t *dev = (ncr53c810_t *) p;
dev->timer_period = 0;
if (!dev->waiting)
ncr53c810_process_script(dev);
if (dev->sstop) {
dev->timer_period = 0;
dev->timer_enabled = 0;
return;
} else
dev->timer_enabled = 1;
if (dev->timer_period == 0)
dev->timer_period = 50LL * TIMER_USEC;
}
static void
ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val)
{
@@ -1377,7 +1434,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val)
ncr53c810_log("Woken by SIGP\n");
dev->waiting = 0;
dev->dsp = dev->dnad;
ncr53c810_execute_script(dev);
/* ncr53c810_execute_script(dev); */
}
if ((val & NCR_ISTAT_SRST) && !(tmp & NCR_ISTAT_SRST)) {
ncr53c810_soft_reset(dev);
@@ -2076,6 +2133,8 @@ ncr53c810_init(device_t *info)
ncr53c810_soft_reset(dev);
timer_add(ncr53c810_callback, &dev->timer_period, &dev->timer_enabled, dev);
return(dev);
}

View File

@@ -11,7 +11,7 @@
* series of SCSI Host Adapters made by Mylex.
* These controllers were designed for various buses.
*
* Version: @(#)scsi_x54x.c 1.0.17 2018/02/25
* Version: @(#)scsi_x54x.c 1.0.18 2018/03/07
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -20,6 +20,7 @@
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -49,22 +50,7 @@
#define X54X_RESET_DURATION_US UINT64_C(50000)
static void x54x_cmd_thread(void *priv);
static volatile
thread_t *poll_tid;
static volatile
int busy;
static volatile
event_t *evt;
static volatile
event_t *wait_evt;
static volatile
event_t *wake_poll_thread;
static volatile
event_t *thread_started;
static void x54x_cmd_callback(void *priv);
static volatile
x54x_t *x54x_dev;
@@ -609,6 +595,13 @@ x54x_cmd_done(x54x_t *dev, int suppress)
}
static void
x54x_add_to_period(int TransferLength)
{
x54x_dev->temp_period += (int64_t) TransferLength;
}
static void
x54x_mbi_setup(x54x_t *dev, uint32_t CCBPointer, CCBU *CmdBlock,
uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc)
@@ -636,6 +629,7 @@ x54x_ccb(x54x_t *dev)
DMAPageWrite(req->CCBPointer + 0x000D, &(req->MailboxCompletionCode), 1);
DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1);
DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1);
x54x_add_to_period(3);
if (dev->MailboxOutInterrupts)
dev->ToRaise = INTR_MBOA | INTR_ANY;
@@ -666,6 +660,7 @@ x54x_mbi(x54x_t *dev)
x54x_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer);
DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1);
DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1);
x54x_add_to_period(2);
} else {
x54x_log("Mailbox not found!\n");
}
@@ -677,6 +672,7 @@ x54x_mbi(x54x_t *dev)
x54x_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer);
DMAPageWrite(Incoming, &(req->MailboxCompletionCode), 1);
DMAPageWrite(Incoming + 1, (uint8_t *)&CCBPointer, 3);
x54x_add_to_period(4);
x54x_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming);
} else {
x54x_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer);
@@ -684,6 +680,7 @@ x54x_mbi(x54x_t *dev)
DMAPageWrite(Incoming + 4, &(req->HostStatus), 1);
DMAPageWrite(Incoming + 5, &(req->TargetStatus), 1);
DMAPageWrite(Incoming + 7, &(req->MailboxCompletionCode), 1);
x54x_add_to_period(7);
x54x_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming);
}
@@ -704,6 +701,7 @@ x54x_rd_sge(int Is24bit, uint32_t Address, SGE32 *SG)
if (Is24bit) {
DMAPageRead(Address, (uint8_t *)&SGE24, sizeof(SGE));
x54x_add_to_period(sizeof(SGE));
/* Convert the 24-bit entries into 32-bit entries. */
x54x_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer);
@@ -711,6 +709,7 @@ x54x_rd_sge(int Is24bit, uint32_t Address, SGE32 *SG)
SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer);
} else {
DMAPageRead(Address, (uint8_t *)SG, sizeof(SGE32));
x54x_add_to_period(sizeof(SGE32));
}
}
@@ -778,9 +777,11 @@ x54x_set_residue(Req_t *req, int32_t TransferLength)
if (req->Is24bit) {
U32_TO_ADDR(Residue24, Residue);
DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue24, 3);
x54x_add_to_period(3);
x54x_log("24-bit Residual data length for reading: %d\n", Residue);
} else {
DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue, 4);
x54x_add_to_period(4);
x54x_log("32-bit Residual data length for reading: %d\n", Residue);
}
}
@@ -832,9 +833,8 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
DMAPageWrite(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer);
}
else {
else
x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address);
}
sg_pos += SGBuffer.Segment;
@@ -850,11 +850,10 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
Address = DataPointer;
if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) {
if (read_from_host) {
if (read_from_host)
DMAPageRead(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength));
} else if (write_to_host) {
else if (write_to_host)
DMAPageWrite(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength));
}
}
}
}
@@ -938,6 +937,7 @@ SenseBufferFree(Req_t *req, int Copy)
x54x_log("SenseBufferFree(): Writing %i bytes at %08X\n",
SenseLength, SenseBufferAddress);
DMAPageWrite(SenseBufferAddress, temp_sense, SenseLength);
x54x_add_to_period(SenseLength);
x54x_log("Sense data written to buffer: %02X %02X %02X\n",
temp_sense[2], temp_sense[12], temp_sense[13]);
}
@@ -957,6 +957,7 @@ x54x_scsi_cmd(x54x_t *dev)
int32_t *BufLen;
uint8_t phase;
uint32_t SenseBufferAddress;
int64_t p;
id = req->TargetID;
lun = req->LUN;
@@ -979,8 +980,10 @@ x54x_scsi_cmd(x54x_t *dev)
if (req->CmdBlock.common.CdbLength <= target_cdb_len) {
memcpy(temp_cdb, req->CmdBlock.common.Cdb,
req->CmdBlock.common.CdbLength);
x54x_add_to_period(req->CmdBlock.common.CdbLength);
} else {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len);
x54x_add_to_period(target_cdb_len);
}
dev->Residue = 0;
@@ -1005,8 +1008,14 @@ x54x_scsi_cmd(x54x_t *dev)
if ((SCSIDevices[id][lun].Status != SCSI_STATUS_OK) && (*BufLen > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, SCSIDevices[id][lun].CmdBuffer, *BufLen);
x54x_add_to_period(*BufLen);
}
} else {
p = scsi_device_get_callback(id, lun);
if (p <= 0LL)
x54x_add_to_period(*BufLen);
else
dev->media_period += p;
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);
@@ -1034,10 +1043,6 @@ x54x_scsi_cmd(x54x_t *dev)
}
x54x_log("SCSIDevices[%02i][%02i].Status = %02X\n", id, lun, SCSIDevices[id][lun].Status);
if (temp_cdb[0] == 0x42) {
thread_wait_event((event_t *) evt, 10);
}
}
@@ -1135,6 +1140,7 @@ x54x_req_abort(x54x_t *dev, uint32_t CCBPointer)
/* Fetch data from the Command Control Block. */
DMAPageRead(CCBPointer, (uint8_t *)&CmdBlock, sizeof(CCB32));
x54x_add_to_period(sizeof(CCB32));
x54x_mbi_setup(dev, CCBPointer, &CmdBlock,
0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
@@ -1163,6 +1169,7 @@ x54x_mbo(x54x_t *dev, Mailbox32_t *Mailbox32)
if (dev->Mbx24bit) {
Outgoing = Addr + (Cur * sizeof(Mailbox_t));
DMAPageRead(Outgoing, (uint8_t *)&MailboxOut, sizeof(Mailbox_t));
x54x_add_to_period(sizeof(Mailbox_t));
ccbp = *(uint32_t *) &MailboxOut;
Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000);
@@ -1171,6 +1178,7 @@ x54x_mbo(x54x_t *dev, Mailbox32_t *Mailbox32)
Outgoing = Addr + (Cur * sizeof(Mailbox32_t));
DMAPageRead(Outgoing, (uint8_t *)Mailbox32, sizeof(Mailbox32_t));
x54x_add_to_period(sizeof(Mailbox32_t));
}
return(Outgoing);
@@ -1203,14 +1211,11 @@ x54x_mbo_process(x54x_t *dev)
/* We got the mailbox, mark it as free in the guest. */
x54x_log("x54x_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, 1);
x54x_add_to_period(1);
if (dev->ToRaise) {
if (dev->ToRaise)
raise_irq(dev, 0, dev->ToRaise);
while (dev->Interrupt)
;
}
if (dev->MailboxIsBIOS)
dev->BIOSMailboxReq--;
else
@@ -1264,84 +1269,29 @@ static void
x54x_cmd_done(x54x_t *dev, int suppress);
void
x54x_wait_for_poll(void)
{
if (x54x_is_busy()) {
thread_wait_event((event_t *) wake_poll_thread, -1);
}
thread_reset_event((event_t *) wake_poll_thread);
}
static void
x54x_cmd_thread(void *priv)
x54x_cmd_callback(void *priv)
{
double period;
x54x_t *dev = (x54x_t *) x54x_dev;
thread_set_event((event_t *) thread_started);
x54x_log("Polling thread started\n");
while (x54x_dev) {
scsi_mutex_wait(1);
if ((dev->Status & STAT_INIT) || (!dev->MailboxInit && !dev->BIOSMailboxInit) || (!dev->MailboxReq && !dev->BIOSMailboxReq)) {
/* If we did not get anything, wait a while. */
thread_wait_event((event_t *) wait_evt, 10);
thread_reset_event((event_t *) wait_evt);
scsi_mutex_wait(0);
continue;
}
if (!(x54x_dev->Status & STAT_INIT) && x54x_dev->MailboxInit && dev->MailboxReq) {
x54x_wait_for_poll();
x54x_do_mail(dev);
}
if (dev->ven_thread) {
dev->ven_thread(dev);
}
scsi_mutex_wait(0);
if ((dev->Status & STAT_INIT) || (!dev->MailboxInit && !dev->BIOSMailboxInit) || (!dev->MailboxReq && !dev->BIOSMailboxReq)) {
/* If we did not get anything, do nothing and wait 10 us. */
dev->timer_period = 10LL * TIMER_USEC;
return;
}
x54x_log("%s: Callback: polling stopped.\n", dev->name);
}
dev->temp_period = dev->media_period = 0LL;
if (!(x54x_dev->Status & STAT_INIT) && x54x_dev->MailboxInit && dev->MailboxReq)
x54x_do_mail(dev);
void
x54x_busy(uint8_t set)
{
busy = !!set;
if (!set)
thread_set_event((event_t *) wake_poll_thread);
}
if (dev->ven_callback)
dev->ven_callback(dev);
void
x54x_thread_start(x54x_t *dev)
{
if (!poll_tid) {
x54x_log("Starting thread...\n");
poll_tid = thread_create(x54x_cmd_thread, dev);
}
}
uint8_t
x54x_is_busy(void)
{
return(!!busy);
}
void
x54x_set_wait_event(void)
{
thread_set_event((event_t *)wait_evt);
period = (1000000.0 / x54x_dev->ha_bps) * ((double) TIMER_USEC) * ((double) dev->temp_period);
dev->timer_period = dev->media_period + ((int64_t) period) + (40LL * TIMER_USEC);
x54x_log("Temporary period: %" PRId64 " us (%" PRIi64 " periods)\n", dev->timer_period, dev->temp_period);
}
@@ -1518,31 +1468,24 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
switch (port & 3) {
case 0:
if ((val & CTRL_HRST) || (val & CTRL_SRST)) {
x54x_busy(1);
reset = (val & CTRL_HRST);
x54x_log("Reset completed = %x\n", reset);
x54x_reset_ctrl(dev, reset);
x54x_log("Controller reset: ");
x54x_busy(0);
break;
}
if (val & CTRL_IRST) {
x54x_busy(1);
clear_irq(dev);
x54x_log("Interrupt reset: ");
x54x_busy(0);
}
break;
case 1:
/* Fast path for the mailbox execution command. */
if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) {
x54x_busy(1);
dev->MailboxReq++;
x54x_set_wait_event();
x54x_log("Start SCSI command: ");
x54x_busy(0);
return;
}
if (dev->ven_fast_cmds) {
@@ -1609,7 +1552,6 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_MBINIT: /* mailbox initialization */
x54x_busy(1);
dev->Mbx24bit = 1;
mbi = (MailboxInit_t *)dev->CmdBuf;
@@ -1628,7 +1570,6 @@ x54x_out(uint16_t port, uint8_t val, void *priv)
dev->Status &= ~STAT_INIT;
dev->DataReplyLeft = 0;
x54x_log("Mailbox init: ");
x54x_busy(0);
break;
case CMD_BIOSCMD: /* execute BIOS */
@@ -1962,22 +1903,11 @@ x54x_init(device_t *info)
dev->bus = info->flags;
timer_add(x54x_reset_poll, &dev->ResetCB, &dev->ResetCB, dev);
dev->timer_period = 10LL * TIMER_USEC;
timer_add(x54x_cmd_callback, &dev->timer_period, TIMER_ALWAYS_ENABLED, dev);
x54x_dev = dev;
scsi_mutex(1);
wake_poll_thread = thread_create_event();
thread_started = thread_create_event();
/* Create a waitable event. */
evt = thread_create_event();
wait_evt = thread_create_event();
x54x_thread_start(dev);
thread_wait_event((event_t *) thread_started, -1);
thread_reset_event((event_t *) thread_started);
return(dev);
}
@@ -1990,17 +1920,8 @@ x54x_close(void *priv)
if (dev) {
x54x_dev = NULL;
/* Tell the thread to terminate. */
if (poll_tid != NULL) {
x54x_busy(0);
x54x_log("Waiting for SCSI thread to end...\n");
/* Wait for the end event. */
thread_wait((event_t *) poll_tid, -1);
x54x_log("SCSI thread ended\n");
poll_tid = NULL;
}
/* Tell the timer to terminate. */
dev->timer_period = 0LL;
dev->MailboxInit = dev->BIOSMailboxInit = 0;
dev->MailboxCount = dev->BIOSMailboxCount = 0;
@@ -2009,28 +1930,6 @@ x54x_close(void *priv)
if (dev->ven_data)
free(dev->ven_data);
if (wait_evt) {
thread_destroy_event((event_t *) evt);
evt = NULL;
}
if (evt) {
thread_destroy_event((event_t *) evt);
evt = NULL;
}
if (thread_started) {
thread_destroy_event((event_t *) thread_started);
thread_started = NULL;
}
if (wake_poll_thread) {
thread_destroy_event((event_t *) wake_poll_thread);
wake_poll_thread = NULL;
}
scsi_mutex(0);
if (dev->nvr != NULL)
free(dev->nvr);

View File

@@ -11,14 +11,14 @@
* of SCSI Host Adapters made by Mylex.
* These controllers were designed for various buses.
*
* Version: @(#)scsi_x54x.h 1.0.4 2017/12/15
* Version: @(#)scsi_x54x.h 1.0.5 2018/03/07
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#ifndef SCSI_X54X_H
@@ -332,6 +332,10 @@ typedef struct {
char vendor[16]; /* name of device vendor */
char name[16]; /* name of device */
int64_t timer_period, temp_period;
int64_t media_period;
double ha_bps; /* bytes per second */
int8_t Irq;
uint8_t IrqEnabled;
@@ -429,8 +433,8 @@ typedef struct {
/* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */
void *ven_data;
/* Pointer to a function that performs vendor-specific operation during the thread */
void (*ven_thread)(void *p);
/* Pointer to a function that performs vendor-specific operation during the timer callback */
void (*ven_callback)(void *p);
/* Pointer to a function that executes the second parameter phase of the vendor-specific command */
void (*ven_cmd_phase1)(void *p);
/* Pointer to a function that gets the host adapter ID in case it has to be read from a non-standard location */
@@ -487,10 +491,6 @@ typedef struct
extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset);
extern void x54x_busy(uint8_t set);
extern void x54x_thread_start(x54x_t *dev);
extern void x54x_set_wait_event(void);
extern uint8_t x54x_is_busy(void);
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 uint8_t x54x_mbo_process(x54x_t *dev);