Files
86Box/src/dma.c

1893 lines
51 KiB
C
Raw Normal View History

/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Intel DMA controllers.
*
2020-03-25 00:46:02 +02:00
*
*
2023-01-06 15:36:29 -05:00
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
2017-10-17 01:59:09 -04:00
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include <86box/machine.h>
#include <86box/mca.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/dma.h>
2023-06-28 13:46:28 -04:00
#include <86box/plat_unused.h>
2022-09-18 17:11:43 -04:00
dma_t dma[8];
uint8_t dma_e;
uint8_t dma_m;
static uint8_t dmaregs[3][16];
static int dma_wp[2];
static uint8_t dma_stat;
static uint8_t dma_stat_rq;
static uint8_t dma_stat_rq_pc;
static uint8_t dma_stat_adv_pend;
2022-09-18 17:11:43 -04:00
static uint8_t dma_command[2];
static uint8_t dma_req_is_soft;
static uint8_t dma_advanced;
static uint8_t dma_at;
static uint8_t dma_buffer[65536];
static uint16_t dma_sg_base;
static uint16_t dma16_buffer[65536];
static uint32_t dma_mask;
2023-06-28 13:46:28 -04:00
static struct dma_ps2_t {
int xfr_command;
int xfr_channel;
2022-09-18 17:11:43 -04:00
int byte_ptr;
2022-09-18 17:11:43 -04:00
int is_ps2;
} dma_ps2;
2022-09-18 17:11:43 -04:00
#define DMA_PS2_IOA (1 << 0)
#define DMA_PS2_AUTOINIT (1 << 1)
#define DMA_PS2_XFER_MEM_TO_IO (1 << 2)
#define DMA_PS2_XFER_IO_TO_MEM (3 << 2)
#define DMA_PS2_XFER_MASK (3 << 2)
#define DMA_PS2_DEC2 (1 << 4)
#define DMA_PS2_SIZE16 (1 << 6)
#ifdef ENABLE_DMA_LOG
int dma_do_log = ENABLE_DMA_LOG;
static void
dma_log(const char *fmt, ...)
{
va_list ap;
if (dma_do_log) {
2022-09-18 17:11:43 -04:00
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
2022-09-18 17:11:43 -04:00
# define dma_log(fmt, ...)
#endif
static void dma_ps2_run(int channel);
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
int
dma_get_drq(int channel)
{
return !!(dma_stat_rq_pc & (1 << channel));
}
void
dma_set_drq(int channel, int set)
{
dma_stat_rq_pc &= ~(1 << channel);
if (set)
2022-09-18 17:11:43 -04:00
dma_stat_rq_pc |= (1 << channel);
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
}
static int
dma_transfer_size(dma_t *dev)
{
return dev->transfer_mode & 0xff;
}
static void
dma_sg_next_addr(dma_t *dev)
{
int ts = dma_transfer_size(dev);
2022-09-18 17:11:43 -04:00
dma_bm_read(dev->ptr_cur, (uint8_t *) &(dev->addr), 4, ts);
dma_bm_read(dev->ptr_cur + 4, (uint8_t *) &(dev->count), 4, ts);
dma_log("DMA S/G DWORDs: %08X %08X\n", dev->addr, dev->count);
dev->eot = dev->count >> 31;
dev->count &= 0xfffe;
dev->cb = (uint16_t) dev->count;
2023-06-09 23:46:54 -04:00
dev->cc = dev->count;
if (!dev->count)
2022-09-18 17:11:43 -04:00
dev->count = 65536;
if (ts == 2)
2022-09-18 17:11:43 -04:00
dev->addr &= 0xfffffffe;
dev->ab = dev->addr & dma_mask;
dev->ac = dev->addr & dma_mask;
dev->page = dev->page_l = (dev->ac >> 16) & 0xff;
2022-09-18 17:11:43 -04:00
dev->page_h = (dev->ac >> 24) & 0xff;
dev->ptr_cur += 8;
}
static void
dma_block_transfer(int channel)
{
2023-06-09 23:46:54 -04:00
int bit16 = (channel >= 4);
if (dma_advanced)
2022-09-18 17:11:43 -04:00
bit16 = !!(dma_transfer_size(&(dma[channel])) == 2);
dma_req_is_soft = 1;
2023-05-11 03:02:36 -04:00
for (uint16_t i = 0; i <= dma[channel].cb; i++) {
2022-09-18 17:11:43 -04:00
if ((dma[channel].mode & 0x8c) == 0x84) {
if (bit16)
dma_channel_write(channel, dma16_buffer[i]);
else
dma_channel_write(channel, dma_buffer[i]);
} else if ((dma[channel].mode & 0x8c) == 0x88) {
if (bit16)
dma16_buffer[i] = dma_channel_read(channel);
else
dma_buffer[i] = dma_channel_read(channel);
}
}
dma_req_is_soft = 0;
}
static void
dma_mem_to_mem_transfer(void)
{
int i;
if ((dma[0].mode & 0x0c) != 0x08)
2022-09-18 17:11:43 -04:00
fatal("DMA memory to memory transfer: channel 0 mode not read\n");
if ((dma[1].mode & 0x0c) != 0x04)
2022-09-18 17:11:43 -04:00
fatal("DMA memory to memory transfer: channel 1 mode not write\n");
dma_req_is_soft = 1;
for (i = 0; i <= dma[0].cb; i++)
2022-09-18 17:11:43 -04:00
dma_buffer[i] = dma_channel_read(0);
for (i = 0; i <= dma[1].cb; i++)
2022-09-18 17:11:43 -04:00
dma_channel_write(1, dma_buffer[i]);
dma_req_is_soft = 0;
}
static void
dma_sg_write(uint16_t port, uint8_t val, void *priv)
{
dma_t *dev = (dma_t *) priv;
dma_log("DMA S/G BYTE write: %04X %02X\n", port, val);
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x00:
dma_log("DMA S/G Cmd : val = %02X, old = %02X\n", val, dev->sg_command);
if ((val & 1) && !(dev->sg_command & 1)) { /*Start*/
#ifdef ENABLE_DMA_LOG
2022-09-18 17:11:43 -04:00
dma_log("DMA S/G start\n");
#endif
2022-09-18 17:11:43 -04:00
dev->ptr_cur = dev->ptr;
dma_sg_next_addr(dev);
dev->sg_status = (dev->sg_status & 0xf7) | 0x01;
}
if (!(val & 1) && (dev->sg_command & 1)) { /*Stop*/
#ifdef ENABLE_DMA_LOG
2022-09-18 17:11:43 -04:00
dma_log("DMA S/G stop\n");
#endif
2022-09-18 17:11:43 -04:00
dev->sg_status &= ~0x81;
}
dev->sg_command = val;
break;
case 0x20:
dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc);
dev->ptr %= (mem_size * 1024);
dev->ptr0 = val;
break;
case 0x21:
dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8);
dev->ptr %= (mem_size * 1024);
break;
case 0x22:
dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16);
dev->ptr %= (mem_size * 1024);
break;
case 0x23:
dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24);
dev->ptr %= (mem_size * 1024);
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static void
dma_sg_writew(uint16_t port, uint16_t val, void *priv)
{
dma_t *dev = (dma_t *) priv;
dma_log("DMA S/G WORD write: %04X %04X\n", port, val);
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x00:
dma_sg_write(port, val & 0xff, priv);
break;
case 0x20:
dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc);
dev->ptr %= (mem_size * 1024);
dev->ptr0 = val & 0xff;
break;
case 0x22:
dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16);
dev->ptr %= (mem_size * 1024);
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static void
dma_sg_writel(uint16_t port, uint32_t val, void *priv)
{
dma_t *dev = (dma_t *) priv;
dma_log("DMA S/G DWORD write: %04X %08X\n", port, val);
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x00:
dma_sg_write(port, val & 0xff, priv);
break;
case 0x20:
dev->ptr = (val & 0xfffffffc);
dev->ptr %= (mem_size * 1024);
dev->ptr0 = val & 0xff;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static uint8_t
dma_sg_read(uint16_t port, void *priv)
{
2023-07-20 18:58:26 -04:00
const dma_t *dev = (dma_t *) priv;
uint8_t ret = 0xff;
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x08:
ret = (dev->sg_status & 0x01);
if (dev->eot)
ret |= 0x80;
if ((dev->sg_command & 0xc0) == 0x40)
ret |= 0x20;
if (dev->ab != 0x00000000)
ret |= 0x08;
if (dev->ac != 0x00000000)
ret |= 0x04;
break;
case 0x20:
ret = dev->ptr0;
break;
case 0x21:
ret = dev->ptr >> 8;
break;
case 0x22:
ret = dev->ptr >> 16;
break;
case 0x23:
ret = dev->ptr >> 24;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
dma_log("DMA S/G BYTE read : %04X %02X\n", port, ret);
return ret;
}
static uint16_t
dma_sg_readw(uint16_t port, void *priv)
{
2023-07-20 18:58:26 -04:00
const dma_t *dev = (dma_t *) priv;
uint16_t ret = 0xffff;
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x08:
ret = (uint16_t) dma_sg_read(port, priv);
break;
case 0x20:
ret = dev->ptr0 | (dev->ptr & 0xff00);
break;
case 0x22:
ret = dev->ptr >> 16;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
dma_log("DMA S/G WORD read : %04X %04X\n", port, ret);
return ret;
}
static uint32_t
dma_sg_readl(uint16_t port, void *priv)
{
2023-07-20 18:58:26 -04:00
const dma_t *dev = (dma_t *) priv;
uint32_t ret = 0xffffffff;
port &= 0xff;
if (port < 0x20)
2022-09-18 17:11:43 -04:00
port &= 0xf8;
else
2022-09-18 17:11:43 -04:00
port &= 0xe3;
switch (port) {
2022-09-18 17:11:43 -04:00
case 0x08:
ret = (uint32_t) dma_sg_read(port, priv);
break;
case 0x20:
ret = dev->ptr0 | (dev->ptr & 0xffffff00);
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
dma_log("DMA S/G DWORD read : %04X %08X\n", port, ret);
return ret;
}
static void
2023-06-28 13:46:28 -04:00
dma_ext_mode_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
int channel = (val & 0x03);
if (addr == 0x4d6)
2022-09-18 17:11:43 -04:00
channel |= 4;
dma[channel].ext_mode = val & 0x7c;
switch ((val > 2) & 0x03) {
2022-09-18 17:11:43 -04:00
case 0x00:
dma[channel].transfer_mode = 0x0101;
break;
case 0x01:
dma[channel].transfer_mode = 0x0202;
break;
case 0x02: /* 0x02 is reserved. */
/* Logic says this should be an undocumented mode that counts by words,
but is 8-bit I/O, thus only transferring every second byte. */
dma[channel].transfer_mode = 0x0201;
break;
case 0x03:
dma[channel].transfer_mode = 0x0102;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma_sg_int_status_read(UNUSED(uint16_t addr), UNUSED(void *priv))
{
uint8_t ret = 0x00;
2023-05-11 03:02:36 -04:00
for (uint8_t i = 0; i < 8; i++) {
2022-09-18 17:11:43 -04:00
if (i != 4)
ret = (!!(dma[i].sg_status & 8)) << i;
}
return ret;
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma_read(uint16_t addr, UNUSED(void *priv))
{
2022-09-18 17:11:43 -04:00
int channel = (addr >> 1) & 3;
2024-05-17 01:28:16 +02:00
int count;
uint8_t ret = (dmaregs[0][addr & 0xf]);
switch (addr & 0xf) {
2022-09-18 17:11:43 -04:00
case 0:
case 2:
case 4:
case 6: /*Address registers*/
dma_wp[0] ^= 1;
if (dma_wp[0])
2024-05-17 01:28:16 +02:00
ret = (dma[channel].ac & 0xff);
else
ret = ((dma[channel].ac >> 8) & 0xff);
break;
2022-09-18 17:11:43 -04:00
case 1:
case 3:
case 5:
case 7: /*Count registers*/
dma_wp[0] ^= 1;
count = dma[channel].cc/* + 1*/;
2022-09-18 17:11:43 -04:00
if (dma_wp[0])
2024-05-17 01:28:16 +02:00
ret = count & 0xff;
2022-09-18 17:11:43 -04:00
else
2024-05-17 01:28:16 +02:00
ret = count >> 8;
break;
2022-09-18 17:11:43 -04:00
case 8: /*Status register*/
2024-05-17 01:28:16 +02:00
ret = dma_stat_rq_pc & 0xf;
ret <<= 4;
ret |= dma_stat & 0xf;
2022-09-18 17:11:43 -04:00
dma_stat &= ~0xf;
2024-05-17 01:28:16 +02:00
break;
2022-09-18 17:11:43 -04:00
case 0xd: /*Temporary register*/
2024-05-17 01:28:16 +02:00
ret = 0x00;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
2024-05-17 01:28:16 +02:00
dma_log("DMA: [R] %04X = %02X\n", addr, ret);
return ret;
}
static void
2023-06-28 13:46:28 -04:00
dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
int channel = (addr >> 1) & 3;
2024-05-17 01:28:16 +02:00
dma_log("DMA: [W] %04X = %02X\n", addr, val);
dmaregs[0][addr & 0xf] = val;
switch (addr & 0xf) {
2022-09-18 17:11:43 -04:00
case 0:
case 2:
case 4:
case 6: /*Address registers*/
dma_wp[0] ^= 1;
if (dma_wp[0])
dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val;
else
dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8);
dma[channel].ac = dma[channel].ab;
return;
case 1:
case 3:
case 5:
case 7: /*Count registers*/
dma_wp[0] ^= 1;
if (dma_wp[0])
dma[channel].cb = (dma[channel].cb & 0xff00) | val;
else
dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8);
dma[channel].cc = dma[channel].cb;
return;
case 8: /*Control register*/
dma_command[0] = val;
#ifdef ENABLE_DMA_LOG
2022-09-18 17:11:43 -04:00
if (val & 0x01)
2024-05-17 01:28:16 +02:00
dma_log("[%08X:%04X] Memory-to-memory enable\n", CS, cpu_state.pc);
#endif
2022-09-18 17:11:43 -04:00
return;
case 9: /*Request register */
channel = (val & 3);
if (val & 4) {
dma_stat_rq_pc |= (1 << channel);
if ((channel == 0) && (dma_command[0] & 0x01)) {
2024-05-17 01:28:16 +02:00
dma_log("Memory to memory transfer start\n");
2022-09-18 17:11:43 -04:00
dma_mem_to_mem_transfer();
} else
dma_block_transfer(channel);
} else
dma_stat_rq_pc &= ~(1 << channel);
break;
case 0xa: /*Mask*/
channel = (val & 3);
if (val & 4)
dma_m |= (1 << channel);
else
dma_m &= ~(1 << channel);
return;
case 0xb: /*Mode*/
channel = (val & 3);
dma[channel].mode = val;
if (dma_ps2.is_ps2) {
dma[channel].ps2_mode &= ~0x1c;
if (val & 0x20)
dma[channel].ps2_mode |= 0x10;
if ((val & 0xc) == 8)
dma[channel].ps2_mode |= 4;
else if ((val & 0xc) == 4)
dma[channel].ps2_mode |= 0xc;
}
return;
case 0xc: /*Clear FF*/
dma_wp[0] = 0;
return;
case 0xd: /*Master clear*/
dma_wp[0] = 0;
dma_m |= 0xf;
dma_stat_rq_pc &= ~0x0f;
return;
case 0xe: /*Clear mask*/
dma_m &= 0xf0;
return;
case 0xf: /*Mask write*/
dma_m = (dma_m & 0xf0) | (val & 0xf);
return;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma_ps2_read(uint16_t addr, UNUSED(void *priv))
{
2023-07-20 18:58:26 -04:00
const dma_t *dma_c = &dma[dma_ps2.xfr_channel];
2022-09-18 17:11:43 -04:00
uint8_t temp = 0xff;
switch (addr) {
2022-09-18 17:11:43 -04:00
case 0x1a:
switch (dma_ps2.xfr_command) {
case 2: /*Address*/
case 3:
switch (dma_ps2.byte_ptr) {
case 0:
temp = dma_c->ac & 0xff;
dma_ps2.byte_ptr = 1;
break;
case 1:
temp = (dma_c->ac >> 8) & 0xff;
dma_ps2.byte_ptr = 2;
break;
case 2:
temp = (dma_c->ac >> 16) & 0xff;
dma_ps2.byte_ptr = 0;
break;
2023-06-28 13:46:28 -04:00
default:
break;
2022-09-18 17:11:43 -04:00
}
break;
case 4: /*Count*/
case 5:
if (dma_ps2.byte_ptr)
temp = dma_c->cc >> 8;
else
temp = dma_c->cc & 0xff;
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
break;
case 6: /*Read DMA status*/
if (dma_ps2.byte_ptr) {
temp = ((dma_stat_rq & 0xf0) >> 4) | (dma_stat & 0xf0);
dma_stat &= ~0xf0;
dma_stat_rq &= ~0xf0;
} else {
temp = (dma_stat_rq & 0xf) | ((dma_stat & 0xf) << 4);
dma_stat &= ~0xf;
dma_stat_rq &= ~0xf;
}
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
break;
case 7: /*Mode*/
temp = dma_c->ps2_mode;
break;
case 8: /*Arbitration Level*/
temp = dma_c->arb_level;
break;
default:
fatal("Bad XFR Read command %i channel %i\n", dma_ps2.xfr_command, dma_ps2.xfr_channel);
}
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
2023-05-11 03:02:36 -04:00
return temp;
}
static void
2023-06-28 13:46:28 -04:00
dma_ps2_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
2022-09-18 17:11:43 -04:00
dma_t *dma_c = &dma[dma_ps2.xfr_channel];
uint8_t mode;
switch (addr) {
2022-09-18 17:11:43 -04:00
case 0x18:
dma_ps2.xfr_channel = val & 0x7;
dma_ps2.xfr_command = val >> 4;
dma_ps2.byte_ptr = 0;
switch (dma_ps2.xfr_command) {
case 9: /*Set DMA mask*/
dma_m |= (1 << dma_ps2.xfr_channel);
break;
case 0xa: /*Reset DMA mask*/
dma_m &= ~(1 << dma_ps2.xfr_channel);
break;
case 0xb:
if (!(dma_m & (1 << dma_ps2.xfr_channel)))
dma_ps2_run(dma_ps2.xfr_channel);
break;
2023-06-28 13:46:28 -04:00
default:
break;
2022-09-18 17:11:43 -04:00
}
break;
case 0x1a:
switch (dma_ps2.xfr_command) {
case 0: /*I/O address*/
if (dma_ps2.byte_ptr)
dma_c->io_addr = (dma_c->io_addr & 0x00ff) | (val << 8);
else
dma_c->io_addr = (dma_c->io_addr & 0xff00) | val;
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
break;
case 2: /*Address*/
switch (dma_ps2.byte_ptr) {
case 0:
dma_c->ac = (dma_c->ac & 0xffff00) | val;
dma_ps2.byte_ptr = 1;
break;
case 1:
dma_c->ac = (dma_c->ac & 0xff00ff) | (val << 8);
dma_ps2.byte_ptr = 2;
break;
case 2:
dma_c->ac = (dma_c->ac & 0x00ffff) | (val << 16);
dma_ps2.byte_ptr = 0;
break;
2023-06-28 13:46:28 -04:00
default:
break;
2022-09-18 17:11:43 -04:00
}
dma_c->ab = dma_c->ac;
break;
case 4: /*Count*/
if (dma_ps2.byte_ptr)
dma_c->cc = (dma_c->cc & 0xff) | (val << 8);
else
dma_c->cc = (dma_c->cc & 0xff00) | val;
dma_ps2.byte_ptr = (dma_ps2.byte_ptr + 1) & 1;
dma_c->cb = dma_c->cc;
break;
case 7: /*Mode register*/
mode = 0;
if (val & DMA_PS2_DEC2)
mode |= 0x20;
if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_MEM_TO_IO)
mode |= 8;
else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM)
mode |= 4;
dma_c->mode = (dma_c->mode & ~0x2c) | mode;
if (val & DMA_PS2_AUTOINIT)
dma_c->mode |= 0x10;
dma_c->ps2_mode = val;
dma_c->size = val & DMA_PS2_SIZE16;
break;
case 8: /*Arbitration Level*/
dma_c->arb_level = val;
break;
default:
fatal("Bad XFR command %i channel %i val %02x\n", dma_ps2.xfr_command, dma_ps2.xfr_channel, val);
}
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma16_read(uint16_t addr, UNUSED(void *priv))
{
2022-09-18 17:11:43 -04:00
int channel = ((addr >> 2) & 3) + 4;
#ifdef ENABLE_DMA_LOG
uint16_t port = addr;
#endif
uint8_t ret;
int count;
addr >>= 1;
ret = dmaregs[1][addr & 0xf];
switch (addr & 0xf) {
2022-09-18 17:11:43 -04:00
case 0:
case 2:
case 4:
case 6: /*Address registers*/
dma_wp[1] ^= 1;
if (dma_ps2.is_ps2) {
if (dma_wp[1])
ret = (dma[channel].ac);
else
ret = ((dma[channel].ac >> 8) & 0xff);
} else if (dma_wp[1])
ret = ((dma[channel].ac >> 1) & 0xff);
else
ret = ((dma[channel].ac >> 9) & 0xff);
break;
2022-09-18 17:11:43 -04:00
case 1:
case 3:
case 5:
case 7: /*Count registers*/
dma_wp[1] ^= 1;
count = dma[channel].cc/* + 1*/;
// if (count > dma[channel].cb)
// count = 0x0000;
2022-09-18 17:11:43 -04:00
if (dma_wp[1])
ret = count & 0xff;
2022-09-18 17:11:43 -04:00
else
ret = count >> 8;
break;
2022-09-18 17:11:43 -04:00
case 8: /*Status register*/
ret = (dma_stat_rq_pc & 0xf0);
ret |= dma_stat >> 4;
2022-09-18 17:11:43 -04:00
dma_stat &= ~0xf0;
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
2024-05-17 01:28:16 +02:00
dma_log("dma16_read(%08X) = %02X\n", port, ret);
return ret;
}
static void
2023-06-28 13:46:28 -04:00
dma16_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
int channel = ((addr >> 2) & 3) + 4;
2024-05-17 01:28:16 +02:00
dma_log("dma16_write(%08X, %02X)\n", addr, val);
addr >>= 1;
dmaregs[1][addr & 0xf] = val;
switch (addr & 0xf) {
2022-09-18 17:11:43 -04:00
case 0:
case 2:
case 4:
case 6: /*Address registers*/
dma_wp[1] ^= 1;
if (dma_ps2.is_ps2) {
if (dma_wp[1])
dma[channel].ab = (dma[channel].ab & 0xffffff00 & dma_mask) | val;
else
dma[channel].ab = (dma[channel].ab & 0xffff00ff & dma_mask) | (val << 8);
} else {
if (dma_wp[1])
dma[channel].ab = (dma[channel].ab & 0xfffffe00 & dma_mask) | (val << 1);
else
dma[channel].ab = (dma[channel].ab & 0xfffe01ff & dma_mask) | (val << 9);
}
dma[channel].ac = dma[channel].ab;
return;
case 1:
case 3:
case 5:
case 7: /*Count registers*/
dma_wp[1] ^= 1;
if (dma_wp[1])
dma[channel].cb = (dma[channel].cb & 0xff00) | val;
else
dma[channel].cb = (dma[channel].cb & 0x00ff) | (val << 8);
dma[channel].cc = dma[channel].cb;
return;
case 8: /*Control register*/
return;
case 9: /*Request register */
channel = (val & 3) + 4;
if (val & 4) {
dma_stat_rq_pc |= (1 << channel);
dma_block_transfer(channel);
} else
dma_stat_rq_pc &= ~(1 << channel);
break;
case 0xa: /*Mask*/
channel = (val & 3);
if (val & 4)
dma_m |= (0x10 << channel);
else
dma_m &= ~(0x10 << channel);
return;
case 0xb: /*Mode*/
channel = (val & 3) + 4;
dma[channel].mode = val;
if (dma_ps2.is_ps2) {
dma[channel].ps2_mode &= ~0x1c;
if (val & 0x20)
dma[channel].ps2_mode |= 0x10;
if ((val & 0xc) == 8)
dma[channel].ps2_mode |= 4;
else if ((val & 0xc) == 4)
dma[channel].ps2_mode |= 0xc;
}
return;
case 0xc: /*Clear FF*/
dma_wp[1] = 0;
return;
case 0xd: /*Master clear*/
dma_wp[1] = 0;
dma_m |= 0xf0;
dma_stat_rq_pc &= ~0xf0;
return;
case 0xe: /*Clear mask*/
dma_m &= 0x0f;
return;
case 0xf: /*Mask write*/
dma_m = (dma_m & 0x0f) | ((val & 0xf) << 4);
return;
2023-06-28 13:46:28 -04:00
default:
break;
}
}
2022-09-18 17:11:43 -04:00
#define CHANNELS \
{ \
8, 2, 3, 1, 8, 8, 8, 0 \
}
static void
2023-06-28 13:46:28 -04:00
dma_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
uint8_t convert[8] = CHANNELS;
2024-05-17 01:28:16 +02:00
dma_log("DMA: [W] %04X = %02X\n", addr, val);
#ifdef USE_DYNAREC
WARNING: CONFIGS MIGHT PARTIALLY BREAK WHERE DEVICE NAMES HAVE CHANGED. Changes to device_t struct to accomodate the upcoming PCI IRQ arbitration rewrite; Added device.c/h API to obtain name from the device_t struct; Significant changes to win/win_settings.c to clean up the code a bit and fix bugs; Ported all the CPU and AudioPCI commits from PCem; Added an API call to allow ACPI soft power off to gracefully stop the emulator; Removed the Siemens PCD-2L from the Dev branch because it now works; Removed the Socket 5 HP Vectra from the Dev branch because it now works; Fixed the Compaq Presario and the Micronics Spitfire; Give the IBM PC330 its own list of 486 CPU so it can have DX2's with CPUID 0x470; SMM fixes; Rewrote the SYSENTER, SYSEXIT, SYSCALL, and SYSRET instructions; Changed IDE reset period to match the specification, fixes #929; The keyboard input and output ports are now forced in front of the queue when read, fixes a number of bugs, including the AMI Apollo hanging on soft reset; Added the Intel AN430TX but Dev branched because it does not work; The network code no longer drops packets if the emulated network card has failed to receive them (eg. when the buffer is full); Changes to PCI card adding and renamed some PCI slot types, also added proper AGP bridge slot types; USB UHCI emulation is no longer a stub (still doesn't fully work, but at least Windows XP chk with Debug no longer ASSERT's on it); Fixed NVR on the the SMC FDC37C932QF and APM variants; A number of fixes to Intel 4x0 chipsets, including fixing every register of the 440LX and 440EX; Some ACPI changes.
2020-11-16 00:01:21 +01:00
if ((addr == 0x84) && cpu_use_dynarec)
2022-09-18 17:11:43 -04:00
update_tsc();
#endif
WARNING: CONFIGS MIGHT PARTIALLY BREAK WHERE DEVICE NAMES HAVE CHANGED. Changes to device_t struct to accomodate the upcoming PCI IRQ arbitration rewrite; Added device.c/h API to obtain name from the device_t struct; Significant changes to win/win_settings.c to clean up the code a bit and fix bugs; Ported all the CPU and AudioPCI commits from PCem; Added an API call to allow ACPI soft power off to gracefully stop the emulator; Removed the Siemens PCD-2L from the Dev branch because it now works; Removed the Socket 5 HP Vectra from the Dev branch because it now works; Fixed the Compaq Presario and the Micronics Spitfire; Give the IBM PC330 its own list of 486 CPU so it can have DX2's with CPUID 0x470; SMM fixes; Rewrote the SYSENTER, SYSEXIT, SYSCALL, and SYSRET instructions; Changed IDE reset period to match the specification, fixes #929; The keyboard input and output ports are now forced in front of the queue when read, fixes a number of bugs, including the AMI Apollo hanging on soft reset; Added the Intel AN430TX but Dev branched because it does not work; The network code no longer drops packets if the emulated network card has failed to receive them (eg. when the buffer is full); Changes to PCI card adding and renamed some PCI slot types, also added proper AGP bridge slot types; USB UHCI emulation is no longer a stub (still doesn't fully work, but at least Windows XP chk with Debug no longer ASSERT's on it); Fixed NVR on the the SMC FDC37C932QF and APM variants; A number of fixes to Intel 4x0 chipsets, including fixing every register of the 440LX and 440EX; Some ACPI changes.
2020-11-16 00:01:21 +01:00
addr &= 0x0f;
dmaregs[2][addr] = val;
if (addr >= 8)
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07] | 4;
else
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07];
if (addr < 8) {
2022-09-18 17:11:43 -04:00
dma[addr].page_l = val;
if (addr > 4) {
dma[addr].page = val & 0xfe;
dma[addr].ab = (dma[addr].ab & 0xff01ffff & dma_mask) | (dma[addr].page << 16);
dma[addr].ac = (dma[addr].ac & 0xff01ffff & dma_mask) | (dma[addr].page << 16);
} else {
2023-05-11 03:02:36 -04:00
dma[addr].page = dma_at ? val : val & 0xf;
2022-09-18 17:11:43 -04:00
dma[addr].ab = (dma[addr].ab & 0xff00ffff & dma_mask) | (dma[addr].page << 16);
dma[addr].ac = (dma[addr].ac & 0xff00ffff & dma_mask) | (dma[addr].page << 16);
}
}
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma_page_read(uint16_t addr, UNUSED(void *priv))
{
uint8_t convert[8] = CHANNELS;
2022-09-18 17:11:43 -04:00
uint8_t ret = 0xff;
if (((addr & 0xfffc) == 0x80) && (CS == 0xf000) &&
((cpu_state.pc & 0xfffffff8) == 0x00007278) &&
!strcmp(machine_get_internal_name(), "megapc")) switch (addr) {
/* The Amstrad MegaPC Quadtel BIOS times a sequence of:
mov ax,di
div bx
And expects this value to be at least 0x06e0 for 20 MHz,
and at least 0x0898 for 25 MHz, everything below 0x06e0
is assumed to be 16 MHz. Given that for some reason, this
does not occur on 86Box, we have to work around it here,
2024-02-02 19:56:55 +01:00
we return 0x0580 for 16 MHz, because it logically follows
in the sequence (0x06e0 = 0x0898 * (20 / 25), and
0x0580 = 0x06e0 * (16 / 20)). */
case 0x0081:
if (cpu_busspeed >= 25000000)
ret = 0x98;
else if (cpu_busspeed >= 20000000)
ret = 0xe0;
else
2024-02-02 19:56:55 +01:00
ret = 0x80;
break;
case 0x0082:
if (cpu_busspeed >= 25000000)
ret = 0x08;
else if (cpu_busspeed >= 20000000)
ret = 0x06;
else
ret = 0x05;
break;
} else {
addr &= 0x0f;
ret = dmaregs[2][addr];
if (addr >= 8)
addr = convert[addr & 0x07] | 4;
else
addr = convert[addr & 0x07];
if (addr < 8)
ret = dma[addr].page_l;
}
2024-05-17 01:28:16 +02:00
dma_log("DMA: [R] %04X = %02X\n", addr, ret);
return ret;
}
static void
2023-06-28 13:46:28 -04:00
dma_high_page_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
{
uint8_t convert[8] = CHANNELS;
addr &= 0x0f;
if (addr >= 8)
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07] | 4;
else
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07];
if (addr < 8) {
2022-09-18 17:11:43 -04:00
dma[addr].page_h = val;
2022-09-18 17:11:43 -04:00
dma[addr].ab = ((dma[addr].ab & 0xffffff) | (dma[addr].page << 24)) & dma_mask;
dma[addr].ac = ((dma[addr].ac & 0xffffff) | (dma[addr].page << 24)) & dma_mask;
}
}
static uint8_t
2023-06-28 13:46:28 -04:00
dma_high_page_read(uint16_t addr, UNUSED(void *priv))
{
uint8_t convert[8] = CHANNELS;
2022-09-18 17:11:43 -04:00
uint8_t ret = 0xff;
addr &= 0x0f;
if (addr >= 8)
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07] | 4;
else
2022-09-18 17:11:43 -04:00
addr = convert[addr & 0x07];
if (addr < 8)
2022-09-18 17:11:43 -04:00
ret = dma[addr].page_h;
return ret;
}
void
dma_set_params(uint8_t advanced, uint32_t mask)
{
dma_advanced = advanced;
2022-09-18 17:11:43 -04:00
dma_mask = mask;
}
void
dma_set_mask(uint32_t mask)
{
dma_mask = mask;
2023-05-11 03:02:36 -04:00
for (uint8_t i = 0; i < 8; i++) {
2022-09-18 17:11:43 -04:00
dma[i].ab &= mask;
dma[i].ac &= mask;
}
}
void
dma_set_at(uint8_t at)
{
dma_at = at;
}
void
dma_reset(void)
{
int c;
dma_wp[0] = dma_wp[1] = 0;
2022-09-18 17:11:43 -04:00
dma_m = 0;
2020-01-14 02:14:39 +01:00
dma_e = 0xff;
for (c = 0; c < 16; c++)
2022-09-18 17:11:43 -04:00
dmaregs[0][c] = dmaregs[1][c] = 0;
for (c = 0; c < 8; c++) {
2022-09-18 17:11:43 -04:00
memset(&(dma[c]), 0x00, sizeof(dma_t));
dma[c].size = (c & 4) ? 1 : 0;
dma[c].transfer_mode = (c & 4) ? 0x0202 : 0x0101;
}
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
dma_stat = 0x00;
dma_stat_rq = 0x00;
dma_stat_rq_pc = 0x00;
dma_stat_adv_pend = 0x00;
dma_req_is_soft = 0;
dma_advanced = 0;
memset(dma_buffer, 0x00, sizeof(dma_buffer));
memset(dma16_buffer, 0x00, sizeof(dma16_buffer));
dma_remove_sg();
dma_sg_base = 0x0400;
dma_mask = 0x00ffffff;
2021-12-19 23:41:23 +01:00
dma_at = is286;
}
void
dma_remove_sg(void)
{
io_removehandler(dma_sg_base + 0x0a, 0x01,
2022-09-18 17:11:43 -04:00
dma_sg_int_status_read, NULL, NULL,
NULL, NULL, NULL,
NULL);
2023-05-11 03:02:36 -04:00
for (uint8_t i = 0; i < 8; i++) {
2022-09-18 17:11:43 -04:00
io_removehandler(dma_sg_base + 0x10 + i, 0x01,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
io_removehandler(dma_sg_base + 0x18 + i, 0x01,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
io_removehandler(dma_sg_base + 0x20 + i, 0x04,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
}
}
void
dma_set_sg_base(uint8_t sg_base)
{
dma_sg_base = sg_base << 8;
io_sethandler(dma_sg_base + 0x0a, 0x01,
2022-09-18 17:11:43 -04:00
dma_sg_int_status_read, NULL, NULL,
NULL, NULL, NULL,
NULL);
2023-05-11 03:02:36 -04:00
for (uint8_t i = 0; i < 8; i++) {
2022-09-18 17:11:43 -04:00
io_sethandler(dma_sg_base + 0x10 + i, 0x01,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
io_sethandler(dma_sg_base + 0x18 + i, 0x01,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
io_sethandler(dma_sg_base + 0x20 + i, 0x04,
dma_sg_read, dma_sg_readw, dma_sg_readl,
dma_sg_write, dma_sg_writew, dma_sg_writel,
&dma[i]);
}
}
void
dma_ext_mode_init(void)
{
io_sethandler(0x040b, 0x01,
2022-09-18 17:11:43 -04:00
NULL, NULL, NULL, dma_ext_mode_write, NULL, NULL, NULL);
io_sethandler(0x04d6, 0x01,
2022-09-18 17:11:43 -04:00
NULL, NULL, NULL, dma_ext_mode_write, NULL, NULL, NULL);
}
void
dma_high_page_init(void)
{
io_sethandler(0x0480, 8,
2022-09-18 17:11:43 -04:00
dma_high_page_read, NULL, NULL, dma_high_page_write, NULL, NULL, NULL);
}
void
dma_init(void)
{
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
dma_reset();
io_sethandler(0x0000, 16,
2022-09-18 17:11:43 -04:00
dma_read, NULL, NULL, dma_write, NULL, NULL, NULL);
io_sethandler(0x0080, 8,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
dma_ps2.is_ps2 = 0;
}
void
dma16_init(void)
{
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
dma_reset();
io_sethandler(0x00C0, 32,
2022-09-18 17:11:43 -04:00
dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL);
io_sethandler(0x0088, 8,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
}
void
dma_alias_set(void)
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
io_sethandler(0x0090, 2,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
io_sethandler(0x0093, 13,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
}
2020-02-29 19:12:23 +01:00
void
dma_alias_set_piix(void)
{
io_sethandler(0x0090, 1,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
2020-02-29 19:12:23 +01:00
io_sethandler(0x0094, 3,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
2020-02-29 19:12:23 +01:00
io_sethandler(0x0098, 1,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
2020-02-29 19:12:23 +01:00
io_sethandler(0x009C, 3,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
2020-02-29 19:12:23 +01:00
}
void
dma_alias_remove(void)
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
io_removehandler(0x0090, 2,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
io_removehandler(0x0093, 13,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
}
void
dma_alias_remove_piix(void)
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
io_removehandler(0x0090, 1,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
io_removehandler(0x0094, 3,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
io_removehandler(0x0098, 1,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
io_removehandler(0x009C, 3,
2022-09-18 17:11:43 -04:00
dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
}
void
ps2_dma_init(void)
{
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
dma_reset();
io_sethandler(0x0018, 1,
2022-09-18 17:11:43 -04:00
dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL);
io_sethandler(0x001a, 1,
2022-09-18 17:11:43 -04:00
dma_ps2_read, NULL, NULL, dma_ps2_write, NULL, NULL, NULL);
dma_ps2.is_ps2 = 1;
}
2022-09-18 17:11:43 -04:00
extern void dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize);
extern void dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize);
static int
dma_sg(uint8_t *data, int transfer_length, int out, void *priv)
{
dma_t *dev = (dma_t *) priv;
#ifdef ENABLE_DMA_LOG
char *sop;
#endif
2023-05-11 03:02:36 -04:00
int force_end = 0;
int buffer_pos = 0;
#ifdef ENABLE_DMA_LOG
sop = out ? "Read" : "Writ";
#endif
if (!(dev->sg_status & 1))
2022-09-18 17:11:43 -04:00
return 2; /*S/G disabled*/
dma_log("DMA S/G %s: %i bytes\n", out ? "write" : "read", transfer_length);
while (1) {
2022-09-18 17:11:43 -04:00
if (dev->count <= transfer_length) {
dma_log("%sing %i bytes to %08X\n", sop, dev->count, dev->addr);
if (out)
dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4);
else
dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), dev->count, 4);
transfer_length -= dev->count;
buffer_pos += dev->count;
} else {
dma_log("%sing %i bytes to %08X\n", sop, transfer_length, dev->addr);
if (out)
dma_bm_read(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4);
else
dma_bm_write(dev->addr, (uint8_t *) (data + buffer_pos), transfer_length, 4);
/* Increase addr and decrease count so that resumed transfers do not mess up. */
dev->addr += transfer_length;
dev->count -= transfer_length;
transfer_length = 0;
force_end = 1;
}
if (force_end) {
dma_log("Total transfer length smaller than sum of all blocks, partial block\n");
return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
} else {
if (!transfer_length && !dev->eot) {
dma_log("Total transfer length smaller than sum of all blocks, full block\n");
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
} else if (transfer_length && dev->eot) {
dma_log("Total transfer length greater than sum of all blocks\n");
return 4; /* There is data left to transfer but we have reached EOT - return with error. */
} else if (dev->eot) {
dma_log("Regular EOT\n");
return 5; /* We have regularly reached EOT - clear status and break. */
} else {
/* We have more to transfer and there are blocks left, get next block. */
dma_sg_next_addr(dev);
}
}
}
}
uint8_t
_dma_read(uint32_t addr, dma_t *dma_c)
{
2023-06-09 23:46:54 -04:00
uint8_t temp = 0;
if (dma_advanced) {
2022-09-18 17:11:43 -04:00
if (dma_c->sg_status & 1)
dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&temp, 1, 1, dma_c) << 4);
else
dma_bm_read(addr, &temp, 1, dma_transfer_size(dma_c));
} else
2022-09-18 17:11:43 -04:00
temp = mem_readb_phys(addr);
2023-05-11 03:02:36 -04:00
return temp;
}
static uint16_t
_dma_readw(uint32_t addr, dma_t *dma_c)
{
2023-06-09 23:46:54 -04:00
uint16_t temp = 0;
if (dma_advanced) {
2022-09-18 17:11:43 -04:00
if (dma_c->sg_status & 1)
dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &temp, 2, 1, dma_c) << 4);
else
dma_bm_read(addr, (uint8_t *) &temp, 2, dma_transfer_size(dma_c));
} else
2022-09-18 17:11:43 -04:00
temp = _dma_read(addr, dma_c) | (_dma_read(addr + 1, dma_c) << 8);
2023-05-11 03:02:36 -04:00
return temp;
}
static void
_dma_write(uint32_t addr, uint8_t val, dma_t *dma_c)
{
if (dma_advanced) {
2022-09-18 17:11:43 -04:00
if (dma_c->sg_status & 1)
dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg(&val, 1, 0, dma_c) << 4);
else
dma_bm_write(addr, &val, 1, dma_transfer_size(dma_c));
} else {
2022-09-18 17:11:43 -04:00
mem_writeb_phys(addr, val);
if (dma_at)
mem_invalidate_range(addr, addr);
}
}
static void
_dma_writew(uint32_t addr, uint16_t val, dma_t *dma_c)
{
if (dma_advanced) {
2022-09-18 17:11:43 -04:00
if (dma_c->sg_status & 1)
dma_c->sg_status = (dma_c->sg_status & 0x0f) | (dma_sg((uint8_t *) &val, 2, 0, dma_c) << 4);
else
dma_bm_write(addr, (uint8_t *) &val, 2, dma_transfer_size(dma_c));
} else {
2022-09-18 17:11:43 -04:00
_dma_write(addr, val & 0xff, dma_c);
_dma_write(addr + 1, val >> 8, dma_c);
}
}
static void
dma_retreat(dma_t *dma_c)
{
int as = dma_c->transfer_mode >> 8;
if (dma->sg_status & 1) {
2022-09-18 17:11:43 -04:00
dma_c->ac = (dma_c->ac - as) & dma_mask;
2022-09-18 17:11:43 -04:00
dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff;
dma_c->page_h = (dma_c->ac >> 24) & 0xff;
} else if (as == 2)
2022-09-18 17:11:43 -04:00
dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac - as) & 0xffff);
else
2022-09-18 17:11:43 -04:00
dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac - as) & 0xffff);
}
void
dma_advance(dma_t *dma_c)
{
int as = dma_c->transfer_mode >> 8;
if (dma->sg_status & 1) {
2022-09-18 17:11:43 -04:00
dma_c->ac = (dma_c->ac + as) & dma_mask;
2022-09-18 17:11:43 -04:00
dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff;
dma_c->page_h = (dma_c->ac >> 24) & 0xff;
} else if (as == 2)
2022-09-18 17:11:43 -04:00
dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac + as) & 0xffff);
else
2022-09-18 17:11:43 -04:00
dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac + as) & 0xffff);
}
int
dma_channel_readable(int channel)
{
dma_t *dma_c = &dma[channel];
int ret = 1;
if (channel < 4) {
if (dma_command[0] & 0x04)
ret = 0;
} else {
if (dma_command[1] & 0x04)
ret = 0;
}
if (!(dma_e & (1 << channel)))
ret = 0;
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
ret = 0;
if ((dma_c->mode & 0xC) != 8)
ret = 0;
return ret;
}
int
dma_channel_read_only(int channel)
{
dma_t *dma_c = &dma[channel];
uint16_t temp;
if (channel < 4) {
if (dma_command[0] & 0x04)
return (DMA_NODATA);
} else {
if (dma_command[1] & 0x04)
return (DMA_NODATA);
}
if (!(dma_e & (1 << channel)))
return (DMA_NODATA);
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
return (DMA_NODATA);
if ((dma_c->mode & 0xC) != 8)
return (DMA_NODATA);
dma_channel_advance(channel);
if (!dma_at && !channel)
refreshread();
if (!dma_c->size) {
temp = _dma_read(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac--;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
temp = _dma_readw(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac -= 2;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
dma_stat_rq |= (1 << channel);
dma_stat_adv_pend |= (1 << channel);
return temp;
}
int
dma_channel_advance(int channel)
{
dma_t *dma_c = &dma[channel];
int tc = 0;
if (dma_stat_adv_pend & (1 << channel)) {
dma_c->cc--;
if (dma_c->cc < 0) {
if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6))
dma_sg_next_addr(dma_c);
else {
tc = 1;
if (dma_c->mode & 0x10) { /*Auto-init*/
dma_c->cc = dma_c->cb;
dma_c->ac = dma_c->ab;
} else
dma_m |= (1 << channel);
dma_stat |= (1 << channel);
}
}
if (tc) {
if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) {
picint(1 << 13);
dma_c->sg_status |= 8;
}
}
dma_stat_adv_pend &= ~(1 << channel);
}
return tc;
}
int
dma_channel_read(int channel)
{
2022-09-18 17:11:43 -04:00
dma_t *dma_c = &dma[channel];
uint16_t temp;
2022-09-18 17:11:43 -04:00
int tc = 0;
if (channel < 4) {
2022-09-18 17:11:43 -04:00
if (dma_command[0] & 0x04)
return (DMA_NODATA);
} else {
2022-09-18 17:11:43 -04:00
if (dma_command[1] & 0x04)
return (DMA_NODATA);
}
2020-01-14 02:14:39 +01:00
if (!(dma_e & (1 << channel)))
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if ((dma_c->mode & 0xC) != 8)
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if (dma_stat_adv_pend & (1 << channel))
dma_channel_advance(channel);
if (!dma_at && !channel)
2022-09-18 17:11:43 -04:00
refreshread();
if (!dma_c->size) {
temp = _dma_read(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac--;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
2022-09-18 17:11:43 -04:00
temp = _dma_readw(dma_c->ac, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac -= 2;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
dma_stat_rq |= (1 << channel);
dma_c->cc--;
if (dma_c->cc < 0) {
2022-09-18 17:11:43 -04:00
if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6))
dma_sg_next_addr(dma_c);
else {
tc = 1;
if (dma_c->mode & 0x10) { /*Auto-init*/
dma_c->cc = dma_c->cb;
dma_c->ac = dma_c->ab;
} else
dma_m |= (1 << channel);
dma_stat |= (1 << channel);
}
}
if (tc) {
2022-09-18 17:11:43 -04:00
if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) {
picint(1 << 13);
dma_c->sg_status |= 8;
}
2022-09-18 17:11:43 -04:00
return (temp | DMA_OVER);
}
2023-05-11 03:02:36 -04:00
return temp;
}
int
dma_channel_write(int channel, uint16_t val)
{
dma_t *dma_c = &dma[channel];
if (channel < 4) {
2022-09-18 17:11:43 -04:00
if (dma_command[0] & 0x04)
return (DMA_NODATA);
} else {
2022-09-18 17:11:43 -04:00
if (dma_command[1] & 0x04)
return (DMA_NODATA);
}
2020-01-14 02:14:39 +01:00
if (!(dma_e & (1 << channel)))
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if ((dma_m & (1 << channel)) && !dma_req_is_soft)
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if ((dma_c->mode & 0xC) != 4)
2022-09-18 17:11:43 -04:00
return (DMA_NODATA);
if (!dma_c->size) {
_dma_write(dma_c->ac, val & 0xff, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac--;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac - 1) & 0xffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac++;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xffff0000 & dma_mask) | ((dma_c->ac + 1) & 0xffff);
}
} else {
2022-09-18 17:11:43 -04:00
_dma_writew(dma_c->ac, val, dma_c);
if (dma_c->mode & 0x20) {
if (dma_ps2.is_ps2)
dma_c->ac -= 2;
else if (dma_advanced)
dma_retreat(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac - 2) & 0x1ffff);
} else {
if (dma_ps2.is_ps2)
dma_c->ac += 2;
else if (dma_advanced)
dma_advance(dma_c);
else
dma_c->ac = (dma_c->ac & 0xfffe0000 & dma_mask) | ((dma_c->ac + 2) & 0x1ffff);
}
}
dma_stat_rq |= (1 << channel);
dma_stat_adv_pend &= ~(1 << channel);
dma_c->cc--;
if (dma_c->cc < 0) {
2022-09-18 17:11:43 -04:00
if (dma_advanced && (dma_c->sg_status & 1) && !(dma_c->sg_status & 6))
dma_sg_next_addr(dma_c);
else {
if (dma_c->mode & 0x10) { /*Auto-init*/
dma_c->cc = dma_c->cb;
dma_c->ac = dma_c->ab;
} else
dma_m |= (1 << channel);
dma_stat |= (1 << channel);
}
}
if (dma_m & (1 << channel)) {
2022-09-18 17:11:43 -04:00
if (dma_advanced && (dma_c->sg_status & 1) && ((dma_c->sg_command & 0xc0) == 0x40)) {
picint(1 << 13);
dma_c->sg_status |= 8;
}
2023-05-11 03:02:36 -04:00
return DMA_OVER;
}
2023-05-11 03:02:36 -04:00
return 0;
}
static void
dma_ps2_run(int channel)
{
dma_t *dma_c = &dma[channel];
switch (dma_c->ps2_mode & DMA_PS2_XFER_MASK) {
2022-09-18 17:11:43 -04:00
case DMA_PS2_XFER_MEM_TO_IO:
do {
if (!dma_c->size) {
uint8_t temp = _dma_read(dma_c->ac, dma_c);
outb(dma_c->io_addr, temp);
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac--;
else
dma_c->ac++;
} else {
uint16_t temp = _dma_readw(dma_c->ac, dma_c);
outw(dma_c->io_addr, temp);
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac -= 2;
else
dma_c->ac += 2;
}
dma_stat_rq |= (1 << channel);
dma_c->cc--;
} while (dma_c->cc > 0);
dma_stat |= (1 << channel);
break;
case DMA_PS2_XFER_IO_TO_MEM:
do {
if (!dma_c->size) {
uint8_t temp = inb(dma_c->io_addr);
_dma_write(dma_c->ac, temp, dma_c);
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac--;
else
dma_c->ac++;
} else {
uint16_t temp = inw(dma_c->io_addr);
_dma_writew(dma_c->ac, temp, dma_c);
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac -= 2;
else
dma_c->ac += 2;
}
dma_stat_rq |= (1 << channel);
dma_c->cc--;
} while (dma_c->cc > 0);
ps2_cache_clean();
dma_stat |= (1 << channel);
break;
default: /*Memory verify*/
do {
if (!dma_c->size) {
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac--;
else
dma_c->ac++;
} else {
if (dma_c->ps2_mode & DMA_PS2_DEC2)
dma_c->ac -= 2;
else
dma_c->ac += 2;
}
dma_stat_rq |= (1 << channel);
dma->cc--;
} while (dma->cc > 0);
dma_stat |= (1 << channel);
break;
}
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
}
int
dma_mode(int channel)
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
2022-09-18 17:11:43 -04:00
return (dma[channel].mode);
}
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
/* DMA Bus Master Page Read/Write */
void
dma_bm_read(uint32_t PhysAddress, uint8_t *DataRead, uint32_t TotalSize, int TransferSize)
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
2023-05-11 03:02:36 -04:00
uint32_t n;
uint32_t n2;
2022-09-18 17:11:43 -04:00
uint8_t bytes[4] = { 0, 0, 0, 0 };
2022-09-18 17:11:43 -04:00
n = TotalSize & ~(TransferSize - 1);
n2 = TotalSize - n;
/* Do the divisible block, if there is one. */
if (n) {
2023-05-11 03:02:36 -04:00
for (uint32_t i = 0; i < n; i += TransferSize)
2022-09-18 17:11:43 -04:00
mem_read_phys((void *) &(DataRead[i]), PhysAddress + i, TransferSize);
}
/* Do the non-divisible block, if there is one. */
if (n2) {
2022-09-18 17:11:43 -04:00
mem_read_phys((void *) bytes, PhysAddress + n, TransferSize);
memcpy((void *) &(DataRead[n]), bytes, n2);
}
}
void
dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, int TransferSize)
{
2023-05-11 03:02:36 -04:00
uint32_t n;
uint32_t n2;
2022-09-18 17:11:43 -04:00
uint8_t bytes[4] = { 0, 0, 0, 0 };
2022-09-18 17:11:43 -04:00
n = TotalSize & ~(TransferSize - 1);
n2 = TotalSize - n;
/* Do the divisible block, if there is one. */
if (n) {
2023-05-11 03:02:36 -04:00
for (uint32_t i = 0; i < n; i += TransferSize)
2022-09-18 17:11:43 -04:00
mem_write_phys((void *) &(DataWrite[i]), PhysAddress + i, TransferSize);
}
/* Do the non-divisible block, if there is one. */
if (n2) {
2022-09-18 17:11:43 -04:00
mem_read_phys((void *) bytes, PhysAddress + n, TransferSize);
memcpy(bytes, (void *) &(DataWrite[n]), n2);
mem_write_phys((void *) bytes, PhysAddress + n, TransferSize);
}
if (dma_at)
2022-09-18 17:11:43 -04:00
mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1);
}