diff --git a/src/86box.c b/src/86box.c index 3a1ad179b..cbd29a6ed 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1048,19 +1048,9 @@ pc_reset_hard_init(void) /* Initialize the actual machine and its basic modules. */ machine_init(); - /* Reset and reconfigure the serial ports. */ - serial_standalone_init(); - serial_passthrough_init(); - - /* Reset and reconfigure the Sound Card layer. */ - sound_card_reset(); - - /* Reset any ISA RTC cards. */ - isartc_reset(); - - fdc_card_init(); - - fdd_reset(); + /* Reset some basic devices. */ + speaker_init(); + shadowbios = 0; /* * Once the machine has been initialized, all that remains @@ -1071,38 +1061,49 @@ pc_reset_hard_init(void) * that will be a call to device_reset_all() later ! */ - /* Reset some basic devices. */ - speaker_init(); - lpt_devices_init(); - shadowbios = 0; - /* * Reset the mouse, this will attach it to any port needed. */ mouse_reset(); + if (joystick_type) + gameport_update_joystick_type(); + + /* Reset and reconfigure the Sound Card layer. */ + sound_card_reset(); + + /* Reset and reconfigure the Network Card layer. */ + network_reset(); + + lpt_devices_init(); + + /* Reset and reconfigure the serial ports. */ + serial_standalone_init(); + serial_passthrough_init(); + /* Reset the Hard Disk Controller module. */ hdc_reset(); + fdc_card_init(); + + fdd_reset(); + /* Reset the CD-ROM Controller module. */ cdrom_interface_reset(); /* Reset and reconfigure the SCSI layer. */ scsi_card_init(); - cdrom_hard_reset(); + scsi_disk_hard_reset(); - zip_hard_reset(); + cdrom_hard_reset(); mo_hard_reset(); - scsi_disk_hard_reset(); + zip_hard_reset(); - /* Reset and reconfigure the Network Card layer. */ - network_reset(); - - if (joystick_type) - gameport_update_joystick_type(); + /* Reset any ISA RTC cards. */ + isartc_reset(); ui_sb_update_panes(); @@ -1119,6 +1120,11 @@ pc_reset_hard_init(void) if (postcard_enabled) device_add(&postcard_device); + if (IS_ARCH(machine, MACHINE_BUS_PCI)) { + pci_register_cards(); + device_reset_all(DEVICE_PCI); + } + /* Reset the CPU module. */ resetx86(); dma_reset(); diff --git a/src/acpi.c b/src/acpi.c index 157e3cadd..91d84be60 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -124,29 +124,29 @@ acpi_update_irq(acpi_t *dev) if (sci_level) { if (dev->irq_mode == 1) - pci_set_irq(dev->slot, dev->irq_pin); + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); else if (dev->irq_mode == 2) - pci_set_mirq(5, dev->mirq_is_level); + pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state); else - pci_set_mirq(0xf0 | dev->irq_line, 1); + pci_set_mirq(PCI_DIRQ_BASE | dev->irq_line, 1, &dev->irq_state); } else { if (dev->irq_mode == 1) - pci_clear_irq(dev->slot, dev->irq_pin); + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); else if (dev->irq_mode == 2) - pci_clear_mirq(5, dev->mirq_is_level); + pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state); else - pci_clear_mirq(0xf0 | dev->irq_line, 1); + pci_clear_mirq(PCI_DIRQ_BASE | dev->irq_line, 1, &dev->irq_state); } acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS)); } -void -acpi_raise_smi(void *priv, int do_smi) +static void +acpi_do_raise_smi(void *priv, int do_smi, int is_apm) { acpi_t *dev = (acpi_t *) priv; - if (dev->regs.glbctl & 0x01) { + if (is_apm || (dev->regs.glbctl & 0x01)) { if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) { if (!dev->regs.smi_lock || !dev->regs.smi_active) { if (do_smi) @@ -168,6 +168,12 @@ acpi_raise_smi(void *priv, int do_smi) } } +void +acpi_raise_smi(void *priv, int do_smi) +{ + acpi_do_raise_smi(priv, do_smi, 0); +} + static uint32_t acpi_reg_read_common_regs(UNUSED(int size), uint16_t addr, void *priv) { @@ -1582,7 +1588,7 @@ acpi_apm_out(uint16_t port, uint8_t val, void *priv) dev->apm->cmd = val; if (dev->vendor == VEN_INTEL) dev->regs.glbsts |= 0x20; - acpi_raise_smi(dev, dev->apm->do_smi); + acpi_do_raise_smi(dev, dev->apm->do_smi, 1); } else dev->apm->stat = val; } @@ -1657,6 +1663,9 @@ acpi_reset(void *priv) dev->regs.pmsts |= 0x8000; acpi_rtc_status = 0; + + acpi_update_irq(dev); + dev->irq_state = 0; } static void diff --git a/src/chipset/ali1435.c b/src/chipset/ali1435.c index 72595cf84..9476d2b45 100644 --- a/src/chipset/ali1435.c +++ b/src/chipset/ali1435.c @@ -46,11 +46,12 @@ typedef struct ali_1435_t { uint8_t index; uint8_t cfg_locked; + uint8_t pci_slot; + uint8_t pad; uint8_t regs[16]; uint8_t pci_regs[256]; } ali1435_t; -#define ENABLE_ALI1435_LOG 1 #ifdef ENABLE_ALI1435_LOG int ali1435_do_log = ENABLE_ALI1435_LOG; @@ -190,24 +191,20 @@ ali1435_write(uint16_t addr, uint8_t val, void *priv) break; case 0x23: -#if 0 -#ifdef ENABLE_ALI1435_LOG - if (dev->index != 0x03) - ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val); -#endif -#endif if (dev->index == 0x03) dev->cfg_locked = (val != 0x69); +#ifdef ENABLE_ALI1435_LOG + else + ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val); +#endif if (!dev->cfg_locked) { - pclog("M1435: dev->regs[%02x] = %02x\n", dev->index, val); - switch (dev->index) { /* PCI Mechanism select? */ case 0x00: dev->regs[dev->index] = val; - pclog("PMC = %i\n", val != 0xc8); - pci_set_pmc(val != 0xc8); + ali1435_log("PMC = %i\n", val != 0xc8); + pci_key_write(((val & 0xc8) == 0xc8) ? 0xf0 : 0x00); break; /* ???? */ @@ -253,8 +250,6 @@ ali1435_reset(void *priv) dev->regs[0x00] = 0xff; - pci_set_pmc(0); - dev->cfg_locked = 1; memset(dev->pci_regs, 0, 256); @@ -298,17 +293,10 @@ ali1435_init(UNUSED(const device_t *info)) */ io_sethandler(0x0022, 0x0002, ali1435_read, NULL, NULL, ali1435_write, NULL, NULL, dev); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev, &dev->pci_slot); ali1435_reset(dev); -#if 0 - pci_set_irq_level(PCI_INTA, 0); - pci_set_irq_level(PCI_INTB, 0); - pci_set_irq_level(PCI_INTC, 0); - pci_set_irq_level(PCI_INTD, 0); -#endif - return dev; } diff --git a/src/chipset/ali1489.c b/src/chipset/ali1489.c index 1b2087e4d..822ab7baf 100644 --- a/src/chipset/ali1489.c +++ b/src/chipset/ali1489.c @@ -622,7 +622,7 @@ ali1489_init(UNUSED(const device_t *info)) io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev); /* Dummy M1489 PCI device */ - dev->pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev, &dev->pci_slot); device_add(&ide_pci_2ch_device); diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index 3812e4ca4..9eb75f7cd 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -35,6 +35,11 @@ #include <86box/chipset.h> typedef struct ali1531_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + uint8_t pci_conf[256]; smram_t *smram; @@ -374,7 +379,7 @@ ali1531_init(UNUSED(const device_t *info)) ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t)); memset(dev, 0, sizeof(ali1531_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot); dev->smram = smram_add(); diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index 55cf5d25d..d57ef51e7 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -35,6 +35,11 @@ #include <86box/chipset.h> typedef struct ali1541_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + uint8_t pci_conf[256]; smram_t *smram; @@ -641,7 +646,7 @@ ali1541_init(UNUSED(const device_t *info)) ali1541_t *dev = (ali1541_t *) malloc(sizeof(ali1541_t)); memset(dev, 0, sizeof(ali1541_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev, &dev->pci_slot); dev->smram = smram_add(); diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index cefaa4f0d..ba8ce4f3b 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -47,6 +47,7 @@ #include <86box/chipset.h> typedef struct ali1543_t { + uint8_t mirq_states[8]; uint8_t pci_conf[256]; uint8_t pmu_conf[256]; uint8_t usb_conf[256]; @@ -1474,12 +1475,12 @@ ali7101_read(int func, int addr, void *priv) static void ali5237_usb_update_interrupt(usb_t* usb, void *priv) { - const ali1543_t *dev = (ali1543_t *) priv; + ali1543_t *dev = (ali1543_t *) priv; if (usb->irq_level) - pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10)); + pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]); else - pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10)); + pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]); } static void @@ -1595,16 +1596,16 @@ ali1543_init(const device_t *info) memset(dev, 0, sizeof(ali1543_t)); /* Device 02: M1533 Southbridge */ - dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev, &dev->pci_slot); /* Device 0B: M5229 IDE Controller*/ - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, ali5229_read, ali5229_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, ali5229_read, ali5229_write, dev, &dev->ide_slot); /* Device 0C: M7101 Power Managment Controller */ - dev->pmu_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_PMU, ali7101_read, ali7101_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_PMU, ali7101_read, ali7101_write, dev, &dev->pmu_slot); /* Device 0F: M5237 USB */ - dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, ali5237_read, ali5237_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, ali5237_read, ali5237_write, dev, &dev->usb_slot); /* ACPI */ dev->acpi = device_add(&acpi_ali_device); diff --git a/src/chipset/ali1621.c b/src/chipset/ali1621.c index b927d3e34..ce3974a70 100644 --- a/src/chipset/ali1621.c +++ b/src/chipset/ali1621.c @@ -36,6 +36,11 @@ #include <86box/chipset.h> typedef struct ali1621_t { + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; + uint8_t pci_conf[256]; smram_t *smram[2]; @@ -671,7 +676,7 @@ ali1621_init(UNUSED(const device_t *info)) ali1621_t *dev = (ali1621_t *) malloc(sizeof(ali1621_t)); memset(dev, 0, sizeof(ali1621_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev, &dev->pci_slot); dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); diff --git a/src/chipset/ims8848.c b/src/chipset/ims8848.c index f84eb5706..3e86a44e1 100644 --- a/src/chipset/ims8848.c +++ b/src/chipset/ims8848.c @@ -122,6 +122,9 @@ typedef struct ims8848_t { uint8_t idx; uint8_t access_data; + uint8_t pci_slot; + uint8_t pad; + uint8_t regs[256]; uint8_t pci_conf[256]; @@ -392,7 +395,7 @@ ims8848_init(UNUSED(const device_t *info)) PCI Device 0: IMS 8849 Dummy for compatibility reasons */ io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); - pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev, &dev->pci_slot); dev->smram = smram_add(); smram_set_separate_smram(1); diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c index 5200d8834..03720b668 100644 --- a/src/chipset/intel_420ex.c +++ b/src/chipset/intel_420ex.c @@ -52,6 +52,9 @@ typedef struct i420ex_t { uint8_t has_ide; uint8_t smram_locked; + uint8_t pci_slot; + uint8_t pad; + uint8_t regs[256]; uint16_t timer_base; @@ -534,7 +537,7 @@ i420ex_init(const device_t *info) dev->smram = smram_add(); - pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev, &dev->pci_slot); dev->has_ide = info->local; diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index c68f6218c..eebe95f58 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -57,6 +57,9 @@ typedef struct i4x0_t { uint8_t max_drb; uint8_t drb_unit; uint8_t drb_default; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; uint8_t regs[256]; uint8_t regs_locked[256]; uint8_t mem_state[256]; @@ -1241,12 +1244,12 @@ i4x0_write(int func, int addr, uint8_t val, void *priv) switch (dev->type) { case INTEL_440FX: regs[0x93] = (val & 0x0f); - trc_write(0x0093, val & 0x06, NULL); + pci_write(0x0cf9, val & 0x06, NULL); break; case INTEL_440LX: case INTEL_440EX: regs[0x93] = (val & 0x0e); - trc_write(0x0093, val & 0x06, NULL); + pci_write(0x0cf9, val & 0x06, NULL); break; default: break; @@ -1518,7 +1521,7 @@ i4x0_read(int func, int addr, void *priv) /* Special behavior for 440FX register 0x93 which is basically TRC in PCI space with the addition of bits 3 and 0. */ if ((func == 0) && (addr == 0x93) && ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || (dev->type == INTEL_440EX))) - ret = (ret & 0xf9) | (trc_read(0x0093, NULL) & 0x06); + ret = (ret & 0xf9) | (pci_read(0x0cf9, NULL) & 0x06); } return ret; @@ -1910,7 +1913,7 @@ i4x0_init(const device_t *info) (dev->type >= INTEL_440BX) ? 0x38 : 0x00, dev); } - pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev, &dev->pci_slot); if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02)) { device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device); diff --git a/src/chipset/intel_i450kx.c b/src/chipset/intel_i450kx.c index b81c3dde4..90b807a6d 100644 --- a/src/chipset/intel_i450kx.c +++ b/src/chipset/intel_i450kx.c @@ -62,11 +62,15 @@ i450kx_log(const char *fmt, ...) typedef struct i450kx_t { smram_t *smram[2]; + uint8_t bus_index; + uint8_t pb_slot; + uint8_t mc_slot; + uint8_t pad; + uint8_t pb_pci_conf[256]; uint8_t mc_pci_conf[256]; - uint8_t mem_state[2][256]; - uint8_t bus_index; + uint8_t mem_state[2][256]; } i450kx_t; static void @@ -801,8 +805,8 @@ i450kx_init(UNUSED(const device_t *info)) { i450kx_t *dev = (i450kx_t *) malloc(sizeof(i450kx_t)); memset(dev, 0, sizeof(i450kx_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19h: Intel 450KX PCI Bridge PB */ - pci_add_card(PCI_ADD_AGPBRIDGE, mc_read, mc_write, dev); /* Device 14h: Intel 450KX Memory Controller MC */ + pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */ + pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */ dev->smram[0] = smram_add(); dev->smram[1] = smram_add(); diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 038f35f97..878fd53ae 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -66,7 +66,7 @@ typedef struct _piix_ { uint8_t max_func; uint8_t pci_slot; uint8_t no_mirq0; - uint8_t pad; + uint8_t usb_irq_state; uint8_t regs[4][256]; uint8_t readout_regs[256]; uint8_t board_config[2]; @@ -1446,12 +1446,12 @@ piix_fast_off_count(void *priv) static void piix_usb_update_interrupt(usb_t* usb, void *priv) { - const piix_t *dev = (piix_t *) priv; + piix_t *dev = (piix_t *) priv; if (usb->irq_level) - pci_set_irq(dev->pci_slot, PCI_INTD); + pci_set_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state); else - pci_clear_irq(dev->pci_slot, PCI_INTD); + pci_clear_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state); } static void @@ -1574,7 +1574,7 @@ piix_init(const device_t *info) dev->no_mirq0 = (info->local >> 12) & 0x0f; dev->func0_id = info->local >> 16; - dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev, &dev->pci_slot); piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index 1dcbafe5a..0f32eb4c8 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -37,6 +37,10 @@ typedef struct sio_t { uint8_t id; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t regs[256]; uint16_t timer_base; @@ -507,7 +511,7 @@ sio_init(const device_t *info) sio_t *dev = (sio_t *) malloc(sizeof(sio_t)); memset(dev, 0, sizeof(sio_t)); - pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot); dev->id = info->local; diff --git a/src/chipset/opti822.c b/src/chipset/opti822.c index 73548adab..ad6db361a 100644 --- a/src/chipset/opti822.c +++ b/src/chipset/opti822.c @@ -43,6 +43,10 @@ typedef struct opti822_t { uint8_t irq_convert; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pci_regs[256]; } opti822_t; @@ -393,7 +397,7 @@ opti822_init(UNUSED(const device_t *info)) opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t)); memset(dev, 0, sizeof(opti822_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot); opti822_reset(dev); diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c index dc2ef42e4..d30ef39ca 100644 --- a/src/chipset/sis_5511.c +++ b/src/chipset/sis_5511.c @@ -66,13 +66,15 @@ sis_5511_log(const char *fmt, ...) #endif typedef struct sis_5511_t { - uint8_t pci_conf[256]; - uint8_t pci_conf_sb[2][256]; uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t regs[16]; - int nb_pci_slot; - int sb_pci_slot; + uint8_t pci_conf[256]; + uint8_t pci_conf_sb[2][256]; sff8038i_t *ide_drive[2]; smram_t *smram; @@ -713,8 +715,8 @@ sis_5511_reset(void *priv) dev->pci_conf_sb[1][0x0a] = 1; dev->pci_conf_sb[1][0x0b] = 1; dev->pci_conf_sb[1][0x0e] = 0x80; - sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot); - sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot); + sff_set_slot(dev->ide_drive[0], dev->sb_slot); + sff_set_slot(dev->ide_drive[1], dev->sb_slot); sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); } @@ -734,8 +736,8 @@ sis_5511_init(UNUSED(const device_t *info)) sis_5511_t *dev = (sis_5511_t *) malloc(sizeof(sis_5511_t)); memset(dev, 0, sizeof(sis_5511_t)); - dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev); /* Device 0: SiS 5511 */ - dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev); /* Device 1: SiS 5513 */ + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); /* Device 0: SiS 5511 */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); /* Device 1: SiS 5513 */ io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); /* Ports 22h-23h: SiS 5513 ISA */ /* MIRQ */ diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 0e09de199..391cc4e8b 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -75,12 +75,14 @@ sis_5571_log(const char *fmt, ...) #endif typedef struct sis_5571_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t usb_irq_state; + uint8_t pci_conf[256]; uint8_t pci_conf_sb[3][256]; - int nb_pci_slot; - int sb_pci_slot; - port_92_t *port_92; sff8038i_t *ide_drive[2]; smram_t *smram; @@ -670,7 +672,7 @@ pci_isa_bridge_read(int func, int addr, void *priv) static void sis_5571_usb_update_interrupt(usb_t* usb, void* priv) { - const sis_5571_t *dev = (sis_5571_t *) priv; + sis_5571_t *dev = (sis_5571_t *) priv; if (dev->pci_conf_sb[0][0x68] & 0x80) { /* TODO: Is the normal PCI interrupt inhibited when USB IRQ remapping is enabled? */ @@ -691,9 +693,9 @@ sis_5571_usb_update_interrupt(usb_t* usb, void* priv) } } else { if (usb->irq_level) - pci_set_irq(dev->sb_pci_slot, PCI_INTA); + pci_set_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state); else - pci_clear_irq(dev->sb_pci_slot, PCI_INTA); + pci_clear_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state); } } @@ -739,8 +741,8 @@ sis_5571_reset(void *priv) dev->pci_conf_sb[1][0x0b] = 0x01; dev->pci_conf_sb[1][0x0e] = 0x80; dev->pci_conf_sb[1][0x4a] = 0x06; - sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot); - sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot); + sff_set_slot(dev->ide_drive[0], dev->sb_slot); + sff_set_slot(dev->ide_drive[1], dev->sb_slot); sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE); sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8); @@ -773,8 +775,8 @@ sis_5571_init(UNUSED(const device_t *info)) sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t)); memset(dev, 0x00, sizeof(sis_5571_t)); - dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev); - dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot); + pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot); /* MIRQ */ pci_enable_mirq(0); diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index 8aac6ecd5..88618b1a0 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -45,9 +45,13 @@ typedef struct sis_85c496_t { uint8_t cur_reg; uint8_t rmsmiblk_count; + uint8_t pci_slot; + uint8_t pad; #ifndef USE_DRB_HACK uint8_t drb_default; uint8_t drb_bits; + uint8_t pad0; + uint8_t pad1; #endif uint8_t regs[127]; uint8_t pci_conf[256]; @@ -648,7 +652,7 @@ static void dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */ dev->pci_conf[0xd1] = 0xff; - pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev, &dev->pci_slot); #if 0 sis_85c497_isa_reset(dev); diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 00556c6f0..7f4aebb7c 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -59,6 +59,10 @@ sis_85c50x_log(const char *fmt, ...) typedef struct sis_85c50x_t { uint8_t index; + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t pad; + uint8_t pci_conf[256]; uint8_t pci_conf_sb[256]; uint8_t regs[256]; @@ -426,10 +430,10 @@ sis_85c50x_init(UNUSED(const device_t *info)) memset(dev, 0x00, sizeof(sis_85c50x_t)); /* 501/502 (Northbridge) */ - pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot); /* 503 (Southbridge) */ - pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev, &dev->sb_slot); io_sethandler(0x0022, 0x0002, sis_85c50x_isa_read, NULL, NULL, sis_85c50x_isa_write, NULL, NULL, dev); dev->smram[0] = smram_add(); diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index 092c0ae32..59d01186a 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -45,6 +45,11 @@ #define STPC_CLIENT 0x100e55cc typedef struct stpc_t { + uint8_t nb_slot; + uint8_t sb_slot; + uint8_t ide_slot; + uint8_t usb_slot; + uint32_t local; /* Main registers (port 22h/23h) */ @@ -54,19 +59,19 @@ typedef struct stpc_t { /* Host bus interface */ uint16_t host_base; uint8_t host_offset; + uint8_t usb_irq_state; uint8_t host_regs[256]; /* Local bus */ uint16_t localbus_base; uint8_t localbus_offset; + uint8_t pad0; uint8_t localbus_regs[256]; /* PCI devices */ uint8_t pci_conf[4][256]; smram_t *smram; usb_t *usb; - int ide_slot; - int usb_slot; sff8038i_t *bm[2]; /* Miscellaneous */ @@ -896,12 +901,12 @@ stpc_setup(stpc_t *dev) static void stpc_usb_update_interrupt(usb_t* usb, void* priv) { - const stpc_t *dev = (stpc_t *) priv; + stpc_t *dev = (stpc_t *) priv; if (usb->irq_level) - pci_set_irq(dev->usb_slot, PCI_INTA); + pci_set_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state); else - pci_clear_irq(dev->usb_slot, PCI_INTA); + pci_clear_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state); } static void @@ -926,16 +931,16 @@ stpc_init(const device_t *info) dev->local = info->local; - pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev); - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev, &dev->nb_slot); + pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev, &dev->sb_slot); if (dev->local == STPC_ATLAS) { dev->usb_params.smi_handle = NULL; dev->usb_params.update_interrupt = stpc_usb_update_interrupt; dev->usb_params.parent_priv = dev; - dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_ide_read, stpc_ide_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, stpc_ide_read, stpc_ide_write, dev, &dev->ide_slot); dev->usb = device_add_parameters(&usb_device, &dev->usb_params); - dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_usb_read, stpc_usb_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, stpc_usb_read, stpc_usb_write, dev, &dev->usb_slot); } dev->bm[0] = device_add_inst(&sff8038i_device, 1); diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index ded9c7e56..f6a923346 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -121,8 +121,13 @@ umc_8886_log(const char *fmt, ...) #define SB_ID dev->sb_id typedef struct umc_8886_t { - uint8_t max_func; /* Last function number */ - uint8_t pci_conf_sb[2][256]; /* PCI Registers */ + uint8_t max_func; /* Last function number */ + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + + uint8_t pci_conf_sb[2][256]; /* PCI Registers */ + uint16_t sb_id; /* Southbridge Revision */ int has_ide; /* Check if Southbridge Revision is AF or F */ } umc_8886_t; @@ -371,7 +376,7 @@ umc_8886_init(const device_t *info) memset(dev, 0, sizeof(umc_8886_t)); dev->has_ide = !!(info->local == 0x886a); - pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev); /* Device 12: UMC 8886xx */ + pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */ /* Add IDE if UM8886AF variant */ if (HAS_IDE) diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index 60b070f0b..4e115eeb6 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -146,6 +146,8 @@ typedef struct hb4_t { uint8_t shadow; uint8_t shadow_read; uint8_t shadow_write; + uint8_t pci_slot; + uint8_t pci_conf[256]; /* PCI Registers */ int mem_state[9]; smram_t *smram[3]; /* SMRAM Handlers */ @@ -393,7 +395,7 @@ hb4_init(UNUSED(const device_t *info)) hb4_t *dev = (hb4_t *) malloc(sizeof(hb4_t)); memset(dev, 0, sizeof(hb4_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev); /* Device 10: UMC 8881x */ + pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev, &dev->pci_slot); /* Device 10: UMC 8881x */ /* Port 92 */ device_add(&port_92_pci_device); diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index bd4445521..2d3633115 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -45,10 +45,15 @@ #define VIA_8601 0x86010500 typedef struct via_apollo_t { - uint32_t id; uint8_t drb_unit; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pci_conf[256]; + uint32_t id; + smram_t *smram; agpgart_t *agpgart; } via_apollo_t; @@ -715,7 +720,7 @@ via_apollo_init(const device_t *info) if (dev->id != VIA_8601) apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */ - pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev, &dev->pci_slot); dev->id = info->local; diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 04bcd5576..58a981814 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -117,9 +117,10 @@ typedef struct { } pipc_io_trap_t; typedef struct _pipc_ { - uint32_t local; uint8_t max_func; uint8_t max_pcs; + uint8_t pci_slot; + uint8_t pad; uint8_t pci_isa_regs[256]; uint8_t ide_regs[256]; @@ -129,10 +130,11 @@ typedef struct _pipc_ { uint8_t fmnmi_regs[4]; uint8_t fmnmi_status; + uint32_t local; + sff8038i_t *bm[2]; nvr_t *nvr; int nvr_enabled; - int slot; ddma_t *ddma; smbus_piix4_t *smbus; usb_t *usb[2]; @@ -1094,7 +1096,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv) case 0x47: if (val & 0x01) - trc_write(0x0047, (val & 0x80) ? 0x06 : 0x04, NULL); + pci_write(0x0cf9, (val & 0x80) ? 0x06 : 0x04, NULL); pic_set_shadow(!!(val & 0x10)); pic_elcr_io_handler(!!(val & 0x20)); dev->pci_isa_regs[0x47] = val & 0xfe; @@ -1620,6 +1622,14 @@ pipc_reset(void *priv) pipc_write(0, 0x44, 0x00, priv); pipc_write(0, 0x77, 0x00, priv); + + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_slot(dev->bm[1], dev->pci_slot); + + if (dev->local >= VIA_PIPC_686A) + ac97_via_set_slot(dev->ac97, dev->pci_slot, PCI_INTC); + if (dev->acpi) + acpi_set_slot(dev->acpi, dev->pci_slot); } static void * @@ -1631,16 +1641,14 @@ pipc_init(const device_t *info) pipc_log("PIPC: init()\n"); dev->local = info->local; - dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev); + pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev, &dev->pci_slot); dev->bm[0] = device_add_inst(&sff8038i_device, 1); - sff_set_slot(dev->bm[0], dev->slot); sff_set_irq_mode(dev->bm[0], 0, 0); sff_set_irq_mode(dev->bm[0], 1, 0); sff_set_irq_pin(dev->bm[0], PCI_INTA); dev->bm[1] = device_add_inst(&sff8038i_device, 2); - sff_set_slot(dev->bm[1], dev->slot); sff_set_irq_mode(dev->bm[1], 0, 0); sff_set_irq_mode(dev->bm[1], 1, 0); sff_set_irq_pin(dev->bm[1], PCI_INTA); @@ -1665,7 +1673,6 @@ pipc_init(const device_t *info) dev->usb[1] = device_add_inst(&usb_device, 2); dev->ac97 = device_add(&ac97_via_device); - ac97_via_set_slot(dev->ac97, dev->slot, PCI_INTC); dev->sb = device_add_inst(&sb_pro_compat_device, 2); sound_add_handler(pipc_sb_get_buffer, dev); @@ -1695,7 +1702,6 @@ pipc_init(const device_t *info) dev->ddma = device_add(&ddma_device); if (dev->acpi) { - acpi_set_slot(dev->acpi, dev->slot); acpi_set_nvr(dev->acpi, dev->nvr); acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f); diff --git a/src/chipset/via_vt82c505.c b/src/chipset/via_vt82c505.c index 136d335c7..34efbead9 100644 --- a/src/chipset/via_vt82c505.c +++ b/src/chipset/via_vt82c505.c @@ -32,6 +32,10 @@ typedef struct vt82c505_t { uint8_t index; + uint8_t pci_slot; + uint8_t pad; + uint8_t pad0; + uint8_t pci_conf[256]; } vt82c505_t; @@ -203,7 +207,7 @@ vt82c505_init(UNUSED(const device_t *info)) vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t)); memset(dev, 0, sizeof(vt82c505_t)); - pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev); + pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev, &dev->pci_slot); dev->pci_conf[0x00] = 0x06; dev->pci_conf[0x01] = 0x11; diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index 39398f996..bb2672abb 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -128,6 +128,10 @@ typedef struct atkbc_t { uint8_t channel; uint8_t stat_hi; uint8_t pending; + uint8_t irq_state; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; uint8_t mem[0x100]; @@ -347,15 +351,15 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) dev->status |= STAT_MFULL; if (dev->mem[0x20] & 0x02) - picint_common(1 << 12, 0, 1); - picint_common(1 << 1, 0, 0); + picint_common(1 << 12, 0, 1, NULL); + picint_common(1 << 1, 0, 0, NULL); } else { if (dev->mem[0x20] & 0x01) - picint_common(1 << 1, 0, 1); - picint_common(1 << 12, 0, 0); + picint_common(1 << 1, 0, 1, NULL); + picint_common(1 << 12, 0, 0, NULL); } } else if (dev->mem[0x20] & 0x01) - picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ + picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ dev->ob = temp; } @@ -720,10 +724,10 @@ write_p2(atkbc_t *dev, uint8_t val) /* PS/2: Handle IRQ's. */ if (dev->misc_flags & FLAG_PS2) { /* IRQ 12 */ - picint_common(1 << 12, 0, val & 0x20); + picint_common(1 << 12, 0, val & 0x20, NULL); /* IRQ 1 */ - picint_common(1 << 1, 0, val & 0x10); + picint_common(1 << 1, 0, val & 0x10, NULL); } #endif @@ -1550,7 +1554,8 @@ kbc_at_process_cmd(void *priv) /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0x4b); - picintc(0x1002); + picintc(0x1000); + picintc(0x0002); } dev->status = (dev->status & 0x0f) | 0x60; @@ -1569,7 +1574,8 @@ kbc_at_process_cmd(void *priv) /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ dev->p1 = dev->p1 & 0xff; write_p2(dev, 0xcf); - picintc(0x0002); + picintclevel(0x0002, &dev->irq_state); + dev->irq_state = 0; } dev->status = (dev->status & 0x0f) | 0x60; @@ -1852,7 +1858,7 @@ kbc_at_read(uint16_t port, void *priv) /* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit. This also means that in AT mode, the IRQ is level-triggered. */ if (!(dev->misc_flags & FLAG_PS2)) - picintc(1 << 1); + picintclevel(1 << 1, &dev->irq_state); break; case 0x64: @@ -1901,8 +1907,13 @@ kbc_at_reset(void *priv) if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { dev->misc_flags |= FLAG_PS2; kbc_at_do_poll = kbc_at_poll_ps2; - } else + picintc(0x1000); + picintc(0x0002); + } else { kbc_at_do_poll = kbc_at_poll_at; + picintclevel(0x0002, &dev->irq_state); + dev->irq_state = 0; + } dev->misc_flags |= FLAG_CACHE; @@ -1924,8 +1935,6 @@ kbc_at_close(void *priv) atkbc_t *dev = (atkbc_t *) priv; int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; - kbc_at_reset(dev); - /* Stop timers. */ timer_disable(&dev->send_delay_timer); diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index eb0c734aa..889ee8ebb 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -54,7 +54,7 @@ typedef struct pci_bridge_t { uint8_t regs[256]; uint8_t bus_index; - int slot; + uint8_t slot; } pci_bridge_t; #ifdef ENABLE_PCI_BRIDGE_LOG @@ -493,7 +493,10 @@ pci_bridge_init(const device_t *info) pci_bridge_reset(dev); - dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev); + if (AGP_BRIDGE(dev->local)) + pci_add_card(PCI_ADD_AGPBRIDGE, pci_bridge_read, pci_bridge_write, dev, &dev->slot); + else + dev->slot = pci_add_bridge(pci_bridge_read, pci_bridge_write, dev); interrupt_count = sizeof(interrupts); interrupt_mask = interrupt_count - 1; diff --git a/src/device/serial.c b/src/device/serial.c index a36e4f99f..56d905c4e 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -48,6 +48,8 @@ enum { SERIAL_INT_TIMEOUT = 16 }; +void serial_update_ints(serial_t *dev); + static int next_inst = 0; static serial_device_t serial_devices[SERIAL_MAX]; @@ -84,6 +86,8 @@ serial_reset_port(serial_t *dev) dev->out_new = 0xffff; memset(dev->xmit_fifo, 0, 16); memset(dev->rcvr_fifo, 0, 16); + serial_update_ints(dev); + dev->irq_state = 0; } void @@ -133,11 +137,15 @@ serial_update_ints(serial_t *dev) if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) { if (dev->type >= SERIAL_16450) - picintlevel(1 << dev->irq); - else + picintlevel(1 << dev->irq, &dev->irq_state); + else picint(1 << dev->irq); - } else - picintc(1 << dev->irq); + } else { + if (dev->type >= SERIAL_16450) + picintclevel(1 << dev->irq, &dev->irq_state); + else + picintc(1 << dev->irq); + } } static void diff --git a/src/disk/hdc_ide_cmd640.c b/src/disk/hdc_ide_cmd640.c index 6cb54aea5..2d203f3f8 100644 --- a/src/disk/hdc_ide_cmd640.c +++ b/src/disk/hdc_ide_cmd640.c @@ -42,9 +42,12 @@ typedef struct cmd640_t { uint8_t id; uint8_t in_cfg; uint8_t channels; - uint8_t pci, regs[256]; + uint8_t pci; + uint8_t irq_state; + uint8_t pci_slot; + uint8_t pad0; + uint8_t regs[256]; uint32_t local; - int slot; int irq_mode[2]; int irq_pin; int irq_line; @@ -95,12 +98,12 @@ cmd640_set_irq(int channel, void *priv) if (irq) { if (dev->irq_mode[channel] == 1) - pci_set_irq(dev->slot, dev->irq_pin); + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); else picint(1 << (14 + channel)); } else { if (dev->irq_mode[channel] == 1) - pci_clear_irq(dev->slot, dev->irq_pin); + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); else picintc(1 << (14 + channel)); } @@ -500,7 +503,10 @@ cmd640_init(const device_t *info) if (info->flags & DEVICE_PCI) { device_add(&ide_pci_2ch_device); - dev->slot = pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev); + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot); if (dev->channels & 0x01) ide_set_bus_master(0, NULL, cmd640_set_irq, dev); diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index 1f727bf6b..397329010 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -41,11 +41,16 @@ typedef struct cmd646_t { uint8_t vlb_idx; uint8_t single_channel; uint8_t in_cfg; + uint8_t pci_slot; + uint8_t regs[256]; + uint32_t local; - int slot; - int irq_mode[2]; + int irq_pin; + + int irq_mode[2]; + sff8038i_t *bm[2]; } cmd646_t; @@ -102,6 +107,9 @@ cmd646_ide_handlers(cmd646_t *dev) uint16_t side; int irq_mode[2] = { 0, 0 }; + sff_set_slot(dev->bm[0], dev->pci_slot); + sff_set_slot(dev->bm[1], dev->pci_slot); + ide_pri_disable(); if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) { @@ -382,7 +390,10 @@ cmd646_init(const device_t *info) device_add(&ide_pci_2ch_device); - dev->slot = pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev); + if (info->local & 0x80000) + pci_add_card(PCI_ADD_NORMAL, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot); + else + pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot); dev->single_channel = !!(info->local & 0x20000); diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 5e8e4e987..90dc016c7 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -409,31 +409,31 @@ sff_bus_master_set_irq(int channel, void *priv) case 1: /* Native PCI IRQ mode with interrupt pin. */ if (irq) - pci_set_irq(dev->slot, dev->irq_pin); + pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state); else - pci_clear_irq(dev->slot, dev->irq_pin); + pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); break; case 2: case 5: /* MIRQ 0 or 1. */ if (irq) - pci_set_mirq(dev->irq_mode[channel] & 1, 0); + pci_set_mirq(dev->irq_mode[channel] & 1, 0, &dev->irq_state); else - pci_clear_mirq(dev->irq_mode[channel] & 1, 0); + pci_clear_mirq(dev->irq_mode[channel] & 1, 0, &dev->irq_state); break; case 3: /* Native PCI IRQ mode with specified interrupt line. */ if (irq) - picintlevel(1 << dev->irq_line); + picintlevel(1 << dev->irq_line, &dev->irq_state); else - picintc(1 << dev->irq_line); + picintclevel(1 << dev->irq_line, &dev->irq_state); break; case 4: /* ALi Aladdin Native PCI INTAJ mode. */ if (irq) - pci_set_mirq(channel + 2, dev->irq_level[channel]); + pci_set_mirq(channel + 2, dev->irq_level[channel], &dev->irq_state); else - pci_clear_mirq(channel + 2, dev->irq_level[channel]); + pci_clear_mirq(channel + 2, dev->irq_level[channel], &dev->irq_state); break; } } @@ -456,6 +456,7 @@ sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base) dev->addr = 0x00000000; dev->ptr0 = 0x00; dev->count = dev->eot = 0x00000000; + dev->irq_state = 0; ide_pri_disable(); ide_sec_disable(); @@ -570,6 +571,7 @@ sff_init(UNUSED(const device_t *info)) dev->irq_pin = PCI_INTA; dev->irq_line = 14; dev->irq_level[0] = dev->irq_level[1] = 0; + dev->irq_state = 0; next_id++; diff --git a/src/include/86box/acpi.h b/src/include/86box/acpi.h index 11be67278..2b8a6396f 100644 --- a/src/include/86box/acpi.h +++ b/src/include/86box/acpi.h @@ -113,7 +113,8 @@ typedef struct acpi_regs_t { typedef struct acpi_t { acpi_regs_t regs; uint8_t gpireg2_default; - uint8_t pad[3]; + uint8_t irq_state; + uint8_t pad[2]; uint8_t gporeg_default[4]; uint8_t suspend_types[8]; uint16_t io_base; diff --git a/src/include/86box/hdc_ide_sff8038i.h b/src/include/86box/hdc_ide_sff8038i.h index 490a13a42..f9c40e29a 100644 --- a/src/include/86box/hdc_ide_sff8038i.h +++ b/src/include/86box/hdc_ide_sff8038i.h @@ -26,11 +26,11 @@ typedef struct sff8038i_t { uint8_t ptr0; uint8_t enabled; uint8_t dma_mode; + uint8_t irq_state; uint8_t pad; uint8_t pad0; - uint8_t pad1; uint16_t base; - uint16_t pad2; + uint16_t pad1; uint32_t ptr; uint32_t ptr_cur; uint32_t addr; diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index df9c4c573..d7d77b560 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -11,146 +11,260 @@ * * * Authors: Miran Grca, - * Fred N. van Kempen, - * Sarah Walker, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2023 Miran Grca. */ - #ifndef EMU_PCI_H #define EMU_PCI_H -#define PCI_REG_COMMAND 0x04 +#define PCI_REG_VENDOR_ID_L 0x00 +#define PCI_REG_VENDOR_ID_H 0x01 +#define PCI_REG_DEVICE_ID_L 0x02 +#define PCI_REG_DEVICE_ID_H 0x03 +#define PCI_REG_COMMAND_L 0x04 +#define PCI_REG_COMMAND_H 0x05 +#define PCI_REG_STATUS_L 0x06 +#define PCI_REG_STATUS_H 0x07 +#define PCI_REG_REVISION 0x08 +#define PCI_REG_PROG_IF 0x09 +#define PCI_REG_SUBCLASS 0x0a +#define PCI_REG_CLASS 0x0b +#define PCI_REG_CACHELINE_SIZE 0x0c +#define PCI_REG_LATENCY_TIMER 0x0d +#define PCI_REG_HEADER_TYPE 0x0e +#define PCI_REG_BIST 0x0f -#define PCI_COMMAND_IO 0x01 -#define PCI_COMMAND_MEM 0x02 +#define PCI_COMMAND_L_IO 0x01 +#define PCI_COMMAND_L_MEM 0x02 +#define PCI_COMMAND_L_BM 0x04 +#define PCI_COMMAND_L_SPECIAL 0x08 +#define PCI_COMMAND_L_MEM_WIEN 0x10 +#define PCI_COMMAND_L_VGASNOOP 0x20 +#define PCI_COMMAND_L_PARITY 0x40 -#define PCI_NO_IRQ_STEERING 0x8000 -#define PCI_CAN_SWITCH_TYPE 0x10000 -#define PCI_NO_BRIDGES 0x20000 -#define PCI_ALWAYS_EXPOSE_DEV0 0x40000 +#define PCI_COMMAND_H_SERR 0x01 +#define PCI_COMMAND_H_FAST_B2B 0x02 +#define PCI_COMMAND_H_INT_DIS 0x04 -#define PCI_CONFIG_TYPE_1 1 -#define PCI_CONFIG_TYPE_2 2 +#define PCI_STATUS_L_INT 0x08 +#define PCI_STATUS_L_CAPAB 0x10 +#define PCI_STATUS_L_66MHZ 0x20 +#define PCI_STATUS_L_FAST_B2B 0x80 -#define PCI_CONFIG_TYPE_MASK 0x7fff +#define PCI_STATUS_H_MDPERR 0x01 /* Master Data Parity Error */ +#define PCI_STATUS_H_DEVSEL 0x06 +#define PCI_STATUS_H_STA 0x08 /* Signaled Target Abort */ +#define PCI_STATUS_H_RTA 0x10 /* Received Target Abort */ +#define PCI_STATUS_H_RMA 0x20 /* Received Master Abort */ +#define PCI_STATUS_H_SSE 0x40 /* Signaled System Error */ +#define PCI_STATUS_H_DPERR 0x80 /* Detected Parity Error */ -#define PCI_INTA 1 -#define PCI_INTB 2 -#define PCI_INTC 3 -#define PCI_INTD 4 +#define PCI_DEVSEL_FAST 0x00 +#define PCI_DEVSEL_MEDIUM 0x02 +#define PCI_DEVSEL_SLOW 0x04 -#define PCI_MIRQ0 0 -#define PCI_MIRQ1 1 -#define PCI_MIRQ2 2 -#define PCI_MIRQ3 3 -#define PCI_MIRQ4 4 -#define PCI_MIRQ5 5 -#define PCI_MIRQ6 6 -#define PCI_MIRQ7 7 +#define FLAG_MECHANISM_1 0x00000001 +#define FLAG_MECHANISM_2 0x00000002 +#define FLAG_MECHANISM_SWITCH 0x00000004 +#define FLAG_CONFIG_IO_ON 0x00000008 +#define FLAG_CONFIG_DEV0_IO_ON 0x00000010 +#define FLAG_CONFIG_M1_IO_ON 0x00000020 +#define FLAG_NO_IRQ_STEERING 0x00000040 +#define FLAG_NO_BRIDGES 0x00000080 -#define PCI_IRQ_DISABLED -1 +#define FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2 +#define FLAG_MASK 0x0000007f -#define PCI_ADD_STRICT 0x80 +#define PCI_INTA 1 +#define PCI_INTB 2 +#define PCI_INTC 3 +#define PCI_INTD 4 + +#define PCI_MIRQ0 0 +#define PCI_MIRQ1 1 +#define PCI_MIRQ2 2 +#define PCI_MIRQ3 3 +#define PCI_MIRQ4 4 +#define PCI_MIRQ5 5 +#define PCI_MIRQ6 6 +#define PCI_MIRQ7 7 + +#define PCI_IRQ_DISABLED -1 + +#define PCI_ADD_STRICT 0x40 +#define PCI_ADD_MASK (PCI_ADD_STRICT - 1) +#define PCI_ADD_VFIO 0x80 +#define PCI_ADD_VFIO_MASK (PCI_ADD_VFIO - 1) + +#define PCI_CARD_VFIO PCI_ADD_VFIO + +#define PCI_BUS_INVALID 0xff + +#define PCI_IGNORE_NO_SLOT 0xff + +/* The number of an invalid PCI card. */ +#define PCI_CARD_INVALID 0xef +/* PCI cards (currently 32). */ +#define PCI_CARDS_NUM 0x20 +#define PCI_CARD_MAX (PCI_CARDS_NUM - 1) +/* The number of PCI card INT pins - always at 4 per the PCI specification. */ +#define PCI_INT_PINS_NUM 4 +/* The base for MIRQ lines accepted by pci_irq(). */ +#define PCI_MIRQ_BASE PCI_CARDS_NUM +/* PCI MIRQ lines (currently 8, this many are needed by the ALi M1543(C). */ +#define PCI_MIRQS_NUM 8 +#define PCI_MIRQ_MAX (PCI_MIRQS_NUM - 1) +/* The base for direct IRQ lines accepted by pci_irq(). */ +#define PCI_DIRQ_BASE 0xf0 +/* PCI direct IRQ lines (currently 16 because we only emulate the legacy PIC). */ +#define PCI_DIRQS_NUM 16 +#define PCI_DIRQ_MAX (PCI_DIRQS_NUM - 1) +/* PCI IRQ routings (currently 16, this many are needed by the OPTi 822). */ +#define PCI_IRQS_NUM 16 +#define PCI_IRQ_MAX (PCI_IRQS_NUM - 1) + +/* Legacy flags. */ +#define PCI_REG_COMMAND PCI_REG_COMMAND_L + +#define PCI_COMMAND_IO PCI_COMMAND_L_IO +#define PCI_COMMAND_MEM PCI_COMMAND_L_MEM + +#define PCI_CONFIG_TYPE_1 FLAG_MECHANISM_1 +#define PCI_CONFIG_TYPE_2 FLAG_MECHANISM_2 + +#define PCI_CAN_SWITCH_TYPE FLAG_MECHANISM_SWITCH +#define PCI_ALWAYS_EXPOSE_DEV0 FLAG_CONFIG_DEV0_IO_ON +#define PCI_NO_IRQ_STEERING FLAG_NO_IRQ_STEERING +#define PCI_NO_BRIDGES FLAG_NO_BRIDGES + +#define PCI_CONFIG_TYPE_MASK FLAG_MECHANISM_MASK + +#define bar_t pci_bar_t +#define trc_init pci_trc_init + +#define pci_register_slot(card, type, inta, intb, intc, intd) \ + pci_register_bus_slot(0, card, type, inta, intb, intc, intd) + +#define pci_set_mirq(mirq, level, irq_state) \ + pci_irq(PCI_MIRQ_BASE | mirq, 0, level, 1, irq_state) +#define pci_set_irq(slot, pci_int, irq_state) \ + pci_irq(slot, pci_int, 0, 1, irq_state) +#define pci_clear_mirq(mirq, level, irq_state) \ + pci_irq(PCI_MIRQ_BASE | mirq, 0, level, 0, irq_state) +#define pci_clear_irq(slot, pci_int, irq_state) \ + pci_irq(slot, pci_int, 0, 0, irq_state) enum { PCI_CARD_NORTHBRIDGE = 0, - PCI_CARD_AGPBRIDGE = 1, - PCI_CARD_SOUTHBRIDGE = 2, - PCI_CARD_SOUTHBRIDGE_IDE = 3, - PCI_CARD_SOUTHBRIDGE_PMU = 4, - PCI_CARD_SOUTHBRIDGE_USB = 5, + PCI_CARD_NORTHBRIDGE_SEC = 1, + PCI_CARD_AGPBRIDGE = 2, + PCI_CARD_SOUTHBRIDGE = 3, + PCI_CARD_SOUTHBRIDGE_IDE = 4, + PCI_CARD_SOUTHBRIDGE_PMU = 5, + PCI_CARD_SOUTHBRIDGE_USB = 6, PCI_CARD_AGP = 0x0f, PCI_CARD_NORMAL = 0x10, PCI_CARD_VIDEO = 0x11, - PCI_CARD_SCSI = 0x12, - PCI_CARD_SOUND = 0x13, - PCI_CARD_IDE = 0x14, - PCI_CARD_NETWORK = 0x15, - PCI_CARD_BRIDGE = 0x16 + PCI_CARD_HANGUL = 0x12, + PCI_CARD_IDE = 0x13, + PCI_CARD_SCSI = 0x14, + PCI_CARD_SOUND = 0x15, + PCI_CARD_MODEM = 0x16, + PCI_CARD_NETWORK = 0x17, + PCI_CARD_UART = 0x18, + PCI_CARD_USB = 0x19, + PCI_CARD_BRIDGE = 0x1a }; enum { PCI_ADD_NORTHBRIDGE = 0, - PCI_ADD_AGPBRIDGE = 1, - PCI_ADD_SOUTHBRIDGE = 2, - PCI_ADD_SOUTHBRIDGE_IDE = 3, - PCI_ADD_SOUTHBRIDGE_PMU = 4, - PCI_ADD_SOUTHBRIDGE_USB = 5, + PCI_ADD_NORTHBRIDGE_SEC = 1, + PCI_ADD_AGPBRIDGE = 2, + PCI_ADD_SOUTHBRIDGE = 3, + PCI_ADD_SOUTHBRIDGE_IDE = 4, + PCI_ADD_SOUTHBRIDGE_PMU = 5, + PCI_ADD_SOUTHBRIDGE_USB = 6, PCI_ADD_AGP = 0x0f, PCI_ADD_NORMAL = 0x10, PCI_ADD_VIDEO = 0x11, - PCI_ADD_SCSI = 0x12, - PCI_ADD_SOUND = 0x13, - PCI_ADD_IDE = 0x14, - PCI_ADD_NETWORK = 0x15, - PCI_ADD_BRIDGE = 0x16 + PCI_ADD_HANGUL = 0x12, + PCI_ADD_IDE = 0x13, + PCI_ADD_SCSI = 0x14, + PCI_ADD_SOUND = 0x15, + PCI_ADD_MODEM = 0x16, + PCI_ADD_NETWORK = 0x17, + PCI_ADD_UART = 0x18, + PCI_ADD_USB = 0x19, + PCI_ADD_BRIDGE = 0x1a }; typedef union { uint32_t addr; uint8_t addr_regs[4]; -} bar_t; +} pci_bar_t; +extern int pci_burst_time; +extern int agp_burst_time; +extern int pci_nonburst_time; +extern int agp_nonburst_time; -#define PCI_IO_ON 0x01 -#define PCI_IO_DEV0 0x02 +extern int pci_flags; +extern uint32_t pci_base; +extern uint32_t pci_size; -extern int pci_burst_time; -extern int agp_burst_time; -extern int pci_nonburst_time; -extern int agp_nonburst_time; -extern int pci_take_over_io; +extern void pci_set_irq_routing(int pci_int, int irq); +extern void pci_set_irq_level(int pci_int, int level); +extern void pci_enable_mirq(int mirq); +extern void pci_set_mirq_routing(int mirq, int irq); -extern uint32_t pci_base; -extern uint32_t pci_size; +/* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE + and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's + hack that may no longer be needed). */ +extern void pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state); +extern uint8_t pci_get_int(uint8_t slot, uint8_t pci_int); -extern void pci_type2_write(uint16_t port, uint8_t val, void *priv); -extern void pci_type2_writew(uint16_t port, uint16_t val, void *priv); -extern void pci_type2_writel(uint16_t port, uint32_t val, void *priv); -extern uint8_t pci_type2_read(uint16_t port, void *priv); -extern uint16_t pci_type2_readw(uint16_t port, void *priv); -extern uint32_t pci_type2_readl(uint16_t port, void *priv); +/* Relocate a PCI device to a new slot, required for the configurable + IDSEL's of ALi M1543(c). */ +extern void pci_relocate_slot(int type, int new_slot); -extern void pci_set_irq_routing(int pci_int, int irq); -extern void pci_set_irq_level(int pci_int, int level); +/* Write PCI enable/disable key, split for the ALi M1435. */ +extern void pci_key_write(uint8_t val); -extern void pci_enable_mirq(int mirq); -extern void pci_set_mirq_routing(int mirq, int irq); +/* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */ +extern void pci_set_pmc(uint8_t pmc); -extern int pci_irq_is_level(int irq); +extern void pci_pic_reset(void); +extern void pci_reset(void); -extern void pci_set_mirq(uint8_t mirq, int level); -extern void pci_set_irq(uint8_t card, uint8_t pci_int); -extern void pci_clear_mirq(uint8_t mirq, int level); -extern void pci_clear_irq(uint8_t card, uint8_t pci_int); -extern uint8_t pci_get_int(uint8_t card, uint8_t pci_int); +/* Needed for the io.c handling of configuration mechanism #2 ports C000-CFFF. */ +extern void pci_write(uint16_t port, uint8_t val, void *priv); +extern void pci_writew(uint16_t port, uint16_t val, void *priv); +extern void pci_writel(uint16_t port, uint32_t val, void *priv); +extern uint8_t pci_read(uint16_t port, void *priv); +extern uint16_t pci_readw(uint16_t port, void *priv); +extern uint32_t pci_readl(uint16_t port, void *priv); -extern void pci_reset(void); -extern void pci_init(int type); -extern uint8_t pci_register_bus(void); -extern void pci_set_pmc(uint8_t pmc); -extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number); -extern void pci_relocate_slot(int type, int new_slot); -extern void pci_register_slot(int card, int type, - int inta, int intb, int intc, int intd); -extern void pci_register_bus_slot(int bus, int card, int type, - int inta, int intb, int intc, int intd); -extern void pci_close(void); -extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); +extern uint8_t pci_register_bus(void); +extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number); +extern void pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, int intd); -extern void trc_init(void); +/* Add a PCI card. */ +extern void pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot); -extern uint8_t trc_read(uint16_t port, void *priv); -extern void trc_write(uint16_t port, uint8_t val, void *priv); +/* Add an instance of the PCI bridge. */ +extern uint8_t pci_add_bridge(uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); -extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); +/* Register the cards that have been added into slots. */ +extern void pci_register_cards(void); -extern void pci_pic_reset(void); +extern void pci_init(int flags); + +/* PCI bridge stuff. */ +extern void pci_bridge_set_ctl(void *priv, uint8_t ctl); #ifdef EMU_DEVICE_H extern const device_t dec21150_device; diff --git a/src/include/86box/pic.h b/src/include/86box/pic.h index dcc6f1358..a66e511b8 100644 --- a/src/include/86box/pic.h +++ b/src/include/86box/pic.h @@ -19,6 +19,13 @@ #ifndef EMU_PIC_H #define EMU_PIC_H +typedef struct pic_latch { + uint8_t d; + uint8_t e; + uint8_t q; + uint8_t nq; +} pic_latch_t; + typedef struct pic { uint8_t icw1; uint8_t icw2; @@ -38,8 +45,13 @@ typedef struct pic { uint8_t special_mask_mode; uint8_t auto_eoi_rotate; uint8_t interrupt; - uint8_t lines; uint8_t data_bus; + uint8_t irq_latch; + uint8_t has_slaves; + uint8_t flags; + uint8_t edge_lines; + uint8_t pad; + uint32_t lines[8]; uint32_t at; struct pic *slaves[8]; } pic_t; @@ -70,12 +82,22 @@ extern void pic2_init(void); extern void pic_reset(void); extern int picint_is_level(int irq); -extern void picint_common(uint16_t num, int level, int set); -extern void picint(uint16_t num); -extern void picintlevel(uint16_t num); -extern void picintc(uint16_t num); +extern void picint_common(uint16_t num, int level, int set, uint8_t *irq_state); extern int picinterrupt(void); +#define PIC_IRQ_EDGE 0 +#define PIC_IRQ_LEVEL 1 + +#define PIC_SLAVE_PENDING 0x01 +#define PIC_FREEZE 0x02 +#define PIC_MASTER_CLEAR 0x04 + +/* Legacy defines. */ +#define picint(num) picint_common(num, PIC_IRQ_EDGE, 1, NULL) +#define picintlevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 1, irq_state) +#define picintc(num) picint_common(num, PIC_IRQ_EDGE, 0, NULL) +#define picintclevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 0, irq_state) + extern uint8_t pic_irq_ack(void); #endif /*EMU_PIC_H*/ diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index 213873c5a..29b7eb4fb 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -396,6 +396,10 @@ typedef struct x54x_t { uint8_t setup_info_len; uint8_t max_id; uint8_t pci_slot; + uint8_t irq_state; + uint8_t pad; + uint8_t pad0; + uint8_t pad1; uint8_t temp_cdb[12]; /* for multi-threading, keep these volatile */ @@ -437,7 +441,7 @@ typedef struct x54x_t { volatile int PendingInterrupt; volatile int Lock; volatile int target_data_len; - volatile int pad0; + volatile int pad2; uint32_t Base; uint32_t fdc_address; diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index b27e54c5e..831d68231 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -74,13 +74,13 @@ typedef struct serial_s { uint8_t out; uint8_t msr_set; uint8_t pad; + uint8_t irq_state; uint8_t pad0; - uint8_t pad1; uint16_t dlab; uint16_t base_address; uint16_t out_new; - uint16_t pad2; + uint16_t pad1; uint8_t rcvr_fifo_pos; uint8_t xmit_fifo_pos; diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 92c608789..64a96fe53 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -271,6 +271,8 @@ typedef struct voodoo_t { int pci_enable; + uint8_t pci_slot; + uint8_t dac_data[8]; int dac_reg; int dac_reg_ff; diff --git a/src/io.c b/src/io.c index 173e6707b..b9db1e73c 100644 --- a/src/io.c +++ b/src/io.c @@ -288,12 +288,12 @@ inb(uint16_t port) int found = 0; int qfound = 0; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - ret = pci_type2_read(port, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_read(port, NULL); found = 1; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - ret = pci_type2_read(port, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_read(port, NULL); found = 1; qfound = 1; } else { @@ -340,12 +340,12 @@ outb(uint16_t port, uint8_t val) int found = 0; int qfound = 0; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - pci_type2_write(port, val, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_write(port, val, NULL); found = 1; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - pci_type2_write(port, val, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_write(port, val, NULL); found = 1; qfound = 1; } else { @@ -384,12 +384,12 @@ inw(uint16_t port) int qfound = 0; uint8_t ret8[2]; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - ret = pci_type2_readw(port, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_readw(port, NULL); found = 2; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - ret = pci_type2_readw(port, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_readw(port, NULL); found = 2; qfound = 1; } else { @@ -446,12 +446,12 @@ outw(uint16_t port, uint16_t val) int found = 0; int qfound = 0; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - pci_type2_writew(port, val, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_writew(port, val, NULL); found = 2; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - pci_type2_writew(port, val, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_writew(port, val, NULL); found = 2; qfound = 1; } else { @@ -504,12 +504,12 @@ inl(uint16_t port) int found = 0; int qfound = 0; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - ret = pci_type2_readl(port, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + ret = pci_readl(port, NULL); found = 4; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - ret = pci_type2_readl(port, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + ret = pci_readl(port, NULL); found = 4; qfound = 1; } else { @@ -594,12 +594,12 @@ outl(uint16_t port, uint32_t val) int qfound = 0; int i = 0; - if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { - pci_type2_writel(port, val, NULL); + if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) { + pci_writel(port, val, NULL); found = 4; qfound = 1; - } else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) { - pci_type2_writel(port, val, NULL); + } else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) { + pci_writel(port, val, NULL); found = 4; qfound = 1; } else { diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 3f37c13c4..f9b340080 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -1527,11 +1527,11 @@ machine_at_pcm5330_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE_IDE, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4); device_add(&stpc_serial_device); device_add(&w83977f_370_device); device_add(&keyboard_ps2_ami_pci_device); @@ -1738,7 +1738,7 @@ machine_at_ms4134_init(const machine_t *model) device_add(&fdc37c665_ide_pri_device); - pci_init(PCI_CAN_SWITCH_TYPE | PCI_ALWAYS_EXPOSE_DEV0); + pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0B, PCI_CARD_SCSI, 4, 1, 2, 3); @@ -1772,7 +1772,7 @@ machine_at_tg486gp_init(const machine_t *model) device_add(&fdc37c665_ide_pri_device); - pci_init(PCI_CAN_SWITCH_TYPE | PCI_ALWAYS_EXPOSE_DEV0); + pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4); diff --git a/src/machine/machine.c b/src/machine/machine.c index 47e98e7b3..b9bb23ed0 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -108,7 +108,7 @@ machine_init_ex(int m) /* Reset the fast off stuff. */ cpu_fast_off_reset(); - pci_take_over_io = 0x00000000; + pci_flags = 0x00000000; } /* All good, boot the machine! */ diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 80dc4ec27..2221fccf4 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -97,36 +97,45 @@ static uint8_t rtl8019as_pnp_rom[] = { typedef struct nic_t { dp8390_t *dp8390; + const char *name; + + uint8_t pnp_csnsav; + uint8_t pci_slot; + uint8_t irq_state; + uint8_t pad; + + /* RTL8019AS/RTL8029AS registers */ + uint8_t config0; + uint8_t config2; + uint8_t config3; + uint8_t _9346cr; + + uint8_t pci_regs[PCI_REGSIZE]; + uint8_t eeprom[128]; /* for RTL8029AS */ + + uint8_t maclocal[6]; /* configured MAC (local) address */ + + /* POS registers, MCA boards only */ + uint8_t pos_regs[8]; + int board; int is_pci; int is_mca; int is_8bit; - uint32_t base_address; int base_irq; + int has_bios; + + uint32_t base_address; uint32_t bios_addr; uint32_t bios_size; uint32_t bios_mask; - int card; /* PCI card slot */ - int has_bios; - int pad; + bar_t pci_bar[2]; - uint8_t pci_regs[PCI_REGSIZE]; - uint8_t eeprom[128]; /* for RTL8029AS */ + rom_t bios_rom; + void *pnp_card; - uint8_t pnp_csnsav; - uint8_t maclocal[6]; /* configured MAC (local) address */ - - /* RTL8019AS/RTL8029AS registers */ - uint8_t config0; - uint8_t config2; - uint8_t config3; - uint8_t _9346cr; - uint32_t pad0; - - /* POS registers, MCA boards only */ - uint8_t pos_regs[8]; } nic_t; #ifdef ENABLE_NE2K_LOG @@ -150,13 +159,13 @@ nelog(int lvl, const char *fmt, ...) static void nic_interrupt(void *priv, int set) { - const nic_t *dev = (nic_t *) priv; + nic_t *dev = (nic_t *) priv; if (dev->is_pci) { if (set) - pci_set_irq(dev->card, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - pci_clear_irq(dev->card, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } else { if (set) picint(1 << dev->base_irq); @@ -1087,8 +1096,7 @@ nic_init(const device_t *info) mem_mapping_disable(&dev->bios_rom.mapping); /* Add device to the PCI bus, keep its slot number. */ - dev->card = pci_add_card(PCI_ADD_NORMAL, - nic_pci_read, nic_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev, &dev->pci_slot); } /* Initialize the RTL8029 EEPROM. */ diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 85d2cb8bb..7cbe10e31 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -216,7 +216,8 @@ typedef struct { uint32_t base_address; int base_irq; int dma_channel; - int card; /* PCI card slot */ + uint8_t pci_slot; /* PCI card slot */ + uint8_t irq_state; int xmit_pos; /** Register Address Pointer */ uint32_t u32RAP; @@ -413,9 +414,9 @@ pcnet_do_irq(nic_t *dev, int issue) { if (dev->is_pci) { if (issue) - pci_set_irq(dev->card, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - pci_clear_irq(dev->card, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } else { if (issue) picint(1 << dev->base_irq); @@ -2995,8 +2996,7 @@ pcnet_init(const device_t *info) pcnet_pci_regs[0x04] = 3; /* Add device to the PCI bus, keep its slot number. */ - dev->card = pci_add_card(PCI_ADD_NORMAL, - pcnet_pci_read, pcnet_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot); } else if (dev->board == DEV_AM79C961) { dev->dma_channel = -1; diff --git a/src/nvr_at.c b/src/nvr_at.c index 1ba9fd2b2..f60d733a0 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -306,7 +306,7 @@ typedef struct local_t { uint8_t read_addr; uint8_t wp_0d; uint8_t wp_32; - uint8_t pad; + uint8_t irq_state; uint8_t pad0; uint8_t addr[8]; @@ -434,6 +434,21 @@ check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2) return 1; } +static void +timer_update_irq(nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + uint8_t irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & (REGB_UIE | REGB_AIE | REGB_PIE); + + if (irq) { + nvr->regs[RTC_REGC] |= REGC_IRQF; + picintlevel(1 << nvr->irq, &local->irq_state); + } else { + nvr->regs[RTC_REGC] &= ~REGC_IRQF; + picintclevel(1 << nvr->irq, &local->irq_state); + } +} + /* Update the NVR registers from the internal clock. */ static void timer_update(void *priv) @@ -442,45 +457,38 @@ timer_update(void *priv) local_t *local = (local_t *) nvr->data; struct tm tm; - local->ecount = 0LL; + if (local->ecount == (244ULL * TIMER_USEC)) { + rtc_tick(); - if (!(nvr->regs[RTC_REGB] & REGB_SET)) { /* Get the current time from the internal clock. */ nvr_time_get(&tm); /* Update registers with current time. */ time_set(nvr, &tm); - /* Clear update status. */ - local->stat = 0x00; - /* Check for any alarms we need to handle. */ - if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) && check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* && - check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && - check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS)*/ - ) { + if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS) */) { nvr->regs[RTC_REGC] |= REGC_AF; - if (nvr->regs[RTC_REGB] & REGB_AIE) { - /* Generate an interrupt. */ - if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) { - picintlevel(1 << nvr->irq); - nvr->regs[RTC_REGC] |= REGC_IRQF; - } - } + timer_update_irq(nvr); } + /* Schedule the end of the update. */ + local->ecount = 1984ULL * TIMER_USEC; + timer_set_delay_u64(&local->update_timer, local->ecount); + } else { /* * The flag and interrupt should be issued * on update ended, not started. */ nvr->regs[RTC_REGC] |= REGC_UF; - if (nvr->regs[RTC_REGB] & REGB_UIE) { - /* Generate an interrupt. */ - if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) { - picintlevel(1 << nvr->irq); - nvr->regs[RTC_REGC] |= REGC_IRQF; - } - } + timer_update_irq(nvr); + + /* Clear update status. */ + local->stat = 0x00; + + local->ecount = 0LL; } } @@ -525,13 +533,7 @@ timer_intr(void *priv) timer_load_count(nvr); nvr->regs[RTC_REGC] |= REGC_PF; - if (nvr->regs[RTC_REGB] & REGB_PIE) { - /* Generate an interrupt. */ - if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) { - picintlevel(1 << nvr->irq); - nvr->regs[RTC_REGC] |= REGC_IRQF; - } - } + timer_update_irq(nvr); } } @@ -541,15 +543,14 @@ timer_tick(nvr_t *nvr) { local_t *local = (local_t *) nvr->data; - /* Only update it there is no SET in progress. */ - if (!(nvr->regs[RTC_REGB] & REGB_SET)) { + /* Only update it there is no SET in progress. + Also avoid updating it is DV2-DV0 are not set to 0, 1, 0. */ + if (((nvr->regs[RTC_REGA] & 0x70) == 0x20) && !(nvr->regs[RTC_REGB] & REGB_SET)) { /* Set the UIP bit, announcing the update. */ local->stat = REGA_UIP; - rtc_tick(); - /* Schedule the actual update. */ - local->ecount = (244ULL + 1984ULL) * TIMER_USEC; + local->ecount = 244ULL * TIMER_USEC; timer_set_delay_u64(&local->update_timer, local->ecount); } } @@ -583,32 +584,29 @@ nvr_reg_write(uint16_t reg, uint8_t val, void *priv) local_t *local = (local_t *) nvr->data; struct tm tm; uint8_t old; - uint8_t irq = 0; - uint8_t old_irq = 0; old = nvr->regs[reg]; switch (reg) { + case RTC_SECONDS: /* bit 7 of seconds is read-only */ + nvr_reg_common_write(reg, val & 0x7f, nvr, local); + break; + case RTC_REGA: - nvr->regs[RTC_REGA] = val; - timer_load_count(nvr); + if ((val & nvr->regs[RTC_REGA]) & ~REGA_UIP) { + nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & REGA_UIP) | (val & ~REGA_UIP); + timer_load_count(nvr); + } break; case RTC_REGB: - old_irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & 0x70; - nvr->regs[RTC_REGB] = val; if (((old ^ val) & REGB_SET) && (val & REGB_SET)) { /* According to the datasheet... */ - nvr->regs[RTC_REGA] &= ~REGA_UIP; - nvr->regs[RTC_REGB] &= ~REGB_UIE; - } - irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & 0x70; - if (old_irq && !irq) { - picintc(1 << nvr->irq); - nvr->regs[RTC_REGC] &= ~REGC_IRQF; - } else if (!old_irq && irq) { - picintlevel(1 << nvr->irq); - nvr->regs[RTC_REGC] |= REGC_IRQF; + val &= ~REGB_UIE; + local->stat &= ~REGA_UIP; } + + nvr->regs[RTC_REGB] = val; + timer_update_irq(nvr); break; case RTC_REGC: /* R/O */ @@ -698,9 +696,9 @@ nvr_read(uint16_t addr, void *priv) break; case RTC_REGC: - ret = nvr->regs[RTC_REGC]; - picintc(1 << nvr->irq); - nvr->regs[RTC_REGC] = 0x00; + ret = nvr->regs[RTC_REGC] & (REGC_IRQF | REGC_PF | REGC_AF | REGC_UF); + nvr->regs[RTC_REGC] &= ~(REGC_IRQF | REGC_PF | REGC_AF | REGC_UF); + timer_update_irq(nvr); break; case RTC_REGD: diff --git a/src/pci.c b/src/pci.c index c86006a1a..790cabaf8 100644 --- a/src/pci.c +++ b/src/pci.c @@ -11,12 +11,8 @@ * * * Authors: Miran Grca, - * Fred N. van Kempen, - * Sarah Walker, * - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2008-2020 Sarah Walker. + * Copyright 2023 Miran Grca. */ #include #include @@ -36,53 +32,67 @@ #include <86box/keyboard.h> #include <86box/plat_unused.h> -typedef struct pci_card_t { - uint8_t bus; - uint8_t id; - uint8_t type; - uint8_t irq_routing[4]; +#define PCI_ENABLED 0x80000000 - void *priv; - void (*write)(int func, int addr, uint8_t val, void *priv); - uint8_t (*read)(int func, int addr, void *priv); +typedef struct pci_card_t { + uint8_t bus; + uint8_t id; + uint8_t type; + uint8_t irq_routing[PCI_INT_PINS_NUM]; + + void * priv; + void (*write)(int func, int addr, uint8_t val, void *priv); + uint8_t (*read)(int func, int addr, void *priv); } pci_card_t; +typedef struct pci_card_desc_t { + uint8_t type; + void * priv; + void (*write)(int func, int addr, uint8_t val, void *priv); + uint8_t (*read)(int func, int addr, void *priv); + uint8_t *slot; +} pci_card_desc_t; + typedef struct pci_mirq_t { - uint8_t enabled; - uint8_t irq_line; + uint8_t enabled; + uint8_t irq_line; } pci_mirq_t; -int pci_burst_time; -int agp_burst_time; -int pci_nonburst_time; -int agp_nonburst_time; -int pci_take_over_io; +int pci_burst_time; +int agp_burst_time; +int pci_nonburst_time; +int agp_nonburst_time; -uint32_t pci_base = 0xc000; -uint32_t pci_size = 0x1000; +int pci_flags; -static pci_card_t pci_cards[32]; -static uint8_t pci_pmc = 0; -static uint8_t last_pci_card = 0; -static uint8_t last_normal_pci_card = 0; -static uint8_t last_pci_bus = 1; -static uint8_t pci_card_to_slot_mapping[256][32]; -static uint8_t pci_bus_number_to_index_mapping[256]; -static uint8_t pci_irqs[16]; -static uint8_t pci_irq_level[16]; -static uint64_t pci_irq_hold[16]; -static pci_mirq_t pci_mirqs[8]; -static int pci_type; -static int pci_switch; -static int pci_index; -static int pci_func; -static int pci_card; -static int pci_bus; -static int pci_enable; -static int pci_key; -static int trc_reg = 0; +uint32_t pci_base = 0xc000; +uint32_t pci_size = 0x1000; -static void pci_reset_regs(void); +static pci_card_t pci_cards[PCI_CARDS_NUM]; +static pci_card_desc_t pci_card_descs[PCI_CARDS_NUM]; +static uint8_t pci_pmc = 0; +static uint8_t last_pci_card = 0; +static uint8_t last_normal_pci_card = 0; +static uint8_t last_normal_pci_card_id = 0; +static uint8_t last_pci_bus = 1; +static uint8_t next_pci_card = 0; +static uint8_t normal_pci_cards = 0; +static uint8_t next_normal_pci_card = 0; +static uint8_t pci_card_to_slot_mapping[256][PCI_CARDS_NUM]; +static uint8_t pci_bus_number_to_index_mapping[256]; +static uint8_t pci_irqs[PCI_IRQS_NUM]; +static uint8_t pci_irq_level[PCI_IRQS_NUM]; +static uint64_t pci_irq_hold[PCI_IRQS_NUM]; +static pci_mirq_t pci_mirqs[PCI_MIRQS_NUM]; +static int pci_index; +static int pci_func; +static int pci_card; +static int pci_bus; +static int pci_key; +static int pci_trc_reg = 0; +static uint32 pci_enable = 0x00000000; + +static void pci_reset_regs(void); #ifdef ENABLE_PCI_LOG int pci_do_log = ENABLE_PCI_LOG; @@ -102,548 +112,6 @@ pci_log(const char *fmt, ...) # define pci_log(fmt, ...) #endif -static void -pci_clear_slot(int card) -{ - pci_card_to_slot_mapping[pci_cards[card].bus][pci_cards[card].id] = 0xff; - - pci_cards[card].id = 0xff; - pci_cards[card].type = 0xff; - - for (uint8_t i = 0; i < 4; i++) - pci_cards[card].irq_routing[i] = 0; - - pci_cards[card].read = NULL; - pci_cards[card].write = NULL; - pci_cards[card].priv = NULL; -} - -void -pci_relocate_slot(int type, int new_slot) -{ - int card = -1; - int old_slot; - uint8_t mapping; - - if ((new_slot < 0) || (new_slot > 31)) - return; - - for (uint8_t i = 0; i < 32; i++) { - if ((pci_cards[i].bus == 0) && (pci_cards[i].type == type)) { - card = i; - break; - } - } - - if (card == -1) - return; - - old_slot = pci_cards[card].id; - pci_cards[card].id = new_slot; - mapping = pci_card_to_slot_mapping[0][old_slot]; - pci_card_to_slot_mapping[0][old_slot] = 0xff; - pci_card_to_slot_mapping[0][new_slot] = mapping; -} - -static void -pci_cf8_write(UNUSED(uint16_t port), uint32_t val, UNUSED(void *priv)) -{ - pci_log("cf8 write: %08X\n", val); - pci_index = val & 0xff; - pci_func = (val >> 8) & 7; - pci_card = (val >> 11) & 31; - pci_bus = (val >> 16) & 0xff; - pci_enable = (val >> 31) & 1; -} - -static uint32_t -pci_cf8_read(UNUSED(uint16_t port), UNUSED(void *priv)) -{ - return pci_index | (pci_func << 8) | (pci_card << 11) | (pci_bus << 16) | (pci_enable << 31); -} - -static void -pci_write(uint16_t port, uint8_t val, UNUSED(void *priv)) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return; - - pci_log("Writing %02X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - - default: - break; - } -} - -static void -pci_writew(uint16_t port, uint16_t val, UNUSED(void *priv)) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return; - - pci_log("Writing %04X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 1), val >> 8, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - - default: - break; - } -} - -static void -pci_writel(uint16_t port, uint32_t val, UNUSED(void *priv)) -{ - uint8_t slot = 0; - - if (in_smm) - pci_log("(%i) %03x write: %02X\n", pci_enable, port, val); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return; - - pci_log("Writing %08X to PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", val, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) { - pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); - pci_cards[slot].write(pci_func, pci_index | (port & 3), val & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 1), (val >> 8) & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 2), (val >> 16) & 0xff, pci_cards[slot].priv); - pci_cards[slot].write(pci_func, pci_index | ((port & 3) + 3), (val >> 24) & 0xff, pci_cards[slot].priv); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - - break; - - default: - break; - } -} - -static uint8_t -pci_read(uint16_t port, UNUSED(void *priv)) -{ - uint8_t slot = 0; - uint8_t ret = 0xff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - break; - - default: - break; - } - - pci_log("Reading %02X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - -static uint16_t -pci_readw(uint16_t port, UNUSED(void *priv)) -{ - uint8_t slot = 0; - uint16_t ret = 0xffff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) { - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 1, pci_cards[slot].priv) << 8); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - break; - - default: - break; - } - - pci_log("Reading %04X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - -static uint32_t -pci_readl(uint16_t port, UNUSED(void *priv)) -{ - uint8_t slot = 0; - uint32_t ret = 0xffffffff; - - if (in_smm) - pci_log("(%i) %03x read\n", pci_enable, port); - - switch (port) { - case 0xcfc: - case 0xcfd: - case 0xcfe: - case 0xcff: - if (!pci_enable) - return 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) { - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 1, pci_cards[slot].priv) << 8); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 2, pci_cards[slot].priv) << 16); - ret |= (pci_cards[slot].read(pci_func, (pci_index | (port & 3)) + 3, pci_cards[slot].priv) << 24); - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index | (port & 3)); -#endif - break; - - default: - break; - } - - pci_log("Reading %08X, from PCI card on bus %i, slot %02X (pci_cards[%i]) (%02X:%02X)...\n", ret, pci_bus, pci_card, slot, pci_func, pci_index | (port & 3)); - - return ret; -} - -void -pci_set_pmc(uint8_t pmc) -{ - pci_log("pci_set_pmc(%02X)\n", pmc); -#if 0 - pci_reset_regs(); -#endif - - if (!pci_pmc && (pmc & 0x01)) { - pci_log("PMC: Dellocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - pci_take_over_io &= ~PCI_IO_ON; - - io_removehandler(0x0cf8, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_removehandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cf8, 1, - NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cfc, 4, - pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); - } else if (pci_pmc && !(pmc & 0x01)) { - pci_log("PMC: Redellocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - pci_take_over_io &= ~PCI_IO_ON; - if (pci_key) { - pci_log("PMC: Allocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - pci_take_over_io |= PCI_IO_ON; - } - - io_removehandler(0x0cf8, 1, - NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL); - io_removehandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_removehandler(0x0cfc, 4, - pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); - io_sethandler(0x0cf8, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - } - - pci_pmc = (pmc & 0x01); -} - -static void -pci_type2_write_reg(uint16_t port, uint8_t val) -{ - uint8_t slot = 0; - - pci_card = (port >> 8) & 0xf; - pci_index = port & 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].write) - pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to empty PCI card on slot %02X:%02X (pci_cards[%i]) (%02X:%02X)...\n", pci_bus, pci_card, slot, pci_func, pci_index); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Writing to unassigned PCI card on slot %02X:%02X (pci_cards[%i]) (%02X:%02X)...\n", pci_bus, pci_card, slot, pci_func, pci_index); -#endif -} - -void -pci_type2_write(uint16_t port, uint8_t val, UNUSED(void *priv)) -{ - switch (port) { - case 0xcf8: - pci_func = (val >> 1) & 7; - - if (val & 0xf0) { - pci_log("CF8: Allocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - pci_take_over_io |= PCI_IO_ON; - } else { - pci_log("CF8: Dellocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - pci_take_over_io &= ~PCI_IO_ON; - } - - pci_key = val & 0xf0; - break; - case 0xcfa: - pci_bus = val; - - pci_log("CFA: Allocating ports %04X-%04X...\n", pci_base, pci_base + pci_size - 1); - - /* Evidently, writing here, we should also enable the - configuration space. */ - pci_take_over_io |= PCI_IO_ON; - - /* Mark as enabled. */ - pci_key |= 0x100; - break; - case 0xcfb: - pci_log("Write %02X to port 0CFB\n", val); - pci_set_pmc(val); - break; - - case 0xc000 ... 0xc0ff: - if (pci_take_over_io == 0x00000000) - break; - - pci_type2_write_reg(port, val); - break; - - case 0xc100 ... 0xcfff: - if (!(pci_take_over_io & PCI_IO_ON)) - break; - - pci_type2_write_reg(port, val); - break; - - default: - break; - } -} - -void -pci_type2_writew(uint16_t port, uint16_t val, void *priv) -{ - pci_type2_write(port, val & 0xff, priv); - pci_type2_write(port + 1, val >> 8, priv); -} - -void -pci_type2_writel(uint16_t port, uint32_t val, void *priv) -{ - pci_type2_writew(port, val & 0xffff, priv); - pci_type2_writew(port + 2, val >> 16, priv); -} - -static void -pci_type2_cfb_writel(uint16_t port, uint32_t val, void *priv) -{ - for (uint8_t i = 0; i < 4; i++) { - /* Make sure to have the DWORD write not pass through to PMC if mechanism 1 is in use, - as otherwise, the PCI enable bits clobber it. */ - if (!pci_pmc || ((port + i) != 0x0cfb)) - pci_type2_write(port + i, val >> 8, priv); - } -} - -static uint8_t -pci_type2_read_reg(uint16_t port) -{ - uint8_t slot = 0; - uint8_t ret = 0xff; - - pci_card = (port >> 8) & 0xf; - pci_index = port & 0xff; - - slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; - if (slot != 0xff) { - if (pci_cards[slot].read) - ret = pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from empty PCI card on slot %02X:%02X (pci_cards[%i]) (%02X:%02X)...\n", pci_bus, pci_card, slot, pci_func, pci_index); -#endif - } -#ifdef ENABLE_PCI_LOG - else - pci_log("Reading from unasisgned PCI card on slot %02X:%02X (pci_cards[%i]) (%02X:%02X)...\n", pci_bus, pci_card, slot, pci_func, pci_index); -#endif - - pci_log("Reading %02X at PCI register %02X at bus %02X, card %02X, function %02X\n", ret, pci_index, pci_bus, pci_card, pci_func); - - return ret; -} - -uint8_t -pci_type2_read(uint16_t port, UNUSED(void *priv)) -{ - uint8_t ret = 0xff; - - switch (port) { - case 0xcf8: - ret = pci_key | (pci_func << 1); - break; - case 0xcfa: - ret = pci_bus; - break; - case 0xcfb: - ret = pci_pmc; - break; - - case 0xc000 ... 0xc0ff: - if (pci_take_over_io == 0x00000000) - break; - - ret = pci_type2_read_reg(port); - break; - - case 0xc100 ... 0xcfff: - if (!(pci_take_over_io & PCI_IO_ON)) - break; - - ret = pci_type2_read_reg(port); - break; - - default: - break; - } - - return ret; -} - -uint16_t -pci_type2_readw(uint16_t port, void *priv) -{ - uint16_t ret = pci_type2_read(port, priv); - ret |= ((uint16_t) pci_type2_read(port + 1, priv)) << 8; - - return ret; -} - -uint32_t -pci_type2_readl(uint16_t port, void *priv) -{ - uint32_t ret = pci_type2_readw(port, priv); - ret |= ((uint32_t) pci_type2_readw(port + 2, priv)) << 16; - - return ret; -} - void pci_set_irq_routing(int pci_int, int irq) { @@ -668,250 +136,79 @@ pci_set_mirq_routing(int mirq, int irq) pci_mirqs[mirq].irq_line = irq; } +/* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE + and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's + hack that may no longer be needed). */ void -pci_set_mirq(uint8_t mirq, int level) +pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state) { - uint8_t irq_line = 0; - uint8_t irq_bit; - - if (mirq >= 0xf0) { - irq_line = mirq & 0x0f; - irq_bit = 0x1D; - } else { - if (!pci_mirqs[mirq].enabled) { - pci_log("pci_set_mirq(%02X): MIRQ0 disabled\n", mirq); - return; - } - - if (pci_mirqs[mirq].irq_line > 0x0f) { - pci_log("pci_set_mirq(%02X): IRQ line is disabled\n", mirq); - return; - } - - irq_line = pci_mirqs[mirq].irq_line; - irq_bit = (0x1E + mirq); - } - pci_log("pci_set_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - - if (level && (pci_irq_hold[irq_line] & (1ULL << irq_bit))) { - /* IRQ already held, do nothing. */ - pci_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq); - picintlevel(1 << irq_line); - return; - } - pci_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq); - - if (!level || !pci_irq_hold[irq_line]) { - pci_log("pci_set_mirq(%02X): Issuing %s-triggered IRQ (%sheld)\n", mirq, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); - - /* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */ - if (level) - picintlevel(1 << irq_line); - else - picint(1 << irq_line); - } else if (level && pci_irq_hold[irq_line]) { - pci_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq); - picintlevel(1 << irq_line); - } - - /* If the IRQ is level-triggered, mark that this MIRQ is holding it. */ - if (level) { - pci_log("pci_set_mirq(%02X): Marking that this card is holding the IRQ\n", mirq); - pci_irq_hold[irq_line] |= (1ULL << irq_bit); - } - - pci_log("pci_set_mirq(%02X): Edge-triggered interrupt, not marking\n", mirq); -} - -void -pci_set_irq(uint8_t card, uint8_t pci_int) -{ - uint8_t slot = 0; uint8_t irq_routing = 0; uint8_t pci_int_index = pci_int - PCI_INTA; uint8_t irq_line = 0; - uint8_t level = 0; + uint8_t is_vfio = 0; - if (!last_pci_card) { - pci_log("pci_set_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int); + /* The fast path out an invalid PCI card. */ + if (slot == PCI_CARD_INVALID) return; - } - pci_log("pci_set_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card); - slot = card; - if (slot == 0xff) { - pci_log("pci_set_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int); - return; - } - pci_log("pci_set_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot); - - if (!pci_cards[slot].irq_routing[pci_int_index]) { - pci_log("pci_set_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int); - return; - } - - if (pci_type & PCI_NO_IRQ_STEERING) - irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); - else { - irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 15; - pci_log("pci_set_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); - - irq_line = pci_irqs[irq_routing]; - level = pci_irq_level[irq_routing]; - } - - if (irq_line > 0x0f) { - pci_log("pci_set_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int); - return; - } else - pci_log("pci_set_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line); - - if (level && (pci_irq_hold[irq_line] & (1ULL << slot))) { - /* IRQ already held, do nothing. */ - pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int); - picintlevel(1 << irq_line); - return; - } - pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int); - - if (!level || !pci_irq_hold[irq_line]) { - pci_log("pci_set_irq(%02X, %02X): Issuing %s-triggered IRQ (%sheld)\n", card, pci_int, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); - - /* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */ - if (level) - picintlevel(1 << irq_line); - else - picint(1 << irq_line); - } else if (level && pci_irq_hold[irq_line]) { - pci_log("pci_set_irq(%02X, %02X): IRQ line already being held\n", card, pci_int); - picintlevel(1 << irq_line); - } - - /* If the IRQ is level-triggered, mark that this card is holding it. */ - if (level) { - pci_log("pci_set_irq(%02X, %02X): Marking that this card is holding the IRQ\n", card, pci_int); - pci_irq_hold[irq_line] |= (1ULL << slot); - } else { - pci_log("pci_set_irq(%02X, %02X): Edge-triggered interrupt, not marking\n", card, pci_int); - } -} - -void -pci_clear_mirq(uint8_t mirq, int level) -{ - uint8_t irq_line = 0; - uint8_t irq_bit; - - if (mirq >= 0xf0) { - irq_line = mirq & 0x0f; - irq_bit = 0x1D; - } else { - if (mirq > 1) { - pci_log("pci_clear_mirq(%02X): Invalid MIRQ\n", mirq); + switch (slot) { + default: return; - } - if (!pci_mirqs[mirq].enabled) { - pci_log("pci_clear_mirq(%02X): MIRQ0 disabled\n", mirq); - return; - } + case 0x00 ... PCI_CARD_MAX: + /* PCI card. */ + if (!last_pci_card) + return; - if (pci_mirqs[mirq].irq_line > 0x0f) { - pci_log("pci_clear_mirq(%02X): IRQ line is disabled\n", mirq); - return; - } + if (pci_flags & FLAG_NO_IRQ_STEERING) + irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); + else { + irq_routing = pci_cards[slot].irq_routing[pci_int_index]; - irq_line = pci_mirqs[mirq].irq_line; - irq_bit = (0x1E + mirq); + switch (irq_routing) { + default: + case 0x00: + return; + + case 0x01 ... PCI_IRQS_NUM: + is_vfio = pci_cards[slot].type & PCI_CARD_VFIO; + irq_routing = (irq_routing - PCI_INTA) & PCI_IRQ_MAX; + + irq_line = pci_irqs[irq_routing]; + /* Ignore what was provided to us as a parameter and override it with whatever + the chipset is set to. */ + level = !!pci_irq_level[irq_routing]; + if (level && is_vfio) + level--; + break; + + /* Sometimes, PCI devices are mapped to direct IRQ's. */ + case (PCI_DIRQ_BASE | 0x00) ... (PCI_DIRQ_BASE | PCI_DIRQ_MAX): + /* Direct IRQ line, always edge-triggered. */ + irq_line = slot & PCI_IRQ_MAX; + break; + } + } + break; + case (PCI_MIRQ_BASE | 0x00) ... (PCI_MIRQ_BASE | PCI_MIRQ_MAX): + /* MIRQ */ + slot &= PCI_MIRQ_MAX; + + if (!pci_mirqs[slot].enabled) + return; + + irq_line = pci_mirqs[slot].irq_line; + break; + case (PCI_DIRQ_BASE | 0x00) ... (PCI_DIRQ_BASE | PCI_DIRQ_MAX): + /* Direct IRQ line (RichardG's ACPI workaround, may no longer be needed). */ + irq_line = slot & PCI_IRQ_MAX; + break; } - pci_log("pci_clear_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - if (level && !(pci_irq_hold[irq_line] & (1ULL << irq_bit))) { - /* IRQ not held, do nothing. */ - pci_log("pci_clear_mirq(%02X): MIRQ is not holding the IRQ\n", mirq); + if (irq_line > PCI_IRQ_MAX) return; - } - if (level) { - pci_log("pci_clear_mirq(%02X): Releasing this MIRQ's hold on the IRQ\n", mirq); - pci_irq_hold[irq_line] &= ~(1 << irq_bit); - - if (!pci_irq_hold[irq_line]) { - pci_log("pci_clear_mirq(%02X): IRQ no longer held by any card, clearing it\n", mirq); - picintc(1 << irq_line); - } else { - pci_log("pci_clear_mirq(%02X): IRQ is still being held\n", mirq); - } - } else { - pci_log("pci_clear_mirq(%02X): Clearing edge-triggered interrupt\n", mirq); - picintc(1 << irq_line); - } -} - -void -pci_clear_irq(uint8_t card, uint8_t pci_int) -{ - uint8_t slot = 0; - uint8_t irq_routing = 0; - uint8_t pci_int_index = pci_int - PCI_INTA; - uint8_t irq_line = 0; - uint8_t level = 0; - - if (!last_pci_card) { - // pci_log("pci_clear_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int); - return; - } - // pci_log("pci_clear_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card); - - slot = card; - if (slot == 0xff) { - // pci_log("pci_clear_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int); - return; - } - // pci_log("pci_clear_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot); - - if (!pci_cards[slot].irq_routing[pci_int_index]) { - // pci_log("pci_clear_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int); - return; - } - - if (pci_type & PCI_NO_IRQ_STEERING) - irq_line = pci_cards[slot].read(0, 0x3c, pci_cards[slot].priv); - else { - irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 15; - // pci_log("pci_clear_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing); - - irq_line = pci_irqs[irq_routing]; - level = pci_irq_level[irq_routing]; - } - - if (irq_line > 0x0f) { - // pci_log("pci_clear_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int); - return; - } - - // pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line); - - if (level && !(pci_irq_hold[irq_line] & (1ULL << slot))) { - /* IRQ not held, do nothing. */ - // pci_log("pci_clear_irq(%02X, %02X): Card is not holding the IRQ\n", card, pci_int); - return; - } - - if (level) { - // pci_log("pci_clear_irq(%02X, %02X): Releasing this card's hold on the IRQ\n", card, pci_int); - pci_irq_hold[irq_line] &= ~(1 << slot); - - if (!pci_irq_hold[irq_line]) { - // pci_log("pci_clear_irq(%02X, %02X): IRQ no longer held by any card, clearing it\n", card, pci_int); - picintc(1 << irq_line); - } // else { - // pci_log("pci_clear_irq(%02X, %02X): IRQ is still being held\n", card, pci_int); - // } - } else { - // pci_log("pci_clear_irq(%02X, %02X): Clearing edge-triggered interrupt\n", card, pci_int); - picintc(1 << irq_line); - } + picint_common(1 << irq_line, level, set, irq_state); } uint8_t @@ -920,12 +217,123 @@ pci_get_int(uint8_t slot, uint8_t pci_int) return pci_cards[slot].irq_routing[pci_int - PCI_INTA]; } +static void +pci_clear_slot(int card) +{ + pci_card_to_slot_mapping[pci_cards[card].bus][pci_cards[card].id] = PCI_CARD_INVALID; + + pci_cards[card].id = 0xff; + pci_cards[card].type = 0xff; + + for (uint8_t i = 0; i < 4; i++) + pci_cards[card].irq_routing[i] = 0; + + pci_cards[card].read = NULL; + pci_cards[card].write = NULL; + pci_cards[card].priv = NULL; +} + +/* Relocate a PCI device to a new slot, required for the configurable + IDSEL's of ALi M1543(c). */ +void +pci_relocate_slot(int type, int new_slot) +{ + int card = -1; + int old_slot; + uint8_t mapping; + + if ((new_slot < 0) || (new_slot > 31)) + return; + + for (uint8_t i = 0; i < PCI_CARDS_NUM; i++) { + if ((pci_cards[i].bus == 0) && (pci_cards[i].type == type)) { + card = i; + break; + } + } + + if (card == -1) + return; + + old_slot = pci_cards[card].id; + pci_cards[card].id = new_slot; + mapping = pci_card_to_slot_mapping[0][old_slot]; + pci_card_to_slot_mapping[0][old_slot] = PCI_CARD_INVALID; + pci_card_to_slot_mapping[0][new_slot] = mapping; +} + +/* Write PCI enable/disable key, split for the ALi M1435. */ +void +pci_key_write(uint8_t val) +{ + pci_key = val & 0xf0; + + if (pci_key) + pci_flags |= FLAG_CONFIG_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_IO_ON; +} + +static void +pci_io_handlers(int set) +{ + io_handler(set, 0x0cf8, 4, pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); + + if (pci_flags & FLAG_MECHANISM_1) + io_handler(set, 0x0cfc, 4, pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); + + if (pci_flags & FLAG_MECHANISM_2) { + if (set && pci_key) + pci_flags |= FLAG_CONFIG_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_IO_ON; + } +} + +/* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */ +void +pci_set_pmc(uint8_t pmc) +{ + pci_log("pci_set_pmc(%02X)\n", pmc); + + pci_io_handlers(0); + + pci_flags &= ~FLAG_MECHANISM_MASK; + pci_flags |= (FLAG_MECHANISM_1 + !(pmc & 0x01)); + + pci_io_handlers(1); + + pci_pmc = (pmc & 0x01); +} + +static void +pci_reg_write(uint16_t port, uint8_t val) +{ + uint8_t slot = 0; + + if (port >= 0xc000) { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xfc; + } + + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != PCI_CARD_INVALID) { + if (pci_cards[slot].write) + pci_cards[slot].write(pci_func, pci_index | (port & 0x03), val, pci_cards[slot].priv); + } + pci_log("PCI: [WB] Mechanism #%i, slot %02X, %s card %02X:%02X, function %02X, index %02X = %02X\n", + (port >= 0xc000) ? 2 : 1, slot, + (slot == PCI_CARD_INVALID) ? "non-existent" : (pci_cards[slot].write ? "used" : "unused"), + pci_card, pci_bus, pci_func, pci_index | (port & 0x03), val); +} + static void pci_reset_regs(void) { pci_index = pci_card = pci_func = pci_bus = pci_key = 0; + pci_enable = 0x00000000; - pci_take_over_io &= ~PCI_IO_ON; + pci_flags &= ~(FLAG_CONFIG_IO_ON | FLAG_CONFIG_M1_IO_ON); } void @@ -940,7 +348,7 @@ pci_reset_hard(void) { pci_reset_regs(); - for (uint8_t i = 0; i < 16; i++) { + for (uint8_t i = 0; i < PCI_IRQS_NUM; i++) { if (pci_irq_hold[i]) { pci_irq_hold[i] = 0; @@ -954,68 +362,16 @@ pci_reset_hard(void) void pci_reset(void) { - if (pci_switch) { + if (pci_flags & FLAG_MECHANISM_SWITCH) { pci_log("pci_reset(): Switchable configuration mechanism\n"); - pci_pmc = 0x00; - - io_removehandler(0x0cf8, 1, - NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL); - io_removehandler(0x0cfc, 4, - pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); - io_removehandler(0x0cf8, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_removehandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cf8, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); + pci_set_pmc(0x00); } pci_reset_hard(); } static void -pci_slots_clear(void) -{ - uint8_t i; - - last_pci_card = last_normal_pci_card = 0; - last_pci_bus = 1; - - for (i = 0; i < 32; i++) - pci_clear_slot(i); - - i = 0; - do { - for (uint8_t j = 0; j < 32; j++) - pci_card_to_slot_mapping[i][j] = 0xff; - pci_bus_number_to_index_mapping[i] = 0xff; - } while (i++ < 0xff); - - pci_bus_number_to_index_mapping[0] = 0; /* always map bus 0 to index 0 */ -} - -uint32_t -trc_readl(UNUSED(uint16_t port), UNUSED(void *priv)) -{ - return 0xffffffff; -} - -uint16_t -trc_readw(UNUSED(uint16_t port), UNUSED(void *priv)) -{ - return 0xffff; -} - -uint8_t -trc_read(UNUSED(uint16_t port), UNUSED(void *priv)) -{ - return trc_reg & 0xfb; -} - -static void -trc_reset(uint8_t val) +pci_trc_reset(uint8_t val) { if (val & 2) { dma_reset(); @@ -1037,110 +393,247 @@ trc_reset(uint8_t val) } void -trc_writel(UNUSED(uint16_t port), UNUSED(uint32_t val), UNUSED(void *priv)) +pci_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { - // + pci_log("PCI: [WB] Mechanism #%i port %04X = %02X\n", ((port >= 0xcfc) && (port <= 0xcff)) ? 1 : 2, port, val); + + switch (port) { + case 0xcf8: + if (pci_flags & FLAG_MECHANISM_2) { + pci_func = (val >> 1) & 7; + pci_key_write(val); + + pci_log("PCI: Mechanism #2 CF8: %sllocating ports %04X-%04X...\n", (pci_flags & FLAG_CONFIG_IO_ON) ? "A" : "Dea", + pci_base, pci_base + pci_size - 1); + } + break; + case 0xcf9: + if (!(pci_trc_reg & 4) && (val & 4)) + pci_trc_reset(val); + + pci_trc_reg = val & 0xfd; + + if (val & 2) + pci_trc_reg &= 0xfb; + break; + case 0xcfa: + if (pci_flags & FLAG_MECHANISM_2) + pci_bus = val; + break; + case 0xcfb: + if (pci_flags & FLAG_MECHANISM_SWITCH) + pci_set_pmc(val); + break; + + case 0xcfc: + case 0xcfd: + case 0xcfe: + case 0xcff: + if ((pci_flags & FLAG_MECHANISM_1) && (pci_flags & FLAG_CONFIG_M1_IO_ON)) + pci_reg_write(port, val); + break; + + case 0xc000 ... 0xc0ff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & (FLAG_CONFIG_IO_ON | FLAG_CONFIG_DEV0_IO_ON))) + pci_reg_write(port, val); + break; + + case 0xc100 ... 0xcfff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_IO_ON)) + pci_reg_write(port, val); + break; + } } void -trc_writew(UNUSED(uint16_t port), UNUSED(uint16_t val), UNUSED(void *priv)) +pci_writew(uint16_t port, uint16_t val, UNUSED(void *priv)) { - // + if (port & 0x0001) { + /* Non-aligned access, split into two byte accesses. */ + pci_write(port, val & 0xff, priv); + pci_write(port + 1, val >> 8, priv); + } else { + /* Aligned access, still split because we cheat. */ + switch (port) { + case 0xcfc: + case 0xcfe: + case 0xc000 ... 0xcffe: + pci_write(port, val & 0xff, priv); + pci_write(port + 1, val >> 8, priv); + break; + } + } } void -trc_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv)) +pci_writel(uint16_t port, uint32_t val, UNUSED(void *priv)) { - pci_log("TRC Write: %02X\n", val); + if (port & 0x0003) { + /* Non-aligned access, split into two word accesses. */ + pci_writew(port, val & 0xffff, priv); + pci_writew(port + 2, val >> 16, priv); + } else { + /* Aligned access. */ + switch (port) { + case 0xcf8: + /* No split here, actual 32-bit access. */ + if (pci_flags & FLAG_MECHANISM_1) { + pci_log("PCI: [WL] Mechanism #1 port 0CF8 = %08X\n", val); - if (!(trc_reg & 4) && (val & 4)) - trc_reset(val); + pci_index = val & 0xff; + pci_func = (val >> 8) & 7; + pci_card = (val >> 11) & 31; + pci_bus = (val >> 16) & 0xff; + pci_enable = (val & PCI_ENABLED); - trc_reg = val & 0xfd; - - if (val & 2) - trc_reg &= 0xfb; + if (pci_enable) + pci_flags |= FLAG_CONFIG_M1_IO_ON; + else + pci_flags &= ~FLAG_CONFIG_M1_IO_ON; + break; + } + break; + case 0xcfc: + case 0xc000 ... 0xcffc: + /* Still split because we cheat. */ + pci_writew(port, val & 0xffff, priv); + pci_writew(port + 2, val >> 16, priv); + break; + } + } } -void -trc_init(void) +static uint8_t +pci_reg_read(uint16_t port) { - trc_reg = 0; + uint8_t slot = 0; + uint8_t ret = 0xff; - io_sethandler(0x0cf9, 0x0001, - trc_read, trc_readw, trc_readl, trc_write, trc_writew, trc_writel, NULL); -} - -void -pci_init(int type) -{ - int c; - - pci_base = 0xc000; - pci_size = 0x1000; - - pci_slots_clear(); - - pci_reset_hard(); - - trc_init(); - - pci_type = type; - pci_switch = !!(type & PCI_CAN_SWITCH_TYPE); - - if (pci_switch) { - pci_log("PCI: Switchable configuration mechanism\n"); - pci_pmc = 0x00; - - io_sethandler(0x0cfb, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, pci_type2_cfb_writel, NULL); + if (port >= 0xc000) { + pci_card = (port >> 8) & 0xf; + pci_index = port & 0xfc; } - if (type & PCI_NO_IRQ_STEERING) { - pic_elcr_io_handler(0); - pic_elcr_set_enabled(0); - } else { - pic_elcr_io_handler(1); - pic_elcr_set_enabled(1); + slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card]; + if (slot != PCI_CARD_INVALID) { + if (pci_cards[slot].read) + ret = pci_cards[slot].read(pci_func, pci_index | (port & 0x03), pci_cards[slot].priv); + } + pci_log("PCI: [RB] Mechanism #%i, slot %02X, %s card %02X:%02X, function %02X, index %02X = %02X\n", + (port >= 0xc000) ? 2 : 1, slot, + (slot == PCI_CARD_INVALID) ? "non-existent" : (pci_cards[slot].read ? "used" : "unused"), + pci_card, pci_bus, pci_func, pci_index | (port & 0x03), ret); + + return ret; +} + +uint8_t +pci_read(uint16_t port, UNUSED(void *priv)) +{ + uint8_t ret = 0xff; + + switch (port) { + case 0xcf8: + if (pci_flags & FLAG_MECHANISM_2) + ret = pci_key | (pci_func << 1); + break; + case 0xcf9: + ret = pci_trc_reg & 0xfb; + break; + case 0xcfa: + if (pci_flags & FLAG_MECHANISM_2) + ret = pci_bus; + break; + case 0xcfb: + if (pci_flags & FLAG_MECHANISM_SWITCH) + ret = pci_pmc; + break; + + case 0xcfc: + case 0xcfd: + case 0xcfe: + case 0xcff: + if ((pci_flags & FLAG_MECHANISM_1) && (pci_flags & FLAG_CONFIG_M1_IO_ON)) + ret = pci_reg_read(port); + break; + + case 0xc000 ... 0xc0ff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & (FLAG_CONFIG_IO_ON | FLAG_CONFIG_DEV0_IO_ON))) + ret = pci_reg_read(port); + break; + + case 0xc100 ... 0xcfff: + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_IO_ON)) + ret = pci_reg_read(port); + break; + + default: + break; } - pci_take_over_io = 0x00000000; + pci_log("PCI: [RB] Mechanism #%i port %04X = %02X\n", ((port >= 0xcfc) && (port <= 0xcff)) ? 1 : 2, port, ret); - if ((type & PCI_CONFIG_TYPE_MASK) == PCI_CONFIG_TYPE_1) { - pci_log("PCI: Configuration mechanism #1\n"); - io_sethandler(0x0cf8, 1, - NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL); - io_sethandler(0x0cfc, 4, - pci_read, pci_readw, pci_readl, pci_write, pci_writew, pci_writel, NULL); - pci_pmc = 1; + return ret; +} + +uint16_t +pci_readw(uint16_t port, UNUSED(void *priv)) +{ + uint16_t ret = 0xffff; + + if (port & 0x0001) { + /* Non-aligned access, split into two byte accesses. */ + ret = pci_read(port, priv); + ret |= ((uint16_t) pci_read(port + 1, priv)) << 8; } else { - pci_log("PCI: Configuration mechanism #2\n"); - io_sethandler(0x0cf8, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - io_sethandler(0x0cfa, 1, - pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL); - pci_pmc = 0; - - if (type & PCI_ALWAYS_EXPOSE_DEV0) { - pci_log("PCI: Always expose device 0\n"); - pci_base = 0xc100; - pci_size = 0x0f00; - - pci_take_over_io |= PCI_IO_DEV0; + /* Aligned access, still split because we cheat. */ + switch (port) { + case 0xcfc: + case 0xcfe: + case 0xc000 ... 0xcffe: + ret = pci_read(port, priv); + ret |= ((uint16_t) pci_read(port + 1, priv)) << 8; + break; } } - for (c = 0; c < 4; c++) { - pci_irqs[c] = PCI_IRQ_DISABLED; - pci_irq_level[c] = (type & PCI_NO_IRQ_STEERING) ? 0 : 1; + return ret; +} + +uint32_t +pci_readl(uint16_t port, UNUSED(void *priv)) +{ + uint32_t ret = 0xffffffff; + + if (port & 0x0003) { + /* Non-aligned access, split into two word accesses. */ + ret = pci_readw(port, priv); + ret |= ((uint32_t) pci_readw(port + 2, priv)) << 16; + } else { + /* Aligned access. */ + switch (port) { + case 0xcf8: + /* No split here, actual 32-bit access. */ + if (pci_flags & FLAG_MECHANISM_1) { + ret = pci_index | (pci_func << 8) | (pci_card << 11) | (pci_bus << 16); + if (pci_flags & FLAG_CONFIG_IO_ON) + ret |= PCI_ENABLED; + + pci_log("PCI: [RL] Mechanism #1 port 0CF8 = %08X\n", ret); + + return ret; + } + break; + case 0xcfc: + case 0xc000 ... 0xcffc: + /* Still split because we cheat. */ + ret = pci_readw(port, priv); + ret |= ((uint32_t) pci_readw(port + 2, priv)) << 16; + break; + } } - for (c = 0; c < 3; c++) { - pci_mirqs[c].enabled = 0; - pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; - } - - pic_set_pci_flag(1); + return ret; } uint8_t @@ -1155,19 +648,13 @@ pci_remap_bus(uint8_t bus_index, uint8_t bus_number) uint8_t i = 1; do { if (pci_bus_number_to_index_mapping[i] == bus_index) - pci_bus_number_to_index_mapping[i] = 0xff; + pci_bus_number_to_index_mapping[i] = PCI_BUS_INVALID; } while (i++ < 0xff); if ((bus_number > 0) && (bus_number < 0xff)) pci_bus_number_to_index_mapping[bus_number] = bus_index; } -void -pci_register_slot(int card, int type, int inta, int intb, int intc, int intd) -{ - pci_register_bus_slot(0, card, type, inta, intb, intc, intd); -} - void pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, int intd) { @@ -1187,73 +674,258 @@ pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, pci_log("pci_register_slot(): pci_cards[%i].bus = %02X; .id = %02X\n", last_pci_card, bus, card); - if (type == PCI_CARD_NORMAL) - last_normal_pci_card = last_pci_card; + if (type == PCI_CARD_NORMAL) { + last_normal_pci_card++; + /* This is needed to know at what position to add the bridge. */ + last_normal_pci_card_id = last_pci_card; + } + last_pci_card++; } -uint8_t +static uint8_t pci_find_slot(uint8_t add_type, uint8_t ignore_slot) { const pci_card_t *dev; - uint8_t ret = 0xff; + /* Is the device being added with a strict slot type matching requirement? */ + uint8_t strict = (add_type & PCI_ADD_STRICT); + /* The actual type of the device being added, with the strip flag, if any, + masked. */ + uint8_t masked_add_type = (add_type & PCI_ADD_MASK); + /* Is the device being added normal, ie. without the possibility of ever + being used as an on-board device? */ + uint8_t normal_add_type = (masked_add_type >= PCI_CARD_NORMAL); + uint8_t match; + uint8_t normal; + uint8_t empty; + uint8_t process; + uint8_t ret = PCI_CARD_INVALID; - for (uint8_t i = 0; i < last_pci_card; i++) { + /* Iterate i until we have either exhausted all the slot or the value of + ret has changed to something other than PCI_CARD_INVALID. */ + for (uint8_t i = 0; (ret == PCI_CARD_INVALID) && (i < last_pci_card); i++) { dev = &pci_cards[i]; - if (!dev->read && !dev->write && ((ignore_slot == 0xff) || (i != ignore_slot))) { - if (add_type & PCI_ADD_STRICT) { - if (dev->type == (add_type & 0x7f)) { - ret = i; - break; - } - } else { - if (((dev->type == PCI_CARD_NORMAL) && ((add_type & 0x7f) >= PCI_ADD_NORMAL)) || (dev->type == (add_type & 0x7f))) { - ret = i; - break; - } - } - } + /* Is the slot we are looking at of the exact same type as the device being + added? */ + match = (dev->type == masked_add_type); + /* Is the slot we are looking at a normal slot (ie. not an on-board chip)? */ + normal = (dev->type == PCI_CARD_NORMAL); + /* Is the slot we are looking at empty? */ + empty = !dev->read && !dev->write; + /* Should we process this slot, ie. were we told to ignore it, if any at all? */ + process = (ignore_slot == PCI_IGNORE_NO_SLOT) || (i != ignore_slot); + + /* This condition is now refactored and made to be easily human-readable. */ + if (empty && process && (match || (!strict && normal && normal_add_type))) + ret = i; } return ret; } -uint8_t -pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) +/* Add a PCI card. */ +void +pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), + void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot) { - pci_card_t *dev; - uint8_t i; - uint8_t j; + pci_card_desc_t *dev; - if (add_type < PCI_ADD_AGP) - pci_log("pci_add_card(): Adding PCI CARD at specific slot %02X [SPECIFIC]\n", add_type); + pci_log("pci_add_card(): PCI card #%02i: type = %i\n", next_pci_card, add_type); - if (!last_pci_card) { - pci_log("pci_add_card(): Adding PCI CARD failed (no PCI slots) [%s]\n", (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_AGP) ? "AGP" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC"))))); - return 0xff; - } - - /* First, find the next available slot. */ - i = pci_find_slot(add_type, 0xff); - - if (i != 0xff) { - dev = &pci_cards[i]; - j = pci_find_slot(add_type, i); - - if (!(pci_type & PCI_NO_BRIDGES) && (dev->type == PCI_CARD_NORMAL) && (add_type != PCI_ADD_BRIDGE) && (j == 0xff)) { - pci_log("pci_add_card(): Reached last NORMAL slot, adding bridge to pci_cards[%i]\n", i); - device_add_inst(&dec21150_device, last_pci_bus); - i = pci_find_slot(add_type, 0xff); - dev = &pci_cards[i]; - } + if (next_pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[next_pci_card]; + dev->type = add_type; dev->read = read; dev->write = write; dev->priv = priv; - pci_log("pci_add_card(): Adding PCI CARD to pci_cards[%i] (bus %02X slot %02X) [%s]\n", i, dev->bus, dev->id, (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_AGP) ? "AGP" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC"))))); - return i; + dev->slot = slot; + + *(dev->slot) = PCI_CARD_INVALID; + + next_pci_card++; + if (add_type == PCI_ADD_NORMAL) + normal_pci_cards++; + } +} + +static void +pci_clear_card(int pci_card) +{ + pci_card_desc_t *dev; + + if (next_pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[next_pci_card]; + + memset(dev, 0x00, sizeof(pci_card_desc_t)); + } +} + +static uint8_t +pci_register_card(int pci_card) +{ + pci_card_desc_t *dev; + pci_card_t *card; + uint8_t i; + uint8_t ret = PCI_CARD_INVALID; + + if (pci_card < PCI_CARDS_NUM) { + dev = &pci_card_descs[pci_card]; + + if (last_pci_card) { + /* First, find the next available slot. */ + i = pci_find_slot(dev->type, 0xff); + + if (i != PCI_CARD_INVALID) { + card = &pci_cards[i]; + card->read = dev->read; + card->write = dev->write; + card->priv = dev->priv; + card->type |= (dev->type & PCI_CARD_VFIO); + + *(dev->slot) = i; + + ret = i; + } + } + + pci_clear_card(pci_card); } - return 0xff; + return ret; +} + +/* Add an instance of the PCI bridge. */ +uint8_t +pci_add_bridge(uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv) +{ + pci_card_t *card; + + card = &pci_cards[last_normal_pci_card_id]; + card->read = read; + card->write = write; + card->priv = priv; + + return last_normal_pci_card_id; +} + +/* Register the cards that have been added into slots. */ +void +pci_register_cards(void) +{ + uint8_t i; + uint8_t normal; +#ifdef ENABLE_PCI_LOG + uint8_t type; + uint8_t *slot; +#endif + + next_normal_pci_card = 0; + + if (next_pci_card > 0) { + for (i = 0; i < next_pci_card; i++) { +#ifdef ENABLE_PCI_LOG + type = pci_card_descs[i].type; + slot = pci_card_descs[i].slot; +#endif + normal = (pci_card_descs[i].type == PCI_CARD_NORMAL); + + /* If this is a normal card, increase the next normal card index. */ + if (normal) + next_normal_pci_card++; + + /* If this is a normal card and the next one is going to be beyond the last slot, + add the bridge. */ + if (normal && (next_normal_pci_card >= last_normal_pci_card) && + (normal_pci_cards > last_normal_pci_card) && !(pci_flags & FLAG_NO_BRIDGES)) + device_add_inst(&dec21150_device, last_pci_bus); + + pci_register_card(i); + pci_log("pci_register_cards(): PCI card #%02i: type = %02X, pci device = %02X:%02X\n", + i, type, pci_cards[*slot].bus, pci_cards[*slot].id); + } + } + + next_pci_card = 0; + normal_pci_cards = 0; + + next_normal_pci_card = 0; +} + +static void +pci_slots_clear(void) +{ + uint8_t i; + + last_pci_card = last_normal_pci_card = 0; + last_normal_pci_card = 0; + last_pci_bus = 1; + + next_pci_card = 0; + normal_pci_cards = 0; + + next_normal_pci_card = 0; + + for (i = 0; i < PCI_CARDS_NUM; i++) + pci_clear_slot(i); + + i = 0; + do { + for (uint8_t j = 0; j < PCI_CARDS_NUM; j++) + pci_card_to_slot_mapping[i][j] = PCI_CARD_INVALID; + pci_bus_number_to_index_mapping[i] = PCI_BUS_INVALID; + } while (i++ < 0xff); + + pci_bus_number_to_index_mapping[0] = 0; /* always map bus 0 to index 0 */ +} + +void +pci_init(int flags) +{ + int c; + + pci_base = 0xc000; + pci_size = 0x1000; + + pci_slots_clear(); + + pci_reset_hard(); + + pci_trc_reg = 0; + pci_flags = flags; + + if (pci_flags & FLAG_NO_IRQ_STEERING) { + pic_elcr_io_handler(0); + pic_elcr_set_enabled(0); + } else { + pic_elcr_io_handler(1); + pic_elcr_set_enabled(1); + } + + pci_pmc = (pci_flags & FLAG_MECHANISM_1) ? 0x01 : 0x00; + + if ((pci_flags & FLAG_MECHANISM_2) && (pci_flags & FLAG_CONFIG_DEV0_IO_ON)) { + pci_log("PCI: Always expose device 0\n"); + pci_base = 0xc100; + pci_size = 0x0f00; + } + + if (pci_flags & FLAG_MECHANISM_SWITCH) { + pci_log("PCI: Switchable configuration mechanism\n"); + pci_set_pmc(pci_pmc); + } else + pci_io_handlers(1); + + for (c = 0; c < PCI_IRQS_NUM; c++) { + pci_irqs[c] = PCI_IRQ_DISABLED; + pci_irq_level[c] = (pci_flags & FLAG_NO_IRQ_STEERING) ? 0 : 1; + } + + for (c = 0; c < PCI_MIRQS_NUM; c++) { + pci_mirqs[c].enabled = 0; + pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; + } + + pic_set_pci_flag(1); } diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 8ed6f9f30..1e49f9f99 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -19,15 +19,21 @@ typedef struct pci_dummy_t { uint8_t card; uint8_t interrupt_on; + + uint8_t irq_level; } pci_dummy_t; static void pci_dummy_interrupt(int set, pci_dummy_t *dev) { - if (set) - pci_set_irq(dev->card, PCI_INTA); - else - pci_clear_irq(dev->card, PCI_INTA); + if (set != dev->irq_level) { + if (set) + pci_set_irq(dev->card, PCI_INTA); + else + pci_clear_irq(dev->card, PCI_INTA); + } + + dev->irq_level = set; } static uint8_t diff --git a/src/pic.c b/src/pic.c index 6173291b4..09ccf5d03 100644 --- a/src/pic.c +++ b/src/pic.c @@ -51,20 +51,22 @@ pic_t pic2; static pc_timer_t pic_timer; +static uint16_t smi_irq_mask = 0x0000; +static uint16_t smi_irq_status = 0x0000; + +static uint16_t enabled_latches = 0x0000; +static uint16_t latched_irqs = 0x0000; + static int shadow = 0; static int elcr_enabled = 0; static int tmr_inited = 0; static int latched = 0; static int pic_pci = 0; -static int kbd_latch = 0; -static int mouse_latch = 0; -static uint16_t smi_irq_mask = 0x0000; -static uint16_t smi_irq_status = 0x0000; +static void (*update_pending)(void); -static uint16_t latched_irqs = 0x0000; - -static void (*update_pending)(void); +static void pic_update_request(pic_t *dev, int irq); +static void pic_cascade(int set); #ifdef ENABLE_PIC_LOG int pic_do_log = ENABLE_PIC_LOG; @@ -236,10 +238,7 @@ pic_update_pending_at(void) { pic2.int_pending = (find_best_interrupt(&pic2) != -1); - if (pic2.int_pending) - pic.irr |= (1 << pic2.icw3); - else - pic.irr &= ~(1 << pic2.icw3); + pic_cascade(pic2.int_pending); pic.int_pending = (find_best_interrupt(&pic) != -1); } @@ -268,8 +267,13 @@ pic_reset(void) pic.is_master = 1; pic.interrupt = pic2.interrupt = 0x17; - if (is_at) + pic.has_slaves = 0; + pic2.has_slaves = 0; + + if (is_at) { pic.slaves[2] = &pic2; + pic.has_slaves = 1; + } if (tmr_inited) timer_on_auto(&pic_timer, 0.0); @@ -326,8 +330,16 @@ pic_acknowledge(pic_t *dev) int pic_int_num = 1 << pic_int; dev->isr |= pic_int_num; - if (!pic_level_triggered(dev, pic_int) || !(dev->lines & pic_int_num)) - dev->irr &= ~pic_int_num; + + /* Simulate the clearing of the edge pulse. */ + dev->edge_lines &= ~pic_int_num; + /* Clear the edge sense latch. */ + dev->irq_latch &= ~pic_int_num; + + dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not + override the one currently being processed. */ + /* Clear the reset latch. */ + pic_update_request(dev, pic_int); } /* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ @@ -403,12 +415,12 @@ pic_latch_read(UNUSED(uint16_t addr), UNUSED(void *priv)) { uint8_t ret = 0xff; - pic_log("pic_latch_read(%i, %i): %02X%02X\n", kbd_latch, mouse_latch, pic2.lines & 0x10, pic.lines & 0x02); + pic_log("pic_latch_read(%04X): %02X%02X\n", enabled_latches, latched_irqs & 0x10, latched_irqs & 0x02); - if (kbd_latch && (latched_irqs & 0x0002)) + if ((latched_irqs & enabled_latches) & 0x0002) picintc(0x0002); - if (mouse_latch && (latched_irqs & 0x1000)) + if ((latched_irqs & enabled_latches) & 0x1000) picintc(0x1000); /* Return FF - we just lower IRQ 1 and IRQ 12. */ @@ -433,12 +445,8 @@ pic_read(uint16_t addr, void *priv) } } else { /* Standard 8259 PIC read */ -#ifndef UNDEFINED_READ - /* Put the IRR on to the data bus by default until the real PIC is probed. */ - dev->data_bus = dev->irr; -#endif if (dev->ocw3 & 0x04) { - dev->interrupt &= ~0x20; /* Freeze the interrupt until the poll is over. */ + dev->flags &= ~PIC_FREEZE; /* Freeze the interrupt until the poll is over. */ if (dev->int_pending) { dev->data_bus = 0x80 | (dev->interrupt & 7); pic_acknowledge(dev); @@ -452,10 +460,8 @@ pic_read(uint16_t addr, void *priv) else if (dev->ocw3 & 0x02) { if (dev->ocw3 & 0x01) dev->data_bus = dev->isr; -#ifdef UNDEFINED_READ else - dev->data_bus = 0x00; -#endif + dev->data_bus = dev->irr; } /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, simply read whatever is currently on the data bus. */ @@ -470,6 +476,7 @@ static void pic_write(uint16_t addr, uint8_t val, void *priv) { pic_t *dev = (pic_t *) priv; + uint8_t i; pic_log("pic_write(%04X, %02X, %08X)\n", addr, val, priv); @@ -511,7 +518,13 @@ pic_write(uint16_t addr, uint8_t val, void *priv) if (!(dev->icw1 & 1)) dev->icw4 = 0x00; dev->ocw2 = dev->ocw3 = 0x00; - dev->irr = dev->lines; + dev->irr = 0x00; + dev->edge_lines = 0x00; + dev->irq_latch = 0x00; + dev->flags |= PIC_MASTER_CLEAR; + for (i = 0; i <= 7; i++) + pic_update_request(dev, i); + dev->flags &= ~PIC_MASTER_CLEAR; dev->imr = dev->isr = 0x00; dev->ack_bytes = dev->priority = 0x00; dev->auto_eoi_rotate = dev->special_mask_mode = 0x00; @@ -522,7 +535,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv) } else if (val & 0x08) { dev->ocw3 = val; if (dev->ocw3 & 0x04) - dev->interrupt |= 0x20; /* Freeze the interrupt until the poll is over. */ + dev->flags |= PIC_FREEZE; /* Freeze the interrupt until the poll is over. */ if (dev->ocw3 & 0x40) dev->special_mask_mode = !!(dev->ocw3 & 0x20); } else { @@ -549,12 +562,15 @@ pic_set_pci(void) void pic_kbd_latch(int enable) { + uint16_t old_latches = enabled_latches; + pic_log("PIC keyboard latch now %sabled\n", enable ? "en" : "dis"); - if (!!(enable | mouse_latch) != !!(kbd_latch | mouse_latch)) - io_handler(!!(enable | mouse_latch), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + enable = (!!enable) << 1; + enabled_latches = (enabled_latches & 0x1000) | enable; - kbd_latch = !!enable; + if (!!(enabled_latches & 0x1002) != !!(old_latches & 0x1002)) + io_handler(!!(enabled_latches & 0x1002), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); if (!enable) picintc(0x0002); @@ -563,12 +579,15 @@ pic_kbd_latch(int enable) void pic_mouse_latch(int enable) { + uint16_t old_latches = enabled_latches; + pic_log("PIC mouse latch now %sabled\n", enable ? "en" : "dis"); - if (!!(kbd_latch | enable) != !!(kbd_latch | mouse_latch)) - io_handler(!!(kbd_latch | enable), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + enable = (!!enable) << 12; + enabled_latches = (enabled_latches & 0x0002) | enable; - mouse_latch = !!enable; + if (!!(enabled_latches & 0x1002) != !!(old_latches & 0x1002)) + io_handler(!!(enabled_latches & 0x1002), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); if (!enable) picintc(0x1000); @@ -580,11 +599,11 @@ pic_reset_hard(void) pic_reset(); /* Explicitly reset the latches. */ - kbd_latch = mouse_latch = 0; + enabled_latches = 0x0000; latched_irqs = 0x0000; /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, - to the point that there's even boards with board-level latched that get used in place of the latches + to the point that there's even boards with board-level latches that get used in place of the latches on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ if (machine_has_bus(machine, MACHINE_BUS_PS2_LATCH)) { pic_kbd_latch(0x01); @@ -621,30 +640,131 @@ pic2_init(void) } void -picint_common(uint16_t num, int level, int set) +pic_update_lines(pic_t *dev, uint16_t num, int level, int set, uint8_t *irq_state) { - int raise; - uint8_t b; - uint8_t slaves = 0; + uint8_t old_edge_lines, bit; + + switch (level) { + case PIC_IRQ_EDGE: + old_edge_lines = dev->edge_lines; + + dev->edge_lines &= ~num; + if (set) + dev->edge_lines |= num; + + if ((dev->isr & num) || (dev->flags & PIC_MASTER_CLEAR)) + dev->irq_latch = (dev->irq_latch & ~num) | (dev->edge_lines & num); + else if ((dev->edge_lines & num) && !(old_edge_lines & num)) + dev->irq_latch |= num; + break; + case PIC_IRQ_LEVEL: + for (uint8_t i = 0; i < 8; i++) { + bit = (1 << i); + if ((num & bit) && ((!!*irq_state) != !!set)) + dev->lines[i] += (set ? 1 : -1); + } + + if ((!!*irq_state) != !!set) + *irq_state = set; + break; + } +} + +static uint8_t +pic_irq_get_request(pic_t *dev, int irq) +{ + uint8_t ret; + + ret = ((dev->edge_lines & (1 << irq)) || (dev->lines[irq] > 0)); + + pic_log("pic_irq_get_request(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret); + return ret; +} + +static uint8_t +pic_es_latch_clear(pic_t *dev, int irq) +{ + uint8_t ret; + + ret = (dev->isr & (1 << irq)) || (dev->flags & PIC_MASTER_CLEAR); + + pic_log("pic_es_latch_clear(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret); + return ret; +} + +static uint8_t +pic_es_latch_out(pic_t *dev, int irq) +{ + uint8_t ret; + + ret = !((pic_es_latch_clear(dev, irq) && (dev->irq_latch & (1 << irq))) || !pic_irq_get_request(dev, irq)); + + pic_log("pic_es_latch_out(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret); + return ret; +} + +static uint8_t +pic_es_latch_nor(pic_t *dev, int irq) +{ + uint8_t ret; + + ret = !(pic_es_latch_out(dev, irq) || picint_is_level(irq)); + + pic_log("pic_es_latch_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret); + return ret; +} + +static uint8_t +pic_irq_request_nor(pic_t *dev, int irq) +{ + uint8_t ret; + + ret = !(pic_es_latch_nor(dev, irq) || !pic_irq_get_request(dev, irq)); + + pic_log("pic_irq_request_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret); + return ret; +} + +static void +pic_update_request(pic_t *dev, int irq) +{ + dev->irr &= ~(1 << irq); + + if (dev->flags & PIC_FREEZE) { + pic_log("pic_update_request(%08X, %i): FREEZE#\n", (uint32_t) (uintptr_t) dev, irq); + } else { + dev->irr |= (pic_irq_request_nor(dev, irq) << irq); + pic_log("pic_update_request(%08X, %i): IRR = %02X\n", (uint32_t) (uintptr_t) dev, irq, dev->irr); + } +} + +static void +pic_update_irr(pic_t *dev, uint16_t num) +{ + for (uint8_t i = 0; i < 8; i++) { + if (num & (1 << i)) + pic_update_request(dev, i); + } + + pic_log("IRQ %04x: IRR now: %02X\n", num, dev->irr); +} + +void +picint_common(uint16_t num, int level, int set, uint8_t *irq_state) +{ + pic_log("picint_common(%04X, %i, %i, %08X)\n", num, level, set, (uint32_t) (uintptr_t) irq_state); + + set = !!set; /* Make sure to ignore all slave IRQ's, and in case of AT+, translate IRQ 2 to IRQ 9. */ - for (uint8_t i = 0; i < 8; i++) { - b = (uint8_t) (1 << i); - raise = num & b; - - if (pic.icw3 & b) { - slaves++; - - if (raise) { - num &= ~b; - if (pic.at && (i == 2)) - num |= (1 << 9); - } - } + if (num & pic.icw3) { + num &= ~pic.icw3; + if (pic.at) + num |= (1 << 9); } - if (!slaves) + if (!pic.has_slaves) num &= 0x00ff; if (!num) { @@ -655,77 +775,41 @@ picint_common(uint16_t num, int level, int set) if (num & 0x0100) acpi_rtc_status = !!set; - if (set) { - if (smi_irq_mask & num) { - smi_raise(); - smi_irq_status |= num; - } - - if (num & 0xff00) { - if (level) - pic2.lines |= (num >> 8); - - /* Latch IRQ 12 if the mouse latch is enabled. */ - if ((num & 0x1000) && mouse_latch) - latched_irqs |= 0x1000; - - pic2.irr |= (num >> 8); - } - - if (num & 0x00ff) { - if (level) - pic.lines |= (num & 0x00ff); - - /* Latch IRQ 1 if the keyboard latch is enabled. */ - if (kbd_latch && (num & 0x0002)) - latched_irqs |= 0x0002; - - pic.irr |= (num & 0x00ff); - } - } else { - smi_irq_status &= ~num; - - if (num & 0xff00) { - pic2.lines &= ~(num >> 8); - - /* Unlatch IRQ 12 if the mouse latch is enabled. */ - if ((num & 0x1000) && mouse_latch) - latched_irqs &= 0xefff; - - pic2.irr &= ~(num >> 8); - } - - if (num & 0x00ff) { - pic.lines &= ~(num & 0x00ff); - - /* Unlatch IRQ 1 if the keyboard latch is enabled. */ - if (kbd_latch && (num & 0x0002)) - latched_irqs &= 0xfffd; - - pic.irr &= ~(num & 0x00ff); - } + smi_irq_status &= ~num; + if (set && (smi_irq_mask & num)) { + smi_raise(); + smi_irq_status |= num; } - if (!(pic.interrupt & 0x20) && !(pic2.interrupt & 0x20)) + if (num & 0xff00) { + pic_update_lines(&pic2, num >> 8, level, set, irq_state); + + /* Latch IRQ 12 if the mouse latch is enabled. */ + if ((num & enabled_latches) & 0x1000) + latched_irqs = (latched_irqs & 0xefff) | (set << 12); + + pic_update_irr(&pic2, num >> 8); + } + + if (num & 0x00ff) { + pic_update_lines(&pic, num & 0x00ff, level, set, irq_state); + + /* Latch IRQ 1 if the keyboard latch is enabled. */ + if ((num & enabled_latches) & 0x0002) + latched_irqs = (latched_irqs & 0xfffd) | (set << 1); + + pic_update_irr(&pic, num & 0x00ff); + } + + if (!(pic.flags & PIC_FREEZE) && !(pic2.flags & PIC_FREEZE)) update_pending(); } -void -picint(uint16_t num) +static void +pic_cascade(int set) { - picint_common(num, 0, 1); -} - -void -picintlevel(uint16_t num) -{ - picint_common(num, 1, 1); -} - -void -picintc(uint16_t num) -{ - picint_common(num, 0, 0); + pic_update_lines(&pic, (1 << pic2.icw3), PIC_IRQ_EDGE, set, NULL); + pic_update_irr(&pic, (1 << pic2.icw3)); } static uint8_t @@ -737,15 +821,12 @@ pic_i86_mode(pic_t *dev) static uint8_t pic_irq_ack_read(pic_t *dev, int phase) { - uint8_t intr = dev->interrupt & 0x47; - uint8_t slave = intr & 0x40; - intr &= 0x07; + uint8_t intr = dev->interrupt & 0x07; + uint8_t slave = dev->flags & PIC_SLAVE_PENDING; pic_log(" pic_irq_ack_read(%08X, %i)\n", dev, phase); if (dev != NULL) { if (phase == 0) { - dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not - override the one currently being processed. */ pic_acknowledge(dev); if (slave) dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); @@ -791,7 +872,7 @@ pic_irq_ack(void) exit(-1); } - pic.interrupt |= 0x40; /* Mark slave pending. */ + pic.flags |= PIC_SLAVE_PENDING; } ret = pic_irq_ack_read(&pic, pic.ack_bytes); @@ -799,8 +880,13 @@ pic_irq_ack(void) if (pic.ack_bytes == 0) { /* Needed for Xi8088. */ - if (pic.interrupt & 0x40) + if (pic.flags & PIC_SLAVE_PENDING) { + pic2.flags &= ~PIC_FREEZE; + pic_update_request(&pic2, pic2.interrupt & 0x07); pic2.interrupt = 0x17; + } + pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE); + pic_update_request(&pic, pic.interrupt & 0x07); pic.interrupt = 0x17; update_pending(); } @@ -821,7 +907,7 @@ picinterrupt(void) exit(-1); } - pic.interrupt |= 0x40; /* Mark slave pending. */ + pic.flags |= PIC_SLAVE_PENDING; } if ((pic.interrupt == 0) && (pit_devs[1].data != NULL)) @@ -833,8 +919,13 @@ picinterrupt(void) pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); if (pic.ack_bytes == 0) { - if (pic.interrupt & 0x40) + if (pic.flags & PIC_SLAVE_PENDING) { + pic2.flags &= ~PIC_FREEZE; + pic_update_request(&pic2, pic2.interrupt & 0x07); pic2.interrupt = 0x17; + } + pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE); + pic_update_request(&pic, pic.interrupt & 0x07); pic.interrupt = 0x17; update_pending(); } diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index d38a967bd..2dcb9688a 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1748,7 +1748,7 @@ buslogic_init(const device_t *info) } if (bl->chip == CHIP_BUSLOGIC_PCI_958D_1995_12_30) { - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev); + pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev, &dev->pci_slot); buslogic_pci_bar[0].addr_regs[0] = 1; buslogic_pci_bar[1].addr_regs[0] = 0; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 897f37d1d..8c70b753b 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -234,6 +234,7 @@ typedef struct ncr53c8xx_t { int waiting; uint8_t current_lun; + uint8_t irq_state; uint8_t istat; uint8_t dcmd; @@ -498,10 +499,10 @@ static void do_irq(ncr53c8xx_t *dev, int level) { if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); ncr53c8xx_log("Raising IRQ...\n"); } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); ncr53c8xx_log("Lowering IRQ...\n"); } } @@ -534,12 +535,16 @@ ncr53c8xx_update_irq(ncr53c8xx_t *dev) level = 1; } +#ifdef STATE_KEEPING if (level != dev->last_level) { +#endif ncr53c8xx_log("Update IRQ level %d dstat %02x sist %02x%02x\n", level, dev->dstat, dev->sist1, dev->sist0); dev->last_level = level; do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ +#ifdef STATE_KEEPING } +#endif } /* Stop SCRIPTS execution and raise a SCSI interrupt. */ @@ -2552,9 +2557,9 @@ ncr53c8xx_init(const device_t *info) dev->has_bios = 0; if (info->local & 0x8000) - dev->pci_slot = pci_add_card(PCI_ADD_SCSI, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); + pci_add_card(PCI_ADD_SCSI, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev, &dev->pci_slot); else - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev, &dev->pci_slot); if (dev->chip == CHIP_875) { dev->chip_rev = 0x04; diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 7fa359396..52ec0b56f 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -197,6 +197,7 @@ typedef struct esp_t { int pos; } dma_86c01; + uint8_t irq_state; uint8_t pos_regs[8]; } esp_t; @@ -247,10 +248,10 @@ esp_irq(esp_t *dev, int level) } } else { if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); esp_log("Raising IRQ...\n"); } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); esp_log("Lowering IRQ...\n"); } } @@ -1842,7 +1843,7 @@ dc390_init(UNUSED(const device_t *info)) dev->PCIBase = 0; dev->MMIOBase = 0; - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, esp_pci_read, esp_pci_write, dev); + pci_add_card(PCI_ADD_NORMAL, esp_pci_read, esp_pci_write, dev, &dev->pci_slot); esp_pci_bar[0].addr_regs[0] = 1; esp_pci_regs[0x04] = 3; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 7a6923def..e2bfc178f 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -83,23 +83,27 @@ x54x_irq(x54x_t *dev, int set) if (dev->card_bus & DEVICE_PCI) { x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); if (set) - pci_set_irq(dev->pci_slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - pci_clear_irq(dev->pci_slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } else { x54x_log("%sing IRQ %i\n", set ? "Rais" : "Lower", irq); - if (set) { - if (dev->interrupt_type) - int_type = dev->interrupt_type(dev); + if (dev->interrupt_type) + int_type = dev->interrupt_type(dev); + if (set) { if (int_type) - picintlevel(1 << irq); + picintlevel(1 << irq, &dev->irq_state); else picint(1 << irq); - } else - picintc(1 << irq); - } + } else { + if (int_type) + picintclevel(1 << irq, &dev->irq_state); + else + picintc(1 << irq); + } + } } static void @@ -1415,6 +1419,7 @@ static void x54x_reset(x54x_t *dev) { clear_irq(dev); + dev->irq_state = 0; if (dev->flags & X54X_INT_GEOM_WRITABLE) dev->Geometry = 0x90; else diff --git a/src/sound/snd_ac97_via.c b/src/sound/snd_ac97_via.c index e074d17e2..ceac42387 100644 --- a/src/sound/snd_ac97_via.c +++ b/src/sound/snd_ac97_via.c @@ -73,7 +73,8 @@ typedef struct _ac97_via_ { uint8_t regs_linear[256]; }; } codec_shadow[2]; - int slot; + uint8_t pci_slot; + uint8_t irq_state; int irq_pin; ac97_codec_t *codec[2][2]; @@ -115,8 +116,8 @@ ac97_via_set_slot(void *priv, int slot, int irq_pin) ac97_via_log("AC97 VIA: set_slot(%d, %d)\n", slot, irq_pin); - dev->slot = slot; - dev->irq_pin = irq_pin; + dev->pci_slot = slot; + dev->irq_pin = irq_pin; } uint8_t @@ -182,12 +183,12 @@ ac97_via_update_irqs(ac97_via_t *dev) /* Stop immediately if any flag is set. Doing it this way optimizes rising edges for the playback SGD (0 - first to be checked). */ if (dev->sgd_regs[i] & (dev->sgd_regs[i | 0x2] & 0x03)) { - pci_set_irq(dev->slot, dev->irq_pin); + pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); return; } } - pci_clear_irq(dev->slot, dev->irq_pin); + pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state); } static void diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index fb156a205..436f99897 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -53,6 +53,7 @@ typedef struct es1371_t { uint32_t base_addr; uint8_t int_line; + uint8_t irq_state; uint16_t pmcsr; @@ -120,7 +121,7 @@ typedef struct es1371_t { int cd_vol_l; int cd_vol_r; - int card; + uint8_t pci_slot; int pos; int16_t buffer[SOUNDBUFLEN * 2]; @@ -235,9 +236,9 @@ es1371_update_irqs(es1371_t *dev) irq = 1; if (irq) - pci_set_irq(dev->card, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else - pci_clear_irq(dev->card, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } static void @@ -2100,7 +2101,7 @@ es1371_init(const device_t *info) dev->gameport = gameport_add(&gameport_pnp_device); gameport_remap(dev->gameport, 0x200); - dev->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev); + pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot); timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index ea81230a9..f865b4d4d 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -97,7 +97,8 @@ typedef struct _cmi8x38_ { uint16_t mpu_base; uint8_t pci_regs[256]; uint8_t io_regs[256]; - int slot; + uint8_t pci_slot; + uint8_t irq_state; sb_t *sb; void *gameport; @@ -148,11 +149,11 @@ cmi8x38_update_irqs(cmi8x38_t *dev) /* Calculate and use the INTR flag. */ if (*((uint32_t *) &dev->io_regs[0x10]) & 0x0401c003) { dev->io_regs[0x13] |= 0x80; - pci_set_irq(dev->slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); cmi8x38_log("CMI8x38: Raising IRQ\n"); } else { dev->io_regs[0x13] &= ~0x80; - pci_clear_irq(dev->slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); } } @@ -823,9 +824,9 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) /* Force IRQ if requested. Clearing this bit is undefined. */ if (val & 0x10) - pci_set_irq(dev->slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); else if ((dev->io_regs[0x17] & 0x10) && !(val & 0x10)) - pci_clear_irq(dev->slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); /* Enable or disable I/O traps. */ dev->io_regs[addr] = val; @@ -1473,7 +1474,7 @@ cmi8x38_init(const device_t *info) } /* Add PCI card. */ - dev->slot = pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev); + pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev, &dev->pci_slot); /* Perform initial reset. */ cmi8x38_reset(dev); diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index c7e6d39f9..7e3f51567 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -98,6 +98,9 @@ typedef struct gus_t { int irqnext; + uint8_t irq_state; + uint8_t midi_irq_state; + pc_timer_t timer_1; pc_timer_t timer_2; @@ -157,8 +160,10 @@ double vol16bit[4096]; void gus_update_int_status(gus_t *gus) { - int irq_pending = 0; - int midi_irq_pending = 0; + int irq_pending = 0; + int midi_irq_pending = 0; + int intr_pending = 0; + int midi_intr_pending = 0; gus->irqstatus &= ~0x60; gus->irqstatus2 = 0xE0; @@ -187,24 +192,35 @@ gus_update_int_status(gus_t *gus) midi_irq_pending = gus->midi_status & MIDI_INT_MASTER; - if (gus->irq == gus->irq_midi && gus->irq != -1) { + if (gus->irq == gus->irq_midi) { if (irq_pending || midi_irq_pending) - picintlevel(1 << gus->irq); + intr_pending = 1; else - picintc(1 << gus->irq); + intr_pending = 0; } else { - if (gus->irq != -1) { - if (irq_pending) - picintlevel(1 << gus->irq); - else - picintc(1 << gus->irq); - } - if (gus->irq_midi != -1) { - if (midi_irq_pending) - picintlevel(1 << gus->irq_midi); - else - picintc(1 << gus->irq_midi); - } + if (irq_pending) + intr_pending = 1; + else + intr_pending = 0; + + if (midi_irq_pending) + midi_intr_pending = 1; + else + midi_intr_pending = 0; + } + + if (gus->irq != -1) { + if (intr_pending) + picintlevel(1 << gus->irq, &gus->irq_state); + else + picintclevel(1 << gus->irq, &gus->irq_state); + } + + if (gus->irq_midi != -1) { + if (midi_intr_pending) + picintlevel(1 << gus->irq_midi, &gus->midi_irq_state); + else + picintclevel(1 << gus->irq_midi, &gus->midi_irq_state); } } @@ -1174,6 +1190,103 @@ gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) return 0; } +static void +gus_reset(void *p) +{ + gus_t *gus = (gus_t *) p; + int c; + double out = 1.0; + + if (gus == NULL) + return; + + memset(gus->ram, 0x00, (gus->gus_end_ram)); + + for (c = 0; c < 32; c++) { + gus->ctrl[c] = 1; + gus->rctrl[c] = 1; + gus->rfreq[c] = 63 * 512; + } + + for (c = 4095; c >= 0; c--) { + vol16bit[c] = out; + out /= 1.002709201; /* 0.0235 dB Steps */ + } + + gus->voices = 14; + + gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0)); + + gus->t1l = gus->t2l = 0xff; + + gus->global = 0; + gus->addr = 0; + gus->dmaaddr = 0; + gus->voice = 0; + memset(gus->start, 0x00, 32 * sizeof(uint32_t)); + memset(gus->end, 0x00, 32 * sizeof(uint32_t)); + memset(gus->cur, 0x00, 32 * sizeof(uint32_t)); + memset(gus->startx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->endx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->curx, 0x00, 32 * sizeof(uint32_t)); + memset(gus->rstart, 0x00, 32 * sizeof(int)); + memset(gus->rend, 0x00, 32 * sizeof(int)); + memset(gus->rcur, 0x00, 32 * sizeof(int)); + memset(gus->freq, 0x00, 32 * sizeof(uint16_t)); + memset(gus->curvol, 0x00, 32 * sizeof(int)); + memset(gus->pan_l, 0x00, 32 * sizeof(int)); + memset(gus->pan_r, 0x00, 32 * sizeof(int)); + gus->t1on = 0; + gus->t2on = 0; + gus->tctrl = 0; + gus->t1 = 0; + gus->t2 = 0; + gus->irqstatus = 0; + gus->irqstatus2 = 0; + gus->adcommand = 0; + memset(gus->waveirqs, 0x00, 32 * sizeof(int)); + memset(gus->rampirqs, 0x00, 32 * sizeof(int)); + gus->dmactrl = 0; + + gus->uart_out = 1; + + gus->sb_2xa = 0; + gus->sb_2xc = 0; + gus->sb_2xe = 0; + gus->sb_ctrl = 0; + gus->sb_nmi = 0; + + gus->reg_ctrl = 0; + + gus->ad_status = 0; + gus->ad_data = 0; + gus->ad_timer_ctrl = 0; + + gus->midi_ctrl = 0; + gus->midi_status = 0; + memset(gus->midi_queue, 0x00, 64 * sizeof(uint8_t)); + gus->midi_data = 0; + gus->midi_r = 0; + gus->midi_w = 0; + gus->uart_in = 0; + gus->uart_out = 0; + gus->sysex = 0; + + gus->gp1 = 0; + gus->gp2 = 0; + gus->gp1_addr = 0; + gus->gp2_addr = 0; + + gus->usrr = 0; + + gus->max_ctrl = 0; + + gus->irq_state = 0; + gus->midi_irq_state = 0; + + gus_update_int_status(gus); +} + void * gus_init(UNUSED(const device_t *info)) { @@ -1181,7 +1294,7 @@ gus_init(UNUSED(const device_t *info)) double out = 1.0; uint8_t gus_ram = device_get_config_int("gus_ram"); gus_t *gus = malloc(sizeof(gus_t)); - memset(gus, 0, sizeof(gus_t)); + memset(gus, 0x00, sizeof(gus_t)); gus->gus_end_ram = 1 << (18 + gus_ram); gus->ram = (uint8_t *) malloc(gus->gus_end_ram); @@ -1359,7 +1472,7 @@ const device_t gus_device = { .local = 0, .init = gus_init, .close = gus_close, - .reset = NULL, + .reset = gus_reset, { .available = NULL }, .speed_changed = gus_speed_changed, .force_redraw = NULL, diff --git a/src/usb.c b/src/usb.c index 0ed98fc12..e6818d849 100644 --- a/src/usb.c +++ b/src/usb.c @@ -317,10 +317,14 @@ ohci_update_irq(usb_t *dev) { uint32_t level = !!(dev->ohci_mmio[OHCI_HcInterruptStatus].l & dev->ohci_mmio[OHCI_HcInterruptEnable].l); +#ifdef STATE_KEEPING if (level != dev->irq_level) { +#endif dev->irq_level = level; usb_interrupt_ohci(dev, level); +#ifdef STATE_KEEPING } +#endif } void diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index c28d4c0aa..25b416a23 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -94,9 +94,11 @@ typedef struct mach64_t { int type; int pci; + uint8_t pci_slot; + uint8_t irq_state; + uint8_t pci_regs[256]; uint8_t int_line; - int card; int bank_r[2]; int bank_w[2]; @@ -647,9 +649,9 @@ mach64_update_irqs(mach64_t *mach64) } if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) - pci_set_irq(mach64->card, PCI_INTA); + pci_set_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); else - pci_clear_irq(mach64->card, PCI_INTA); + pci_clear_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); } static __inline void @@ -4401,7 +4403,7 @@ mach64_common_init(const device_t *info) mach64_io_set(mach64); if (info->flags & DEVICE_PCI) - mach64->card = pci_add_card(PCI_ADD_VIDEO, mach64_pci_read, mach64_pci_write, mach64); + pci_add_card(PCI_ADD_NORMAL, mach64_pci_read, mach64_pci_write, mach64, &mach64->pci_slot); mach64->pci_regs[PCI_REG_COMMAND] = 3; mach64->pci_regs[0x30] = 0x00; diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 1aa55bd6b..23c0bf0f2 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -58,7 +58,8 @@ typedef struct mach_t { uint8_t regs[256]; uint8_t pci_regs[256]; uint8_t int_line; - int card; + uint8_t pci_slot; + uint8_t irq_state; int index; uint32_t memory; @@ -5571,7 +5572,7 @@ mach8_init(const device_t *info) else if (mach->pci_bus) { ati_eeprom_load(&mach->eeprom, "mach32_pci.nvr", 1); mem_mapping_disable(&mach->bios_rom.mapping); - mach->card = pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach); + pci_add_card(PCI_ADD_VIDEO, mach32_pci_read, mach32_pci_write, mach, &mach->pci_slot); mach->pci_regs[PCI_REG_COMMAND] = 0x83; mach->pci_regs[0x30] = 0x00; mach->pci_regs[0x32] = 0x0c; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 225810974..00b588631 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -217,7 +217,10 @@ typedef struct gd54xx_t { uint8_t fc; /* Feature Connector */ - int card, id; + int id; + + uint8_t pci_slot; + uint8_t irq_state; uint8_t pos_regs[8]; @@ -484,9 +487,9 @@ gd54xx_update_irqs(gd54xx_t *gd54xx) return; if ((gd54xx->vblank_irq > 0) && gd54xx_vga_vsync_enabled(gd54xx)) - pci_set_irq(gd54xx->card, PCI_INTA); + pci_set_irq(gd54xx->pci_slot, PCI_INTA, &gd54xx->irq_state); else - pci_clear_irq(gd54xx->card, PCI_INTA); + pci_clear_irq(gd54xx->pci_slot, PCI_INTA, &gd54xx->irq_state); } static void @@ -4056,7 +4059,10 @@ static void io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); if (gd54xx->pci && id >= CIRRUS_ID_CLGD5430) { - pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx); + if (romfn == NULL) + pci_add_card(PCI_ADD_VIDEO, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, cl_pci_read, cl_pci_write, gd54xx, &gd54xx->pci_slot); mem_mapping_disable(&gd54xx->bios_rom.mapping); } diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c2ce39778..791b65912 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -69,7 +69,7 @@ typedef struct et4000w32p_t { svga_t svga; - uint8_t banking, banking2, adjust_cursor, rev; + uint8_t banking, banking2, adjust_cursor, rev, pci_slot; uint8_t regs[256], pci_regs[256]; @@ -2800,7 +2800,7 @@ et4000w32p_init(const device_t *info) et4000w32p_io_set(et4000); if (info->flags & DEVICE_PCI) - pci_add_card(PCI_ADD_VIDEO, et4000w32p_pci_read, et4000w32p_pci_write, et4000); + pci_add_card(PCI_ADD_NORMAL, et4000w32p_pci_read, et4000w32p_pci_write, et4000, &et4000->pci_slot); /* Hardwired bits: 00000000 1xx0x0xx */ /* R/W bits: xx xxxx */ diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 67f8d5751..b258f71b1 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -424,11 +424,12 @@ typedef struct mystique_t { xcolkeyl, xcolkeyh, xcrcbitsel; + uint8_t pci_slot, irq_state, pad, pad0; + uint8_t pci_regs[256], crtcext_regs[6], xreg_regs[256], dmamap[16]; - int card, vram_size, crtcext_idx, xreg_idx, - xzoomctrl, + int vram_size, crtcext_idx, xreg_idx, xzoomctrl, pixel_count, trap_count; atomic_int busy, blitter_submit_refcount, @@ -1031,9 +1032,9 @@ mystique_update_irqs(mystique_t *mystique) irq = 1; if (irq) - pci_set_irq(mystique->card, PCI_INTA); + pci_set_irq(mystique->pci_slot, PCI_INTA, &mystique->irq_state); else - pci_clear_irq(mystique->card, PCI_INTA); + pci_clear_irq(mystique->pci_slot, PCI_INTA, &mystique->irq_state); } #define READ8(addr, var) \ @@ -5460,7 +5461,7 @@ static void * mystique_init(const device_t *info) { mystique_t *mystique = malloc(sizeof(mystique_t)); - char *romfn; + char *romfn = NULL; memset(mystique, 0, sizeof(mystique_t)); @@ -5524,7 +5525,10 @@ mystique_init(const device_t *info) NULL, 0, mystique); mem_mapping_disable(&mystique->iload_mapping); - mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); + if (romfn = NULL) + pci_add_card(PCI_ADD_NORMAL, mystique_pci_read, mystique_pci_write, mystique, &mystique->pci_slot); + else + pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique, &mystique->pci_slot); mystique->pci_regs[0x06] = 0x80; mystique->pci_regs[0x07] = 0 << 1; mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index bcdd64d40..8fcacee38 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -209,7 +209,9 @@ typedef struct s3_t { uint32_t linear_base, linear_size; uint8_t pci_regs[256]; - int card; + + uint8_t pci_slot; + uint8_t irq_state; uint32_t vram_mask; uint8_t data_available; @@ -465,9 +467,9 @@ s3_update_irqs(s3_t *s3) return; if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) { - pci_set_irq(s3->card, PCI_INTA); + pci_set_irq(s3->pci_slot, PCI_INTA, &s3->irq_state); } else { - pci_clear_irq(s3->card, PCI_INTA); + pci_clear_irq(s3->pci_slot, PCI_INTA, &s3->irq_state); } } @@ -8349,8 +8351,12 @@ s3_init(const device_t *info) return NULL; } - if (s3->pci) - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + if (s3->pci) { + if (bios_fn == NULL) + pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3, &s3->pci_slot); + else + pci_add_card(PCI_ADD_NORMAL, s3_pci_read, s3_pci_write, s3, &s3->pci_slot); + } s3->i2c = i2c_gpio_init("ddc_s3"); s3->ddc = ddc_init(i2c_gpio_get_bus(s3->i2c)); diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 6c382cf7f..2e6cffd96 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -172,7 +172,9 @@ typedef struct virge_t { uint32_t linear_base, linear_size; uint8_t pci_regs[256]; - int card; + + uint8_t pci_slot; + uint8_t irq_state; int pci; int chip; @@ -278,7 +280,6 @@ typedef struct virge_t { uint32_t cmd_dma_base; uint32_t dma_ptr; uint64_t blitter_time; - volatile int fifo_slot; int fifo_slots_num; pc_timer_t tri_timer; @@ -419,9 +420,9 @@ static void s3_virge_update_irqs(virge_t *virge) { if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & (virge->subsys_cntl & INT_MASK))) - pci_set_irq(virge->card, PCI_INTA); + pci_set_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); else - pci_clear_irq(virge->card, PCI_INTA); + pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } static void @@ -998,9 +999,9 @@ s3_virge_vblank_start(svga_t *svga) static void s3_virge_mmio_fifo_write(uint32_t addr, uint8_t val, virge_t *virge) { - if ((addr & 0xffff) < 0x8000) { + if ((addr & 0xffff) < 0x8000) s3_virge_bitblt(virge, 8, val); - } else { + else { switch (addr & 0xffff) { case 0x859c: virge->cmd_dma = val; @@ -1032,9 +1033,6 @@ s3_virge_mmio_fifo_write_l(uint32_t addr, uint32_t val, virge_t *virge) else s3_virge_bitblt(virge, 32, val); } else { - if (virge->fifo_slot >= virge->fifo_slots_num) - return; - virge->fifo_slot++; switch (addr & 0xfffc) { case 0x8590: virge->cmd_dma_base = val; @@ -1482,24 +1480,24 @@ s3_virge_mmio_read(uint32_t addr, void *priv) s3_virge_log("[%04X:%08X]: MMIO ReadB addr = %04x\n", CS, cpu_state.pc, addr & 0xffff); switch (addr & 0xffff) { + case 0x8504: + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret = virge->subsys_stat; + s3_virge_update_irqs(virge); + return ret; case 0x8505: - ret = 0xc0; - if (!virge->s3d_busy && !virge->fifo_slot) + ret = 0xd0; + if (!virge->s3d_busy) ret |= 0x20; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot); return ret; case 0x850c: ret = virge->advfunc_cntl & 0x3f; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6; + ret |= virge->fifo_slots_num << 6; ret &= 0xff; break; case 0x850d: - ret = (virge->fifo_slots_num - virge->fifo_slot) >> 2; + ret = virge->fifo_slots_num >> 2; break; case 0x83b0: @@ -1576,23 +1574,17 @@ s3_virge_mmio_read_w(uint32_t addr, void *priv) switch (addr & 0xfffe) { case 0x8504: - ret = 0xc000; - if (!virge->s3d_busy && !virge->fifo_slot) + ret = 0xd000; + if (!virge->s3d_busy) ret |= 0x2000; - if (!virge->fifo_slot) - virge->subsys_stat |= INT_FIFO_EMP; + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); ret |= virge->subsys_stat; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot) << 8; s3_virge_update_irqs(virge); return ret; case 0x850c: ret = virge->advfunc_cntl & 0x3f; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6; + ret |= virge->fifo_slots_num << 6; break; case 0x859c: @@ -1682,26 +1674,17 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv) break; case 0x8504: - ret = 0x0000c000; - if (!virge->s3d_busy && !virge->fifo_slot) { + ret = 0x0000d000; + if (!virge->s3d_busy) ret |= 0x00002000; - if (!virge->s3d_busy) - virge->subsys_stat |= INT_3DF_EMP; - if (!virge->fifo_slot) - virge->subsys_stat |= INT_FIFO_EMP; - } + virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); ret |= virge->subsys_stat; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot) << 8; s3_virge_update_irqs(virge); break; case 0x850c: ret = virge->advfunc_cntl & 0x3f; - if (virge->fifo_slot) - virge->fifo_slot--; - ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6; + ret |= virge->fifo_slots_num << 6; break; case 0x8590: @@ -4421,7 +4404,10 @@ s3_virge_init(const device_t *info) virge->svga.crtc[0x37] = 1 | (7 << 5); virge->svga.crtc[0x53] = 8; - virge->card = pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); + if (bios_fn == NULL) + pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge, &virge->pci_slot); + else + pci_add_card(virge->is_agp ? PCI_ADD_AGP : PCI_ADD_NORMAL, s3_virge_pci_read, s3_virge_pci_write, virge, &virge->pci_slot); virge->i2c = i2c_gpio_init("ddc_s3_virge"); virge->ddc = ddc_init(i2c_gpio_get_bus(virge->i2c)); diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index f659f90fe..15c03097a 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -103,7 +103,10 @@ typedef struct tgui_t { svga_t svga; int pci; - int type, card; + uint8_t pci_slot; + uint8_t irq_state; + + int type; uint8_t int_line; uint8_t pci_regs[256]; @@ -220,9 +223,9 @@ tgui_update_irqs(tgui_t *tgui) return; if (!(tgui->oldctrl1 & 0x40)) { - pci_set_irq(tgui->card, PCI_INTA); + pci_set_irq(tgui->pci_slot, PCI_INTA, &tgui->irq_state); } else { - pci_clear_irq(tgui->card, PCI_INTA); + pci_clear_irq(tgui->pci_slot, PCI_INTA, &tgui->irq_state); } } @@ -3516,9 +3519,9 @@ tgui_init(const device_t *info) if (tgui->pci && (tgui->type >= TGUI_9440)) { if (tgui->has_bios) - tgui->card = pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); + pci_add_card(PCI_ADD_NORMAL, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); else - tgui->card = pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui); + pci_add_card(PCI_ADD_VIDEO | PCI_ADD_STRICT, tgui_pci_read, tgui_pci_write, tgui, &tgui->pci_slot); } tgui->pci_regs[PCI_REG_COMMAND] = 7; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 610e15e6c..21df563ff 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -923,7 +923,7 @@ voodoo_card_init(void) else voodoo_generate_filter_v1(voodoo); - pci_add_card(PCI_ADD_NORMAL, voodoo_pci_read, voodoo_pci_write, voodoo); + pci_add_card(PCI_ADD_NORMAL, voodoo_pci_read, voodoo_pci_write, voodoo, &voodoo->pci_slot); mem_mapping_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo); diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 0b3a3a043..772de2fea 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -142,8 +142,11 @@ typedef struct banshee_t { int desktop_y; uint32_t desktop_stride_tiled; - int type, card, agp, has_bios; - int vblank_irq; + int type, agp; + int has_bios, vblank_irq; + + uint8_t pci_slot; + uint8_t irq_state; void *i2c, *i2c_ddc, *ddc; } banshee_t; @@ -306,9 +309,9 @@ static void banshee_update_irqs(banshee_t *banshee) { if (banshee->vblank_irq > 0 && banshee_vga_vsync_enabled(banshee)) { - pci_set_irq(banshee->card, PCI_INTA); + pci_set_irq(banshee->pci_slot, PCI_INTA, &banshee->irq_state); } else { - pci_clear_irq(banshee->card, PCI_INTA); + pci_clear_irq(banshee->pci_slot, PCI_INTA, &banshee->irq_state); } } @@ -3146,7 +3149,10 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int banshee->dramInit1 = 1 << 30; /*SDRAM*/ banshee->svga.decode_mask = 0x1ffffff; - banshee->card = pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); + if (banshee->has_bios) + pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee, &banshee->pci_slot); + else + pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_NORMAL, banshee_pci_read, banshee_pci_write, banshee, &banshee->pci_slot); banshee->voodoo = voodoo_2d3d_card_init(voodoo_type); banshee->voodoo->p = banshee;