Added the NCR 53C810 PCI SCSI controller;
Fixed the behavior of the CD-ROM GET CONFIGURATION command when unimplemented features are requested; Fixed the behavior of the CD-ROM READ DVD STRUCTURE command in some situations and made it correctly report 05/30/02 for incompatible format; Reworked the PS/2 Model 80 Type 2 memory handling a bit; The emulator now allocates the few MB of space needed for pages for the entire 4 GB RAM space at the startup and only memset's it to 0 on hard reset - should make sure DMA page reads from/writes to memory-mapped devices no longer crash the emulator on invalidating the memory range; Applied app applicable PCem patches; The PS/1 Model 2133 now also applies PS/2-style NMI mask handling - fixes the 486 recompiler on this machine; Added the missing #include of "cpu/cpu.h" in io.c, fixes compiling when I/O tracing is enabled.
This commit is contained in:
@@ -32,6 +32,8 @@
|
||||
#include "../mem.h"
|
||||
#include "../pic.h"
|
||||
#include "../rom.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
@@ -206,7 +208,7 @@ esdi_writew(uint16_t port, uint16_t val, void *priv)
|
||||
if (esdi->pos >= 512) {
|
||||
esdi->pos = 0;
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 6LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
}
|
||||
@@ -269,7 +271,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
case CMD_RESTORE:
|
||||
esdi->command &= ~0x0f; /*mask off step rate*/
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -277,7 +279,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
case CMD_SEEK:
|
||||
esdi->command &= ~0x0f; /*mask off step rate*/
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -286,7 +288,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
switch (val) {
|
||||
case CMD_NOP:
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -301,7 +303,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
case 0xa0:
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -321,7 +323,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
case CMD_VERIFY+1:
|
||||
esdi->command &= ~0x01;
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -333,14 +335,14 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 30LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
|
||||
case CMD_DIAGNOSE: /* Execute Drive Diagnostics */
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -348,7 +350,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0xe0: /*???*/
|
||||
case CMD_READ_PARAMETERS:
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -357,7 +359,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
pclog("WD1007: bad command %02X\n", val);
|
||||
case 0xe8: /*???*/
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 200LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -367,7 +369,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
case 0x3f6: /* Device control */
|
||||
if ((esdi->fdisk & 0x04) && !(val & 0x04)) {
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 500LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
esdi->reset = 1;
|
||||
@@ -376,7 +378,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
if (val & 0x04) {
|
||||
/*Drive held in reset*/
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 0LL;
|
||||
timer_update_outstanding();
|
||||
esdi->status = STAT_BUSY;
|
||||
@@ -404,7 +406,7 @@ esdi_readw(uint16_t port, void *priv)
|
||||
if (esdi->secount) {
|
||||
next_sector(esdi);
|
||||
esdi->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
esdi->callback = 6LL*HDC_TIME;
|
||||
timer_update_outstanding();
|
||||
} else {
|
||||
|
||||
@@ -185,6 +185,7 @@ typedef struct esdi {
|
||||
#define CMD_READ_VERIFY 0x03
|
||||
#define CMD_WRITE_VERIFY 0x04
|
||||
#define CMD_SEEK 0x05
|
||||
#define CMD_GET_DEV_STATUS 0x08
|
||||
#define CMD_GET_DEV_CONFIG 0x09
|
||||
#define CMD_GET_POS_INFO 0x0a
|
||||
|
||||
@@ -249,6 +250,25 @@ device_not_present(esdi_t *dev)
|
||||
set_irq(dev);
|
||||
}
|
||||
|
||||
static void rba_out_of_range(esdi_t *dev)
|
||||
{
|
||||
dev->status_len = 9;
|
||||
dev->status_data[0] = dev->command | STATUS_LEN(9) | dev->cmd_dev;
|
||||
dev->status_data[1] = 0x0e01; /*Command block error, invalid parameter*/
|
||||
dev->status_data[2] = 0x0007; /*RBA out of range*/
|
||||
dev->status_data[3] = 0;
|
||||
dev->status_data[4] = 0;
|
||||
dev->status_data[5] = 0;
|
||||
dev->status_data[6] = 0;
|
||||
dev->status_data[7] = 0;
|
||||
dev->status_data[8] = 0;
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_FAILURE;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
}
|
||||
|
||||
#define ESDI_ADAPTER_ONLY() do \
|
||||
{ \
|
||||
if (dev->cmd_dev != ATTN_HOST_ADAPTER) \
|
||||
@@ -306,6 +326,11 @@ esdi_callback(void *priv)
|
||||
dev->sector_pos = 0;
|
||||
dev->sector_count = dev->cmd_data[1];
|
||||
|
||||
if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) {
|
||||
rba_out_of_range(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY;
|
||||
dev->irq_in_progress = 1;
|
||||
@@ -375,6 +400,11 @@ esdi_callback(void *priv)
|
||||
dev->sector_pos = 0;
|
||||
dev->sector_count = dev->cmd_data[1];
|
||||
|
||||
if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) {
|
||||
rba_out_of_range(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_CMD_IN_PROGRESS | STATUS_TRANSFER_REQ;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_DATA_TRANSFER_READY;
|
||||
dev->irq_in_progress = 1;
|
||||
@@ -436,6 +466,11 @@ esdi_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dev->rba + dev->sector_count) > hdd_image_get_last_sector(drive->hdd_num)) {
|
||||
rba_out_of_range(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->status = STATUS_IRQ;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
@@ -456,6 +491,36 @@ esdi_callback(void *priv)
|
||||
set_irq(dev);
|
||||
break;
|
||||
|
||||
case CMD_GET_DEV_STATUS:
|
||||
ESDI_DRIVE_ONLY();
|
||||
|
||||
if (! drive->present) {
|
||||
device_not_present(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->status_pos)
|
||||
fatal("Status send in progress\n");
|
||||
if ((dev->status & STATUS_IRQ) || dev->irq_in_progress)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
dev->status_len = 9;
|
||||
dev->status_data[0] = CMD_GET_DEV_STATUS | STATUS_LEN(9) | STATUS_DEVICE_HOST_ADAPTER;
|
||||
dev->status_data[1] = 0x0000; /*Error bits*/
|
||||
dev->status_data[2] = 0x1900; /*Device status*/
|
||||
dev->status_data[3] = 0; /*ESDI Standard Status*/
|
||||
dev->status_data[4] = 0; /*ESDI Vendor Unique Status*/
|
||||
dev->status_data[5] = 0;
|
||||
dev->status_data[6] = 0;
|
||||
dev->status_data[7] = 0;
|
||||
dev->status_data[8] = 0;
|
||||
|
||||
dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL;
|
||||
dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS;
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
break;
|
||||
|
||||
case CMD_GET_DEV_CONFIG:
|
||||
ESDI_DRIVE_ONLY();
|
||||
|
||||
@@ -470,7 +535,7 @@ esdi_callback(void *priv)
|
||||
fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress);
|
||||
|
||||
dev->status_len = 6;
|
||||
dev->status_data[0] = CMD_GET_POS_INFO | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER;
|
||||
dev->status_data[0] = CMD_GET_DEV_CONFIG | STATUS_LEN(6) | STATUS_DEVICE_HOST_ADAPTER;
|
||||
dev->status_data[1] = 0x10; /*Zero defect*/
|
||||
dev->status_data[2] = drive->sectors & 0xffff;
|
||||
dev->status_data[3] = drive->sectors >> 16;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "../device.h"
|
||||
#include "../io.h"
|
||||
#include "../pic.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../machine/machine.h"
|
||||
#include "../timer.h"
|
||||
#include "../plat.h"
|
||||
#include "../ui.h"
|
||||
@@ -223,7 +225,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
mfm->drvsel, val);
|
||||
mfm->command = 0xff;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
|
||||
@@ -250,7 +252,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
drive->steprate = (val & 0x0f);
|
||||
mfm->command = (val & 0xf0);
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -269,7 +271,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
if (val & 2)
|
||||
fatal("WD1003: READ with ECC\n");
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -293,7 +295,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
case CMD_VERIFY+1:
|
||||
mfm->command = (val & 0xfe);
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -307,7 +309,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
case CMD_DIAGNOSE:
|
||||
mfm->command = val;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -350,7 +352,7 @@ mfm_cmd(mfm_t *mfm, uint8_t val)
|
||||
default:
|
||||
pclog("WD1003: bad command %02X\n", val);
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 200LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
break;
|
||||
@@ -370,7 +372,7 @@ mfm_writew(uint16_t port, uint16_t val, void *priv)
|
||||
if (mfm->pos >= 512) {
|
||||
mfm->pos = 0;
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 6LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
}
|
||||
@@ -428,7 +430,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
|
||||
if ((mfm->fdisk & 0x04) && !(val & 0x04)) {
|
||||
mfm->status = STAT_BUSY;
|
||||
mfm->reset = 1;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 500LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
}
|
||||
@@ -437,7 +439,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
|
||||
/* Drive held in reset. */
|
||||
mfm->status = STAT_BUSY;
|
||||
mfm->callback = 0LL;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
timer_update_outstanding();
|
||||
}
|
||||
mfm->fdisk = val;
|
||||
@@ -462,7 +464,7 @@ mfm_readw(uint16_t port, void *priv)
|
||||
if (mfm->secount) {
|
||||
next_sector(mfm);
|
||||
mfm->status = STAT_BUSY;
|
||||
timer_process();
|
||||
timer_clock();
|
||||
mfm->callback = 6LL*MFM_TIME;
|
||||
timer_update_outstanding();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user