2017-05-30 03:38:38 +02:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Emulation of the SiS 85c471 chip.
|
|
|
|
|
*
|
2017-08-24 01:14:39 -04:00
|
|
|
* SiS sis85c471 Super I/O Chip
|
2017-09-02 20:39:57 +02:00
|
|
|
* Used by DTK PKM-0038S E-2
|
2017-08-24 01:14:39 -04:00
|
|
|
*
|
2018-11-09 09:37:48 +01:00
|
|
|
* Version: @(#)m_at_sis85c471.c 1.0.12 2018/11/09
|
2017-05-30 03:38:38 +02:00
|
|
|
*
|
|
|
|
|
* Author: Miran Grca, <mgrca8@gmail.com>
|
2017-10-07 22:18:30 -04:00
|
|
|
*
|
2018-01-17 18:43:36 +01:00
|
|
|
* Copyright 2015-2018 Miran Grca.
|
2017-05-30 03:38:38 +02:00
|
|
|
*/
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdint.h>
|
2018-11-08 19:21:55 +01:00
|
|
|
#include <stdlib.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <wchar.h>
|
2017-10-17 01:59:09 -04:00
|
|
|
#include "../86box.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../io.h"
|
|
|
|
|
#include "../memregs.h"
|
2017-10-01 16:29:15 -04:00
|
|
|
#include "../device.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../lpt.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../serial.h"
|
2017-10-02 02:15:35 -04:00
|
|
|
#include "../disk/hdc.h"
|
|
|
|
|
#include "../disk/hdc_ide.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../floppy/fdd.h"
|
2018-01-17 18:43:36 +01:00
|
|
|
#include "../floppy/fdc.h"
|
2017-10-07 22:18:30 -04:00
|
|
|
#include "machine.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-08-24 01:14:39 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
typedef struct {
|
|
|
|
|
uint8_t cur_reg,
|
|
|
|
|
regs[39];
|
|
|
|
|
} sis_85c471_t;
|
2017-09-02 20:39:57 +02:00
|
|
|
|
|
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static void
|
|
|
|
|
sis_85c471_write(uint16_t port, uint8_t val, void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2018-11-08 19:21:55 +01:00
|
|
|
sis_85c471_t *dev = (sis_85c471_t *) priv;
|
|
|
|
|
uint8_t index = (port & 1) ? 0 : 1;
|
|
|
|
|
uint8_t valxor;
|
|
|
|
|
serial_t *uart[2];
|
|
|
|
|
|
|
|
|
|
if (index) {
|
|
|
|
|
if ((val >= 0x50) && (val <= 0x76))
|
|
|
|
|
dev->cur_reg = val;
|
2016-06-26 00:34:39 +02:00
|
|
|
return;
|
2018-11-08 19:21:55 +01:00
|
|
|
} else {
|
|
|
|
|
if ((dev->cur_reg < 0x50) || (dev->cur_reg > 0x76))
|
|
|
|
|
return;
|
|
|
|
|
valxor = val ^ dev->regs[dev->cur_reg - 0x50];
|
|
|
|
|
/* Writes to 0x52 are blocked as otherwise, large hard disks don't read correctly. */
|
|
|
|
|
if (dev->cur_reg != 0x52)
|
|
|
|
|
dev->regs[dev->cur_reg - 0x50] = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(dev->cur_reg) {
|
|
|
|
|
case 0x73:
|
|
|
|
|
if (valxor & 0x40) {
|
|
|
|
|
ide_pri_disable();
|
|
|
|
|
if (val & 0x40)
|
|
|
|
|
ide_pri_enable();
|
|
|
|
|
}
|
|
|
|
|
if (valxor & 0x20) {
|
|
|
|
|
uart[0] = machine_get_serial(0);
|
|
|
|
|
uart[1] = machine_get_serial(1);
|
|
|
|
|
serial_remove(uart[0]);
|
|
|
|
|
serial_remove(uart[1]);
|
|
|
|
|
if (val & 0x20) {
|
|
|
|
|
serial_setup(uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
|
|
|
|
|
serial_setup(uart[0], SERIAL2_ADDR, SERIAL2_IRQ);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2018-11-08 19:21:55 +01:00
|
|
|
}
|
|
|
|
|
if (valxor & 0x10) {
|
|
|
|
|
lpt1_remove();
|
|
|
|
|
if (val & 0x10)
|
|
|
|
|
lpt1_init(0x378);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev->cur_reg = 0;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static uint8_t
|
|
|
|
|
sis_85c471_read(uint16_t port, void *priv)
|
|
|
|
|
{
|
|
|
|
|
sis_85c471_t *dev = (sis_85c471_t *) priv;
|
|
|
|
|
uint8_t index = (port & 1) ? 0 : 1;
|
|
|
|
|
uint8_t ret = 0xff;;
|
|
|
|
|
|
|
|
|
|
if (index)
|
|
|
|
|
ret = dev->cur_reg;
|
|
|
|
|
else {
|
|
|
|
|
if ((dev->cur_reg >= 0x50) && (dev->cur_reg <= 0x76)) {
|
|
|
|
|
ret = dev->regs[dev->cur_reg - 0x50];
|
|
|
|
|
dev->cur_reg = 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2018-11-08 19:21:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-08-24 01:14:39 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static void
|
|
|
|
|
sis_85c471_close(void *priv)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2018-11-08 19:21:55 +01:00
|
|
|
sis_85c471_t *dev = (sis_85c471_t *) priv;
|
|
|
|
|
|
|
|
|
|
free(dev);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-08-24 01:14:39 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
static void *
|
|
|
|
|
sis_85c471_init(const device_t *info)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2018-11-08 19:21:55 +01:00
|
|
|
int mem_size_mb, i = 0;
|
|
|
|
|
|
|
|
|
|
sis_85c471_t *dev = (sis_85c471_t *) malloc(sizeof(sis_85c471_t));
|
|
|
|
|
memset(dev, 0, sizeof(sis_85c471_t));
|
|
|
|
|
|
|
|
|
|
lpt2_remove();
|
|
|
|
|
|
|
|
|
|
dev->cur_reg = 0;
|
|
|
|
|
for (i = 0; i < 0x27; i++)
|
|
|
|
|
dev->regs[i] = 0x00;
|
|
|
|
|
|
|
|
|
|
dev->regs[9] = 0x40;
|
|
|
|
|
|
|
|
|
|
mem_size_mb = mem_size >> 10;
|
|
|
|
|
switch (mem_size_mb) {
|
|
|
|
|
case 0: case 1:
|
|
|
|
|
dev->regs[9] |= 0;
|
|
|
|
|
break;
|
|
|
|
|
case 2: case 3:
|
|
|
|
|
dev->regs[9] |= 1;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
dev->regs[9] |= 2;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
dev->regs[9] |= 0x20;
|
|
|
|
|
break;
|
|
|
|
|
case 6: case 7:
|
|
|
|
|
dev->regs[9] |= 9;
|
|
|
|
|
break;
|
|
|
|
|
case 8: case 9:
|
|
|
|
|
dev->regs[9] |= 4;
|
|
|
|
|
break;
|
|
|
|
|
case 10: case 11:
|
|
|
|
|
dev->regs[9] |= 5;
|
|
|
|
|
break;
|
|
|
|
|
case 12: case 13: case 14: case 15:
|
|
|
|
|
dev->regs[9] |= 0xB;
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
dev->regs[9] |= 0x13;
|
|
|
|
|
break;
|
|
|
|
|
case 17:
|
|
|
|
|
dev->regs[9] |= 0x21;
|
|
|
|
|
break;
|
|
|
|
|
case 18: case 19:
|
|
|
|
|
dev->regs[9] |= 6;
|
|
|
|
|
break;
|
|
|
|
|
case 20: case 21: case 22: case 23:
|
|
|
|
|
dev->regs[9] |= 0xD;
|
|
|
|
|
break;
|
|
|
|
|
case 24: case 25: case 26: case 27:
|
|
|
|
|
case 28: case 29: case 30: case 31:
|
|
|
|
|
dev->regs[9] |= 0xE;
|
|
|
|
|
break;
|
|
|
|
|
case 32: case 33: case 34: case 35:
|
|
|
|
|
dev->regs[9] |= 0x1B;
|
|
|
|
|
break;
|
|
|
|
|
case 36: case 37: case 38: case 39:
|
|
|
|
|
dev->regs[9] |= 0xF;
|
|
|
|
|
break;
|
|
|
|
|
case 40: case 41: case 42: case 43:
|
|
|
|
|
case 44: case 45: case 46: case 47:
|
|
|
|
|
dev->regs[9] |= 0x17;
|
|
|
|
|
break;
|
|
|
|
|
case 48:
|
|
|
|
|
dev->regs[9] |= 0x1E;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (mem_size_mb < 64)
|
|
|
|
|
dev->regs[9] |= 0x1E;
|
|
|
|
|
else if ((mem_size_mb >= 65) && (mem_size_mb < 68))
|
|
|
|
|
dev->regs[9] |= 0x22;
|
|
|
|
|
else
|
|
|
|
|
dev->regs[9] |= 0x24;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
dev->regs[0x11] = 9;
|
|
|
|
|
dev->regs[0x12] = 0xFF;
|
|
|
|
|
dev->regs[0x23] = 0xF0;
|
|
|
|
|
dev->regs[0x26] = 1;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
io_sethandler(0x0022, 0x0002,
|
|
|
|
|
sis_85c471_read, NULL, NULL, sis_85c471_write, NULL, NULL, dev);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
return dev;
|
2017-09-02 20:39:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
const device_t sis_85c471_device = {
|
|
|
|
|
"SiS 85c471",
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
sis_85c471_init, sis_85c471_close, NULL,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2017-10-07 22:18:30 -04:00
|
|
|
void
|
2018-03-19 01:02:04 +01:00
|
|
|
machine_at_dtk486_init(const machine_t *model)
|
2017-09-02 20:39:57 +02:00
|
|
|
{
|
2018-11-08 19:21:55 +01:00
|
|
|
machine_at_ide_init(model);
|
|
|
|
|
device_add(&fdc_at_device);
|
2017-10-07 22:18:30 -04:00
|
|
|
|
2018-11-08 19:21:55 +01:00
|
|
|
memregs_init();
|
|
|
|
|
device_add(&sis_85c471_device);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|