PCI/AGP bridge support, part 1

This commit is contained in:
RichardG867
2020-09-19 00:56:12 -03:00
parent e1865a1790
commit 3314bd4035
5 changed files with 460 additions and 126 deletions

View File

@@ -24,8 +24,8 @@
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/pci.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
#include <86box/spd.h>
@@ -52,7 +52,7 @@ enum
typedef struct
{
uint8_t pm2_cntrl, max_func,
uint8_t pm2_cntrl,
smram_locked, max_drb,
drb_unit, drb_default;
uint8_t regs[2][256], regs_locked[2][256];
@@ -277,7 +277,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
uint8_t *regs_l = (uint8_t *) dev->regs_locked[func];
int i;
if (func > dev->max_func)
if (func)
return;
if ((addr >= 0x10) && (addr < 0x4f))
@@ -447,7 +447,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x51] |= 0x10; /* Virtual PC 2007 BIOS requires a reserved bus speed bit to be set */
break;
case INTEL_440GX:
regs[0x51] = (regs[0x50] & 0x88) | (val & 0x08);
regs[0x51] = (regs[0x50] & 0x88) | (val & 0x08);
/*regs[0x51] = (regs[0x50] & 0x88) | (val & 0x77);*/
break;
}
@@ -1258,7 +1258,7 @@ i4x0_read(int func, int addr, void *priv)
uint8_t ret = 0xff;
uint8_t *regs = (uint8_t *) dev->regs[func];
if (func > dev->max_func)
if (func)
ret = 0xff;
else {
ret = regs[addr];
@@ -1298,8 +1298,7 @@ i4x0_reset(void *priv)
}
if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) {
for (i = 0; i <= dev->max_func; i++)
memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t));
memset(dev->regs_locked[0], 0x00, 256 * sizeof(uint8_t));
}
}
@@ -1492,8 +1491,6 @@ static void
dev->drb_default = 0x02;
break;
case INTEL_440LX:
dev->max_func = 1;
regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443LX */
regs[0x06] = 0x90;
regs[0x10] = 0x08;
@@ -1517,8 +1514,6 @@ static void
dev->drb_default = 0x01;
break;
case INTEL_440EX:
dev->max_func = 1;
regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX */
regs[0x06] = 0x90;
regs[0x10] = 0x08;
@@ -1543,7 +1538,6 @@ static void
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x7a] = (info->local >> 8) & 0xff;
dev->max_func = (regs[0x7a] & 0x02) ? 0 : 1;
regs[0x02] = (regs[0x7a] & 0x02) ? 0x92 : 0x90; regs[0x03] = 0x71; /* 82443BX */
regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10;
@@ -1574,7 +1568,6 @@ static void
break;
case INTEL_440GX:
regs[0x7a] = (info->local >> 8) & 0xff;
dev->max_func = (regs[0x7a] & 0x02) ? 0 : 1;
regs[0x02] = (regs[0x7a] & 0x02) ? 0xa2 : 0xa0; regs[0x03] = 0x71; /* 82443GX */
regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10;
@@ -1617,42 +1610,13 @@ static void
i4x0_write(regs[0x5f], 0x5f, 0x00, dev);
i4x0_write(regs[0x72], 0x72, 0x00, dev);
if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1];
regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */
regs[0x02] = 0x81; regs[0x03] = 0x71; /* 82443LX */
regs[0x06] = 0xa0; regs[0x07] = 0x02;
regs[0x0a] = 0x04; regs[0x0b] = 0x06;
regs[0x0e] = 0x01;
regs[0x1c] = 0xf0;
regs[0x1e] = 0xa0; regs[0x1f] = 0x02;
regs[0x20] = 0xf0; regs[0x21] = 0xff;
regs[0x24] = 0xf0; regs[0x25] = 0xff;
}
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440GX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1];
regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */
if(dev->type != INTEL_440GX) {
regs[0x02] = 0x91; regs[0x03] = 0x71; /* 82443BX */
} else {
regs[0x02] = 0xa1; regs[0x03] = 0x71; /* 82443GX (They seem to share the same deal*/
}
regs[0x06] = 0x20; regs[0x07] = 0x02;
regs[0x08] = 0x02;
regs[0x0a] = 0x04; regs[0x0b] = 0x06;
regs[0x0e] = 0x01;
regs[0x1c] = 0xf0;
regs[0x1e] = 0xa0; regs[0x1f] = 0x02;
regs[0x20] = 0xf0; regs[0x21] = 0xff;
regs[0x24] = 0xf0; regs[0x25] = 0xff;
regs[0x3e] = 0x80;
}
pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev);
if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02))
device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device);
else if (dev->type >= INTEL_440LX)
device_add(&i440lx_agp_device);
return dev;
}

