/* * 86Box A hypervisor and IBM PC system emulator that specializes in * running old operating systems and software designed for IBM * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * * This file is part of the 86Box distribution. * * Definitions for the PCI handler module. * * * * Authors: Miran Grca, * * Copyright 2023 Miran Grca. */ #ifndef EMU_PCI_H #define EMU_PCI_H #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_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_COMMAND_H_SERR 0x01 #define PCI_COMMAND_H_FAST_B2B 0x02 #define PCI_COMMAND_H_INT_DIS 0x04 #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_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_DEVSEL_FAST 0x00 #define PCI_DEVSEL_MEDIUM 0x02 #define PCI_DEVSEL_SLOW 0x04 #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 FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2 #define FLAG_MASK 0x0000007f #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_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_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_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_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]; } pci_bar_t; extern int pci_burst_time; extern int agp_burst_time; extern int pci_nonburst_time; extern int agp_nonburst_time; extern int pci_flags; extern uint32_t pci_base; extern uint32_t pci_size; 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); /* 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); /* 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); /* Write PCI enable/disable key, split for the ALi M1435. */ extern void pci_key_write(uint8_t val); /* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */ extern void pci_set_pmc(uint8_t pmc); extern void pci_pic_reset(void); extern void pci_reset(void); /* 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 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); /* 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); /* 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); /* Register the cards that have been added into slots. */ extern void pci_register_cards(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; extern const device_t ali5243_agp_device; extern const device_t ali5247_agp_device; extern const device_t i440lx_agp_device; extern const device_t i440bx_agp_device; extern const device_t i440gx_agp_device; extern const device_t via_vp3_agp_device; extern const device_t via_mvp3_agp_device; extern const device_t via_apro_agp_device; extern const device_t via_vt8601_agp_device; #endif #endif /*EMU_PCI_H*/