526 lines
19 KiB
C
526 lines
19 KiB
C
#include <string.h>
|
|
|
|
#include "ibm.h"
|
|
#include "ide.h"
|
|
#include "ide_sff8038i.h"
|
|
#include "io.h"
|
|
#include "mem.h"
|
|
#include "pci.h"
|
|
#include "x86.h"
|
|
|
|
#include "vt82c586b.h"
|
|
|
|
static struct
|
|
{
|
|
uint8_t pci_isa_bridge_regs[256];
|
|
uint8_t ide_regs[256];
|
|
uint8_t usb_regs[256];
|
|
uint8_t power_regs[256];
|
|
|
|
uint8_t sysctrl;
|
|
|
|
sff_busmaster_t busmaster[2];
|
|
|
|
struct
|
|
{
|
|
uint16_t io_base;
|
|
} usb;
|
|
struct
|
|
{
|
|
uint16_t io_base;
|
|
|
|
uint16_t pm_status;
|
|
uint16_t pm_enable;
|
|
uint16_t pm_ctrl;
|
|
|
|
uint16_t gbl_status;
|
|
uint16_t gbl_enable;
|
|
uint16_t gbl_ctrl;
|
|
|
|
uint8_t smi_cmd;
|
|
} power;
|
|
} vt82c586b;
|
|
|
|
#define ACPI_TIMER_FREQ 3579545
|
|
|
|
#define ACPI_IO_ENABLE (1 << 7)
|
|
#define ACPI_TIMER_32BIT (1 << 3)
|
|
|
|
#define GBL_SW_SMI_STS (1 << 6)
|
|
#define GBL_SW_SMI_EN (1 << 6)
|
|
|
|
#define PM_CTRL_SLP_EN (1 << 13)
|
|
#define PM_CTRL_SLP_TYP_MASK (7 << 10)
|
|
|
|
static uint8_t vt82c586b_read(int func, int addr, void *priv)
|
|
{
|
|
switch (func)
|
|
{
|
|
case 0:
|
|
return vt82c586b.pci_isa_bridge_regs[addr];
|
|
|
|
case 1:
|
|
return vt82c586b.ide_regs[addr];
|
|
|
|
case 2:
|
|
return vt82c586b.usb_regs[addr];
|
|
|
|
case 3:
|
|
return vt82c586b.power_regs[addr];
|
|
|
|
default:
|
|
return 0xff;
|
|
}
|
|
}
|
|
|
|
static void vt82c586b_pci_isa_bridge_write(int addr, uint8_t val)
|
|
{
|
|
/*Read-only addresses*/
|
|
if ((addr < 4) || (addr == 5) || (addr == 6)
|
|
|| (addr >= 8 && addr < 0x40)
|
|
|| (addr == 0x49)
|
|
|| (addr == 0x4b)
|
|
|| (addr >= 0x51 && addr < 0x54)
|
|
|| (addr >= 0x5d && addr < 0x60)
|
|
|| (addr >= 0x68 && addr < 0x6a)
|
|
|| (addr >= 0x71))
|
|
return;
|
|
|
|
switch (addr)
|
|
{
|
|
case 4:
|
|
vt82c586b.pci_isa_bridge_regs[4] = (val & 8) | 7;
|
|
break;
|
|
case 6:
|
|
vt82c586b.pci_isa_bridge_regs[6] &= ~(val & 0xb0);
|
|
break;
|
|
|
|
case 0x47:
|
|
if ((val & 0x81) == 0x81)
|
|
resetx86();
|
|
vt82c586b.pci_isa_bridge_regs[0x47] = val & 0xfe;
|
|
break;
|
|
|
|
case 0x55:
|
|
if (!(val & 0xf0))
|
|
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
|
|
else
|
|
pci_set_irq_routing(PCI_INTD, val >> 4);
|
|
vt82c586b.pci_isa_bridge_regs[0x55] = val;
|
|
break;
|
|
case 0x56:
|
|
if (!(val & 0xf0))
|
|
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
|
|
else
|
|
pci_set_irq_routing(PCI_INTA, val >> 4);
|
|
if (!(val & 0x0f))
|
|
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
|
|
else
|
|
pci_set_irq_routing(PCI_INTB, val & 0xf);
|
|
vt82c586b.pci_isa_bridge_regs[0x56] = val;
|
|
break;
|
|
case 0x57:
|
|
if (!(val & 0xf0))
|
|
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
|
|
else
|
|
pci_set_irq_routing(PCI_INTC, val >> 4);
|
|
vt82c586b.pci_isa_bridge_regs[0x57] = val;
|
|
break;
|
|
|
|
default:
|
|
vt82c586b.pci_isa_bridge_regs[addr] = val;
|
|
break;
|
|
}
|
|
}
|
|
static void vt82c586b_ide_write(int addr, uint8_t val)
|
|
{
|
|
/*Read-only addresses*/
|
|
if ((addr < 4) || (addr == 5) || (addr == 8)
|
|
|| (addr >= 0xa && addr < 0x0d)
|
|
|| (addr >= 0x0e && addr < 0x20)
|
|
|| (addr >= 0x22 && addr < 0x3c)
|
|
|| (addr >= 0x3d && addr < 0x40)
|
|
|| (addr >= 0x54 && addr < 0x60)
|
|
|| (addr >= 0x52 && addr < 0x68)
|
|
|| (addr >= 0x62))
|
|
return;
|
|
|
|
switch (addr)
|
|
{
|
|
case 4:
|
|
vt82c586b.ide_regs[4] = val & 0x85;
|
|
break;
|
|
case 6:
|
|
vt82c586b.ide_regs[6] &= ~(val & 0xb0);
|
|
break;
|
|
|
|
case 9:
|
|
vt82c586b.ide_regs[9] = (vt82c586b.pci_isa_bridge_regs[9] & ~0x70) | 0x8a;
|
|
break;
|
|
|
|
case 0x20:
|
|
vt82c586b.ide_regs[0x20] = (val & ~0xf) | 1;
|
|
break;
|
|
|
|
default:
|
|
vt82c586b.ide_regs[addr] = val;
|
|
break;
|
|
}
|
|
|
|
if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/
|
|
{
|
|
uint16_t base = (vt82c586b.ide_regs[0x20] & 0xf0) | (vt82c586b.ide_regs[0x21] << 8);
|
|
io_removehandler(0, 0x10000, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster);
|
|
if (vt82c586b.ide_regs[0x04] & 1)
|
|
io_sethandler(base, 0x10, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster);
|
|
}
|
|
if (addr == 4 || addr == 0x40)
|
|
{
|
|
ide_pri_disable();
|
|
ide_sec_disable();
|
|
if (vt82c586b.ide_regs[0x04] & 1)
|
|
{
|
|
if (vt82c586b.ide_regs[0x40] & 0x02)
|
|
ide_pri_enable();
|
|
if (vt82c586b.ide_regs[0x40] & 0x01)
|
|
ide_sec_enable();
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint8_t usb_reg_read(uint16_t addr, void *p)
|
|
{
|
|
// pclog("usb_reg_read: addr=%04x\n", addr);
|
|
switch (addr & 0x1f)
|
|
{
|
|
case 0x10: case 0x11: case 0x12: case 0x13: /*Port status*/
|
|
return 0;
|
|
}
|
|
return 0xff;
|
|
}
|
|
static void usb_reg_write(uint16_t addr, uint8_t val, void *p)
|
|
{
|
|
// pclog("usb_reg_write: addr=%04x val=%02x\n", addr, val);
|
|
}
|
|
static void usb_update_io_mapping()
|
|
{
|
|
io_removehandler(vt82c586b.usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, NULL);
|
|
vt82c586b.usb.io_base = (vt82c586b.usb_regs[0x20] & ~0x1f) | (vt82c586b.usb_regs[0x21] << 8);
|
|
if (vt82c586b.usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
|
io_sethandler(vt82c586b.usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, NULL);
|
|
}
|
|
static void vt82c586b_usb_write(int addr, uint8_t val)
|
|
{
|
|
/*Read-only addresses*/
|
|
if ((addr < 4) || (addr == 5) || (addr == 6)
|
|
|| (addr >= 8 && addr < 0xd)
|
|
|| (addr >= 0xe && addr < 0x20)
|
|
|| (addr >= 0x22 && addr < 0x3c)
|
|
|| (addr >= 0x3e && addr < 0x40)
|
|
|| (addr >= 0x42 && addr < 0x44)
|
|
|| (addr >= 0x46 && addr < 0xc0)
|
|
|| (addr >= 0xc2))
|
|
return;
|
|
|
|
switch (addr)
|
|
{
|
|
case 4:
|
|
vt82c586b.usb_regs[4] = val & 0x97;
|
|
usb_update_io_mapping();
|
|
break;
|
|
case 7:
|
|
vt82c586b.usb_regs[7] = val & 0x7f;
|
|
break;
|
|
|
|
case 0x20:
|
|
vt82c586b.usb_regs[0x20] = (val & ~0x1f) | 1;
|
|
usb_update_io_mapping();
|
|
break;
|
|
case 0x21:
|
|
vt82c586b.usb_regs[0x21] = val;
|
|
usb_update_io_mapping();
|
|
break;
|
|
|
|
default:
|
|
vt82c586b.usb_regs[addr] = val;
|
|
break;
|
|
}
|
|
// pclog(" USB write %02x %02x\n", addr, val);
|
|
}
|
|
|
|
static uint8_t power_reg_read(uint16_t addr, void *p)
|
|
{
|
|
uint32_t timer;
|
|
uint8_t ret = 0xff;
|
|
|
|
switch (addr & 0xff)
|
|
{
|
|
case 0x00: case 0x01:
|
|
ret = vt82c586b.power.pm_status >> ((addr & 1) * 8);
|
|
break;
|
|
case 0x02: case 0x03:
|
|
ret = vt82c586b.power.pm_enable >> ((addr & 1) * 8);
|
|
break;
|
|
case 0x04: case 0x05:
|
|
ret = vt82c586b.power.pm_ctrl >> ((addr & 1) * 8);
|
|
break;
|
|
|
|
case 0x08: case 0x09: case 0x0a: case 0x0b: /*ACPI timer*/
|
|
timer = (tsc * ACPI_TIMER_FREQ) / cpu_get_speed();
|
|
if (!(vt82c586b.power_regs[0x41] & ACPI_TIMER_32BIT))
|
|
timer &= 0x00ffffff;
|
|
return (timer >> (8 * (addr & 3))) & 0xff;
|
|
|
|
case 0x28: case 0x29:
|
|
ret = vt82c586b.power.gbl_status >> ((addr & 1) * 8);
|
|
break;
|
|
case 0x2a: case 0x2b:
|
|
ret = vt82c586b.power.gbl_enable >> ((addr & 1) * 8);
|
|
break;
|
|
case 0x2c: case 0x2d:
|
|
ret = vt82c586b.power.gbl_ctrl >> ((addr & 1) * 8);
|
|
break;
|
|
|
|
case 0x2f:
|
|
ret = vt82c586b.power.smi_cmd;
|
|
break;
|
|
}
|
|
// pclog("power_reg_read: addr=%04x ret=%02x\n", addr, ret);
|
|
return ret;
|
|
}
|
|
static void power_reg_write(uint16_t addr, uint8_t val, void *p)
|
|
{
|
|
// pclog("power_reg_write: addr=%04x val=%02x\n", addr, val);
|
|
switch (addr & 0xff)
|
|
{
|
|
case 0x00:
|
|
vt82c586b.power.pm_status &= ~(val & 0x31);
|
|
break;
|
|
case 0x01:
|
|
vt82c586b.power.pm_status &= ~((val & 0x8d) << 8);
|
|
break;
|
|
|
|
case 0x02:
|
|
vt82c586b.power.pm_enable = (vt82c586b.power.pm_enable & ~0xff) | (val & 0x21);
|
|
break;
|
|
case 0x03:
|
|
vt82c586b.power.pm_enable = (vt82c586b.power.pm_enable & ~0xff00) | ((val & 0x05) << 8);
|
|
break;
|
|
|
|
case 0x04:
|
|
vt82c586b.power.pm_ctrl = (vt82c586b.power.pm_ctrl & ~0xff) | (val & 0x07);
|
|
if (val & (1 << 2))
|
|
pclog("VT82C586B set GBL_RLS\n");
|
|
break;
|
|
case 0x05:
|
|
vt82c586b.power.pm_ctrl = (vt82c586b.power.pm_ctrl & ~0xff00) | ((val & 0x1c) << 8);
|
|
/*Note: PM_CTRL_SLP_EN is write-only, hence not stored in pm_ctrl*/
|
|
if (val & (PM_CTRL_SLP_EN >> 8))
|
|
{
|
|
pclog("VT82C586B transition to power state %i\n", (val >> 2) & 7);
|
|
if (!(vt82c586b.power.pm_ctrl & PM_CTRL_SLP_TYP_MASK))
|
|
{
|
|
pclog("Power off\n");
|
|
stop_emulation_now();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x28:
|
|
vt82c586b.power.gbl_status &= ~(val & 0x7f);
|
|
break;
|
|
|
|
case 0x2a:
|
|
vt82c586b.power.gbl_enable = (vt82c586b.power.gbl_enable & ~0xff) | (val & 0x7f);
|
|
break;
|
|
|
|
case 0x2c:
|
|
vt82c586b.power.gbl_ctrl = (vt82c586b.power.gbl_ctrl & ~0xff) | (val & 0x17);
|
|
if (val & (1 << 1))
|
|
pclog("VT82C586B set BIOS_RLS\n");
|
|
break;
|
|
case 0x2d:
|
|
if (val & 1)
|
|
vt82c586b.power.gbl_ctrl &= ~0x100;
|
|
break;
|
|
|
|
case 0x2f:
|
|
vt82c586b.power.smi_cmd = val;
|
|
vt82c586b.power_regs[0x47] = val;
|
|
if (vt82c586b.power.gbl_enable & GBL_SW_SMI_EN)
|
|
{
|
|
vt82c586b.power.gbl_status |= GBL_SW_SMI_STS;
|
|
x86_smi_trigger();
|
|
}
|
|
pclog("SMI_CMD write %02x\n", val);
|
|
break;
|
|
}
|
|
}
|
|
static void vt82c586b_power_write(int addr, uint8_t val)
|
|
{
|
|
/*Read-only addresses*/
|
|
if ((addr < 0xd) || (addr >= 0xe && addr < 0x40)
|
|
|| (addr == 0x43)
|
|
|| (addr == 0x48)
|
|
|| (addr >= 0x4a && addr < 0x50)
|
|
|| (addr >= 0x54))
|
|
return;
|
|
|
|
switch (addr)
|
|
{
|
|
case 0x41:
|
|
io_removehandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL);
|
|
vt82c586b.power_regs[addr] = val;
|
|
if (vt82c586b.power_regs[0x41] & ACPI_IO_ENABLE)
|
|
io_sethandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL);
|
|
break;
|
|
|
|
case 0x49:
|
|
io_removehandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL);
|
|
vt82c586b.power_regs[addr] = val;
|
|
vt82c586b.power.io_base = val << 8;
|
|
if (vt82c586b.power_regs[0x41] & ACPI_IO_ENABLE)
|
|
io_sethandler(vt82c586b.power.io_base, 0x0100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, NULL);
|
|
break;
|
|
|
|
default:
|
|
vt82c586b.power_regs[addr] = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void vt82c586b_write(int func, int addr, uint8_t val, void *priv)
|
|
{
|
|
switch (func)
|
|
{
|
|
case 0:
|
|
vt82c586b_pci_isa_bridge_write(addr, val);
|
|
break;
|
|
|
|
case 1:
|
|
vt82c586b_ide_write(addr, val);
|
|
break;
|
|
|
|
case 2:
|
|
vt82c586b_usb_write(addr, val);
|
|
break;
|
|
|
|
case 3:
|
|
vt82c586b_power_write(addr, val);
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint8_t vt82c586b_read_sysctrl(uint16_t port, void *p)
|
|
{
|
|
return vt82c586b.sysctrl;
|
|
}
|
|
|
|
void vt82c586b_write_sysctrl(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
if ((mem_a20_alt ^ val) & 2)
|
|
{
|
|
mem_a20_alt = val & 2;
|
|
mem_a20_recalc();
|
|
}
|
|
if ((~vt82c586b.sysctrl & val) & 1)
|
|
{
|
|
softresetx86();
|
|
cpu_set_edx();
|
|
}
|
|
vt82c586b.sysctrl = val;
|
|
}
|
|
|
|
void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d)
|
|
{
|
|
pci_add_specific(card, vt82c586b_read, vt82c586b_write, NULL);
|
|
io_sethandler(0x0092, 0x0001, vt82c586b_read_sysctrl, NULL, NULL, vt82c586b_write_sysctrl, NULL, NULL, NULL);
|
|
|
|
memset(&vt82c586b, 0, sizeof(vt82c586b));
|
|
vt82c586b.pci_isa_bridge_regs[0x00] = 0x06; vt82c586b.pci_isa_bridge_regs[0x01] = 0x11; /*VIA*/
|
|
vt82c586b.pci_isa_bridge_regs[0x02] = 0x86; vt82c586b.pci_isa_bridge_regs[0x03] = 0x05; /*VT82C586B*/
|
|
vt82c586b.pci_isa_bridge_regs[0x04] = 0x0f; vt82c586b.pci_isa_bridge_regs[0x05] = 0x00;
|
|
vt82c586b.pci_isa_bridge_regs[0x06] = 0x00; vt82c586b.pci_isa_bridge_regs[0x07] = 0x02;
|
|
vt82c586b.pci_isa_bridge_regs[0x0a] = 0x01;
|
|
vt82c586b.pci_isa_bridge_regs[0x0b] = 0x06;
|
|
vt82c586b.pci_isa_bridge_regs[0x0e] = 0x80;
|
|
|
|
/*ISA bus control*/
|
|
vt82c586b.pci_isa_bridge_regs[0x48] = 0x01;
|
|
vt82c586b.pci_isa_bridge_regs[0x4a] = 0x04;
|
|
vt82c586b.pci_isa_bridge_regs[0x4f] = 0x03;
|
|
|
|
/*Plug and Play control*/
|
|
vt82c586b.pci_isa_bridge_regs[0x50] = 0x24;
|
|
vt82c586b.pci_isa_bridge_regs[0x59] = 0x04;
|
|
|
|
vt82c586b.ide_regs[0x00] = 0x06; vt82c586b.ide_regs[0x01] = 0x11; /*VIA*/
|
|
vt82c586b.ide_regs[0x02] = 0x71; vt82c586b.ide_regs[0x03] = 0x05;
|
|
vt82c586b.ide_regs[0x04] = 0x80; vt82c586b.ide_regs[0x05] = 0x00;
|
|
vt82c586b.ide_regs[0x06] = 0x80; vt82c586b.ide_regs[0x07] = 0x02;
|
|
vt82c586b.ide_regs[0x09] = 0x85;
|
|
vt82c586b.ide_regs[0x0a] = 0x01;
|
|
vt82c586b.ide_regs[0x0b] = 0x01;
|
|
|
|
vt82c586b.ide_regs[0x10] = 0xf1; vt82c586b.ide_regs[0x11] = 0x01;
|
|
vt82c586b.ide_regs[0x14] = 0xf5; vt82c586b.ide_regs[0x15] = 0x03;
|
|
vt82c586b.ide_regs[0x18] = 0x71; vt82c586b.ide_regs[0x19] = 0x01;
|
|
vt82c586b.ide_regs[0x1c] = 0x75; vt82c586b.ide_regs[0x1d] = 0x03;
|
|
vt82c586b.ide_regs[0x20] = 0x01; vt82c586b.ide_regs[0x21] = 0xcc;
|
|
vt82c586b.ide_regs[0x3c] = 0x0e;
|
|
|
|
vt82c586b.ide_regs[0x40] = 0x08;
|
|
vt82c586b.ide_regs[0x41] = 0x02;
|
|
vt82c586b.ide_regs[0x42] = 0x09;
|
|
vt82c586b.ide_regs[0x43] = 0x3a;
|
|
vt82c586b.ide_regs[0x44] = 0x68;
|
|
vt82c586b.ide_regs[0x46] = 0xc0;
|
|
vt82c586b.ide_regs[0x48] = 0xa8;
|
|
vt82c586b.ide_regs[0x49] = 0xa8;
|
|
vt82c586b.ide_regs[0x4a] = 0xa8;
|
|
vt82c586b.ide_regs[0x4b] = 0xa8;
|
|
vt82c586b.ide_regs[0x4c] = 0xff;
|
|
vt82c586b.ide_regs[0x4e] = 0xff;
|
|
vt82c586b.ide_regs[0x4f] = 0xff;
|
|
vt82c586b.ide_regs[0x50] = 0x03;
|
|
vt82c586b.ide_regs[0x51] = 0x03;
|
|
vt82c586b.ide_regs[0x52] = 0x03;
|
|
vt82c586b.ide_regs[0x53] = 0x03;
|
|
vt82c586b.ide_regs[0x61] = 0x02;
|
|
vt82c586b.ide_regs[0x68] = 0x02;
|
|
|
|
vt82c586b.usb_regs[0x00] = 0x06; vt82c586b.usb_regs[0x01] = 0x11; /*VIA*/
|
|
vt82c586b.usb_regs[0x02] = 0x38; vt82c586b.usb_regs[0x03] = 0x30;
|
|
vt82c586b.usb_regs[0x04] = 0x00; vt82c586b.usb_regs[0x05] = 0x00;
|
|
vt82c586b.usb_regs[0x06] = 0x00; vt82c586b.usb_regs[0x07] = 0x02;
|
|
vt82c586b.usb_regs[0x0a] = 0x03;
|
|
vt82c586b.usb_regs[0x0b] = 0x0c;
|
|
vt82c586b.usb_regs[0x0d] = 0x16;
|
|
vt82c586b.usb_regs[0x20] = 0x01;
|
|
vt82c586b.usb_regs[0x21] = 0x03;
|
|
vt82c586b.usb_regs[0x3d] = 0x04;
|
|
|
|
vt82c586b.usb_regs[0x60] = 0x10;
|
|
vt82c586b.usb_regs[0xc1] = 0x20;
|
|
|
|
vt82c586b.power_regs[0x00] = 0x06; vt82c586b.power_regs[0x01] = 0x11; /*VIA*/
|
|
vt82c586b.power_regs[0x02] = 0x40; vt82c586b.power_regs[0x03] = 0x30;
|
|
vt82c586b.power_regs[0x04] = 0x00; vt82c586b.power_regs[0x05] = 0x00;
|
|
vt82c586b.power_regs[0x06] = 0x80; vt82c586b.power_regs[0x07] = 0x02;
|
|
vt82c586b.power_regs[0x08] = 0x10; /*Production version (3041)*/
|
|
vt82c586b.power_regs[0x48] = 0x01;
|
|
|
|
if (pci_a)
|
|
pci_set_card_routing(pci_a, PCI_INTA);
|
|
if (pci_b)
|
|
pci_set_card_routing(pci_b, PCI_INTB);
|
|
if (pci_c)
|
|
pci_set_card_routing(pci_c, PCI_INTC);
|
|
if (pci_d)
|
|
pci_set_card_routing(pci_d, PCI_INTD);
|
|
|
|
sff_bus_master_init(vt82c586b.busmaster);
|
|
|
|
ide_pri_disable();
|
|
ide_sec_disable();
|
|
}
|