325
src/device/pci_bridge.c Normal file
View File

@@ -0,0 +1,325 @@
/*
* 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.
*
* Implementation of PCI-PCI and host-AGP bridges.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/machine.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/pci.h>
#define PCI_BRIDGE_DEC_21150 0x10110022
#define AGP_BRIDGE_INTEL_440LX 0x80867181
#define AGP_BRIDGE_INTEL_440BX 0x80867191
#define AGP_BRIDGE_INTEL_440GX 0x808671a1
#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_INTEL_440LX)
typedef struct
{
uint32_t local;
uint8_t type;
uint8_t regs[256];
uint8_t bus_index;
int slot;
} pci_bridge_t;
#ifdef ENABLE_PCI_BRIDGE_LOG
int pci_bridge_do_log = ENABLE_PCI_BRIDGE_LOG;
static void
pci_bridge_log(const char *fmt, ...)
{
va_list ap;
if (pci_bridge_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define pci_bridge_log(fmt, ...)
#endif
static void
pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
pci_bridge_t *dev = (pci_bridge_t *) priv;
pci_bridge_log("PCI Bridge %d: write(%d, %02X, %02X)\n", dev->bus_index, func, addr, val);
if (func > 0)
return;
switch (addr) {
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x06: case 0x07: case 0x08: case 0x09:
case 0x0a: case 0x0b: case 0x0e: case 0x1e:
case 0x1f: case 0x34: case 0x3d: case 0x67:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
return;
case 0x04:
val &= 0x67;
break;
case 0x05:
val &= 0x03;
break;
case 0x19:
/* Set our bus number. */
pci_bridge_log("PCI Bridge %d: switching from bus %02X to %02X\n", dev->bus_index, dev->regs[addr], val);
if (dev->regs[addr])
pci_bus_number_to_index_mapping[dev->regs[addr]] = 0xff;
if (val)
pci_bus_number_to_index_mapping[val] = dev->bus_index;
break;
case 0x1c: case 0x1d: case 0x20: case 0x22:
case 0x24: case 0x26:
val &= 0xf0;
break;
case 0x3e:
val &= 0xef;
break;
case 0x3f:
val &= 0x0f;
break;
case 0x40:
val &= 0x32;
break;
case 0x41:
val &= 0x07;
break;
case 0x43:
val &= 0x03;
break;
case 0x64:
val &= 0x7e;
break;
case 0x69:
val &= 0x3f;
break;
}
dev->regs[addr] = val;
}
static uint8_t
pci_bridge_read(int func, int addr, void *priv)
{
pci_bridge_t *dev = (pci_bridge_t *) priv;
uint8_t ret;
if (func > 0)
ret = 0xff;
else
ret = dev->regs[addr];
pci_bridge_log("PCI Bridge %d: read(%d, %02X) = %02X\n", dev->bus_index, func, addr, ret);
return ret;
}
static void
pci_bridge_reset(void *priv)
{
pci_bridge_t *dev = (pci_bridge_t *) priv;
pci_bridge_log("PCI Bridge %d: reset()\n", dev->bus_index);
/* IDs */
dev->regs[0x00] = dev->local >> 16;
dev->regs[0x01] = dev->local >> 24;
dev->regs[0x02] = dev->local;
dev->regs[0x03] = dev->local >> 8;
switch (dev->local) {
case PCI_BRIDGE_DEC_21150:
dev->regs[0x06] = 0x80;
dev->regs[0x07] = 0x02;
break;
case AGP_BRIDGE_INTEL_440LX:
dev->regs[0x06] = 0xa0;
dev->regs[0x07] = 0x02;
dev->regs[0x08] = 0x03;
break;
case AGP_BRIDGE_INTEL_440BX:
case AGP_BRIDGE_INTEL_440GX:
dev->regs[0x06] = 0x20;
dev->regs[0x07] = dev->regs[0x08] = 0x02;
break;
}
dev->regs[0x0a] = 0x04; /* PCI-PCI bridge */
dev->regs[0x0b] = 0x06; /* bridge device */
dev->regs[0x0e] = 0x01;
/* IO BARs */
if (AGP_BRIDGE(dev->local)) {
dev->regs[0x1c] = 0xf0;
} else {
dev->regs[0x1c] = dev->regs[0x1d] = 0x01;
}
dev->regs[0x1e] = AGP_BRIDGE(dev->local) ? 0xa0 : 0x80;
dev->regs[0x1f] = 0x02;
/* prefetchable memory limits */
if (AGP_BRIDGE(dev->local)) {
dev->regs[0x20] = dev->regs[0x24] = 0xf0;
dev->regs[0x21] = dev->regs[0x25] = 0xff;
} else {
dev->regs[0x24] = dev->regs[0x26] = 0x01;
}
if (dev->local == AGP_BRIDGE_INTEL_440LX)
dev->regs[0x3e] = 0x80;
if (dev->local == PCI_BRIDGE_DEC_21150) {
dev->regs[0x34] = 0xdc;
dev->regs[0x43] = 0x02;
dev->regs[0xdc] = dev->regs[0xde] = 0x01;
}
}
static void *
pci_bridge_init(const device_t *info)
{
uint8_t interrupts[4], interrupt_count, interrupt_mask, slot_count, i;
pci_bridge_t *dev = (pci_bridge_t *) malloc(sizeof(pci_bridge_t));
memset(dev, 0, sizeof(pci_bridge_t));
dev->local = info->local;
dev->bus_index = last_pci_bus++;
pci_bridge_log("PCI Bridge %d: init()\n", dev->bus_index);
pci_bridge_reset(dev);
dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? 0x01 : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev);
interrupt_count = sizeof(interrupts);
interrupt_mask = interrupt_count - 1;
for (i = 0; i < interrupt_count; i++)
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n", dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0], interrupts[1], interrupts[2], interrupts[3]);
if (info->local == PCI_BRIDGE_DEC_21150)
slot_count = 9; /* 9 bus masters */
else
slot_count = 1; /* AGP bridges always have 1 slot */
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]);
pci_register_bus_slot(dev->bus_index, i, /*AGP_BRIDGE(dev->local) ? PCI_CARD_SPECIAL : */PCI_CARD_NORMAL,
interrupts[i & interrupt_mask],
interrupts[(i + 1) & interrupt_mask],
interrupts[(i + 2) & interrupt_mask],
interrupts[(i + 3) & interrupt_mask]);
}
return dev;
}
/* PCI bridges */
const device_t dec21150_device =
{
"DEC 21150 PCI Bridge",
DEVICE_PCI,
PCI_BRIDGE_DEC_21150,
pci_bridge_init,
NULL,
pci_bridge_reset,
NULL,
NULL,
NULL,
NULL
};
/* AGP bridges */
const device_t i440lx_agp_device =
{
"Intel 82443LX AGP Bridge",
DEVICE_PCI,
AGP_BRIDGE_INTEL_440LX,
pci_bridge_init,
NULL,
pci_bridge_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t i440bx_agp_device =
{
"Intel 82443BX AGP Bridge",
DEVICE_PCI,
AGP_BRIDGE_INTEL_440BX,
pci_bridge_init,
NULL,
pci_bridge_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t i440gx_agp_device =
{
"Intel 82443GX AGP Bridge",
DEVICE_PCI,
AGP_BRIDGE_INTEL_440GX,
pci_bridge_init,
NULL,
pci_bridge_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -64,7 +64,8 @@ enum {
PCI_ADD_VIDEO,
PCI_ADD_SCSI,
PCI_ADD_SOUND,
PCI_ADD_IDE
PCI_ADD_IDE,
PCI_ADD_BRIDGE
};
typedef union {
@@ -75,6 +76,8 @@ typedef union {
extern int pci_burst_time,
pci_nonburst_time;
extern uint8_t last_pci_bus;
extern uint8_t pci_bus_number_to_index_mapping[256];
extern void pci_set_irq_routing(int pci_int, int irq);
@@ -88,16 +91,19 @@ extern uint8_t pci_use_mirq(uint8_t mirq);
extern int pci_irq_is_level(int irq);
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_set_irq(int 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 void pci_clear_irq(int card, uint8_t pci_int);
extern uint8_t pci_get_int(int card, uint8_t pci_int);
extern void pci_reset(void);
extern void pci_init(int type);
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 int 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 void trc_init(void);
@@ -110,4 +116,13 @@ extern void elcr_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t elcr_read(uint16_t port, void *priv);
#ifdef EMU_DEVICE_H
extern const device_t dec21150_device;
extern const device_t i440lx_agp_device;
extern const device_t i440bx_agp_device;
extern const device_t i440gx_agp_device;
#endif
#endif /*EMU_PCI_H*/

178
src/pci.c
View File

@@ -37,7 +37,7 @@
typedef struct {
uint8_t id, type;
uint8_t bus, id, type;
uint8_t irq_routing[4];
void *priv;
@@ -53,10 +53,12 @@ typedef struct {
int pci_burst_time,
pci_nonburst_time;
uint8_t last_pci_bus = 1;
uint8_t pci_bus_number_to_index_mapping[256];
static pci_card_t pci_cards[32];
static uint8_t pci_pmc = 0, last_pci_card = 0;
static uint8_t pci_card_to_slot_mapping[32];
static uint8_t pci_pmc = 0, last_pci_card = 0, last_normal_pci_card = 0;
static uint8_t pci_card_to_slot_mapping[256][32];
static uint8_t elcr[2] = { 0, 0 };
static uint8_t pci_irqs[4], pci_irq_level[4];
static uint64_t pci_irq_hold[16];
@@ -121,7 +123,7 @@ pci_write(uint16_t port, uint8_t val, void *priv)
uint8_t slot = 0;
if (in_smm)
pci_log("(%i) %03x write: %02X\n", pci_enable, port, val);
pci_log("(%i) %03x write: %02X\n", pci_enable, port, val);
switch (port) {
case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
@@ -129,24 +131,22 @@ pci_write(uint16_t port, uint8_t val, void *priv)
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);
if (! pci_bus) {
slot = pci_card_to_slot_mapping[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);
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);
#endif
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);
pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv);
}
#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);
pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
#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);
#endif
break;
}
}
@@ -166,25 +166,23 @@ pci_read(uint16_t port, void *priv)
if (! pci_enable)
return 0xff;
if (! pci_bus) {
slot = pci_card_to_slot_mapping[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);
#endif
}
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 unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
#endif
}
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);
#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);
#endif
}
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);
return ret;
}
@@ -285,21 +283,19 @@ pci_type2_write(uint16_t port, uint8_t val, void *priv)
pci_card = (port >> 8) & 0xf;
pci_index = port & 0xff;
if (! pci_bus) {
slot = pci_card_to_slot_mapping[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 (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
#endif
}
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 unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
#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);
#endif
}
}
@@ -319,21 +315,19 @@ pci_type2_read(uint16_t port, void *priv)
pci_card = (port >> 8) & 0xf;
pci_index = port & 0xff;
if (! pci_bus) {
slot = pci_card_to_slot_mapping[pci_card];
if (slot != 0xff) {
if (pci_cards[slot].read)
return 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);
#endif
}
slot = pci_card_to_slot_mapping[pci_bus_number_to_index_mapping[pci_bus]][pci_card];
if (slot != 0xff) {
if (pci_cards[slot].read)
return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv);
#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);
pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index);
#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);
#endif
return 0xff;
}
@@ -450,7 +444,7 @@ pci_set_mirq(uint8_t mirq, int level)
void
pci_set_irq(uint8_t card, uint8_t pci_int)
pci_set_irq(int card, uint8_t pci_int)
{
uint8_t slot = 0;
uint8_t irq_routing = 0;
@@ -464,7 +458,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int)
}
pci_log("pci_set_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card);
slot = pci_card_to_slot_mapping[card];
slot = pci_card_to_slot_mapping[(card >> 5) & 0xff][card & 31];
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;
@@ -492,7 +486,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int)
} else
pci_log("pci_set_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
if (pci_irq_is_level(irq_line) && (pci_irq_hold[irq_line] & (1ULL << card))) {
if (pci_irq_is_level(irq_line) && (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);
return;
@@ -514,7 +508,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int)
/* 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 << card);
pci_irq_hold[irq_line] |= (1ULL << slot);
} else {
pci_log("pci_set_irq(%02X, %02X): Edge-triggered interrupt, not marking\n", card, pci_int);
}
@@ -556,7 +550,7 @@ pci_clear_mirq(uint8_t mirq, int level)
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);
picintc(1 << irq_line);
} else {
pci_log("pci_clear_mirq(%02X): IRQ is still being held\n", mirq);
}
@@ -568,7 +562,7 @@ pci_clear_mirq(uint8_t mirq, int level)
void
pci_clear_irq(uint8_t card, uint8_t pci_int)
pci_clear_irq(int card, uint8_t pci_int)
{
uint8_t slot = 0;
uint8_t irq_routing = 0;
@@ -582,7 +576,7 @@ pci_clear_irq(uint8_t card, uint8_t pci_int)
}
pci_log("pci_clear_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card);
slot = pci_card_to_slot_mapping[card];
slot = pci_card_to_slot_mapping[(card >> 5) & 0xff][card & 31];
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;
@@ -611,7 +605,7 @@ pci_clear_irq(uint8_t card, uint8_t pci_int)
pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
if (level && !(pci_irq_hold[irq_line] & (1ULL << card))) {
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;
@@ -619,11 +613,11 @@ pci_clear_irq(uint8_t card, uint8_t pci_int)
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 << card);
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);
picintc(1 << irq_line);
} else {
pci_log("pci_clear_irq(%02X, %02X): IRQ is still being held\n", card, pci_int);
}
@@ -634,6 +628,17 @@ pci_clear_irq(uint8_t card, uint8_t pci_int)
}
uint8_t
pci_get_int(int card, uint8_t pci_int)
{
uint8_t slot = pci_card_to_slot_mapping[(card >> 5) & 0xff][card & 31];
if (slot == 0xff)
return 0xff;
return pci_cards[slot].irq_routing[pci_int - PCI_INTA];
}
void
pci_elcr_set_enabled(int enabled)
{
@@ -704,7 +709,7 @@ pci_slots_clear(void)
{
uint8_t i, j;
last_pci_card = 0;
last_pci_card = last_normal_pci_card = 0;
for (i = 0; i < 32; i++) {
pci_cards[i].id = 0xFF;
@@ -716,9 +721,16 @@ pci_slots_clear(void)
pci_cards[i].read = NULL;
pci_cards[i].write = NULL;
pci_cards[i].priv = NULL;
pci_card_to_slot_mapping[i] = 0xFF;
}
i = 0;
do {
for (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 */
}
@@ -858,9 +870,17 @@ pci_init(int type)
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)
{
pci_card_t *dev = &pci_cards[last_pci_card];
dev->bus = bus;
dev->id = card;
dev->type = type;
dev->irq_routing[0] = inta;
@@ -870,15 +890,17 @@ pci_register_slot(int card, int type, int inta, int intb, int intc, int intd)
dev->read = NULL;
dev->write = NULL;
dev->priv = NULL;
pci_card_to_slot_mapping[card] = last_pci_card;
pci_card_to_slot_mapping[bus][card] = last_pci_card;
pci_log("pci_register_slot(): pci_cards[%i].id = %02X\n", last_pci_card, card);
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;
last_pci_card++;
}
uint8_t
int
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)
{
pci_card_t *dev;
@@ -889,12 +911,12 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv),
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"))));
return 0xff;
return 0xffff;
}
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"))));
return 0xff;
return 0xffff;
}
for (i = 0; i < last_pci_card; i++) {
@@ -908,17 +930,25 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv),
((dev->type == PCI_CARD_IDE) && (add_type == PCI_ADD_IDE)) ||
((dev->type == PCI_CARD_NORTHBRIDGE) && (add_type == PCI_ADD_NORTHBRIDGE)) ||
((dev->type == PCI_CARD_SOUTHBRIDGE) && (add_type == PCI_ADD_SOUTHBRIDGE)) ||
((dev->id == add_type) && (add_type < PCI_ADD_NORTHBRIDGE))) {
((dev->bus == 0) && (dev->id == add_type) && (add_type < PCI_ADD_NORTHBRIDGE))) {
/* Add DEC 21150 PCI bridge if this is the last available NORMAL slot and
the machine supports IRQ steering (the bridge code requires steering). */
if (!(pci_type & PCI_NO_IRQ_STEERING) && (dev->type == PCI_CARD_NORMAL) && (add_type != PCI_ADD_BRIDGE) && (i == last_normal_pci_card)) {
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);
continue;
}
dev->read = read;
dev->write = write;
dev->priv = priv;
pci_log("pci_add_card(): Adding PCI CARD to pci_cards[%i] (slot %02X) [%s]\n", i, 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"))));
return dev->id;
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"))));
return (dev->bus << 5) | dev->id;
}
}
}
pci_log("pci_add_card(): Adding PCI CARD failed (unable to find a suitable PCI slot) [%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"))));
return 0xff;
return 0xffff;
}

View File

@@ -660,7 +660,7 @@ MCHOBJ := machine.o machine_table.o \
m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \
m_at_misc.o
DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o serial.o vpc2007.o \
DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o ibm_5161.o isamem.o isartc.o lpt.o pci_bridge.o postcard.o serial.o vpc2007.o \
smbus.o smbus_piix4.o \
keyboard.o \
keyboard_xt.o keyboard_at.o \