From 27115d80d306202114058f35b3f0d8c7acf85861 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 14 Mar 2021 21:31:02 -0300 Subject: [PATCH] Add AGP video card support and Voodoo 3 AGP --- src/device/pci_bridge.c | 3 +- src/include/86box/pci.h | 8 +-- src/include/86box/video.h | 5 +- src/pci.c | 15 ++--- src/video/vid_table.c | 2 + src/video/vid_voodoo_banshee.c | 116 ++++++++++++++++++++++++++++----- src/video/video.c | 7 ++ 7 files changed, 126 insertions(+), 30 deletions(-) diff --git a/src/device/pci_bridge.c b/src/device/pci_bridge.c index eff3e93bc..ab2d010ac 100644 --- a/src/device/pci_bridge.c +++ b/src/device/pci_bridge.c @@ -335,8 +335,7 @@ pci_bridge_init(const device_t *info) for (i = 0; i < slot_count; i++) { /* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */ pci_bridge_log("PCI Bridge %d: downstream slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, i, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], interrupts[(i + 3) & interrupt_mask]); - /* Use _NOBRIDGE for VIA AGP bridges, as they don't like PCI bridges under them. */ - pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE_VIA(dev->local) ? PCI_CARD_NORMAL_NOBRIDGE : PCI_CARD_NORMAL, + pci_register_bus_slot(dev->bus_index, i, AGP_BRIDGE(dev->local) ? PCI_CARD_AGP : PCI_CARD_NORMAL, interrupts[i & interrupt_mask], interrupts[(i + 1) & interrupt_mask], interrupts[(i + 2) & interrupt_mask], diff --git a/src/include/86box/pci.h b/src/include/86box/pci.h index db4e7f332..e01deb371 100644 --- a/src/include/86box/pci.h +++ b/src/include/86box/pci.h @@ -51,8 +51,8 @@ enum { PCI_CARD_NORTHBRIDGE = 0, PCI_CARD_AGPBRIDGE, PCI_CARD_SOUTHBRIDGE, + PCI_CARD_AGP = 0x0f, PCI_CARD_NORMAL = 0x10, - PCI_CARD_NORMAL_NOBRIDGE, PCI_CARD_VIDEO, PCI_CARD_SCSI, PCI_CARD_SOUND, @@ -65,8 +65,8 @@ enum { PCI_ADD_NORTHBRIDGE = 0, PCI_ADD_AGPBRIDGE, PCI_ADD_SOUTHBRIDGE, + PCI_ADD_AGP = 0x0f, PCI_ADD_NORMAL = 0x10, - PCI_ADD_NORMAL_NOBRIDGE, PCI_ADD_VIDEO, PCI_ADD_SCSI, PCI_ADD_SOUND, @@ -81,8 +81,8 @@ typedef union { } bar_t; -extern int pci_burst_time, - pci_nonburst_time; +extern int pci_burst_time, agp_burst_time, + pci_nonburst_time, agp_nonburst_time; extern void pci_set_irq_routing(int pci_int, int irq); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 17a564069..c335f8969 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -48,7 +48,8 @@ enum { VIDEO_ISA = 0, VIDEO_MCA, VIDEO_BUS, - VIDEO_PCI + VIDEO_PCI, + VIDEO_AGP }; #define VIDEO_FLAG_TYPE_CGA 0 @@ -381,7 +382,9 @@ extern const device_t voodoo_device; extern const device_t voodoo_banshee_device; extern const device_t creative_voodoo_banshee_device; extern const device_t voodoo_3_2000_device; +extern const device_t voodoo_3_2000_agp_device; extern const device_t voodoo_3_3000_device; +extern const device_t voodoo_3_3000_agp_device; /* Wyse 700 */ extern const device_t wy700_device; diff --git a/src/pci.c b/src/pci.c index b7420c953..22ec1dc26 100644 --- a/src/pci.c +++ b/src/pci.c @@ -51,8 +51,8 @@ typedef struct { } pci_mirq_t; -int pci_burst_time, - pci_nonburst_time; +int pci_burst_time, agp_burst_time, + pci_nonburst_time, agp_nonburst_time; static pci_card_t pci_cards[32]; static uint8_t pci_pmc = 0, last_pci_card = 0, last_normal_pci_card = 0, last_pci_bus = 1; @@ -860,8 +860,7 @@ pci_find_slot(uint8_t add_type, uint8_t ignore_slot) if (!dev->read && !dev->write && ((ignore_slot == 0xff) || (i != ignore_slot))) { if (((dev->type == PCI_CARD_NORMAL) && (add_type >= PCI_ADD_NORMAL)) || - (dev->type == add_type) || - ((dev->type == PCI_CARD_NORMAL_NOBRIDGE) && (add_type >= PCI_ADD_NORMAL) && (add_type != PCI_ADD_BRIDGE))) { + (dev->type == add_type)) { ret = i; break; } @@ -878,16 +877,16 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), pci_card_t *dev; uint8_t i, j; - if (add_type < PCI_ADD_NORMAL) + if (add_type < PCI_ADD_AGP) pci_log("pci_add_card(): Adding PCI CARD at specific slot %02X [SPECIFIC]\n", add_type); if (! PCI) { - pci_log("pci_add_card(): Adding PCI CARD failed (non-PCI machine) [%s]\n", (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC")))); + pci_log("pci_add_card(): Adding PCI CARD failed (non-PCI machine) [%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; } 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_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC")))); + 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; } @@ -908,7 +907,7 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), 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_VIDEO) ? "VIDEO" : ((add_type == PCI_ADD_SCSI) ? "SCSI" : ((add_type == PCI_ADD_SOUND) ? "SOUND" : "SPECIFIC")))); + 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; } diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d81e19147..f1a6ba30a 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -186,6 +186,8 @@ video_cards[] = { { "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device }, { "tgui9400cxi_vlb", &tgui9400cxi_device }, { "tgui9440_vlb", &tgui9440_vlb_device }, + { "voodoo3_2k_agp", &voodoo_3_2000_agp_device }, + { "voodoo3_3k_agp", &voodoo_3_3000_agp_device }, { "", NULL } }; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index bb9f00de3..2d6a26fe0 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -44,7 +44,8 @@ #include <86box/vid_voodoo_render.h> -static video_timings_t timing_banshee = {VIDEO_BUS, 2, 2, 1, 20, 20, 21}; +static video_timings_t timing_banshee = {VIDEO_PCI, 2, 2, 1, 20, 20, 21}; +static video_timings_t timing_banshee_agp = {VIDEO_AGP, 2, 2, 1, 20, 20, 21}; #ifdef CLAMP @@ -116,7 +117,7 @@ typedef struct banshee_t int desktop_y; uint32_t desktop_stride_tiled; - int type, card; + int type, card, agp; int vblank_irq; void *i2c, *i2c_ddc, *ddc; @@ -617,9 +618,9 @@ static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p) { case Init_pciInit0: banshee->pciInit0 = val; - voodoo->read_time = pci_nonburst_time + pci_burst_time * ((val & 0x100) ? 2 : 1); - voodoo->burst_time = pci_burst_time * ((val & 0x200) ? 1 : 0); - voodoo->write_time = pci_nonburst_time + voodoo->burst_time; + voodoo->read_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x100) ? 2 : 1); + voodoo->burst_time = (banshee->agp ? agp_burst_time : pci_burst_time) * ((val & 0x200) ? 1 : 0); + voodoo->write_time = (banshee->agp ? agp_nonburst_time : pci_nonburst_time) + voodoo->burst_time; break; case Init_lfbMemoryConfig: @@ -2426,13 +2427,39 @@ static uint8_t banshee_pci_read(int func, int addr, void *p) case 0x32: ret = banshee->pci_regs[0x32]; break; case 0x33: ret = banshee->pci_regs[0x33]; break; + case 0x34: ret = banshee->agp ? 0x54 : 0x60; break; + case 0x3c: ret = banshee->pci_regs[0x3c]; break; case 0x3d: ret = 0x01; break; /*INTA*/ case 0x3e: ret = 0x04; break; case 0x3f: ret = 0xff; break; - + + case 0x40: ret = 0x01; break; + + case 0x50: ret = banshee->pci_regs[0x50]; break; + + case 0x54: ret = 0x02; break; + case 0x55: ret = 0x60; break; + case 0x56: ret = 0x10; break; /* assumed AGP 1.0 */ + + case 0x58: ret = (banshee->type == TYPE_BANSHEE) ? 0x21 : 0x23; break; + case 0x59: ret = 0x02; break; + case 0x5b: ret = 0x07; break; + + case 0x5c: ret = banshee->pci_regs[0x5c]; break; + case 0x5d: ret = banshee->pci_regs[0x5d]; break; + case 0x5e: ret = banshee->pci_regs[0x5e]; break; + case 0x5f: ret = banshee->pci_regs[0x5f]; break; + + case 0x60: ret = 0x01; break; + case 0x62: ret = 0x21; break; + + case 0x64: ret = banshee->pci_regs[0x64]; break; + case 0x65: ret = banshee->pci_regs[0x65]; break; + case 0x66: ret = banshee->pci_regs[0x66]; break; + case 0x67: ret = banshee->pci_regs[0x67]; break; } // banshee_log("%02X\n", ret); return ret; @@ -2524,8 +2551,28 @@ static void banshee_pci_write(int func, int addr, uint8_t val, void *p) mem_mapping_disable(&banshee->bios_rom.mapping); } return; - case 0x3c: - banshee->pci_regs[0x3c] = val; + case 0x3c: case 0x50: case 0x65: case 0x67: + banshee->pci_regs[addr] = val; + return; + + case 0x5c: + banshee->pci_regs[0x5c] = val & 0x27; + return; + + case 0x5d: + banshee->pci_regs[0x5d] = val & 0x03; + return; + + case 0x5f: + banshee->pci_regs[0x5e] = val; + return; + + case 0x64: + banshee->pci_regs[0x64] = val & 0x03; + return; + + case 0x66: + banshee->pci_regs[0x66] = val & 0xc0; return; } } @@ -2652,13 +2699,14 @@ static const device_config_t banshee_sdram_config[] = } }; -static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgram, int type, int voodoo_type) +static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgram, int type, int voodoo_type, int agp) { int mem_size; banshee_t *banshee = malloc(sizeof(banshee_t)); memset(banshee, 0, sizeof(banshee_t)); banshee->type = type; + banshee->agp = agp; rom_init(&banshee->bios_rom, fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&banshee->bios_rom.mapping); @@ -2717,7 +2765,7 @@ static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgra banshee->dramInit1 = 1 << 30; /*SDRAM*/ banshee->svga.decode_mask = 0x1ffffff; - banshee->card = pci_add_card(PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); + banshee->card = pci_add_card(banshee->agp ? PCI_ADD_AGP : PCI_ADD_VIDEO, banshee_pci_read, banshee_pci_write, banshee); banshee->voodoo = voodoo_2d3d_card_init(voodoo_type); banshee->voodoo->p = banshee; @@ -2769,26 +2817,34 @@ static void *banshee_init_common(const device_t *info, wchar_t *fn, int has_sgra break; } - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_banshee); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, banshee->agp ? &timing_banshee_agp : &timing_banshee); return banshee; } static void *banshee_init(const device_t *info) { - return banshee_init_common(info, L"roms/video/voodoo/Pci_sg.rom", 1, TYPE_BANSHEE, VOODOO_BANSHEE); + return banshee_init_common(info, L"roms/video/voodoo/Pci_sg.rom", 1, TYPE_BANSHEE, VOODOO_BANSHEE, 1); } static void *creative_banshee_init(const device_t *info) { - return banshee_init_common(info, L"roms/video/voodoo/BlasterPCI.rom", 0, TYPE_BANSHEE, VOODOO_BANSHEE); + return banshee_init_common(info, L"roms/video/voodoo/BlasterPCI.rom", 0, TYPE_BANSHEE, VOODOO_BANSHEE, 0); } static void *v3_2000_init(const device_t *info) { - return banshee_init_common(info, L"roms/video/voodoo/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3); + return banshee_init_common(info, L"roms/video/voodoo/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3, 0); +} +static void *v3_2000_agp_init(const device_t *info) +{ + return banshee_init_common(info, L"roms/video/voodoo/2k11sd.rom", 0, TYPE_V3_2000, VOODOO_3, 1); } static void *v3_3000_init(const device_t *info) { - return banshee_init_common(info, L"roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3); + return banshee_init_common(info, L"roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3, 0); +} +static void *v3_3000_agp_init(const device_t *info) +{ + return banshee_init_common(info, L"roms/video/voodoo/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3, 1); } static int banshee_available(void) @@ -2803,10 +2859,12 @@ static int v3_2000_available(void) { return rom_present(L"roms/video/voodoo/2k11sd.rom"); } +#define v3_2000_agp_available v3_2000_available static int v3_3000_available(void) { return rom_present(L"roms/video/voodoo/3k12sd.rom"); } +#define v3_3000_agp_available v3_3000_available static void banshee_close(void *p) { @@ -2878,6 +2936,20 @@ const device_t voodoo_3_2000_device = banshee_sdram_config }; +const device_t voodoo_3_2000_agp_device = +{ + "3dfx Voodoo3 2000", + DEVICE_AGP, + 0, + v3_2000_agp_init, + banshee_close, + NULL, + { v3_2000_agp_available }, + banshee_speed_changed, + banshee_force_redraw, + banshee_sdram_config +}; + const device_t voodoo_3_3000_device = { "3dfx Voodoo3 3000", @@ -2891,3 +2963,17 @@ const device_t voodoo_3_3000_device = banshee_force_redraw, banshee_sdram_config }; + +const device_t voodoo_3_3000_agp_device = +{ + "3dfx Voodoo3 3000", + DEVICE_AGP, + 0, + v3_3000_agp_init, + banshee_close, + NULL, + { v3_3000_agp_available }, + banshee_speed_changed, + banshee_force_redraw, + banshee_sdram_config +}; diff --git a/src/video/video.c b/src/video/video.c index 66fb1d024..00329b07c 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -653,6 +653,13 @@ video_update_timing(void) video_timing_write_b = (int)(pci_timing * vid_timings->write_b); video_timing_write_w = (int)(pci_timing * vid_timings->write_w); video_timing_write_l = (int)(pci_timing * vid_timings->write_l); + } else if (vid_timings->type == VIDEO_AGP) { + video_timing_read_b = (int)(agp_timing * vid_timings->read_b); + video_timing_read_w = (int)(agp_timing * vid_timings->read_w); + video_timing_read_l = (int)(agp_timing * vid_timings->read_l); + video_timing_write_b = (int)(agp_timing * vid_timings->write_b); + video_timing_write_w = (int)(agp_timing * vid_timings->write_w); + video_timing_write_l = (int)(agp_timing * vid_timings->write_l); } else { video_timing_read_b = (int)(bus_timing * vid_timings->read_b); video_timing_read_w = (int)(bus_timing * vid_timings->read_w);