The Pro Audio Spectrum SCSI controller is now based on the Trantor T128 (which it is considerable closer to), rather than on the 53c400.

This commit is contained in:
OBattler
2024-05-06 13:09:08 +02:00
parent ccc788ff98
commit 4c84cccae7
11 changed files with 165 additions and 262 deletions

View File

@@ -2794,6 +2794,15 @@ begin:
return;
}
if (max_len <= 0) {
scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS);
dev->packet_status = PHASE_COMPLETE;
dev->callback = 20.0 * CDROM_TIME;
scsi_cdrom_set_callback(dev);
scsi_cdrom_buf_free(dev);
return;
}
if (!(cdb[2] & 0x40))
alloc_length = 4;
else
@@ -3189,7 +3198,10 @@ begin:
size_idx = 4;
memset(dev->buffer, 0, 8);
dev->buffer[0] = 5; /*CD-ROM*/
if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff)))
dev->buffer[0] = 0x7f; /*No physical device on this LUN*/
else
dev->buffer[0] = 5; /*CD-ROM*/
dev->buffer[1] = 0x80; /*Removable*/
if (dev->drv->bus_type == CDROM_BUS_SCSI) {

View File

@@ -1328,7 +1328,10 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb)
size_idx = 4;
memset(dev->temp_buffer, 0, 8);
dev->temp_buffer[0] = 0; /*SCSI HD*/
if ((cdb[1] & 0xe0) || ((dev->cur_lun > 0x00) && (dev->cur_lun < 0xff)))
dev->temp_buffer[0] = 0x7f; /*No physical device on this LUN*/
else
dev->temp_buffer[0] = 0; /*SCSI HD*/
dev->temp_buffer[1] = 0; /*Fixed*/
dev->temp_buffer[2] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/
dev->temp_buffer[3] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x21;

View File

