Implement PIIX4 power management. Soft power off is currently 'implemented'
by killing the emulator.
This commit is contained in:
parent
0cbbd22c88
commit
8f04c11a76
10 changed files with 493 additions and 190 deletions
|
|
@ -37,7 +37,7 @@ hdd_file.c headland.c i430lx.c i430fx.c i430hx.c i430vx.c i440fx.c i440bx.c ide.
|
|||
jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c joystick_tm_fcs.c keyboard.c \
|
||||
keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c laserxt.c lpt.c lpt_dac.c lpt_dss.c \
|
||||
mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c \
|
||||
neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c pc87307.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \
|
||||
neat.c nmi.c nvr.c olivetti_m24.c opti495.c paths.c pc.c pc87306.c pc87307.c pci.c pic.c piix.c piix_pm.c pit.c ppi.c ps1.c ps2.c ps2_mca.c \
|
||||
ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scamp.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c \
|
||||
scsi_ibm.c scsi_zip.c serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c \
|
||||
sound_azt2316a.c sound_cms.c sound_emu8k.c sound_gus.c sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c \
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203
|
|||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
|
||||
mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
|
||||
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pc87307.o pci.o pic.o \
|
||||
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
|
||||
piix.o piix_pm.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
|
||||
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
|
||||
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
|
||||
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o 82091aa.o acc203
|
|||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
|
||||
mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
|
||||
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pc87307.o pci.o pic.o \
|
||||
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
|
||||
piix.o piix_pm.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o scamp.o scat.o scsi.o \
|
||||
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_ibm.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
|
||||
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_azt2316a.o sound_cms.o sound_dbopl.o \
|
||||
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
|
||||
|
|
|
|||
16
src/i440bx.c
16
src/i440bx.c
|
|
@ -145,6 +145,19 @@ uint8_t i440bx_read(int func, int addr, void *priv)
|
|||
return card_i440bx[addr];
|
||||
}
|
||||
|
||||
static void i440bx_smram_enable(void)
|
||||
{
|
||||
// pclog("i440bx_smram_enable: 440BX 0x72=%02x\n", card_i440bx[0x72]);
|
||||
if (card_i440bx[0x72] & 8)
|
||||
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
}
|
||||
static void i440bx_smram_disable(void)
|
||||
{
|
||||
// pclog("i440bx_smram_disable: 440BX 0x72=%02x\n", card_i440bx[0x72]);
|
||||
if (card_i440bx[0x72] & 8)
|
||||
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
}
|
||||
|
||||
void i440bx_init()
|
||||
{
|
||||
pci_add_specific(0, i440bx_read, i440bx_write, NULL);
|
||||
|
|
@ -162,6 +175,9 @@ void i440bx_init()
|
|||
card_i440bx[0x72] = 0x02;
|
||||
card_i440bx[0x73] = 0x38;
|
||||
card_i440bx[0x7a] = 0x02; /*AGP disabled*/
|
||||
|
||||
smram_enable = i440bx_smram_enable;
|
||||
smram_disable = i440bx_smram_disable;
|
||||
}
|
||||
|
||||
void i440bx_reset()
|
||||
|
|
|
|||
10
src/mem.c
10
src/mem.c
|
|
@ -51,6 +51,9 @@ uint64_t *byte_code_present_mask;
|
|||
|
||||
uint32_t mem_logical_addr;
|
||||
|
||||
void (*smram_enable)(void);
|
||||
void (*smram_disable)(void);
|
||||
|
||||
int mmuflush=0;
|
||||
int mmu_perm=4;
|
||||
|
||||
|
|
@ -1420,6 +1423,9 @@ void mem_init()
|
|||
page_lookup = malloc((1 << 20) * sizeof(page_t *));
|
||||
|
||||
memset(ff_array, 0xff, sizeof(ff_array));
|
||||
|
||||
smram_enable = NULL;
|
||||
smram_disable = NULL;
|
||||
}
|
||||
|
||||
void mem_alloc()
|
||||
|
|
@ -1462,7 +1468,7 @@ void mem_alloc()
|
|||
memset(_mem_state, 0, sizeof(_mem_state));
|
||||
|
||||
mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
mem_set_mem_state(0x0a0000, 0x60000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
|
||||
mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL);
|
||||
if (mem_size > 1024)
|
||||
|
|
@ -1479,7 +1485,7 @@ void mem_alloc()
|
|||
}
|
||||
}
|
||||
if (mem_size > 768)
|
||||
mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
|
||||
mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL);
|
||||
|
||||
if (romset == ROM_IBMPS1_2011)
|
||||
mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
|
||||
|
|
|
|||
|
|
@ -236,4 +236,7 @@ void mmu_invalidate(uint32_t addr);
|
|||
int loadbios();
|
||||
|
||||
extern int purgeable_page_count;
|
||||
|
||||
extern void (*smram_enable)(void);
|
||||
extern void (*smram_disable)(void);
|
||||
#endif
|
||||
|
|
|
|||
191
src/piix.c
191
src/piix.c
|
|
@ -13,8 +13,8 @@
|
|||
#include "mem.h"
|
||||
#include "pci.h"
|
||||
#include "pic.h"
|
||||
|
||||
#include "piix.h"
|
||||
#include "piix_pm.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -23,156 +23,12 @@ enum
|
|||
TYPE_PIIX4
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
int type;
|
||||
|
||||
/*PIIX4*/
|
||||
uint8_t card_pm[256];
|
||||
|
||||
uint16_t pmba;
|
||||
struct
|
||||
{
|
||||
uint64_t timer_offset;
|
||||
} pm;
|
||||
|
||||
uint16_t smbba;
|
||||
struct
|
||||
{
|
||||
uint8_t host_ctrl;
|
||||
} smbus;
|
||||
|
||||
uint8_t port_92;
|
||||
} piix;
|
||||
|
||||
static piix_t piix;
|
||||
static uint8_t card_piix[256], card_piix_ide[256];
|
||||
static sff_busmaster_t piix_busmaster[2];
|
||||
static uint8_t piix_rc = 0;
|
||||
static void (*piix_nb_reset)();
|
||||
|
||||
static void piix_pm_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
// pclog("piix_pm_write: port=%04x val=%02x\n", port, val);
|
||||
}
|
||||
static uint8_t piix_pm_read(uint16_t port, void *p)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port & 0x3f)
|
||||
{
|
||||
case 0x02: case 0x03:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x04: case 0x05:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
||||
{
|
||||
uint64_t timer = tsc - piix.pm.timer_offset;
|
||||
uint32_t pm_timer = (timer * 3579545) / cpu_get_speed();
|
||||
|
||||
ret = pm_timer >> ((port & 3) * 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0e: case 0x0f:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x10: case 0x11:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x18: case 0x19:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x20: case 0x21:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x28: case 0x29: case 0x2a: case 0x2b:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0x31:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0x32:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
// default:
|
||||
// fatal("piix_pm_read: unknown read %04x\n", port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void piix_smbus_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
// pclog("piix_smbus_write: port=%04x val=%02x\n", port, val);
|
||||
|
||||
switch (port & 0xf)
|
||||
{
|
||||
case 0x2:
|
||||
piix.smbus.host_ctrl = (val & 0x5f) | (piix.smbus.host_ctrl & 0x40);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static uint8_t piix_smbus_read(uint16_t port, void *p)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port & 0x0f)
|
||||
{
|
||||
case 0x0:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
ret = piix.smbus.host_ctrl;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
// default:
|
||||
// fatal("piix_smbus_read: unknown read %04x\n", port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pm_clear_io(void)
|
||||
{
|
||||
io_removehandler(piix.pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, NULL);
|
||||
io_removehandler(piix.smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, NULL);
|
||||
}
|
||||
static void pm_set_io(void)
|
||||
{
|
||||
// pclog("pm_set_io: %02x %04x\n", piix.card_pm[0x04], piix.smbba);
|
||||
if ((piix.card_pm[0x04] & 0x01) && piix.pmba)
|
||||
{
|
||||
// pclog("PMBA=%04x\n", piix.pmba);
|
||||
io_sethandler(piix.pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, NULL);
|
||||
}
|
||||
if ((piix.card_pm[0x04] & 0x01) && piix.smbba)
|
||||
{
|
||||
// pclog("SMBBA=%04x\n", piix.smbba);
|
||||
io_sethandler(piix.smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
|
|
@ -241,34 +97,7 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
|
|||
}
|
||||
else if (func == 3) /*PM*/
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04:
|
||||
pm_clear_io();
|
||||
piix.card_pm[0x04] = val & 1;
|
||||
pm_set_io();
|
||||
break;
|
||||
case 0x40:
|
||||
pm_clear_io();
|
||||
piix.pmba = (piix.pmba & 0xff00) | (val & 0xc0);
|
||||
pm_set_io();
|
||||
break;
|
||||
case 0x41:
|
||||
pm_clear_io();
|
||||
piix.pmba = (piix.pmba & 0xc0) | (val << 8);
|
||||
pm_set_io();
|
||||
break;
|
||||
case 0x90:
|
||||
pm_clear_io();
|
||||
piix.smbba = (piix.smbba & 0xff00) | (val & 0xf0);
|
||||
pm_set_io();
|
||||
break;
|
||||
case 0x91:
|
||||
pm_clear_io();
|
||||
piix.smbba = (piix.smbba & 0xf0) | (val << 8);
|
||||
pm_set_io();
|
||||
break;
|
||||
}
|
||||
piix_pm_pci_write(addr, val, &piix);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -329,7 +158,7 @@ uint8_t piix_read(int func, int addr, void *priv)
|
|||
else if (func == 2) /*USB*/
|
||||
return 0xff; /*Not implemented*/
|
||||
else if (func == 3)
|
||||
return piix.card_pm[addr];
|
||||
return piix_pm_pci_read(addr, &piix);
|
||||
else
|
||||
return card_piix[addr];
|
||||
}
|
||||
|
|
@ -376,6 +205,7 @@ static void piix_92_write(uint16_t port, uint8_t val, void *p)
|
|||
piix.port_92 = val;
|
||||
}
|
||||
|
||||
|
||||
void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)())
|
||||
{
|
||||
pci_add_specific(card, piix_read, piix_write, NULL);
|
||||
|
|
@ -443,15 +273,6 @@ void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_
|
|||
|
||||
card_piix_ide[0x02] = 0x11; card_piix_ide[0x03] = 0x71; /*82371EB (PIIX4)*/
|
||||
|
||||
memset(&piix.card_pm, 0, sizeof(piix.card_pm));
|
||||
piix.card_pm[0x00] = 0x86; piix.card_pm[0x01] = 0x80; /*Intel*/
|
||||
piix.card_pm[0x02] = 0x13; piix.card_pm[0x03] = 0x71; /*82371EB (PIIX4)*/
|
||||
piix.card_pm[0x06] = 0x80; piix.card_pm[0x07] = 0x02;
|
||||
piix.card_pm[0x09] = 0x00; piix.card_pm[0x0a] = 0x80; piix.card_pm[0x0b] = 0x06; /*Bridge device*/
|
||||
piix.card_pm[0x3d] = 0x01; /*IRQA*/
|
||||
piix.card_pm[0x40] = 0x01;
|
||||
piix.card_pm[0x90] = 0x01;
|
||||
piix.pm.timer_offset = 0;
|
||||
|
||||
io_sethandler(0x0092, 0x0001, piix_92_read, NULL, NULL, piix_92_write, NULL, NULL, NULL);
|
||||
piix_pm_init(&piix);
|
||||
}
|
||||
|
|
|
|||
40
src/piix.h
40
src/piix.h
|
|
@ -1,2 +1,42 @@
|
|||
void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)());
|
||||
void piix4_init(int card, int pci_a, int pci_b, int pci_c, int pci_d, void (*nb_reset)());
|
||||
|
||||
typedef struct piix_t
|
||||
{
|
||||
int type;
|
||||
|
||||
/*PIIX4*/
|
||||
uint8_t card_pm[256];
|
||||
|
||||
uint16_t pmba;
|
||||
struct
|
||||
{
|
||||
uint8_t apmc, apms;
|
||||
|
||||
uint64_t timer_offset;
|
||||
|
||||
uint16_t pmsts;
|
||||
uint16_t pmen;
|
||||
uint16_t pmcntrl;
|
||||
uint32_t devctl;
|
||||
uint32_t devsts;
|
||||
uint16_t glbsts;
|
||||
uint16_t gpen;
|
||||
uint16_t gpsts;
|
||||
uint32_t pcntrl;
|
||||
uint16_t glben;
|
||||
uint32_t glbctl;
|
||||
uint32_t gporeg;
|
||||
|
||||
int dev13_enable;
|
||||
uint16_t dev13_base, dev13_size;
|
||||
} pm;
|
||||
|
||||
uint16_t smbba;
|
||||
struct
|
||||
{
|
||||
uint8_t host_ctrl;
|
||||
} smbus;
|
||||
|
||||
uint8_t port_92;
|
||||
} piix_t;
|
||||
|
|
|
|||
414
src/piix_pm.c
Normal file
414
src/piix_pm.c
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
#include "ibm.h"
|
||||
#include "io.h"
|
||||
#include "piix.h"
|
||||
#include "piix_pm.h"
|
||||
#include "x86.h"
|
||||
|
||||
#define DEVSTS_TRP_STS_DEV13 (1 << 29)
|
||||
|
||||
#define DEVCTL_TRP_EN_DEV13 (1 << 25)
|
||||
|
||||
#define GLBSTS_APM_STS (1 << 5)
|
||||
|
||||
static uint8_t dev13_read(uint16_t addr, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
// pclog("dev13_read: addr=%04x %08x\n", addr, piix.pm.devctl);
|
||||
if (piix->pm.devctl & DEVCTL_TRP_EN_DEV13)
|
||||
{
|
||||
piix->pm.devsts |= DEVSTS_TRP_STS_DEV13;
|
||||
x86_smi_trigger();
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
static void dev13_write(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
// pclog("dev13_write: addr=%04x val=%02x %08x\n", addr, val, piix.pm.devctl);
|
||||
if (piix->pm.devctl & DEVCTL_TRP_EN_DEV13)
|
||||
{
|
||||
piix->pm.devsts |= DEVSTS_TRP_STS_DEV13;
|
||||
x86_smi_trigger();
|
||||
}
|
||||
}
|
||||
|
||||
static void dev13_recalc(piix_t *piix)
|
||||
{
|
||||
if (piix->pm.dev13_enable)
|
||||
io_removehandler(piix->pm.dev13_base, piix->pm.dev13_size,
|
||||
dev13_read, NULL, NULL,
|
||||
dev13_write, NULL, NULL, piix);
|
||||
piix->pm.dev13_base = piix->card_pm[0x70] | (piix->card_pm[0x71] << 8);
|
||||
piix->pm.dev13_size = (piix->card_pm[0x72] & 0xf) + 1;
|
||||
piix->pm.dev13_enable = piix->card_pm[0x72] & 0x10;
|
||||
if (piix->pm.dev13_enable)
|
||||
io_sethandler(piix->pm.dev13_base, piix->pm.dev13_size,
|
||||
dev13_read, NULL, NULL,
|
||||
dev13_write, NULL, NULL, piix);
|
||||
}
|
||||
|
||||
static void piix_pm_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
// pclog("piix_pm_write: port=%04x val=%02x\n", port, val);
|
||||
switch (port & 0x3f)
|
||||
{
|
||||
case 0x00:
|
||||
piix->pm.pmsts &= ~(val & 0x31);
|
||||
break;
|
||||
case 0x01:
|
||||
piix->pm.pmsts &= ~((val & 0x8d) << 8);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
piix->pm.pmen = (piix->pm.pmen & ~0xff) | (val & 0x21);
|
||||
break;
|
||||
case 0x03:
|
||||
piix->pm.pmen = (piix->pm.pmen & ~0xff00) | ((val & 0x05) << 8);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
piix->pm.pmcntrl = (piix->pm.pmcntrl & ~0xff) | (val & 0x03);
|
||||
break;
|
||||
case 0x05:
|
||||
pclog("PM reg 5 write %02x\n", val);
|
||||
if (val & 0x20)
|
||||
{
|
||||
pclog("PIIX transition to power state %i\n", (val >> 2) & 7);
|
||||
if (val == 0x20)
|
||||
fatal("Power off\n");
|
||||
}
|
||||
piix->pm.pmcntrl = (piix->pm.pmcntrl & ~0xff00) | ((val & 0x1c) << 8);
|
||||
break;
|
||||
|
||||
case 0x0c: case 0x0d:
|
||||
piix->pm.gpsts &= ~(val << ((port & 1) * 8));
|
||||
break;
|
||||
|
||||
case 0x0e:
|
||||
piix->pm.pmen = (piix->pm.pmen & ~0xff) | (val & 0x01);
|
||||
break;
|
||||
case 0x0f:
|
||||
piix->pm.pmen = (piix->pm.pmen & ~0xff00) | ((val & 0x0f) << 8);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
piix->pm.pcntrl = (piix->pm.pcntrl & ~0xff) | (val & 0x1e);
|
||||
break;
|
||||
case 0x11:
|
||||
piix->pm.pcntrl = (piix->pm.pcntrl & ~0xff00) | ((val & 0x3e) << 8);
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
piix->pm.glbsts &= ~(val & 0x25);
|
||||
break;
|
||||
case 0x19:
|
||||
piix->pm.glbsts &= ~((val & 0x0d) << 8);
|
||||
break;
|
||||
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
piix->pm.devsts &= ~(val << ((port & 3) * 8));
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
piix->pm.glben = (piix->pm.glben & ~0xff) | (val & 0x01);
|
||||
break;
|
||||
case 0x21:
|
||||
piix->pm.glben = (piix->pm.glben & ~0xff00) | ((val & 0x0f) << 8);
|
||||
break;
|
||||
|
||||
case 0x28:
|
||||
piix->pm.glbctl = (piix->pm.glbctl & ~0xff) | (val & 0x05);
|
||||
break;
|
||||
case 0x29:
|
||||
piix->pm.glbctl = (piix->pm.glbctl & ~0xff00) | ((val & 0xff) << 8);
|
||||
break;
|
||||
case 0x2a:
|
||||
piix->pm.glbctl = (piix->pm.glbctl & ~0xff0000) | ((val & 0x01) << 16);
|
||||
break;
|
||||
case 0x2b:
|
||||
piix->pm.glbctl = (piix->pm.glbctl & ~0xff000000) | ((val & 0x07) << 24);
|
||||
break;
|
||||
|
||||
case 0x2c:
|
||||
piix->pm.devctl = (piix->pm.devctl & ~0xff) | val;
|
||||
break;
|
||||
case 0x2d:
|
||||
piix->pm.devctl = (piix->pm.devctl & ~0xff00) | (val << 8);
|
||||
break;
|
||||
case 0x2e:
|
||||
piix->pm.devctl = (piix->pm.devctl & ~0xff0000) | (val << 16);
|
||||
break;
|
||||
case 0x2f:
|
||||
piix->pm.devctl = (piix->pm.devctl & ~0xff000000) | ((val & 0x0f) << 24);
|
||||
break;
|
||||
|
||||
case 0x34:
|
||||
piix->pm.gporeg = (piix->pm.gporeg & ~0xff) | val;
|
||||
break;
|
||||
case 0x35:
|
||||
piix->pm.gporeg = (piix->pm.gporeg & ~0xff00) | (val << 8);
|
||||
break;
|
||||
case 0x36:
|
||||
piix->pm.gporeg = (piix->pm.gporeg & ~0xff0000) | (val << 16);
|
||||
break;
|
||||
case 0x37:
|
||||
piix->pm.gporeg = (piix->pm.gporeg & ~0xff000000) | (val << 24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static uint8_t piix_pm_read(uint16_t port, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port & 0x3f)
|
||||
{
|
||||
case 0x00: case 0x01:
|
||||
ret = piix->pm.pmsts >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x02: case 0x03:
|
||||
ret = piix->pm.pmen >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x04: case 0x05:
|
||||
ret = piix->pm.pmcntrl >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
||||
{
|
||||
uint64_t timer = tsc - piix->pm.timer_offset;
|
||||
uint32_t pm_timer = (timer * 3579545) / cpu_get_speed();
|
||||
|
||||
ret = pm_timer >> ((port & 3) * 8);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0c: case 0x0d:
|
||||
ret = piix->pm.gpsts >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x0e: case 0x0f:
|
||||
ret = piix->pm.pmen >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
ret = piix->pm.pcntrl >> ((port & 3) * 8);
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
ret = 0;
|
||||
break;
|
||||
case 0x15:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x18: case 0x19:
|
||||
ret = piix->pm.glbsts >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
|
||||
ret = piix->pm.devsts >> ((port & 3) * 8);
|
||||
break;
|
||||
|
||||
case 0x20: case 0x21:
|
||||
ret = piix->pm.glben >> ((port & 1) * 8);
|
||||
break;
|
||||
|
||||
case 0x28: case 0x29: case 0x2a: case 0x2b:
|
||||
ret = piix->pm.glbctl >> ((port & 3) * 8);
|
||||
break;
|
||||
|
||||
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
|
||||
ret = piix->pm.devctl >> ((port & 3) * 8);
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
ret = 0x00;
|
||||
break;
|
||||
case 0x31:
|
||||
ret = 0x00;
|
||||
break;
|
||||
case 0x32:
|
||||
/*GA686BX - bit 1 = low battery*/
|
||||
ret = 0x00;
|
||||
break;
|
||||
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
ret = piix->pm.gporeg >> ((port & 3) * 8);
|
||||
break;
|
||||
|
||||
// default:
|
||||
// fatal("piix_pm_read: unknown read %04x\n", port);
|
||||
}
|
||||
|
||||
// pclog("piix_pm_read: port=%04x val=%02x\n", port, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void piix_smbus_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
// pclog("piix_smbus_write: port=%04x val=%02x\n", port, val);
|
||||
|
||||
switch (port & 0xf)
|
||||
{
|
||||
case 0x2:
|
||||
piix->smbus.host_ctrl = (val & 0x5f) | (piix->smbus.host_ctrl & 0x40);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static uint8_t piix_smbus_read(uint16_t port, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port & 0x0f)
|
||||
{
|
||||
case 0x0:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
ret = piix->smbus.host_ctrl;
|
||||
break;
|
||||
|
||||
case 0x5:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
// default:
|
||||
// fatal("piix_smbus_read: unknown read %04x\n", port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t piix_apm_read(uint16_t port, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case 0xb2:
|
||||
ret = piix->pm.apmc;
|
||||
break;
|
||||
|
||||
case 0xb3:
|
||||
ret = piix->pm.apms;
|
||||
break;
|
||||
}
|
||||
// pclog("piix_apm_read: port=%04x ret=%02x\n", port, ret);
|
||||
return ret;
|
||||
}
|
||||
static void piix_apm_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
// pclog("piix_apm_write: port=%04x val=%02x\n", port, val);
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case 0xb2:
|
||||
piix->pm.apmc = val;
|
||||
if (piix->card_pm[0x5b] & (1 << 1))
|
||||
{
|
||||
piix->pm.glbsts |= GLBSTS_APM_STS;
|
||||
// pclog("APMC write causes SMI\n");
|
||||
x86_smi_trigger();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb3:
|
||||
piix->pm.apms = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void pm_clear_io(piix_t *piix)
|
||||
{
|
||||
io_removehandler(piix->pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, piix);
|
||||
io_removehandler(piix->smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, piix);
|
||||
}
|
||||
static void pm_set_io(piix_t *piix)
|
||||
{
|
||||
// pclog("pm_set_io: %02x %04x\n", piix.card_pm[0x04], piix.smbba);
|
||||
if ((piix->card_pm[0x04] & 0x01) && piix->pmba)
|
||||
{
|
||||
// pclog("PMBA=%04x\n", piix.pmba);
|
||||
io_sethandler(piix->pmba, 0x0040, piix_pm_read, NULL, NULL, piix_pm_write, NULL, NULL, piix);
|
||||
}
|
||||
if ((piix->card_pm[0x04] & 0x01) && piix->smbba)
|
||||
{
|
||||
// pclog("SMBBA=%04x\n", piix.smbba);
|
||||
io_sethandler(piix->smbba, 0x0010, piix_smbus_read, NULL, NULL, piix_smbus_write, NULL, NULL, piix);
|
||||
}
|
||||
}
|
||||
|
||||
void piix_pm_pci_write(int addr, uint8_t val, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x04:
|
||||
pm_clear_io(piix);
|
||||
piix->card_pm[0x04] = val & 1;
|
||||
pm_set_io(piix);
|
||||
break;
|
||||
case 0x40:
|
||||
pm_clear_io(piix);
|
||||
piix->pmba = (piix->pmba & 0xff00) | (val & 0xc0);
|
||||
pm_set_io(piix);
|
||||
break;
|
||||
case 0x41:
|
||||
pm_clear_io(piix);
|
||||
piix->pmba = (piix->pmba & 0xc0) | (val << 8);
|
||||
pm_set_io(piix);
|
||||
break;
|
||||
case 0x58: case 0x59: case 0x5b: case 0x5c:
|
||||
piix->card_pm[addr] = val;
|
||||
break;
|
||||
case 0x70: case 0x71: case 0x72:
|
||||
piix->card_pm[addr] = val;
|
||||
dev13_recalc(piix);
|
||||
break;
|
||||
case 0x90:
|
||||
pm_clear_io(piix);
|
||||
piix->smbba = (piix->smbba & 0xff00) | (val & 0xf0);
|
||||
pm_set_io(piix);
|
||||
break;
|
||||
case 0x91:
|
||||
pm_clear_io(piix);
|
||||
piix->smbba = (piix->smbba & 0xf0) | (val << 8);
|
||||
pm_set_io(piix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint8_t piix_pm_pci_read(int addr, void *p)
|
||||
{
|
||||
piix_t *piix = (piix_t *)p;
|
||||
|
||||
return piix->card_pm[addr];
|
||||
}
|
||||
|
||||
void piix_pm_init(piix_t *piix)
|
||||
{
|
||||
memset(&piix->card_pm, 0, sizeof(piix->card_pm));
|
||||
piix->card_pm[0x00] = 0x86; piix->card_pm[0x01] = 0x80; /*Intel*/
|
||||
piix->card_pm[0x02] = 0x13; piix->card_pm[0x03] = 0x71; /*82371EB (PIIX4)*/
|
||||
piix->card_pm[0x06] = 0x80; piix->card_pm[0x07] = 0x02;
|
||||
piix->card_pm[0x09] = 0x00; piix->card_pm[0x0a] = 0x80; piix->card_pm[0x0b] = 0x06; /*Bridge device*/
|
||||
piix->card_pm[0x3d] = 0x01; /*IRQA*/
|
||||
piix->card_pm[0x40] = 0x01;
|
||||
piix->card_pm[0x90] = 0x01;
|
||||
piix->pm.timer_offset = 0;
|
||||
piix->pm.gporeg = 0x7fffbfff;
|
||||
|
||||
io_sethandler(0x00b2, 0x0002, piix_apm_read, NULL, NULL, piix_apm_write, NULL, NULL, piix);
|
||||
}
|
||||
3
src/piix_pm.h
Normal file
3
src/piix_pm.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
void piix_pm_init(piix_t *piix);
|
||||
void piix_pm_pci_write(int addr, uint8_t val, void *p);
|
||||
uint8_t piix_pm_pci_read(int addr, void *p);
|
||||
Loading…
Reference in a new issue