2016-08-14 22:07:17 -04:00
|
|
|
/* Copyright holders: Sarah Walker
|
|
|
|
|
see COPYING for more details
|
|
|
|
|
*/
|
2016-06-26 00:34:39 +02:00
|
|
|
#include <stdlib.h>
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../ibm.h"
|
|
|
|
|
#include "../cpu/cpu.h"
|
|
|
|
|
#include "../io.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../pci.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "../mem.h"
|
|
|
|
|
#include "../memregs.h"
|
2017-09-04 01:52:29 -04:00
|
|
|
#include "../sio.h"
|
2017-09-02 20:39:57 +02:00
|
|
|
#include "machine_at.h"
|
|
|
|
|
#include "machine_at_sis_85c496.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct sis_85c496_t
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
uint8_t pci_conf[256];
|
2017-09-02 20:39:57 +02:00
|
|
|
} sis_85c496_t;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
sis_85c496_t sis496;
|
2017-05-21 19:16:23 +02:00
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void sis_85c496_recalcmapping(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
for (c = 0; c < 8; c++)
|
|
|
|
|
{
|
|
|
|
|
uint32_t base = 0xc0000 + (c << 15);
|
2017-05-21 19:16:23 +02:00
|
|
|
if (sis496.pci_conf[0x44] & (1 << c))
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-21 19:16:23 +02:00
|
|
|
switch (sis496.pci_conf[0x45] & 3)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flushmmucache();
|
2017-05-21 19:16:23 +02:00
|
|
|
shadowbios = (sis496.pci_conf[0x44] & 0xf0);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void sis_85c496_write(int func, int addr, uint8_t val, void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
switch (addr)
|
|
|
|
|
{
|
|
|
|
|
case 0x44: /*Shadow configure*/
|
2017-05-21 19:16:23 +02:00
|
|
|
if ((sis496.pci_conf[0x44] & val) ^ 0xf0)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x44] = val;
|
2017-09-02 20:39:57 +02:00
|
|
|
sis_85c496_recalcmapping();
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 0x45: /*Shadow configure*/
|
2017-05-21 19:16:23 +02:00
|
|
|
if ((sis496.pci_conf[0x45] & val) ^ 0x01)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x45] = val;
|
2017-09-02 20:39:57 +02:00
|
|
|
sis_85c496_recalcmapping();
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2017-06-02 01:38:25 +02:00
|
|
|
case 0xc0:
|
|
|
|
|
if (val & 0x80)
|
|
|
|
|
pci_set_irq_routing(PCI_INTA, val & 0xf);
|
|
|
|
|
else
|
|
|
|
|
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
|
|
|
|
|
break;
|
|
|
|
|
case 0xc1:
|
|
|
|
|
if (val & 0x80)
|
|
|
|
|
pci_set_irq_routing(PCI_INTB, val & 0xf);
|
|
|
|
|
else
|
|
|
|
|
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
|
|
|
|
|
break;
|
|
|
|
|
case 0xc2:
|
|
|
|
|
if (val & 0x80)
|
|
|
|
|
pci_set_irq_routing(PCI_INTC, val & 0xf);
|
|
|
|
|
else
|
|
|
|
|
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
|
|
|
|
|
break;
|
|
|
|
|
case 0xc3:// pclog("IRQ routing %02x %02x\n", addr, val);
|
|
|
|
|
if (val & 0x80)
|
|
|
|
|
pci_set_irq_routing(PCI_INTD, val & 0xf);
|
|
|
|
|
else
|
|
|
|
|
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
if ((addr >= 4 && addr < 8) || addr >= 0x40)
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[addr] = val;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static uint8_t sis_85c496_read(int func, int addr, void *p)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-05-21 19:16:23 +02:00
|
|
|
return sis496.pci_conf[addr];
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void sis_85c496_reset(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-09-02 20:39:57 +02:00
|
|
|
memset(&sis496, 0, sizeof(sis_85c496_t));
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x00] = 0x39; /*SiS*/
|
|
|
|
|
sis496.pci_conf[0x01] = 0x10;
|
|
|
|
|
sis496.pci_conf[0x02] = 0x96; /*496/497*/
|
|
|
|
|
sis496.pci_conf[0x03] = 0x04;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x04] = 7;
|
|
|
|
|
sis496.pci_conf[0x05] = 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x06] = 0x80;
|
|
|
|
|
sis496.pci_conf[0x07] = 0x02;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x08] = 2; /*Device revision*/
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/
|
|
|
|
|
sis496.pci_conf[0x0a] = 0x00;
|
|
|
|
|
sis496.pci_conf[0x0b] = 0x06;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-05-21 19:16:23 +02:00
|
|
|
sis496.pci_conf[0x0e] = 0x00; /*Single function device*/
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void sis_85c496_pci_reset(void)
|
2017-05-21 19:16:23 +02:00
|
|
|
{
|
|
|
|
|
uint8_t val = 0;
|
|
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
val = sis_85c496_read(0, 0x44, NULL); /* Read current value of 0x44. */
|
|
|
|
|
sis_85c496_write(0, 0x44, val & 0xf, NULL); /* Turn off shadow BIOS but keep the lower 4 bits. */
|
2017-05-21 19:16:23 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void sis_85c496_init(void)
|
2017-05-21 19:16:23 +02:00
|
|
|
{
|
2017-09-02 20:39:57 +02:00
|
|
|
pci_add_card(5, sis_85c496_read, sis_85c496_write, NULL);
|
2017-05-21 19:16:23 +02:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
sis_85c496_reset();
|
2017-05-21 19:16:23 +02:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
pci_reset_handler.pci_master_reset = sis_85c496_pci_reset;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2017-06-16 16:00:44 -04:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
static void machine_at_sis_85c496_common_init(void)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2017-09-02 20:39:57 +02:00
|
|
|
machine_at_ide_init();
|
|
|
|
|
memregs_init();
|
|
|
|
|
pci_init(PCI_CONFIG_TYPE_1);
|
|
|
|
|
pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0);
|
|
|
|
|
pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
|
|
|
|
pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
|
|
|
|
pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
|
|
|
|
pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
|
|
|
|
sis_85c496_init();
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2017-09-02 20:39:57 +02:00
|
|
|
void machine_at_r418_init(void)
|
|
|
|
|
{
|
|
|
|
|
machine_at_sis_85c496_common_init();
|
|
|
|
|
fdc37c665_init();
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|