PCI and IRQ rework, pci.c rewritten from ground up, fixes numerous issues such as the bridge being added when the number of normal PCI devices equals the number of normal PCI slots, Windows 95 PCI operation on Intel 430NX, sharing of PCI IRQ's with non-PCI level-triggered devices, having both configuration mechanisms operating at the same time (ALi M1435), etc., and makes the code much more readable.

This commit is contained in:
OBattler
2023-08-07 03:04:52 +02:00
parent cb24ee27cb
commit c30d5d90b7
66 changed files with 1824 additions and 1643 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -11,146 +11,260 @@
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* 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;

View File

@@ -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*/

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;