Added support for multiple PCI host controllers and allow multiple PCI domains (needed for PPC).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16086 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,27 +1,13 @@
|
||||
#include "pci_priv.h"
|
||||
#include "pci_controller.h"
|
||||
|
||||
int gMaxBusDevices;
|
||||
|
||||
status_t
|
||||
pci_config_init()
|
||||
pci_controller_init(void)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
pci_ram_address(const void *physical_address_in_system_memory)
|
||||
{
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#include "pci_priv.h"
|
||||
|
||||
status_t
|
||||
pci_irq_init(void)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
pci_read_irq(uint8 bus, uint8 device, uint8 function, uint8 pin)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_write_irq(uint8 bus, uint8 device, uint8 function, uint8 pin, uint8 irq)
|
||||
{
|
||||
}
|
||||
@@ -3,7 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers pci arch x86 ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||
|
||||
KernelStaticLibrary pci_arch_bus_manager :
|
||||
bios.c
|
||||
pci_bios.c
|
||||
pci_controller.c
|
||||
pci_io.c
|
||||
pci_irq.c
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "pci_priv.h"
|
||||
#include "bios.h"
|
||||
|
||||
void
|
||||
pci_bios_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
pci_bios_available(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_bios_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_bios_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
void pci_bios_init(void);
|
||||
|
||||
bool pci_bios_available(void);
|
||||
|
||||
uint32 pci_bios_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
void pci_bios_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "pci_priv.h"
|
||||
#include "pci_bios.h"
|
||||
|
||||
status_t
|
||||
pci_bios_init(void)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pci_bios_read_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pci_bios_write_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pci_bios_get_max_bus_devices(void *cookie, int32 *count)
|
||||
{
|
||||
*count = 32;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef __PCI_X86_BIOS_H
|
||||
#define __PCI_X86_BIOS_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
status_t pci_bios_init(void);
|
||||
|
||||
status_t pci_bios_read_config(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value);
|
||||
|
||||
status_t pci_bios_write_config(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value);
|
||||
|
||||
status_t pci_bios_get_max_bus_devices(void *cookie, int32 *count);
|
||||
|
||||
#endif
|
||||
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include "pci_irq.h"
|
||||
#include "pci_bios.h"
|
||||
#include "pci_priv.h"
|
||||
#include "bios.h"
|
||||
#include "pci_controller.h"
|
||||
#include "arch_cpu.h"
|
||||
|
||||
static uint32 (*gReadConfigFunc)(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
static void (*gWriteConfigFunc)(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
|
||||
int gMaxBusDevices;
|
||||
|
||||
status_t detect_config_mechanism(void);
|
||||
bool pci_config_access_ok(void);
|
||||
uint32 pci_mech1_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
void pci_mech1_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
uint32 pci_mech2_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
void pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
|
||||
|
||||
#define PCI_MECH1_REQ_PORT 0xCF8
|
||||
#define PCI_MECH1_DATA_PORT 0xCFC
|
||||
#define PCI_MECH1_REQ_DATA(bus, device, func, offset) \
|
||||
@@ -26,203 +21,125 @@ void pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offse
|
||||
#define PCI_MECH2_CONFIG_PORT(dev, offset) \
|
||||
(uint16)(0xC00 | (dev << 8) | offset)
|
||||
|
||||
#define PCI_LOCK_CONFIG(cpu_status) \
|
||||
{ \
|
||||
cpu_status = disable_interrupts(); \
|
||||
acquire_spinlock(&sConfigLock); \
|
||||
}
|
||||
|
||||
status_t
|
||||
pci_config_init(void)
|
||||
#define PCI_UNLOCK_CONFIG(cpu_status) \
|
||||
{ \
|
||||
release_spinlock(&sConfigLock); \
|
||||
restore_interrupts(cpu_status); \
|
||||
}
|
||||
|
||||
spinlock sConfigLock = 0;
|
||||
|
||||
static status_t
|
||||
pci_mech1_read_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value)
|
||||
{
|
||||
pci_bios_init();
|
||||
cpu_status cpu;
|
||||
status_t status = B_OK;
|
||||
|
||||
if (B_OK != detect_config_mechanism()) {
|
||||
dprintf("PCI: failed to detect configuration mechanism\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
detect_config_mechanism(void)
|
||||
{
|
||||
// PCI configuration mechanism 1 is the preferred one.
|
||||
// If it doesn't work, try mechanism 2.
|
||||
// Finally, try to fallback to PCI BIOS
|
||||
|
||||
if (1) {
|
||||
// check for mechanism 1
|
||||
out32(0x80000000, PCI_MECH1_REQ_PORT);
|
||||
if (0x80000000 == in32(PCI_MECH1_REQ_PORT)) {
|
||||
dprintf("PCI: mechanism 1 found\n");
|
||||
gMaxBusDevices = 32;
|
||||
gReadConfigFunc = pci_mech1_read_config;
|
||||
gWriteConfigFunc = pci_mech1_write_config;
|
||||
if (pci_config_access_ok()) {
|
||||
dprintf("PCI: using mechanism 1\n");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (1) {
|
||||
// check for mechanism 2
|
||||
out8(0x00, 0xCFB);
|
||||
out8(0x00, 0xCF8);
|
||||
out8(0x00, 0xCFA);
|
||||
if (in8(0xCF8) == 0x00 && in8(0xCFA) == 0x00) {
|
||||
dprintf("PCI: mechanism 2 found\n");
|
||||
gMaxBusDevices = 16;
|
||||
gReadConfigFunc = pci_mech2_read_config;
|
||||
gWriteConfigFunc = pci_mech2_write_config;
|
||||
if (pci_config_access_ok()) {
|
||||
dprintf("PCI: using mechanism 2\n");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (1) {
|
||||
// check for PCI BIOS
|
||||
if (pci_bios_available()) {
|
||||
gReadConfigFunc = pci_bios_read_config;
|
||||
gWriteConfigFunc = pci_bios_write_config;
|
||||
gMaxBusDevices = 32;
|
||||
if (pci_config_access_ok()) {
|
||||
dprintf("PCI: using PCI BIOS\n");
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("PCI: no configuration mechanism found\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
pci_config_access_ok(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
{
|
||||
return gReadConfigFunc(bus, device, function, offset, size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
gWriteConfigFunc(bus, device, function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_mech1_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
{
|
||||
uint32 result;
|
||||
cpu_status status;
|
||||
if (device > 31 || function > 7 || (size != 1 && size != 2 && size != 4)
|
||||
|| (size == 2 && (offset & 3) == 3) || (size == 4 && (offset & 3) != 0)) {
|
||||
dprintf("PCI: mech1 can't read config for bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
bus, device, function, offset, size);
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
PCI_LOCK_CONFIG(status);
|
||||
PCI_LOCK_CONFIG(cpu);
|
||||
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
||||
switch (size) {
|
||||
case 1:
|
||||
result = in8(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
*value = in8(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
break;
|
||||
case 2:
|
||||
result = in16(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
*value = in16(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
break;
|
||||
case 4:
|
||||
result = in32(PCI_MECH1_DATA_PORT);
|
||||
*value = in32(PCI_MECH1_DATA_PORT);
|
||||
break;
|
||||
default:
|
||||
result = 0xffffffff;
|
||||
status = B_ERROR;
|
||||
break;
|
||||
}
|
||||
PCI_UNLOCK_CONFIG(status);
|
||||
return result;
|
||||
PCI_UNLOCK_CONFIG(cpu);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_mech1_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
static status_t
|
||||
pci_mech1_write_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
cpu_status status;
|
||||
if (device > 31 || function > 7 || (size != 1 && size != 2 && size != 4)
|
||||
|| (size == 2 && (offset & 3) == 3) || (size == 4 && (offset & 3) != 0)) {
|
||||
dprintf("PCI: mech1 can't write config for bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
bus, device, function, offset, size);
|
||||
return;
|
||||
}
|
||||
cpu_status cpu;
|
||||
status_t status = B_OK;
|
||||
|
||||
PCI_LOCK_CONFIG(status);
|
||||
PCI_LOCK_CONFIG(cpu);
|
||||
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
||||
switch (size) {
|
||||
case 1:
|
||||
out8(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
break;
|
||||
break;
|
||||
case 2:
|
||||
out16(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
||||
break;
|
||||
case 4:
|
||||
out32(value, PCI_MECH1_DATA_PORT);
|
||||
break;
|
||||
default:
|
||||
status = B_ERROR;
|
||||
break;
|
||||
}
|
||||
PCI_UNLOCK_CONFIG(status);
|
||||
PCI_UNLOCK_CONFIG(cpu);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_mech2_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
static status_t
|
||||
pci_mech1_get_max_bus_devices(void *cookie, int32 *count)
|
||||
{
|
||||
uint32 result;
|
||||
cpu_status status;
|
||||
if (device > 15 || function > 7 || (size != 1 && size != 2 && size != 4)) {
|
||||
dprintf("PCI: mech2 can't read config for bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
bus, device, function, offset, size);
|
||||
return 0xffffffff;
|
||||
}
|
||||
*count = 32;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_mech2_read_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value)
|
||||
{
|
||||
cpu_status cpu;
|
||||
status_t status = B_OK;
|
||||
|
||||
PCI_LOCK_CONFIG(status);
|
||||
PCI_LOCK_CONFIG(cpu);
|
||||
out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT);
|
||||
out8(bus, PCI_MECH2_FORWARD_PORT);
|
||||
switch (size) {
|
||||
case 1:
|
||||
result = in8(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
*value = in8(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
break;
|
||||
case 2:
|
||||
result = in16(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
*value = in16(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
break;
|
||||
case 4:
|
||||
result = in32(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
*value = in32(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
break;
|
||||
default:
|
||||
result = 0xffffffff;
|
||||
status = B_ERROR;
|
||||
break;
|
||||
}
|
||||
out8(0, PCI_MECH2_ENABLE_PORT);
|
||||
PCI_UNLOCK_CONFIG(status);
|
||||
return result;
|
||||
PCI_UNLOCK_CONFIG(cpu);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
static status_t
|
||||
pci_mech2_write_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
cpu_status status;
|
||||
if (device > 15 || function > 7 || (size != 1 && size != 2 && size != 4)) {
|
||||
dprintf("PCI: mech2 can't write config for bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
bus, device, function, offset, size);
|
||||
return;
|
||||
}
|
||||
cpu_status cpu;
|
||||
status_t status = B_OK;
|
||||
|
||||
PCI_LOCK_CONFIG(status);
|
||||
PCI_LOCK_CONFIG(cpu);
|
||||
out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT);
|
||||
out8(bus, PCI_MECH2_FORWARD_PORT);
|
||||
switch (size) {
|
||||
@@ -235,9 +152,22 @@ pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, ui
|
||||
case 4:
|
||||
out32(value, PCI_MECH2_CONFIG_PORT(device, offset));
|
||||
break;
|
||||
default:
|
||||
status = B_ERROR;
|
||||
break;
|
||||
}
|
||||
out8(0, PCI_MECH2_ENABLE_PORT);
|
||||
PCI_UNLOCK_CONFIG(status);
|
||||
PCI_UNLOCK_CONFIG(cpu);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_mech2_get_max_bus_devices(void *cookie, int32 *count)
|
||||
{
|
||||
*count = 16;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,3 +176,82 @@ pci_ram_address(const void *physical_address_in_system_memory)
|
||||
{
|
||||
return (void *)physical_address_in_system_memory;
|
||||
}
|
||||
|
||||
|
||||
pci_controller pci_controller_x86_mech1 =
|
||||
{
|
||||
.read_pci_config = pci_mech1_read_config,
|
||||
.write_pci_config = pci_mech1_write_config,
|
||||
.get_max_bus_devices = pci_mech1_get_max_bus_devices,
|
||||
.read_pci_irq = pci_x86_irq_read,
|
||||
.write_pci_irq = pci_x86_irq_write,
|
||||
};
|
||||
|
||||
pci_controller pci_controller_x86_mech2 =
|
||||
{
|
||||
.read_pci_config = pci_mech2_read_config,
|
||||
.write_pci_config = pci_mech2_write_config,
|
||||
.get_max_bus_devices = pci_mech2_get_max_bus_devices,
|
||||
.read_pci_irq = pci_x86_irq_read,
|
||||
.write_pci_irq = pci_x86_irq_write,
|
||||
};
|
||||
|
||||
pci_controller pci_controller_x86_bios =
|
||||
{
|
||||
.read_pci_config = pci_bios_read_config,
|
||||
.write_pci_config = pci_bios_write_config,
|
||||
.get_max_bus_devices = pci_bios_get_max_bus_devices,
|
||||
.read_pci_irq = pci_x86_irq_read,
|
||||
.write_pci_irq = pci_x86_irq_write,
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
pci_controller_init(void)
|
||||
{
|
||||
bool search_mech1 = true;
|
||||
bool search_mech2 = true;
|
||||
bool search_bios = true;
|
||||
status_t status;
|
||||
|
||||
status = pci_x86_irq_init();
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
// PCI configuration mechanism 1 is the preferred one.
|
||||
// If it doesn't work, try mechanism 2.
|
||||
// Finally, try to fallback to PCI BIOS
|
||||
|
||||
if (search_mech1) {
|
||||
// check for mechanism 1
|
||||
out32(0x80000000, PCI_MECH1_REQ_PORT);
|
||||
if (0x80000000 == in32(PCI_MECH1_REQ_PORT)) {
|
||||
dprintf("PCI: mechanism 1 controller found\n");
|
||||
return pci_controller_add(&pci_controller_x86_mech1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (search_mech2) {
|
||||
// check for mechanism 2
|
||||
out8(0x00, 0xCFB);
|
||||
out8(0x00, 0xCF8);
|
||||
out8(0x00, 0xCFA);
|
||||
if (in8(0xCF8) == 0x00 && in8(0xCFA) == 0x00) {
|
||||
dprintf("PCI: mechanism 2 controller found\n");
|
||||
return pci_controller_add(&pci_controller_x86_mech2, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (search_bios) {
|
||||
// check for PCI BIOS
|
||||
if (pci_bios_init() == B_OK) {
|
||||
dprintf("PCI: BIOS support found\n");
|
||||
return pci_controller_add(&pci_controller_x86_bios, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("PCI: no configuration mechanism found\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
#include "pci_priv.h"
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include "pci_irq.h"
|
||||
|
||||
status_t
|
||||
pci_irq_init(void)
|
||||
|
||||
status_t
|
||||
pci_x86_irq_init(void)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
pci_x86_irq_read(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8 *irq)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
pci_read_irq(uint8 bus, uint8 device, uint8 function, uint8 pin)
|
||||
status_t
|
||||
pci_x86_irq_write(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8 irq)
|
||||
{
|
||||
return 0;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_write_irq(uint8 bus, uint8 device, uint8 function, uint8 pin, uint8 irq)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef __PCI_X86_IRQ_H
|
||||
#define __PCI_X86_IRQ_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
status_t pci_x86_irq_init(void);
|
||||
|
||||
status_t pci_x86_irq_read(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8 *irq);
|
||||
|
||||
status_t pci_x86_irq_write(void *cookie,
|
||||
uint8 bus, uint8 device, uint8 function,
|
||||
uint8 pin, uint8 irq);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
@@ -14,32 +15,76 @@
|
||||
#include "pci_priv.h"
|
||||
#include "pci.h"
|
||||
|
||||
|
||||
bool gIrqRouterAvailable = false;
|
||||
spinlock gConfigLock = 0;
|
||||
|
||||
static PCI *sPCI;
|
||||
|
||||
// #pragma mark bus manager exports
|
||||
|
||||
|
||||
status_t
|
||||
pci_controller_add(pci_controller *controller, void *cookie)
|
||||
{
|
||||
return sPCI->AddController(controller, cookie);
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
pci_get_nth_pci_info(long index, pci_info *outInfo)
|
||||
{
|
||||
return sPCI->GetNthPciInfo(index, outInfo);
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
||||
{
|
||||
uint8 bus;
|
||||
int domain;
|
||||
uint32 value;
|
||||
|
||||
if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK)
|
||||
return 0xffffffff;
|
||||
|
||||
if (sPCI->ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK)
|
||||
return 0xffffffff;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
uint8 bus;
|
||||
int domain;
|
||||
|
||||
if (sPCI->GetVirtBus(virt_bus, &domain, &bus) != B_OK)
|
||||
return;
|
||||
|
||||
sPCI->WritePciConfig(domain, bus, device, function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark bus manager init/uninit
|
||||
|
||||
status_t
|
||||
pci_init(void)
|
||||
{
|
||||
sPCI = new PCI;
|
||||
|
||||
if (pci_io_init() != B_OK) {
|
||||
TRACE(("PCI: pci_io_init failed\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (pci_config_init() != B_OK) {
|
||||
TRACE(("PCI: pci_config_init failed\n"));
|
||||
if (pci_controller_init() != B_OK) {
|
||||
TRACE(("PCI: pci_controller_init failed\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (pci_irq_init() != B_OK)
|
||||
TRACE(("PCI: IRQ router not available\n"));
|
||||
else
|
||||
gIrqRouterAvailable = true;
|
||||
|
||||
sPCI = new PCI;
|
||||
sPCI->InitDomainData();
|
||||
sPCI->InitBus();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -52,22 +97,35 @@ pci_uninit(void)
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
pci_get_nth_pci_info(long index, pci_info *outInfo)
|
||||
// #pragma mark PCI class
|
||||
|
||||
PCI::PCI()
|
||||
: fRootBus(0)
|
||||
, fDomainCount(0)
|
||||
{
|
||||
return sPCI->GetNthPciInfo(index, outInfo);
|
||||
}
|
||||
|
||||
|
||||
PCI::PCI()
|
||||
void
|
||||
PCI::InitBus()
|
||||
{
|
||||
fRootBus.parent = 0;
|
||||
fRootBus.bus = 0;
|
||||
fRootBus.child = 0;
|
||||
PCIBus **ppnext = &fRootBus;
|
||||
|
||||
DiscoverBus(&fRootBus);
|
||||
|
||||
RefreshDeviceInfo(&fRootBus);
|
||||
for (int i = 0; i < fDomainCount; i++) {
|
||||
PCIBus *bus = new PCIBus;
|
||||
bus->next = NULL;
|
||||
bus->parent = NULL;
|
||||
bus->child = NULL;
|
||||
bus->domain = i;
|
||||
bus->bus = 0;
|
||||
*ppnext = bus;
|
||||
ppnext = &bus->next;
|
||||
}
|
||||
|
||||
if (fRootBus) {
|
||||
DiscoverBus(fRootBus);
|
||||
RefreshDeviceInfo(fRootBus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,11 +134,78 @@ PCI::~PCI()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PCI::AddVirtBus(int domain, uint8 bus, uint8 *virt_bus)
|
||||
{
|
||||
if (MAX_PCI_DOMAINS != 8)
|
||||
panic("PCI::AddVirtBus only 8 controllers supported");
|
||||
|
||||
if (domain > 7)
|
||||
panic("PCI::AddVirtBus domain %d too large");
|
||||
|
||||
if (bus > 31)
|
||||
panic("PCI::AddVirtBus bus %d too large");
|
||||
|
||||
*virt_bus = (domain << 5) | bus;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PCI::GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus)
|
||||
{
|
||||
// XXX if you modify this, also change pci_info.cpp print_info_basic() !!
|
||||
*domain = virt_bus >> 5;
|
||||
*bus = virt_bus & 0x1f;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
PCI::AddController(pci_controller *controller, void *controller_cookie)
|
||||
{
|
||||
if (fDomainCount == MAX_PCI_DOMAINS)
|
||||
return B_ERROR;
|
||||
|
||||
fDomainData[fDomainCount].controller = controller;
|
||||
fDomainData[fDomainCount].controller_cookie = controller_cookie;
|
||||
|
||||
// initialized later to avoid call back into controller at this point
|
||||
fDomainData[fDomainCount].max_bus_devices = -1;
|
||||
|
||||
fDomainCount++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PCI::InitDomainData()
|
||||
{
|
||||
for (int i = 0; i < fDomainCount; i++) {
|
||||
int32 count;
|
||||
status_t status;
|
||||
|
||||
status = (*fDomainData[i].controller->get_max_bus_devices)(fDomainData[i].controller_cookie, &count);
|
||||
fDomainData[i].max_bus_devices = (status == B_OK) ? count : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
domain_data *
|
||||
PCI::GetDomainData(int domain)
|
||||
{
|
||||
if (domain < 0 || domain >= fDomainCount)
|
||||
return NULL;
|
||||
|
||||
return &fDomainData[domain];
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PCI::GetNthPciInfo(long index, pci_info *outInfo)
|
||||
{
|
||||
long curindex = 0;
|
||||
return GetNthPciInfo(&fRootBus, &curindex, index, outInfo);
|
||||
if (!fRootBus)
|
||||
return B_ERROR;
|
||||
return GetNthPciInfo(fRootBus, &curindex, index, outInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +224,10 @@ PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInf
|
||||
return B_OK;
|
||||
dev = dev->next;
|
||||
}
|
||||
|
||||
if (bus->next)
|
||||
return GetNthPciInfo(bus->next, curindex, wantindex, outInfo);
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -106,49 +235,56 @@ PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInf
|
||||
void
|
||||
PCI::DiscoverBus(PCIBus *bus)
|
||||
{
|
||||
TRACE(("PCI: DiscoverBus, bus %u\n", bus->bus));
|
||||
TRACE(("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus));
|
||||
|
||||
int max_bus_devices = GetDomainData(bus->domain)->max_bus_devices;
|
||||
|
||||
for (int dev = 0; dev < gMaxBusDevices; dev++) {
|
||||
uint16 vendor_id = pci_read_config(bus->bus, dev, 0, PCI_vendor_id, 2);
|
||||
for (int dev = 0; dev < max_bus_devices; dev++) {
|
||||
uint16 vendor_id = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_vendor_id, 2);
|
||||
if (vendor_id == 0xffff)
|
||||
continue;
|
||||
|
||||
uint8 type = pci_read_config(bus->bus, dev, 0, PCI_header_type, 1);
|
||||
uint8 type = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_header_type, 1);
|
||||
int nfunc = (type & PCI_multifunction) ? 8 : 1;
|
||||
for (int func = 0; func < nfunc; func++)
|
||||
DiscoverDevice(bus, dev, func);
|
||||
}
|
||||
|
||||
if (bus->next)
|
||||
DiscoverBus(bus->next);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func)
|
||||
{
|
||||
TRACE(("PCI: DiscoverDevice, bus %u, dev %u, func %u\n", bus->bus, dev, func));
|
||||
TRACE(("PCI: DiscoverDevice, domain %u, bus %u, dev %u, func %u\n", bus->domain, bus->bus, dev, func));
|
||||
|
||||
uint16 device_id = pci_read_config(bus->bus, dev, func, PCI_device_id, 2);
|
||||
uint16 device_id = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_device_id, 2);
|
||||
if (device_id == 0xffff)
|
||||
return;
|
||||
|
||||
PCIDev *newdev = CreateDevice(bus, dev, func);
|
||||
|
||||
uint8 base_class = pci_read_config(bus->bus, dev, func, PCI_class_base, 1);
|
||||
uint8 sub_class = pci_read_config(bus->bus, dev, func, PCI_class_sub, 1);
|
||||
uint8 base_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_base, 1);
|
||||
uint8 sub_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_sub, 1);
|
||||
if (base_class == PCI_bridge && sub_class == PCI_pci) {
|
||||
uint8 secondary_bus = pci_read_config(bus->bus, dev, func, PCI_secondary_bus, 1);
|
||||
PCIBus *newbus = CreateBus(newdev, secondary_bus);
|
||||
uint8 secondary_bus = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_secondary_bus, 1);
|
||||
PCIBus *newbus = CreateBus(newdev, bus->domain, secondary_bus);
|
||||
DiscoverBus(newbus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PCIBus *
|
||||
PCI::CreateBus(PCIDev *parent, uint8 bus)
|
||||
PCI::CreateBus(PCIDev *parent, int domain, uint8 bus)
|
||||
{
|
||||
PCIBus *newbus = new PCIBus;
|
||||
newbus->next = NULL;
|
||||
newbus->parent = parent;
|
||||
newbus->child = NULL;
|
||||
newbus->domain = domain;
|
||||
newbus->bus = bus;
|
||||
newbus->child = 0;
|
||||
|
||||
// append
|
||||
parent->child = newbus;
|
||||
@@ -160,12 +296,13 @@ PCI::CreateBus(PCIDev *parent, uint8 bus)
|
||||
PCIDev *
|
||||
PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func)
|
||||
{
|
||||
TRACE(("PCI: CreateDevice, bus %u, dev %u, func %u:\n", parent->bus, dev, func));
|
||||
TRACE(("PCI: CreateDevice, domain %u, bus %u, dev %u, func %u:\n", parent->domain, parent->bus, dev, func));
|
||||
|
||||
PCIDev *newdev = new PCIDev;
|
||||
newdev->next = 0;
|
||||
newdev->next = NULL;
|
||||
newdev->parent = parent;
|
||||
newdev->child = 0;
|
||||
newdev->child = NULL;
|
||||
newdev->domain = parent->domain;
|
||||
newdev->bus = parent->bus;
|
||||
newdev->dev = dev;
|
||||
newdev->func = func;
|
||||
@@ -205,10 +342,10 @@ PCI::BarSize(uint32 bits, uint32 mask)
|
||||
void
|
||||
PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
|
||||
{
|
||||
uint32 oldvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff);
|
||||
uint32 newvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||
uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff);
|
||||
uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||
|
||||
*address = oldvalue & PCI_address_memory_32_mask;
|
||||
if (size)
|
||||
@@ -221,10 +358,10 @@ PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8
|
||||
void
|
||||
PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
|
||||
{
|
||||
uint32 oldvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0
|
||||
uint32 newvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||
uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0
|
||||
uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||
|
||||
*address = oldvalue & PCI_rom_address_mask;
|
||||
if (size)
|
||||
@@ -237,20 +374,27 @@ PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uin
|
||||
void
|
||||
PCI::ReadPciBasicInfo(PCIDev *dev)
|
||||
{
|
||||
dev->info.vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_vendor_id, 2);
|
||||
dev->info.device_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_device_id, 2);
|
||||
dev->info.bus = dev->bus;
|
||||
uint8 virt_bus;
|
||||
|
||||
if (AddVirtBus(dev->domain, dev->bus, &virt_bus) != B_OK) {
|
||||
dprintf("PCI: AddVirtBus failed, domain %u, bus %u\n", dev->domain, dev->bus);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->info.vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_vendor_id, 2);
|
||||
dev->info.device_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_device_id, 2);
|
||||
dev->info.bus = virt_bus;
|
||||
dev->info.device = dev->dev;
|
||||
dev->info.function = dev->func;
|
||||
dev->info.revision = pci_read_config(dev->bus, dev->dev, dev->func, PCI_revision, 1);
|
||||
dev->info.class_api = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_api, 1);
|
||||
dev->info.class_sub = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_sub, 1);
|
||||
dev->info.class_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_base, 1);
|
||||
dev->info.line_size = pci_read_config(dev->bus, dev->dev, dev->func, PCI_line_size, 1);
|
||||
dev->info.latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_latency, 1);
|
||||
dev->info.revision = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_revision, 1);
|
||||
dev->info.class_api = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_api, 1);
|
||||
dev->info.class_sub = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_sub, 1);
|
||||
dev->info.class_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_class_base, 1);
|
||||
dev->info.line_size = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_line_size, 1);
|
||||
dev->info.latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_latency, 1);
|
||||
// BeOS does not mask off the multifunction bit, developer must use (header_type & PCI_header_type_mask)
|
||||
dev->info.header_type = pci_read_config(dev->bus, dev->dev, dev->func, PCI_header_type, 1);
|
||||
dev->info.bist = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bist, 1);
|
||||
dev->info.header_type = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_header_type, 1);
|
||||
dev->info.bist = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bist, 1);
|
||||
dev->info.reserved = 0;
|
||||
}
|
||||
|
||||
@@ -262,8 +406,8 @@ PCI::ReadPciHeaderInfo(PCIDev *dev)
|
||||
case PCI_header_type_generic:
|
||||
{
|
||||
// disable PCI device address decoding (io and memory) while BARs are modified
|
||||
uint16 pcicmd = pci_read_config(dev->bus, dev->dev, dev->func, PCI_command, 2);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
|
||||
uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
|
||||
|
||||
// get BAR size infos
|
||||
GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, &dev->info.u.h0.rom_size);
|
||||
@@ -275,28 +419,28 @@ PCI::ReadPciHeaderInfo(PCIDev *dev)
|
||||
}
|
||||
|
||||
// restore PCI device address decoding
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
|
||||
|
||||
dev->info.u.h0.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h0.rom_base_pci);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h0.base_registers_pci[i]);
|
||||
}
|
||||
|
||||
dev->info.u.h0.cardbus_cis = pci_read_config(dev->bus, dev->dev, dev->func, PCI_cardbus_cis, 4);
|
||||
dev->info.u.h0.subsystem_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subsystem_id, 2);
|
||||
dev->info.u.h0.subsystem_vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subsystem_vendor_id, 2);
|
||||
dev->info.u.h0.interrupt_line = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
|
||||
dev->info.u.h0.interrupt_pin = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
|
||||
dev->info.u.h0.min_grant = pci_read_config(dev->bus, dev->dev, dev->func, PCI_min_grant, 1);
|
||||
dev->info.u.h0.max_latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_max_latency, 1);
|
||||
dev->info.u.h0.cardbus_cis = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_cardbus_cis, 4);
|
||||
dev->info.u.h0.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_id, 2);
|
||||
dev->info.u.h0.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subsystem_vendor_id, 2);
|
||||
dev->info.u.h0.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
|
||||
dev->info.u.h0.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
|
||||
dev->info.u.h0.min_grant = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_min_grant, 1);
|
||||
dev->info.u.h0.max_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_max_latency, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case PCI_header_type_PCI_to_PCI_bridge:
|
||||
{
|
||||
// disable PCI device address decoding (io and memory) while BARs are modified
|
||||
uint16 pcicmd = pci_read_config(dev->bus, dev->dev, dev->func, PCI_command, 2);
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
|
||||
uint16 pcicmd = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
|
||||
|
||||
GetRomBarInfo(dev, PCI_bridge_rom_base, &dev->info.u.h1.rom_base_pci);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@@ -307,56 +451,56 @@ PCI::ReadPciHeaderInfo(PCIDev *dev)
|
||||
}
|
||||
|
||||
// restore PCI device address decoding
|
||||
pci_write_config(dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
|
||||
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd);
|
||||
|
||||
dev->info.u.h1.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h1.rom_base_pci);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h1.base_registers_pci[i]);
|
||||
}
|
||||
|
||||
dev->info.u.h1.primary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_primary_bus, 1);
|
||||
dev->info.u.h1.secondary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_bus, 1);
|
||||
dev->info.u.h1.subordinate_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subordinate_bus, 1);
|
||||
dev->info.u.h1.secondary_latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_latency, 1);
|
||||
dev->info.u.h1.io_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base, 1);
|
||||
dev->info.u.h1.io_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit, 1);
|
||||
dev->info.u.h1.secondary_status = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_status, 2);
|
||||
dev->info.u.h1.memory_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_base, 2);
|
||||
dev->info.u.h1.memory_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_limit, 2);
|
||||
dev->info.u.h1.prefetchable_memory_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base, 2);
|
||||
dev->info.u.h1.prefetchable_memory_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2);
|
||||
dev->info.u.h1.prefetchable_memory_base_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base_upper32, 4);
|
||||
dev->info.u.h1.prefetchable_memory_limit_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_upper32, 4);
|
||||
dev->info.u.h1.io_base_upper16 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2);
|
||||
dev->info.u.h1.io_limit_upper16 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit_upper16, 2);
|
||||
dev->info.u.h1.interrupt_line = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
|
||||
dev->info.u.h1.interrupt_pin = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
|
||||
dev->info.u.h1.bridge_control = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
|
||||
dev->info.u.h1.subsystem_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_device_id_1, 2);
|
||||
dev->info.u.h1.subsystem_vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_1, 2);
|
||||
dev->info.u.h1.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus, 1);
|
||||
dev->info.u.h1.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus, 1);
|
||||
dev->info.u.h1.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus, 1);
|
||||
dev->info.u.h1.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency, 1);
|
||||
dev->info.u.h1.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base, 1);
|
||||
dev->info.u.h1.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit, 1);
|
||||
dev->info.u.h1.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status, 2);
|
||||
dev->info.u.h1.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base, 2);
|
||||
dev->info.u.h1.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit, 2);
|
||||
dev->info.u.h1.prefetchable_memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base, 2);
|
||||
dev->info.u.h1.prefetchable_memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2);
|
||||
dev->info.u.h1.prefetchable_memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base_upper32, 4);
|
||||
dev->info.u.h1.prefetchable_memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_upper32, 4);
|
||||
dev->info.u.h1.io_base_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2);
|
||||
dev->info.u.h1.io_limit_upper16 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit_upper16, 2);
|
||||
dev->info.u.h1.interrupt_line = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
|
||||
dev->info.u.h1.interrupt_pin = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1);
|
||||
dev->info.u.h1.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
|
||||
dev->info.u.h1.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_1, 2);
|
||||
dev->info.u.h1.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_1, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
case PCI_header_type_cardbus:
|
||||
{
|
||||
// for testing only, not final:
|
||||
dev->info.u.h2.subsystem_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_device_id_2, 2);
|
||||
dev->info.u.h2.subsystem_vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_2, 2);
|
||||
dev->info.u.h2.primary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_primary_bus_2, 1);
|
||||
dev->info.u.h2.secondary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_bus_2, 1);
|
||||
dev->info.u.h2.subordinate_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subordinate_bus_2, 1);
|
||||
dev->info.u.h2.secondary_latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_latency_2, 1);
|
||||
dev->info.u.h2.subsystem_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_device_id_2, 2);
|
||||
dev->info.u.h2.subsystem_vendor_id = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_sub_vendor_id_2, 2);
|
||||
dev->info.u.h2.primary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_primary_bus_2, 1);
|
||||
dev->info.u.h2.secondary_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_bus_2, 1);
|
||||
dev->info.u.h2.subordinate_bus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_subordinate_bus_2, 1);
|
||||
dev->info.u.h2.secondary_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_latency_2, 1);
|
||||
dev->info.u.h2.reserved = 0;
|
||||
dev->info.u.h2.memory_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_base0_2, 4);
|
||||
dev->info.u.h2.memory_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_limit0_2, 4);
|
||||
dev->info.u.h2.memory_base_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_base1_2, 4);
|
||||
dev->info.u.h2.memory_limit_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_limit1_2, 4);
|
||||
dev->info.u.h2.io_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base0_2, 4);
|
||||
dev->info.u.h2.io_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit0_2, 4);
|
||||
dev->info.u.h2.io_base_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base1_2, 4);
|
||||
dev->info.u.h2.io_limit_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit1_2, 4);
|
||||
dev->info.u.h2.secondary_status = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_status_2, 2);
|
||||
dev->info.u.h2.bridge_control = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bridge_control_2, 1);
|
||||
dev->info.u.h2.memory_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base0_2, 4);
|
||||
dev->info.u.h2.memory_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit0_2, 4);
|
||||
dev->info.u.h2.memory_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_base1_2, 4);
|
||||
dev->info.u.h2.memory_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_memory_limit1_2, 4);
|
||||
dev->info.u.h2.io_base = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base0_2, 4);
|
||||
dev->info.u.h2.io_limit = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit0_2, 4);
|
||||
dev->info.u.h2.io_base_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_base1_2, 4);
|
||||
dev->info.u.h2.io_limit_upper32 = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_io_limit1_2, 4);
|
||||
dev->info.u.h2.secondary_status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status_2, 2);
|
||||
dev->info.u.h2.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control_2, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -376,4 +520,75 @@ PCI::RefreshDeviceInfo(PCIBus *bus)
|
||||
if (dev->child)
|
||||
RefreshDeviceInfo(dev->child);
|
||||
}
|
||||
|
||||
if (bus->next)
|
||||
RefreshDeviceInfo(bus->next);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value)
|
||||
{
|
||||
domain_data *info;
|
||||
info = GetDomainData(domain);
|
||||
if (!info)
|
||||
return B_ERROR;
|
||||
|
||||
if (device > (info->max_bus_devices - 1)
|
||||
|| function > 7
|
||||
|| (size != 1 && size != 2 && size != 4)
|
||||
|| (size == 2 && (offset & 3) == 3)
|
||||
|| (size == 4 && (offset & 3) != 0)) {
|
||||
dprintf("PCI: can't read config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
domain, bus, device, function, offset, size);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t status;
|
||||
status = (*info->controller->read_pci_config)(info->controller_cookie,
|
||||
bus, device, function,
|
||||
offset, size, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
PCI::ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size)
|
||||
{
|
||||
uint32 value;
|
||||
|
||||
if (ReadPciConfig(domain, bus, device, function, offset, size, &value) != B_OK)
|
||||
return 0xffffffff;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PCI::WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
domain_data *info;
|
||||
info = GetDomainData(domain);
|
||||
if (!info)
|
||||
return B_ERROR;
|
||||
|
||||
if (device > (info->max_bus_devices - 1)
|
||||
|| function > 7
|
||||
|| (size != 1 && size != 2 && size != 4)
|
||||
|| (size == 2 && (offset & 3) == 3)
|
||||
|| (size == 4 && (offset & 3) != 0)) {
|
||||
dprintf("PCI: can't write config for domain %d, bus %u, device %u, function %u, offset %u, size %u\n",
|
||||
domain, bus, device, function, offset, size);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t status;
|
||||
status = (*info->controller->write_pci_config)(info->controller_cookie,
|
||||
bus, device, function,
|
||||
offset, size, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
@@ -7,8 +8,7 @@
|
||||
#ifndef __PCI_H__
|
||||
#define __PCI_H__
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include "pci_controller.h"
|
||||
|
||||
|
||||
#define TRACE_PCI
|
||||
@@ -21,38 +21,69 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
struct PCIBus;
|
||||
struct PCIDev;
|
||||
|
||||
struct PCIBus {
|
||||
PCIBus *next;
|
||||
PCIDev *parent;
|
||||
uint8 bus;
|
||||
PCIDev *child;
|
||||
int domain;
|
||||
uint8 bus;
|
||||
};
|
||||
|
||||
struct PCIDev {
|
||||
PCIDev *next;
|
||||
PCIBus *parent;
|
||||
PCIBus *child;
|
||||
int domain;
|
||||
uint8 bus;
|
||||
uint8 dev;
|
||||
uint8 func;
|
||||
pci_info info;
|
||||
};
|
||||
|
||||
|
||||
struct domain_data
|
||||
{
|
||||
// These two are set in PCI::AddController:
|
||||
pci_controller * controller;
|
||||
void * controller_cookie;
|
||||
|
||||
// All the rest is set in PCI::InitDomainData
|
||||
int max_bus_devices;
|
||||
};
|
||||
|
||||
|
||||
class PCI {
|
||||
public:
|
||||
PCI();
|
||||
~PCI();
|
||||
PCI();
|
||||
~PCI();
|
||||
|
||||
void InitDomainData();
|
||||
void InitBus();
|
||||
|
||||
status_t GetNthPciInfo(long index, pci_info *outInfo);
|
||||
status_t AddController(pci_controller *controller, void *controller_cookie);
|
||||
|
||||
status_t GetNthPciInfo(long index, pci_info *outInfo);
|
||||
|
||||
status_t ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 *value);
|
||||
|
||||
uint32 ReadPciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size);
|
||||
|
||||
status_t WritePciConfig(int domain, uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value);
|
||||
|
||||
status_t GetVirtBus(uint8 virt_bus, int *domain, uint8 *bus);
|
||||
|
||||
private:
|
||||
|
||||
void DiscoverBus(PCIBus *bus);
|
||||
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func);
|
||||
|
||||
PCIDev *CreateDevice(PCIBus *parent, uint8 dev, uint8 func);
|
||||
PCIBus *CreateBus(PCIDev *parent, uint8 bus);
|
||||
PCIBus *CreateBus(PCIDev *parent, int domain, uint8 bus);
|
||||
|
||||
status_t GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo);
|
||||
void ReadPciBasicInfo(PCIDev *dev);
|
||||
@@ -63,9 +94,19 @@ class PCI {
|
||||
uint32 BarSize(uint32 bits, uint32 mask);
|
||||
void GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0);
|
||||
void GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0);
|
||||
|
||||
|
||||
domain_data * GetDomainData(int domain);
|
||||
|
||||
status_t AddVirtBus(int domain, uint8 bus, uint8 *virt_bus);
|
||||
|
||||
private:
|
||||
PCIBus fRootBus;
|
||||
PCIBus * fRootBus;
|
||||
|
||||
enum { MAX_PCI_DOMAINS = 8 };
|
||||
|
||||
domain_data fDomainData[MAX_PCI_DOMAINS];
|
||||
int fDomainCount;
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
@@ -75,10 +116,13 @@ class PCI {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
status_t pci_init(void);
|
||||
void pci_uninit(void);
|
||||
status_t pci_init(void);
|
||||
void pci_uninit(void);
|
||||
|
||||
long pci_get_nth_pci_info(long index, pci_info *outInfo);
|
||||
long pci_get_nth_pci_info(long index, pci_info *outInfo);
|
||||
|
||||
uint32 pci_read_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
void pci_write_config(uint8 virt_bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright 2003-2005, Marcus Overhagen. All rights reserved.
|
||||
** Copyright 2003-2006, Marcus Overhagen. All rights reserved.
|
||||
** Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -151,7 +151,9 @@ print_capabilities(const pci_info *info)
|
||||
static void
|
||||
print_info_basic(const pci_info *info, bool verbose)
|
||||
{
|
||||
TRACE(("PCI: bus %2d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
|
||||
TRACE(("PCI: [dom %d, bus %2d] bus %3d, device %2d, function %2d: vendor %04x, device %04x, revision %02x\n",
|
||||
// XXX this works only as long as PCI manager virtual bus mapping isn't changed:
|
||||
(info->bus >> 5) /* domain */, (info->bus & 0x1f) /* bus */,
|
||||
info->bus, info->device, info->function, info->vendor_id, info->device_id, info->revision));
|
||||
TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n",
|
||||
info->class_base, info->class_sub, info->class_api));
|
||||
|
||||
@@ -48,6 +48,11 @@ pci_module_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
static status_t
|
||||
pci_module_register_device(device_node_handle parent)
|
||||
{
|
||||
|
||||
// XXX how do we handle this for PPC?
|
||||
// I/O port for PCI config space address
|
||||
#define PCI_CONFIG_ADDRESS 0xcf8
|
||||
|
||||
io_resource resources[2] = {
|
||||
{ IO_PORT, PCI_CONFIG_ADDRESS, 8 },
|
||||
{}
|
||||
@@ -140,22 +145,6 @@ pci_module_get_paths(const char ***_bus, const char ***_device)
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
pci_module_read_config(uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size)
|
||||
{
|
||||
return pci_read_config(bus, device, function, offset, size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_module_write_config(uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
pci_write_config(bus, device, function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_module_init(device_node_handle node, void *user_cookie, void **_cookie)
|
||||
{
|
||||
@@ -255,8 +244,8 @@ static struct pci_root_info sPCIModule = {
|
||||
NULL, // rescan bus
|
||||
},
|
||||
|
||||
pci_module_read_config,
|
||||
pci_module_write_config
|
||||
&pci_read_config,
|
||||
&pci_write_config
|
||||
};
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
// name of PCI device modules
|
||||
#define PCI_DEVICE_MODULE_NAME "bus_managers/pci/device_v1"
|
||||
|
||||
// I/O port for PCI config space address
|
||||
#define PCI_CONFIG_ADDRESS 0xcf8
|
||||
// I/O port for PCI config space data
|
||||
#define PCI_CONFIG_DATA 0xcfc
|
||||
|
||||
extern device_manager_info *gDeviceManager;
|
||||
|
||||
|
||||
@@ -42,30 +37,10 @@ typedef struct pci_root_info {
|
||||
extern pci_device_module_info gPCIDeviceModule;
|
||||
|
||||
|
||||
extern spinlock gConfigLock;
|
||||
extern int gMaxBusDevices;
|
||||
extern bool gIrqRouterAvailable;
|
||||
|
||||
#define PCI_LOCK_CONFIG(cpu_status) \
|
||||
{ \
|
||||
cpu_status = disable_interrupts(); \
|
||||
acquire_spinlock(&gConfigLock); \
|
||||
}
|
||||
|
||||
#define PCI_UNLOCK_CONFIG(cpu_status) \
|
||||
{ \
|
||||
release_spinlock(&gConfigLock); \
|
||||
restore_interrupts(cpu_status); \
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
status_t pci_config_init(void);
|
||||
uint32 pci_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size);
|
||||
void pci_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value);
|
||||
void *pci_ram_address(const void *physical_address_in_system_memory);
|
||||
|
||||
status_t pci_io_init(void);
|
||||
@@ -76,10 +51,6 @@ void pci_write_io_16(int mapped_io_addr, uint16 value);
|
||||
uint32 pci_read_io_32(int mapped_io_addr);
|
||||
void pci_write_io_32(int mapped_io_addr, uint32 value);
|
||||
|
||||
status_t pci_irq_init(void);
|
||||
uint8 pci_read_irq(uint8 bus, uint8 device, uint8 function, uint8 pin);
|
||||
void pci_write_irq(uint8 bus, uint8 device, uint8 function, uint8 pin, uint8 irq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user