Ported PCI clean-ups from VARCem.
This commit is contained in:
587
src/pci.c
587
src/pci.c
@@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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 the PCI bus.
|
||||||
|
*
|
||||||
|
* Version: @(#)pci.c 1.0.0 2018/10/21
|
||||||
|
*
|
||||||
|
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||||
|
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||||
|
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2016-2018 Miran Grca.
|
||||||
|
* Copyright 2017,2018 Fred N. van Kempen.
|
||||||
|
* Copyright 2008-2018 Sarah Walker.
|
||||||
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -16,39 +36,40 @@
|
|||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
|
||||||
static uint64_t pci_irq_hold[16];
|
typedef struct {
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t id, type;
|
uint8_t id, type;
|
||||||
uint8_t irq_routing[4];
|
uint8_t irq_routing[4];
|
||||||
void (*write) (int func, int addr, uint8_t val, void *priv);
|
|
||||||
uint8_t (*read) (int func, int addr, void *priv);
|
void *priv;
|
||||||
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;
|
} pci_card_t;
|
||||||
|
|
||||||
static pci_card_t pci_cards[32];
|
typedef struct {
|
||||||
static uint8_t last_pci_card = 0;
|
|
||||||
|
|
||||||
static uint8_t pci_card_to_slot_mapping[32];
|
|
||||||
|
|
||||||
static uint8_t elcr[2] = { 0, 0 };
|
|
||||||
|
|
||||||
static uint8_t pci_irqs[4];
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t enabled;
|
uint8_t enabled;
|
||||||
uint8_t irq_line;
|
uint8_t irq_line;
|
||||||
} pci_mirq_t;
|
} pci_mirq_t;
|
||||||
|
|
||||||
|
|
||||||
|
int pci_burst_time,
|
||||||
|
pci_nonburst_time;
|
||||||
|
|
||||||
|
static pci_card_t pci_cards[32];
|
||||||
|
static uint8_t last_pci_card = 0;
|
||||||
|
static uint8_t pci_card_to_slot_mapping[32];
|
||||||
|
static uint8_t elcr[2] = { 0, 0 };
|
||||||
|
static uint8_t pci_irqs[4];
|
||||||
|
static uint64_t pci_irq_hold[16];
|
||||||
static pci_mirq_t pci_mirqs[2];
|
static pci_mirq_t pci_mirqs[2];
|
||||||
|
static int pci_index,
|
||||||
static int pci_index, pci_func, pci_card, pci_bus, pci_enable, pci_key;
|
pci_func,
|
||||||
int pci_burst_time, pci_nonburst_time;
|
pci_card,
|
||||||
|
pci_bus,
|
||||||
|
pci_enable,
|
||||||
|
pci_key;
|
||||||
static int trc_reg = 0;
|
static int trc_reg = 0;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_PCI_LOG
|
#ifdef ENABLE_PCI_LOG
|
||||||
int pci_do_log = ENABLE_PCI_LOG;
|
int pci_do_log = ENABLE_PCI_LOG;
|
||||||
|
|
||||||
@@ -69,7 +90,8 @@ pci_log(const char *fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void pci_cf8_write(uint16_t port, uint32_t val, void *p)
|
static void
|
||||||
|
pci_cf8_write(uint16_t port, uint32_t val, void *priv)
|
||||||
{
|
{
|
||||||
pci_index = val & 0xff;
|
pci_index = val & 0xff;
|
||||||
pci_func = (val >> 8) & 7;
|
pci_func = (val >> 8) & 7;
|
||||||
@@ -78,29 +100,30 @@ static void pci_cf8_write(uint16_t port, uint32_t val, void *p)
|
|||||||
pci_enable = (val >> 31) & 1;
|
pci_enable = (val >> 31) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t pci_cf8_read(uint16_t port, void *p)
|
|
||||||
|
static uint32_t
|
||||||
|
pci_cf8_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
return pci_index | (pci_func << 8) | (pci_card << 11) | (pci_bus << 16) | (pci_enable << 31);
|
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, void *priv)
|
|
||||||
|
static void
|
||||||
|
pci_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
|
|
||||||
switch (port)
|
switch (port) {
|
||||||
{
|
|
||||||
case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
|
case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
|
||||||
if (!pci_enable)
|
if (! pci_enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pci_bus)
|
if (! pci_bus) {
|
||||||
{
|
|
||||||
slot = pci_card_to_slot_mapping[pci_card];
|
slot = pci_card_to_slot_mapping[pci_card];
|
||||||
if (slot != 0xFF)
|
if (slot != 0xff) {
|
||||||
{
|
if (pci_cards[slot].write) {
|
||||||
if (pci_cards[slot].write)
|
pci_log("Reading PCI card on slot %02X (pci_cards[%i])...\n", pci_card, slot);
|
||||||
{
|
|
||||||
/* pci_log("Reading PCI card on slot %02X (pci_cards[%i])...\n", pci_card, slot); */
|
|
||||||
pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv);
|
pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,23 +133,21 @@ static void pci_write(uint16_t port, uint8_t val, void *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t pci_read(uint16_t port, void *priv)
|
|
||||||
|
static uint8_t
|
||||||
|
pci_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
|
|
||||||
switch (port)
|
switch (port) {
|
||||||
{
|
|
||||||
case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
|
case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
|
||||||
if (!pci_enable)
|
if (! pci_enable)
|
||||||
return 0xff;
|
return 0xff;
|
||||||
|
|
||||||
if (!pci_bus)
|
if (! pci_bus) {
|
||||||
{
|
|
||||||
slot = pci_card_to_slot_mapping[pci_card];
|
slot = pci_card_to_slot_mapping[pci_card];
|
||||||
if (slot != 0xFF)
|
if (slot != 0xff) {
|
||||||
{
|
if (pci_cards[slot].read) {
|
||||||
if (pci_cards[slot].read)
|
|
||||||
{
|
|
||||||
return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv);
|
return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,102 +155,145 @@ static uint8_t pci_read(uint16_t port, void *priv)
|
|||||||
|
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elcr_write(uint16_t port, uint8_t val, void *priv)
|
|
||||||
|
static void
|
||||||
|
elcr_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
/* pci_log("ELCR%i: WRITE %02X\n", port & 1, val); */
|
pci_log("ELCR%i: WRITE %02X\n", port & 1, val);
|
||||||
|
|
||||||
if (port & 1)
|
if (port & 1)
|
||||||
val &= 0xDE;
|
val &= 0xde;
|
||||||
else
|
else
|
||||||
val &= 0xF8;
|
val &= 0xf8;
|
||||||
|
|
||||||
elcr[port & 1] = val;
|
elcr[port & 1] = val;
|
||||||
|
|
||||||
pci_log("ELCR %i: %c %c %c %c %c %c %c %c\n", port & 1, (val & 1) ? 'L' : 'E', (val & 2) ? 'L' : 'E', (val & 4) ? 'L' : 'E', (val & 8) ? 'L' : 'E', (val & 0x10) ? 'L' : 'E', (val & 0x20) ? 'L' : 'E', (val & 0x40) ? 'L' : 'E', (val & 0x80) ? 'L' : 'E');
|
pci_log("ELCR %i: %c %c %c %c %c %c %c %c\n",
|
||||||
|
port & 1,
|
||||||
|
(val & 1) ? 'L' : 'E',
|
||||||
|
(val & 2) ? 'L' : 'E',
|
||||||
|
(val & 4) ? 'L' : 'E',
|
||||||
|
(val & 8) ? 'L' : 'E',
|
||||||
|
(val & 0x10) ? 'L' : 'E',
|
||||||
|
(val & 0x20) ? 'L' : 'E',
|
||||||
|
(val & 0x40) ? 'L' : 'E',
|
||||||
|
(val & 0x80) ? 'L' : 'E');
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t elcr_read(uint16_t port, void *priv)
|
|
||||||
|
static uint8_t
|
||||||
|
elcr_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
/* pci_log("ELCR%i: READ %02X\n", port & 1, elcr[port & 1]); */
|
pci_log("ELCR%i: READ %02X\n", port & 1, elcr[port & 1]);
|
||||||
|
|
||||||
return elcr[port & 1];
|
return elcr[port & 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elcr_reset(void)
|
|
||||||
|
static void
|
||||||
|
elcr_reset(void)
|
||||||
{
|
{
|
||||||
pic_reset();
|
pic_reset();
|
||||||
elcr[0] = elcr[1] = 0x00;
|
|
||||||
|
elcr[0] = 0x00;
|
||||||
|
elcr[1] = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pci_type2_write(uint16_t port, uint8_t val, void *priv);
|
static void pci_type2_write(uint16_t port, uint8_t val, void *priv);
|
||||||
static uint8_t pci_type2_read(uint16_t port, void *priv);
|
static uint8_t pci_type2_read(uint16_t port, void *priv);
|
||||||
|
|
||||||
static void pci_type2_write(uint16_t port, uint8_t val, void *priv)
|
|
||||||
|
static void
|
||||||
|
pci_type2_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
|
|
||||||
if (port == 0xcf8) {
|
if (port == 0xcf8) {
|
||||||
pci_func = (val >> 1) & 7;
|
pci_func = (val >> 1) & 7;
|
||||||
|
|
||||||
if (!pci_key && (val & 0xf0))
|
if (!pci_key && (val & 0xf0))
|
||||||
io_sethandler(0xc000, 0x1000, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL);
|
io_sethandler(0xc000, 0x1000,
|
||||||
|
pci_type2_read, NULL, NULL,
|
||||||
|
pci_type2_write, NULL, NULL, priv);
|
||||||
else
|
else
|
||||||
io_removehandler(0xc000, 0x1000, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL);
|
io_removehandler(0xc000, 0x1000,
|
||||||
|
pci_type2_read, NULL, NULL,
|
||||||
|
pci_type2_write, NULL, NULL, priv);
|
||||||
|
|
||||||
pci_key = val & 0xf0;
|
pci_key = val & 0xf0;
|
||||||
} else if (port == 0xcfa)
|
} else if (port == 0xcfa) {
|
||||||
pci_bus = val;
|
pci_bus = val;
|
||||||
else {
|
} else {
|
||||||
pci_card = (port >> 8) & 0xf;
|
pci_card = (port >> 8) & 0xf;
|
||||||
pci_index = port & 0xff;
|
pci_index = port & 0xff;
|
||||||
|
|
||||||
if (!pci_bus) {
|
if (! pci_bus) {
|
||||||
slot = pci_card_to_slot_mapping[pci_card];
|
slot = pci_card_to_slot_mapping[pci_card];
|
||||||
if (slot != 0xFF) {
|
if (slot != 0xff) {
|
||||||
if (pci_cards[slot].write)
|
if (pci_cards[slot].write) {
|
||||||
pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv);
|
pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t pci_type2_read(uint16_t port, void *priv)
|
|
||||||
|
static uint8_t
|
||||||
|
pci_type2_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
|
|
||||||
if (port == 0xcf8)
|
if (port == 0xcf8)
|
||||||
return pci_key | (pci_func << 1);
|
return pci_key | (pci_func << 1);
|
||||||
else if (port == 0xcfa)
|
|
||||||
|
if (port == 0xcfa)
|
||||||
return pci_bus;
|
return pci_bus;
|
||||||
|
|
||||||
pci_card = (port >> 8) & 0xf;
|
pci_card = (port >> 8) & 0xf;
|
||||||
pci_index = port & 0xff;
|
pci_index = port & 0xff;
|
||||||
|
|
||||||
if (!pci_bus) {
|
if (! pci_bus) {
|
||||||
slot = pci_card_to_slot_mapping[pci_card];
|
slot = pci_card_to_slot_mapping[pci_card];
|
||||||
if (slot != 0xFF) {
|
if (slot != 0xff) {
|
||||||
if (pci_cards[slot].read)
|
if (pci_cards[slot].read) {
|
||||||
return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv);
|
return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0xff;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_set_irq_routing(int pci_int, int irq)
|
|
||||||
|
void
|
||||||
|
pci_set_irq_routing(int pci_int, int irq)
|
||||||
{
|
{
|
||||||
pci_irqs[pci_int - 1] = irq;
|
pci_irqs[pci_int - 1] = irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_enable_mirq(int mirq)
|
|
||||||
|
void
|
||||||
|
pci_enable_mirq(int mirq)
|
||||||
{
|
{
|
||||||
pci_mirqs[mirq].enabled = 1;
|
pci_mirqs[mirq].enabled = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_set_mirq_routing(int mirq, int irq)
|
|
||||||
|
void
|
||||||
|
pci_set_mirq_routing(int mirq, int irq)
|
||||||
{
|
{
|
||||||
pci_mirqs[mirq].irq_line = irq;
|
pci_mirqs[mirq].irq_line = irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pci_irq_is_level(int irq)
|
|
||||||
|
int
|
||||||
|
pci_irq_is_level(int irq)
|
||||||
{
|
{
|
||||||
int real_irq = irq & 7;
|
int real_irq = irq & 7;
|
||||||
|
|
||||||
@@ -238,11 +302,13 @@ int pci_irq_is_level(int irq)
|
|||||||
|
|
||||||
if (irq > 7)
|
if (irq > 7)
|
||||||
return !!(elcr[1] & (1 << real_irq));
|
return !!(elcr[1] & (1 << real_irq));
|
||||||
else
|
|
||||||
return !!(elcr[0] & (1 << real_irq));
|
return !!(elcr[0] & (1 << real_irq));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t pci_use_mirq(uint8_t mirq)
|
|
||||||
|
uint8_t
|
||||||
|
pci_use_mirq(uint8_t mirq)
|
||||||
{
|
{
|
||||||
if (!PCI || !pci_mirqs[0].enabled)
|
if (!PCI || !pci_mirqs[0].enabled)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -253,68 +319,56 @@ uint8_t pci_use_mirq(uint8_t mirq)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define pci_mirq_log pci_log
|
|
||||||
|
|
||||||
void pci_set_mirq(uint8_t mirq)
|
void
|
||||||
|
pci_set_mirq(uint8_t mirq)
|
||||||
{
|
{
|
||||||
uint8_t irq_line = 0;
|
uint8_t irq_line = 0;
|
||||||
uint8_t level = 0;
|
uint8_t level = 0;
|
||||||
|
|
||||||
if (!pci_mirqs[mirq].enabled)
|
if (! pci_mirqs[mirq].enabled) {
|
||||||
{
|
pci_log("pci_set_mirq(%02X): MIRQ0 disabled\n", mirq);
|
||||||
pci_mirq_log("pci_set_mirq(%02X): MIRQ0 disabled\n", mirq);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pci_mirqs[mirq].irq_line > 0x0F)
|
if (pci_mirqs[mirq].irq_line > 0x0f) {
|
||||||
{
|
pci_log("pci_set_mirq(%02X): IRQ line is disabled\n", mirq);
|
||||||
pci_mirq_log("pci_set_mirq(%02X): IRQ line is disabled\n", mirq);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_line = pci_mirqs[mirq].irq_line;
|
irq_line = pci_mirqs[mirq].irq_line;
|
||||||
pci_mirq_log("pci_set_mirq(%02X): Using IRQ %i\n", mirq, irq_line);
|
pci_log("pci_set_mirq(%02X): Using IRQ %i\n", mirq, irq_line);
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_irq_is_level(irq_line) && (pci_irq_hold[irq_line] & (1 << (0x1E + mirq))))
|
if (pci_irq_is_level(irq_line) &&
|
||||||
{
|
(pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) {
|
||||||
/* IRQ already held, do nothing. */
|
/* IRQ already held, do nothing. */
|
||||||
pci_mirq_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq);
|
pci_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
pci_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq);
|
||||||
{
|
|
||||||
pci_mirq_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq);
|
|
||||||
}
|
|
||||||
|
|
||||||
level = pci_irq_is_level(irq_line);
|
level = pci_irq_is_level(irq_line);
|
||||||
|
if (!level || !pci_irq_hold[irq_line]) {
|
||||||
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 ");
|
||||||
{
|
|
||||||
pci_mirq_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. */
|
/* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */
|
||||||
picintlevel(1 << irq_line);
|
picintlevel(1 << irq_line);
|
||||||
}
|
} else if (level && pci_irq_hold[irq_line]) {
|
||||||
else if (level && pci_irq_hold[irq_line])
|
pci_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq);
|
||||||
{
|
|
||||||
pci_mirq_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the IRQ is level-triggered, mark that this MIRQ is holding it. */
|
/* If the IRQ is level-triggered, mark that this MIRQ is holding it. */
|
||||||
if (level)
|
if (level) {
|
||||||
{
|
pci_log("pci_set_mirq(%02X): Marking that this card is holding the IRQ\n", mirq);
|
||||||
pci_mirq_log("pci_set_mirq(%02X): Marking that this card is holding the IRQ\n", mirq);
|
pci_irq_hold[irq_line] |= (1ULL << (0x1E + mirq));
|
||||||
pci_irq_hold[irq_line] |= (1 << (0x1E + mirq));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_mirq_log("pci_set_mirq(%02X): Edge-triggered interrupt, not marking\n", mirq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_log("pci_set_mirq(%02X): Edge-triggered interrupt, not marking\n", mirq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_set_irq(uint8_t card, uint8_t pci_int)
|
|
||||||
|
void
|
||||||
|
pci_set_irq(uint8_t card, uint8_t pci_int)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
uint8_t irq_routing = 0;
|
uint8_t irq_routing = 0;
|
||||||
@@ -322,147 +376,113 @@ void pci_set_irq(uint8_t card, uint8_t pci_int)
|
|||||||
uint8_t irq_line = 0;
|
uint8_t irq_line = 0;
|
||||||
uint8_t level = 0;
|
uint8_t level = 0;
|
||||||
|
|
||||||
if (!last_pci_card)
|
if (! last_pci_card) {
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card);
|
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];
|
||||||
|
if (slot == 0xff) {
|
||||||
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);
|
pci_log("pci_set_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot);
|
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])
|
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);
|
pci_log("pci_set_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3;
|
irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3;
|
||||||
pci_log("pci_set_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing);
|
pci_log("pci_set_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing);
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_irqs[irq_routing] > 0x0F)
|
if (pci_irqs[irq_routing] > 0x0f) {
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_line = pci_irqs[irq_routing];
|
irq_line = pci_irqs[irq_routing];
|
||||||
pci_log("pci_set_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
|
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] & (1 << card)))
|
if (pci_irq_is_level(irq_line) && (pci_irq_hold[irq_line] & (1ULL << card))) {
|
||||||
{
|
|
||||||
/* IRQ already held, do nothing. */
|
/* IRQ already held, do nothing. */
|
||||||
pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int);
|
||||||
}
|
|
||||||
|
|
||||||
level = pci_irq_is_level(irq_line);
|
level = pci_irq_is_level(irq_line);
|
||||||
|
if (!level || !pci_irq_hold[irq_line]) {
|
||||||
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 ");
|
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. */
|
/* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */
|
||||||
picintlevel(1 << irq_line);
|
picintlevel(1 << irq_line);
|
||||||
}
|
} else if (level && pci_irq_hold[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);
|
pci_log("pci_set_irq(%02X, %02X): IRQ line already being held\n", card, pci_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the IRQ is level-triggered, mark that this card is holding it. */
|
/* If the IRQ is level-triggered, mark that this card is holding it. */
|
||||||
if (pci_irq_is_level(irq_line))
|
if (pci_irq_is_level(irq_line)) {
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): Marking that this card is holding the IRQ\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): Marking that this card is holding the IRQ\n", card, pci_int);
|
||||||
pci_irq_hold[irq_line] |= (1 << card);
|
pci_irq_hold[irq_line] |= (1ULL << card);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_set_irq(%02X, %02X): Edge-triggered interrupt, not marking\n", card, pci_int);
|
pci_log("pci_set_irq(%02X, %02X): Edge-triggered interrupt, not marking\n", card, pci_int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_clear_mirq(uint8_t mirq)
|
|
||||||
|
void
|
||||||
|
pci_clear_mirq(uint8_t mirq)
|
||||||
{
|
{
|
||||||
uint8_t irq_line = 0;
|
uint8_t irq_line = 0;
|
||||||
uint8_t level = 0;
|
uint8_t level = 0;
|
||||||
|
|
||||||
if (mirq > 1)
|
if (mirq > 1) {
|
||||||
{
|
pci_log("pci_clear_mirq(%02X): Invalid MIRQ\n", mirq);
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): Invalid MIRQ\n", mirq);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pci_mirqs[mirq].enabled)
|
if (! pci_mirqs[mirq].enabled) {
|
||||||
{
|
pci_log("pci_clear_mirq(%02X): MIRQ0 disabled\n", mirq);
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): MIRQ0 disabled\n", mirq);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pci_mirqs[mirq].irq_line > 0x0F)
|
if (pci_mirqs[mirq].irq_line > 0x0f) {
|
||||||
{
|
pci_log("pci_clear_mirq(%02X): IRQ line is disabled\n", mirq);
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): IRQ line is disabled\n", mirq);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_line = pci_mirqs[mirq].irq_line;
|
irq_line = pci_mirqs[mirq].irq_line;
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): Using IRQ %i\n", mirq, irq_line);
|
pci_log("pci_clear_mirq(%02X): Using IRQ %i\n", mirq, irq_line);
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_irq_is_level(irq_line) && !(pci_irq_hold[irq_line] & (1 << (0x1E + mirq))))
|
if (pci_irq_is_level(irq_line) &&
|
||||||
{
|
!(pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) {
|
||||||
/* IRQ not held, do nothing. */
|
/* IRQ not held, do nothing. */
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): MIRQ is not holding the IRQ\n", mirq);
|
pci_log("pci_clear_mirq(%02X): MIRQ is not holding the IRQ\n", mirq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
level = pci_irq_is_level(irq_line);
|
level = pci_irq_is_level(irq_line);
|
||||||
|
if (level) {
|
||||||
if (level)
|
pci_log("pci_clear_mirq(%02X): Releasing this MIRQ's hold on the IRQ\n", mirq);
|
||||||
{
|
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): Releasing this MIRQ's hold on the IRQ\n", mirq);
|
|
||||||
pci_irq_hold[irq_line] &= ~(1 << (0x1E + mirq));
|
pci_irq_hold[irq_line] &= ~(1 << (0x1E + mirq));
|
||||||
|
|
||||||
if (!pci_irq_hold[irq_line])
|
if (! pci_irq_hold[irq_line]) {
|
||||||
{
|
pci_log("pci_clear_mirq(%02X): IRQ no longer held by any card, clearing it\n", mirq);
|
||||||
pci_mirq_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);
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
pci_log("pci_clear_mirq(%02X): Clearing edge-triggered interrupt\n", mirq);
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): IRQ is still being held\n", mirq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_mirq_log("pci_clear_mirq(%02X): Clearing edge-triggered interrupt\n", mirq);
|
|
||||||
picintc(1 << irq_line);
|
picintc(1 << irq_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_clear_irq(uint8_t card, uint8_t pci_int)
|
|
||||||
|
void
|
||||||
|
pci_clear_irq(uint8_t card, uint8_t pci_int)
|
||||||
{
|
{
|
||||||
uint8_t slot = 0;
|
uint8_t slot = 0;
|
||||||
uint8_t irq_routing = 0;
|
uint8_t irq_routing = 0;
|
||||||
@@ -470,89 +490,67 @@ void pci_clear_irq(uint8_t card, uint8_t pci_int)
|
|||||||
uint8_t irq_line = 0;
|
uint8_t irq_line = 0;
|
||||||
uint8_t level = 0;
|
uint8_t level = 0;
|
||||||
|
|
||||||
if (!last_pci_card)
|
if (! last_pci_card) {
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int);
|
pci_log("pci_clear_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): %i PCI slots\n", card, pci_int, last_pci_card);
|
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];
|
||||||
|
if (slot == 0xff) {
|
||||||
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);
|
pci_log("pci_clear_irq(%02X, %02X): Card is not on a PCI slot (how are we even here?!)\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): Card is on PCI slot %02X\n", card, pci_int, slot);
|
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])
|
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);
|
pci_log("pci_clear_irq(%02X, %02X): No IRQ routing for this slot and INT pin combination\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3;
|
irq_routing = (pci_cards[slot].irq_routing[pci_int_index] - PCI_INTA) & 3;
|
||||||
pci_log("pci_clear_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing);
|
pci_log("pci_clear_irq(%02X, %02X): IRQ routing for this slot and INT pin combination: %02X\n", card, pci_int, irq_routing);
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_irqs[irq_routing] > 0x0F)
|
if (pci_irqs[irq_routing] > 0x0f) {
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int);
|
pci_log("pci_clear_irq(%02X, %02X): IRQ line is disabled\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
irq_line = pci_irqs[irq_routing];
|
irq_line = pci_irqs[irq_routing];
|
||||||
pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
|
pci_log("pci_clear_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_irq_is_level(irq_line) && !(pci_irq_hold[irq_line] & (1 << card)))
|
if (pci_irq_is_level(irq_line) &&
|
||||||
{
|
!(pci_irq_hold[irq_line] & (1ULL << card))) {
|
||||||
/* IRQ not held, do nothing. */
|
/* IRQ not held, do nothing. */
|
||||||
pci_log("pci_clear_irq(%02X, %02X): Card is not holding the IRQ\n", card, pci_int);
|
pci_log("pci_clear_irq(%02X, %02X): Card is not holding the IRQ\n", card, pci_int);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
level = pci_irq_is_level(irq_line);
|
level = pci_irq_is_level(irq_line);
|
||||||
|
if (level) {
|
||||||
if (level)
|
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): Releasing this card's hold on the IRQ\n", card, pci_int);
|
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 << card);
|
||||||
|
|
||||||
if (!pci_irq_hold[irq_line])
|
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);
|
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 {
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): IRQ is still being held\n", card, pci_int);
|
pci_log("pci_clear_irq(%02X, %02X): IRQ is still being held\n", card, pci_int);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pci_log("pci_clear_irq(%02X, %02X): Clearing edge-triggered interrupt\n", card, pci_int);
|
pci_log("pci_clear_irq(%02X, %02X): Clearing edge-triggered interrupt\n", card, pci_int);
|
||||||
picintc(1 << irq_line);
|
picintc(1 << irq_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_reset(void)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
void
|
||||||
{
|
pci_reset(void)
|
||||||
if (pci_irq_hold[i])
|
{
|
||||||
{
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if (pci_irq_hold[i]) {
|
||||||
pci_irq_hold[i] = 0;
|
pci_irq_hold[i] = 0;
|
||||||
|
|
||||||
picintc(1 << i);
|
picintc(1 << i);
|
||||||
@@ -562,22 +560,20 @@ void pci_reset(void)
|
|||||||
elcr_reset();
|
elcr_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_slots_clear(void)
|
|
||||||
|
static void
|
||||||
|
pci_slots_clear(void)
|
||||||
{
|
{
|
||||||
uint8_t i = 0;
|
uint8_t i, j;
|
||||||
uint8_t j = 0;
|
|
||||||
|
|
||||||
last_pci_card = 0;
|
last_pci_card = 0;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++) {
|
||||||
{
|
|
||||||
pci_cards[i].id = 0xFF;
|
pci_cards[i].id = 0xFF;
|
||||||
pci_cards[i].type = 0xFF;
|
pci_cards[i].type = 0xFF;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
|
||||||
pci_cards[i].irq_routing[j] = 0;
|
pci_cards[i].irq_routing[j] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
pci_cards[i].read = NULL;
|
pci_cards[i].read = NULL;
|
||||||
pci_cards[i].write = NULL;
|
pci_cards[i].write = NULL;
|
||||||
@@ -587,42 +583,53 @@ static void pci_slots_clear(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t trc_read(uint16_t port, void *priv)
|
|
||||||
|
static uint8_t
|
||||||
|
trc_read(uint16_t port, void *priv)
|
||||||
{
|
{
|
||||||
return trc_reg & 0xfb;
|
return trc_reg & 0xfb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trc_reset(uint8_t val)
|
|
||||||
|
static void
|
||||||
|
trc_reset(uint8_t val)
|
||||||
{
|
{
|
||||||
if (val & 2)
|
if (val & 2) {
|
||||||
{
|
|
||||||
device_reset_all_pci();
|
device_reset_all_pci();
|
||||||
|
|
||||||
port_92_reset();
|
port_92_reset();
|
||||||
|
|
||||||
pci_reset();
|
pci_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
resetx86();
|
resetx86();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trc_write(uint16_t port, uint8_t val, void *priv)
|
|
||||||
|
static void
|
||||||
|
trc_write(uint16_t port, uint8_t val, void *priv)
|
||||||
{
|
{
|
||||||
/* pci_log("TRC Write: %02X\n", val); */
|
pci_log("TRC Write: %02X\n", val);
|
||||||
|
|
||||||
if (!(trc_reg & 4) && (val & 4))
|
if (!(trc_reg & 4) && (val & 4))
|
||||||
{
|
|
||||||
trc_reset(val);
|
trc_reset(val);
|
||||||
}
|
|
||||||
trc_reg = val & 0xfd;
|
trc_reg = val & 0xfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trc_init(void)
|
|
||||||
|
void
|
||||||
|
trc_init(void)
|
||||||
{
|
{
|
||||||
trc_reg = 0;
|
trc_reg = 0;
|
||||||
|
|
||||||
io_sethandler(0x0cf9, 0x0001, trc_read, NULL, NULL, trc_write, NULL, NULL, NULL);
|
io_sethandler(0x0cf9, 0x0001,
|
||||||
|
trc_read, NULL, NULL, trc_write, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_init(int type)
|
|
||||||
|
void
|
||||||
|
pci_init(int type)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
@@ -634,85 +641,89 @@ void pci_init(int type)
|
|||||||
|
|
||||||
trc_init();
|
trc_init();
|
||||||
|
|
||||||
io_sethandler(0x04d0, 0x0002, elcr_read, NULL, NULL, elcr_write, NULL, NULL, NULL);
|
io_sethandler(0x04d0, 0x0002,
|
||||||
|
elcr_read,NULL,NULL, elcr_write,NULL,NULL, NULL);
|
||||||
|
|
||||||
if (type == PCI_CONFIG_TYPE_1)
|
if (type == PCI_CONFIG_TYPE_1) {
|
||||||
{
|
io_sethandler(0x0cf8, 1,
|
||||||
io_sethandler(0x0cf8, 0x0001, NULL, NULL, pci_cf8_read, NULL, NULL, pci_cf8_write, NULL);
|
NULL,NULL,pci_cf8_read, NULL,NULL,pci_cf8_write, NULL);
|
||||||
io_sethandler(0x0cfc, 0x0004, pci_read, NULL, NULL, pci_write, NULL, NULL, NULL);
|
io_sethandler(0x0cfc, 4,
|
||||||
}
|
pci_read,NULL,NULL, pci_write,NULL,NULL, NULL);
|
||||||
else
|
} else {
|
||||||
{
|
io_sethandler(0x0cf8, 1,
|
||||||
io_sethandler(0x0cf8, 0x0001, pci_type2_read, NULL, NULL, pci_type2_write, NULL, NULL, NULL);
|
pci_type2_read,NULL,NULL, pci_type2_write,NULL,NULL, NULL);
|
||||||
io_sethandler(0x0cfa, 0x0001, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c = 0; c < 4; c++)
|
for (c = 0; c < 4; c++)
|
||||||
{
|
|
||||||
pci_irqs[c] = PCI_IRQ_DISABLED;
|
pci_irqs[c] = PCI_IRQ_DISABLED;
|
||||||
}
|
|
||||||
|
|
||||||
for (c = 0; c < 2; c++)
|
for (c = 0; c < 2; c++) {
|
||||||
{
|
|
||||||
pci_mirqs[c].enabled = 0;
|
pci_mirqs[c].enabled = 0;
|
||||||
pci_mirqs[c].irq_line = PCI_IRQ_DISABLED;
|
pci_mirqs[c].irq_line = PCI_IRQ_DISABLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd)
|
|
||||||
|
void
|
||||||
|
pci_register_slot(int card, int type, int inta, int intb, int intc, int intd)
|
||||||
{
|
{
|
||||||
pci_cards[last_pci_card].id = card;
|
pci_card_t *dev = &pci_cards[last_pci_card];
|
||||||
pci_cards[last_pci_card].type = type;
|
|
||||||
pci_cards[last_pci_card].irq_routing[0] = inta;
|
dev->id = card;
|
||||||
pci_cards[last_pci_card].irq_routing[1] = intb;
|
dev->type = type;
|
||||||
pci_cards[last_pci_card].irq_routing[2] = intc;
|
dev->irq_routing[0] = inta;
|
||||||
pci_cards[last_pci_card].irq_routing[3] = intd;
|
dev->irq_routing[1] = intb;
|
||||||
pci_cards[last_pci_card].read = NULL;
|
dev->irq_routing[2] = intc;
|
||||||
pci_cards[last_pci_card].write = NULL;
|
dev->irq_routing[3] = intd;
|
||||||
pci_cards[last_pci_card].priv = NULL;
|
dev->read = NULL;
|
||||||
|
dev->write = NULL;
|
||||||
|
dev->priv = NULL;
|
||||||
pci_card_to_slot_mapping[card] = last_pci_card;
|
pci_card_to_slot_mapping[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].id = %02X\n", last_pci_card, card);
|
||||||
|
|
||||||
last_pci_card++;
|
last_pci_card++;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
uint8_t i = 0;
|
pci_card_t *dev;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
if (add_type < PCI_ADD_NORMAL)
|
if (add_type < PCI_ADD_NORMAL)
|
||||||
{
|
|
||||||
pci_log("pci_add_card(): Adding PCI CARD at specific slot %02X [SPECIFIC]\n", add_type);
|
pci_log("pci_add_card(): Adding PCI CARD at specific slot %02X [SPECIFIC]\n", add_type);
|
||||||
}
|
|
||||||
|
|
||||||
if (!PCI)
|
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" : "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_VIDEO) ? "VIDEO" : "SPECIFIC"));
|
||||||
return 0xFF;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!last_pci_card)
|
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" : "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_VIDEO) ? "VIDEO" : "SPECIFIC"));
|
||||||
return 0xFF;
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < last_pci_card; i++)
|
for (i = 0; i < last_pci_card; i++) {
|
||||||
{
|
dev = &pci_cards[i];
|
||||||
if (!pci_cards[i].read && !pci_cards[i].write)
|
|
||||||
{
|
if (!dev->read && !dev->write) {
|
||||||
if (((pci_cards[i].type == PCI_CARD_NORMAL) && (add_type >= PCI_ADD_NORMAL)) ||
|
if (((dev->type == PCI_CARD_NORMAL) && (add_type >= PCI_ADD_NORMAL)) ||
|
||||||
((pci_cards[i].type == PCI_CARD_ONBOARD) && (add_type == PCI_ADD_VIDEO)) ||
|
((dev->type == PCI_CARD_ONBOARD) && (add_type == PCI_ADD_VIDEO)) ||
|
||||||
((pci_cards[i].id == add_type) && (add_type < PCI_ADD_NORMAL)))
|
((dev->id == add_type) && (add_type < PCI_ADD_NORMAL))) {
|
||||||
{
|
dev->read = read;
|
||||||
pci_cards[i].read = read;
|
dev->write = write;
|
||||||
pci_cards[i].write = write;
|
dev->priv = priv;
|
||||||
pci_cards[i].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" : "SPECIFIC"));
|
||||||
pci_log("pci_add_card(): Adding PCI CARD to pci_cards[%i] (slot %02X) [%s]\n", i, pci_cards[i].id, (add_type == PCI_ADD_NORMAL) ? "NORMAL" : ((add_type == PCI_ADD_VIDEO) ? "VIDEO" : "SPECIFIC"));
|
return dev->id;
|
||||||
return pci_cards[i].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" : "SPECIFIC"));
|
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" : "SPECIFIC"));
|
||||||
return 0xFF;
|
|
||||||
|
return 0xff;
|
||||||
}
|
}
|
||||||
|
|||||||
74
src/pci.h
74
src/pci.h
@@ -1,22 +1,26 @@
|
|||||||
void pci_set_irq_routing(int pci_int, int irq);
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Version: @(#)pci.h 1.0.0 2018/10/21
|
||||||
|
*
|
||||||
|
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||||
|
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||||
|
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||||
|
*
|
||||||
|
* Copyright 2016-2018 Miran Grca.
|
||||||
|
* Copyright 2017,2018 Fred N. van Kempen.
|
||||||
|
* Copyright 2008-2018 Sarah Walker.
|
||||||
|
*/
|
||||||
|
#ifndef EMU_PCI_H
|
||||||
|
# define EMU_PCI_H
|
||||||
|
|
||||||
void pci_enable_mirq(int mirq);
|
|
||||||
void pci_set_mirq_routing(int mirq, int irq);
|
|
||||||
|
|
||||||
uint8_t pci_use_mirq(uint8_t mirq);
|
|
||||||
|
|
||||||
int pci_irq_is_level(int irq);
|
|
||||||
|
|
||||||
void pci_set_mirq(uint8_t mirq);
|
|
||||||
void pci_set_irq(uint8_t card, uint8_t pci_int);
|
|
||||||
void pci_clear_mirq(uint8_t mirq);
|
|
||||||
void pci_clear_irq(uint8_t card, uint8_t pci_int);
|
|
||||||
|
|
||||||
void pci_reset(void);
|
|
||||||
void pci_init(int type);
|
|
||||||
void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd);
|
|
||||||
void pci_close(void);
|
|
||||||
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);
|
|
||||||
|
|
||||||
#define PCI_REG_COMMAND 0x04
|
#define PCI_REG_COMMAND 0x04
|
||||||
|
|
||||||
@@ -36,8 +40,7 @@ uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void
|
|||||||
|
|
||||||
#define PCI_IRQ_DISABLED -1
|
#define PCI_IRQ_DISABLED -1
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
PCI_CARD_NORMAL = 0,
|
PCI_CARD_NORMAL = 0,
|
||||||
PCI_CARD_ONBOARD,
|
PCI_CARD_ONBOARD,
|
||||||
PCI_CARD_SPECIAL
|
PCI_CARD_SPECIAL
|
||||||
@@ -47,11 +50,38 @@ enum
|
|||||||
#define PCI_ADD_NORMAL 0x80
|
#define PCI_ADD_NORMAL 0x80
|
||||||
#define PCI_ADD_VIDEO 0x81
|
#define PCI_ADD_VIDEO 0x81
|
||||||
|
|
||||||
extern int pci_burst_time, pci_nonburst_time;
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint8_t addr_regs[4];
|
uint8_t addr_regs[4];
|
||||||
} bar_t;
|
} bar_t;
|
||||||
|
|
||||||
|
|
||||||
|
extern int pci_burst_time,
|
||||||
|
pci_nonburst_time;
|
||||||
|
|
||||||
|
|
||||||
|
extern void pci_set_irq_routing(int pci_int, int irq);
|
||||||
|
|
||||||
|
extern void pci_enable_mirq(int mirq);
|
||||||
|
extern void pci_set_mirq_routing(int mirq, int irq);
|
||||||
|
|
||||||
|
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);
|
||||||
|
extern void pci_set_irq(uint8_t card, uint8_t pci_int);
|
||||||
|
extern void pci_clear_mirq(uint8_t mirq);
|
||||||
|
extern void pci_clear_irq(uint8_t 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_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 void trc_init(void);
|
extern void trc_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /*EMU_PCI_H*/
|
||||||
|
|||||||
Reference in New Issue
Block a user