@@ -161,8 +161,28 @@ ncr5380_get_bus_host(ncr_t *ncr)
if (ncr->icr & ICR_BSY)
bus_host |= BUS_BSY;
if (ncr->icr & ICR_ATN)
bus_host |= BUS_ATN;
/*
TODO: See which method of fixing this is the most correct.
The #define's come from PCem and, for some reason, define
BUS_ATN to the same value as BUS_ACK (0x200). This breaks
the Corel driver for the Pro Audio Spectrum Trantor SCSI
controller, as it first asserts ATN without ACK, then ACK
without ATN, which should by definition result in ACK going
ON and OFF but because of these ambiguous #define's, it
instead manifests as ACK stuck on, therefore never clearing
BUS_REQ and progressing to the next phase.
Since I have no idea why BUS_ATN was #define's to the same
value as BUS_ACK, and the problem appears to only occur in
the Message Out phase, where ATN is not used, I have decided
to solve this by never asserting ATN in the Message Out phase
for time being.
*/
if (ncr->state != STATE_MESSAGEOUT) {
if (ncr->icr & ICR_ATN)
bus_host |= BUS_ATN;
}
if (ncr->icr & ICR_ACK)
bus_host |= BUS_ACK;
@@ -326,19 +346,6 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
ncr5380_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", ncr->target_id, ncr->command[0], scsi_device_get_callback(dev), ncr->period, dev->buffer_length, ncr->dma_mode);
}
}
if (ncr->simple_pseudo_dma) {
if (dev->phase == SCSI_PHASE_DATA_IN) {
ncr->block_count = dev->buffer_length / 512;
ncr->dma_init_ext(ncr, ncr->priv, 1);
} else if (dev->phase == SCSI_PHASE_DATA_OUT) {
ncr->block_count = dev->buffer_length / 512;
ncr->dma_init_ext(ncr, ncr->priv, 0);
}
}
ncr->new_phase = dev->phase;
}
}
@@ -358,10 +365,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle in\n");
if (ncr->simple_pseudo_dma)
ncr->dma_init_ext(ncr, ncr->priv, 1);
else
ncr->timer(ncr->priv, ncr->period);
ncr->timer(ncr->priv, ncr->period);
} else {
ncr5380_log("DMA mode IN.\n");
ncr->clear_req = 3;
@@ -388,10 +392,7 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle out\n");
if (!ncr->simple_pseudo_dma)
ncr->timer(ncr->priv, ncr->period);
if (ncr->simple_pseudo_dma)
ncr->dma_init_ext(ncr, ncr->priv, 0);
ncr->timer(ncr->priv, ncr->period);
} else
ncr->clear_req = 3;
@@ -517,21 +518,6 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
ncr5380_bus_update(ncr, bus_host);
}
uint8_t
ncr5380_drq(ncr_t *ncr)
{
uint8_t ret = 0;
int bus;
ncr5380_bus_read(ncr);
bus = ncr->cur_bus;
if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA))
ret = 1;
return ret;
}
uint8_t
ncr5380_read(uint16_t port, ncr_t *ncr)
{
@@ -579,6 +565,8 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
ret |= BUS_SEL;
if (ncr->icr & ICR_BSY)
ret |= BUS_BSY;
// if ((ret & SCSI_PHASE_MESSAGE_IN) == SCSI_PHASE_MESSAGE_IN)
// ret &= ~BUS_REQ;
break;
case 5: /* Bus and Status register */

View File

@@ -41,7 +41,6 @@
#include <86box/scsi.h>
#include <86box/scsi_device.h>
#include <86box/scsi_ncr5380.h>
#include <86box/scsi_ncr53c400.h>
#define LCS6821N_ROM "roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin"
#define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin"
@@ -49,14 +48,43 @@
#define RT1000B_820R_ROM "roms/scsi/ncr5380/RTBIOS82.ROM"
#define T130B_ROM "roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin"
#define CTRL_DATA_DIR 0x40
#define STATUS_BUFFER_NOT_READY 0x04
#define STATUS_5380_ACCESSIBLE 0x80
enum {
ROM_LCS6821N = 0,
ROM_LS2000,
ROM_RT1000B,
ROM_T130B,
ROM_PAS
ROM_T130B
};
typedef struct ncr53c400_t {
rom_t bios_rom;
mem_mapping_t mapping;
ncr_t ncr;
uint8_t buffer[128];
uint8_t int_ram[0x40];
uint8_t ext_ram[0x600];
uint32_t rom_addr;
uint16_t base;
int8_t type;
uint8_t block_count;
uint8_t status_ctrl;
int block_count_loaded;
int buffer_pos;
int buffer_host_pos;
int busy;
uint8_t pos_regs[8];
pc_timer_t timer;
} ncr53c400_t;
#ifdef ENABLE_NCR53C400_LOG
int ncr53c400_do_log = ENABLE_NCR53C400_LOG;
@@ -75,29 +103,8 @@ ncr53c400_log(const char *fmt, ...)
# define ncr53c400_log(fmt, ...)
#endif
void
ncr53c400_simple_write(uint8_t val, void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
if (ncr400->buffer_host_pos < MIN(512, dev->buffer_length)) {
ncr400->buffer[ncr400->buffer_host_pos++] = val;
ncr53c400_log("Write host pos = %i, val = %02x\n", ncr400->buffer_host_pos, val);
if (ncr400->buffer_host_pos == MIN(512, dev->buffer_length)) {
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
ncr400->busy = 1;
ncr53c400_callback(priv);
}
}
}
/* Memory-mapped I/O WRITE handler. */
void
static void
ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
@@ -185,30 +192,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
}
}
uint8_t
ncr53c400_simple_read(void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
uint8_t ret = 0xff;
if (ncr400->buffer_host_pos < MIN(512, dev->buffer_length)) {
ret = ncr400->buffer[ncr400->buffer_host_pos++];
ncr53c400_log("Read host pos = %i, ret = %02x\n", ncr400->buffer_host_pos, ret);
if (ncr400->buffer_host_pos == MIN(512, dev->buffer_length)) {
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
ncr53c400_log("Transfer busy read, status = %02x\n", ncr400->status_ctrl);
ncr53c400_callback(priv);
}
}
return ret;
}
/* Memory-mapped I/O READ handler. */
uint8_t
static uint8_t
ncr53c400_read(uint32_t addr, void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
@@ -400,34 +385,6 @@ t130b_in(uint16_t port, void *priv)
return ret;
}
static void
ncr53c400_dma_init_ext(void *priv, void *ext_priv, int send)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
uint8_t val = send ? CTRL_DATA_DIR : 0x00;
ncr53c400_log("NCR 53c400 control = %02x, mode = %02x.\n", val, ncr->mode);
ncr400->status_ctrl = (ncr400->status_ctrl & 0x87) | (val & 0x78);
ncr400->block_count_loaded = 1;
if (ncr400->status_ctrl & CTRL_DATA_DIR) {
ncr400->buffer_host_pos = MIN(512, dev->buffer_length);
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
} else {
ncr400->buffer_host_pos = 0;
ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
}
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
memset(ncr400->buffer, 0, MIN(512, dev->buffer_length));
ncr53c400_log("DMA buffer init\n");
ncr->timer(ncr->priv, ncr->period);
}
ncr53c400_log("NCR DMA init\n");
}
static void
ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
{
@@ -455,21 +412,17 @@ ncr53c400_timer_on_auto(void *ext_priv, double period)
timer_on_auto(&ncr400->timer, period);
}
void
static void
ncr53c400_callback(void *priv)
{
ncr53c400_t *ncr400 = (void *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
int bus;
int blocks_left;
uint8_t c;
uint8_t temp;
const int buf_len = ncr400->simple_ctrl ? 512 : 128;
ncr53c400_log("DMA mode = %i\n", ncr->dma_mode);
if (!ncr400->simple_ctrl && (ncr->dma_mode != DMA_IDLE))
if (ncr->dma_mode != DMA_IDLE)
timer_on_auto(&ncr400->timer, 1.0);
if (ncr->data_wait & 1) {
@@ -488,7 +441,7 @@ ncr53c400_callback(void *priv)
switch (ncr->dma_mode) {
case DMA_SEND:
if (!ncr400->simple_ctrl && (ncr400->status_ctrl & CTRL_DATA_DIR)) {
if (ncr400->status_ctrl & CTRL_DATA_DIR) {
ncr53c400_log("DMA_SEND with DMA direction set wrong\n");
break;
}
@@ -522,20 +475,14 @@ ncr53c400_callback(void *priv)
ncr400->buffer_pos++;
ncr53c400_log("NCR 53c400 Buffer pos for writing = %d\n", ncr400->buffer_pos);
if (ncr400->buffer_pos == MIN(buf_len, dev->buffer_length)) {
if (ncr400->buffer_pos == MIN(128, dev->buffer_length)) {
ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
ncr400->buffer_pos = 0;
ncr400->buffer_host_pos = 0;
ncr400->busy = 0;
if (ncr400->simple_ctrl) {
ncr->block_count = (ncr->block_count - 1) & 0xffffffff;
blocks_left = ncr->block_count;
} else {
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
blocks_left = ncr400->block_count;
}
ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", blocks_left);
if (blocks_left == 0) {
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -552,7 +499,7 @@ ncr53c400_callback(void *priv)
break;
case DMA_INITIATOR_RECEIVE:
if (!ncr400->simple_ctrl && !(ncr400->status_ctrl & CTRL_DATA_DIR)) {
if (!(ncr400->status_ctrl & CTRL_DATA_DIR)) {
ncr53c400_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n");
break;
}
@@ -568,10 +515,8 @@ ncr53c400_callback(void *priv)
while (1) {
for (c = 0; c < 10; c++) {
ncr5380_bus_read(ncr);
if (ncr->cur_bus & BUS_REQ) {
ncr53c400_log("ncr->cur_bus & BUS_REQ\n");
if (ncr->cur_bus & BUS_REQ)
break;
}
}
/* Data ready. */
@@ -586,19 +531,13 @@ ncr53c400_callback(void *priv)
ncr400->buffer[ncr400->buffer_pos++] = temp;
ncr53c400_log("NCR 53c400 Buffer pos for reading = %d\n", ncr400->buffer_pos);
if (ncr400->buffer_pos == MIN(buf_len, dev->buffer_length)) {
if (ncr400->buffer_pos == MIN(128, dev->buffer_length)) {
ncr400->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
ncr400->buffer_pos = 0;
ncr400->buffer_host_pos = 0;
if (ncr400->simple_ctrl) {
ncr->block_count = (ncr->block_count - 1) & 0xffffffff;
blocks_left = ncr->block_count;
} else {
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
blocks_left = ncr400->block_count;
}
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", blocks_left);
if (blocks_left == 0) {
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
@@ -623,8 +562,6 @@ ncr53c400_callback(void *priv)
ncr53c400_log("Updating DMA\n");
ncr->mode &= ~MODE_DMA;
ncr->dma_mode = DMA_IDLE;
if (ncr400->simple_ctrl)
ncr400->block_count_loaded = 0;
}
}
@@ -719,6 +656,7 @@ ncr53c400_init(const device_t *info)
ncr400->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr400);
break;
case ROM_LS2000: /* Corel LS2000 */
ncr400->rom_addr = device_get_config_hex20("bios_addr");
ncr->irq = device_get_config_int("irq");
@@ -777,13 +715,6 @@ ncr53c400_init(const device_t *info)
t130b_in, NULL, NULL, t130b_out, NULL, NULL, ncr400);
break;
case ROM_PAS: /* Pro Audio Spectrum Plus/16 SCSI controller */
ncr400->simple_ctrl = 1;
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
ncr->simple_pseudo_dma = 1;
ncr->dma_init_ext = ncr53c400_dma_init_ext;
break;
default:
break;
}
@@ -1076,17 +1007,3 @@ const device_t scsi_ls2000_device = {
.force_redraw = NULL,
.config = ncr53c400_mmio_config
};
const device_t scsi_pas_device = {
.name = "Pro Audio Spectrum Plus/16 SCSI",
.internal_name = "scsi_pas",
.flags = DEVICE_ISA,
.local = ROM_PAS,
.init = ncr53c400_init,
.close = ncr53c400_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -41,31 +41,10 @@
#include <86box/scsi.h>
#include <86box/scsi_device.h>
#include <86box/scsi_ncr5380.h>
#include <86box/scsi_t128.h>
#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin"
typedef struct t128_t {
ncr_t ncr;
rom_t bios_rom;
mem_mapping_t mapping;
uint8_t ctrl;
uint8_t status;
uint8_t buffer[512];
uint8_t ext_ram[0x80];
uint8_t block_count;
int block_loaded;
int pos, host_pos;
uint32_t rom_addr;
int bios_enabled;
uint8_t pos_regs[8];
pc_timer_t timer;
} t128_t;
#ifdef ENABLE_T128_LOG
int t128_do_log = ENABLE_T128_LOG;
@@ -85,7 +64,7 @@ t128_log(const char *fmt, ...)
#endif
/* Memory-mapped I/O WRITE handler. */
static void
void
t128_write(uint32_t addr, uint8_t val, void *priv)
{
t128_t *t128 = (t128_t *) priv;
@@ -122,7 +101,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
}
/* Memory-mapped I/O READ handler. */
static uint8_t
uint8_t
t128_read(uint32_t addr, void *priv)
{
t128_t *t128 = (t128_t *) priv;
@@ -243,7 +222,7 @@ t128_timer_on_auto(void *ext_priv, double period)
timer_on_auto(&t128->timer, period);
}
static void
void
t128_callback(void *priv)
{
t128_t *t128 = (void *) priv;
@@ -506,7 +485,7 @@ t128_init(const device_t *info)
t128->pos_regs[0] = 0x8c;
t128->pos_regs[1] = 0x50;
mca_add(t228_read, t228_write, t228_feedb, NULL, t128);
} else {
} else if (info->local == 0) {
ncr->irq = device_get_config_int("irq");
t128->rom_addr = device_get_config_hex20("bios_addr");
t128->bios_enabled = device_get_config_int("boot");
@@ -525,12 +504,13 @@ t128_init(const device_t *info)
ncr->dma_send_ext = t128_dma_send_ext;
ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext;
ncr->timer = t128_timer_on_auto;
t128->status = 0x04;
t128->status = 0x00 /*0x04*/;
t128->host_pos = 512;
if (!t128->bios_enabled && !(info->flags & DEVICE_MCA))
t128->status |= 0x80;
timer_add(&t128->timer, t128_callback, t128, 0);
if (info->local == 0)
timer_add(&t128->timer, t128_callback, t128, 0);
scsi_bus_set_speed(ncr->bus, 5000000.0);
@@ -616,6 +596,7 @@ const device_t scsi_t128_device = {
.config = t128_config
};
const device_t scsi_t228_device = {
.name = "Trantor T228",
.internal_name = "t228",
@@ -629,3 +610,17 @@ const device_t scsi_t228_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t scsi_pas_device = {
.name = "Pro Audio Spectrum Plus/16 SCSI",
.internal_name = "scsi_pas",
.flags = DEVICE_ISA,
.local = 1,
.init = t128_init,
.close = t128_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};