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
|
status_t
|
||||||
pci_config_init()
|
pci_controller_init(void)
|
||||||
{
|
{
|
||||||
return B_OK;
|
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 *
|
void *
|
||||||
pci_ram_address(const void *physical_address_in_system_memory)
|
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) ] ;
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||||
|
|
||||||
KernelStaticLibrary pci_arch_bus_manager :
|
KernelStaticLibrary pci_arch_bus_manager :
|
||||||
bios.c
|
pci_bios.c
|
||||||
pci_controller.c
|
pci_controller.c
|
||||||
pci_io.c
|
pci_io.c
|
||||||
pci_irq.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 <KernelExport.h>
|
||||||
|
#include "pci_irq.h"
|
||||||
|
#include "pci_bios.h"
|
||||||
#include "pci_priv.h"
|
#include "pci_priv.h"
|
||||||
#include "bios.h"
|
#include "pci_controller.h"
|
||||||
#include "arch_cpu.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_REQ_PORT 0xCF8
|
||||||
#define PCI_MECH1_DATA_PORT 0xCFC
|
#define PCI_MECH1_DATA_PORT 0xCFC
|
||||||
#define PCI_MECH1_REQ_DATA(bus, device, func, offset) \
|
#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) \
|
#define PCI_MECH2_CONFIG_PORT(dev, offset) \
|
||||||
(uint16)(0xC00 | (dev << 8) | offset)
|
(uint16)(0xC00 | (dev << 8) | offset)
|
||||||
|
|
||||||
|
#define PCI_LOCK_CONFIG(cpu_status) \
|
||||||
|
{ \
|
||||||
|
cpu_status = disable_interrupts(); \
|
||||||
|
acquire_spinlock(&sConfigLock); \
|
||||||
|
}
|
||||||
|
|
||||||
status_t
|
#define PCI_UNLOCK_CONFIG(cpu_status) \
|
||||||
pci_config_init(void)
|
{ \
|
||||||
|
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()) {
|
PCI_LOCK_CONFIG(cpu);
|
||||||
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);
|
|
||||||
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
result = in8(PCI_MECH1_DATA_PORT + (offset & 3));
|
*value = in8(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
result = in16(PCI_MECH1_DATA_PORT + (offset & 3));
|
*value = in16(PCI_MECH1_DATA_PORT + (offset & 3));
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
result = in32(PCI_MECH1_DATA_PORT);
|
*value = in32(PCI_MECH1_DATA_PORT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = 0xffffffff;
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
PCI_UNLOCK_CONFIG(status);
|
PCI_UNLOCK_CONFIG(cpu);
|
||||||
return result;
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static status_t
|
||||||
pci_mech1_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
pci_mech1_write_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||||
|
uint8 offset, uint8 size, uint32 value)
|
||||||
{
|
{
|
||||||
cpu_status status;
|
cpu_status cpu;
|
||||||
if (device > 31 || function > 7 || (size != 1 && size != 2 && size != 4)
|
status_t status = B_OK;
|
||||||
|| (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCI_LOCK_CONFIG(status);
|
PCI_LOCK_CONFIG(cpu);
|
||||||
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
out8(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
out8(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
out16(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
out16(value, PCI_MECH1_DATA_PORT + (offset & 3));
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
out32(value, PCI_MECH1_DATA_PORT);
|
out32(value, PCI_MECH1_DATA_PORT);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
PCI_UNLOCK_CONFIG(status);
|
PCI_UNLOCK_CONFIG(cpu);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
static status_t
|
||||||
pci_mech2_read_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size)
|
pci_mech1_get_max_bus_devices(void *cookie, int32 *count)
|
||||||
{
|
{
|
||||||
uint32 result;
|
*count = 32;
|
||||||
cpu_status status;
|
return B_OK;
|
||||||
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;
|
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((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT);
|
||||||
out8(bus, PCI_MECH2_FORWARD_PORT);
|
out8(bus, PCI_MECH2_FORWARD_PORT);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
result = in8(PCI_MECH2_CONFIG_PORT(device, offset));
|
*value = in8(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
result = in16(PCI_MECH2_CONFIG_PORT(device, offset));
|
*value = in16(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
result = in32(PCI_MECH2_CONFIG_PORT(device, offset));
|
*value = in32(PCI_MECH2_CONFIG_PORT(device, offset));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = 0xffffffff;
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
out8(0, PCI_MECH2_ENABLE_PORT);
|
out8(0, PCI_MECH2_ENABLE_PORT);
|
||||||
PCI_UNLOCK_CONFIG(status);
|
PCI_UNLOCK_CONFIG(cpu);
|
||||||
return result;
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static status_t
|
||||||
pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, uint8 size, uint32 value)
|
pci_mech2_write_config(void *cookie, uint8 bus, uint8 device, uint8 function,
|
||||||
|
uint8 offset, uint8 size, uint32 value)
|
||||||
{
|
{
|
||||||
cpu_status status;
|
cpu_status cpu;
|
||||||
if (device > 15 || function > 7 || (size != 1 && size != 2 && size != 4)) {
|
status_t status = B_OK;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCI_LOCK_CONFIG(status);
|
PCI_LOCK_CONFIG(cpu);
|
||||||
out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT);
|
out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT);
|
||||||
out8(bus, PCI_MECH2_FORWARD_PORT);
|
out8(bus, PCI_MECH2_FORWARD_PORT);
|
||||||
switch (size) {
|
switch (size) {
|
||||||
@@ -235,9 +152,22 @@ pci_mech2_write_config(uint8 bus, uint8 device, uint8 function, uint8 offset, ui
|
|||||||
case 4:
|
case 4:
|
||||||
out32(value, PCI_MECH2_CONFIG_PORT(device, offset));
|
out32(value, PCI_MECH2_CONFIG_PORT(device, offset));
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
out8(0, PCI_MECH2_ENABLE_PORT);
|
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;
|
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;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
status_t
|
||||||
pci_read_irq(uint8 bus, uint8 device, uint8 function, uint8 pin)
|
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 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -14,32 +15,76 @@
|
|||||||
#include "pci_priv.h"
|
#include "pci_priv.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
|
|
||||||
bool gIrqRouterAvailable = false;
|
|
||||||
spinlock gConfigLock = 0;
|
spinlock gConfigLock = 0;
|
||||||
|
|
||||||
static PCI *sPCI;
|
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
|
status_t
|
||||||
pci_init(void)
|
pci_init(void)
|
||||||
{
|
{
|
||||||
|
sPCI = new PCI;
|
||||||
|
|
||||||
if (pci_io_init() != B_OK) {
|
if (pci_io_init() != B_OK) {
|
||||||
TRACE(("PCI: pci_io_init failed\n"));
|
TRACE(("PCI: pci_io_init failed\n"));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pci_config_init() != B_OK) {
|
if (pci_controller_init() != B_OK) {
|
||||||
TRACE(("PCI: pci_config_init failed\n"));
|
TRACE(("PCI: pci_controller_init failed\n"));
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pci_irq_init() != B_OK)
|
sPCI->InitDomainData();
|
||||||
TRACE(("PCI: IRQ router not available\n"));
|
sPCI->InitBus();
|
||||||
else
|
|
||||||
gIrqRouterAvailable = true;
|
|
||||||
|
|
||||||
sPCI = new PCI;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -52,22 +97,35 @@ pci_uninit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long
|
// #pragma mark PCI class
|
||||||
pci_get_nth_pci_info(long index, pci_info *outInfo)
|
|
||||||
|
PCI::PCI()
|
||||||
|
: fRootBus(0)
|
||||||
|
, fDomainCount(0)
|
||||||
{
|
{
|
||||||
return sPCI->GetNthPciInfo(index, outInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PCI::PCI()
|
void
|
||||||
|
PCI::InitBus()
|
||||||
{
|
{
|
||||||
fRootBus.parent = 0;
|
PCIBus **ppnext = &fRootBus;
|
||||||
fRootBus.bus = 0;
|
|
||||||
fRootBus.child = 0;
|
|
||||||
|
|
||||||
DiscoverBus(&fRootBus);
|
for (int i = 0; i < fDomainCount; i++) {
|
||||||
|
PCIBus *bus = new PCIBus;
|
||||||
RefreshDeviceInfo(&fRootBus);
|
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
|
status_t
|
||||||
PCI::GetNthPciInfo(long index, pci_info *outInfo)
|
PCI::GetNthPciInfo(long index, pci_info *outInfo)
|
||||||
{
|
{
|
||||||
long curindex = 0;
|
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;
|
return B_OK;
|
||||||
dev = dev->next;
|
dev = dev->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bus->next)
|
||||||
|
return GetNthPciInfo(bus->next, curindex, wantindex, outInfo);
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,49 +235,56 @@ PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInf
|
|||||||
void
|
void
|
||||||
PCI::DiscoverBus(PCIBus *bus)
|
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++) {
|
for (int dev = 0; dev < max_bus_devices; dev++) {
|
||||||
uint16 vendor_id = pci_read_config(bus->bus, dev, 0, PCI_vendor_id, 2);
|
uint16 vendor_id = ReadPciConfig(bus->domain, bus->bus, dev, 0, PCI_vendor_id, 2);
|
||||||
if (vendor_id == 0xffff)
|
if (vendor_id == 0xffff)
|
||||||
continue;
|
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;
|
int nfunc = (type & PCI_multifunction) ? 8 : 1;
|
||||||
for (int func = 0; func < nfunc; func++)
|
for (int func = 0; func < nfunc; func++)
|
||||||
DiscoverDevice(bus, dev, func);
|
DiscoverDevice(bus, dev, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bus->next)
|
||||||
|
DiscoverBus(bus->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func)
|
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)
|
if (device_id == 0xffff)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PCIDev *newdev = CreateDevice(bus, dev, func);
|
PCIDev *newdev = CreateDevice(bus, dev, func);
|
||||||
|
|
||||||
uint8 base_class = pci_read_config(bus->bus, dev, func, PCI_class_base, 1);
|
uint8 base_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_base, 1);
|
||||||
uint8 sub_class = pci_read_config(bus->bus, dev, func, PCI_class_sub, 1);
|
uint8 sub_class = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_class_sub, 1);
|
||||||
if (base_class == PCI_bridge && sub_class == PCI_pci) {
|
if (base_class == PCI_bridge && sub_class == PCI_pci) {
|
||||||
uint8 secondary_bus = pci_read_config(bus->bus, dev, func, PCI_secondary_bus, 1);
|
uint8 secondary_bus = ReadPciConfig(bus->domain, bus->bus, dev, func, PCI_secondary_bus, 1);
|
||||||
PCIBus *newbus = CreateBus(newdev, secondary_bus);
|
PCIBus *newbus = CreateBus(newdev, bus->domain, secondary_bus);
|
||||||
DiscoverBus(newbus);
|
DiscoverBus(newbus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PCIBus *
|
PCIBus *
|
||||||
PCI::CreateBus(PCIDev *parent, uint8 bus)
|
PCI::CreateBus(PCIDev *parent, int domain, uint8 bus)
|
||||||
{
|
{
|
||||||
PCIBus *newbus = new PCIBus;
|
PCIBus *newbus = new PCIBus;
|
||||||
|
newbus->next = NULL;
|
||||||
newbus->parent = parent;
|
newbus->parent = parent;
|
||||||
|
newbus->child = NULL;
|
||||||
|
newbus->domain = domain;
|
||||||
newbus->bus = bus;
|
newbus->bus = bus;
|
||||||
newbus->child = 0;
|
|
||||||
|
|
||||||
// append
|
// append
|
||||||
parent->child = newbus;
|
parent->child = newbus;
|
||||||
@@ -160,12 +296,13 @@ PCI::CreateBus(PCIDev *parent, uint8 bus)
|
|||||||
PCIDev *
|
PCIDev *
|
||||||
PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func)
|
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;
|
PCIDev *newdev = new PCIDev;
|
||||||
newdev->next = 0;
|
newdev->next = NULL;
|
||||||
newdev->parent = parent;
|
newdev->parent = parent;
|
||||||
newdev->child = 0;
|
newdev->child = NULL;
|
||||||
|
newdev->domain = parent->domain;
|
||||||
newdev->bus = parent->bus;
|
newdev->bus = parent->bus;
|
||||||
newdev->dev = dev;
|
newdev->dev = dev;
|
||||||
newdev->func = func;
|
newdev->func = func;
|
||||||
@@ -205,10 +342,10 @@ PCI::BarSize(uint32 bits, uint32 mask)
|
|||||||
void
|
void
|
||||||
PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
|
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);
|
uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff);
|
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff);
|
||||||
uint32 newvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4);
|
uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||||
|
|
||||||
*address = oldvalue & PCI_address_memory_32_mask;
|
*address = oldvalue & PCI_address_memory_32_mask;
|
||||||
if (size)
|
if (size)
|
||||||
@@ -221,10 +358,10 @@ PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8
|
|||||||
void
|
void
|
||||||
PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags)
|
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);
|
uint32 oldvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0
|
WritePciConfig(dev->domain, 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);
|
uint32 newvalue = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4);
|
||||||
pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, offset, 4, oldvalue);
|
||||||
|
|
||||||
*address = oldvalue & PCI_rom_address_mask;
|
*address = oldvalue & PCI_rom_address_mask;
|
||||||
if (size)
|
if (size)
|
||||||
@@ -237,20 +374,27 @@ PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uin
|
|||||||
void
|
void
|
||||||
PCI::ReadPciBasicInfo(PCIDev *dev)
|
PCI::ReadPciBasicInfo(PCIDev *dev)
|
||||||
{
|
{
|
||||||
dev->info.vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_vendor_id, 2);
|
uint8 virt_bus;
|
||||||
dev->info.device_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_device_id, 2);
|
|
||||||
dev->info.bus = dev->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.device = dev->dev;
|
||||||
dev->info.function = dev->func;
|
dev->info.function = dev->func;
|
||||||
dev->info.revision = pci_read_config(dev->bus, dev->dev, dev->func, PCI_revision, 1);
|
dev->info.revision = ReadPciConfig(dev->domain, 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_api = ReadPciConfig(dev->domain, 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_sub = ReadPciConfig(dev->domain, 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.class_base = ReadPciConfig(dev->domain, 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.line_size = ReadPciConfig(dev->domain, 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.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)
|
// 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.header_type = ReadPciConfig(dev->domain, 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.bist = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bist, 1);
|
||||||
dev->info.reserved = 0;
|
dev->info.reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,8 +406,8 @@ PCI::ReadPciHeaderInfo(PCIDev *dev)
|
|||||||
case PCI_header_type_generic:
|
case PCI_header_type_generic:
|
||||||
{
|
{
|
||||||
// disable PCI device address decoding (io and memory) while BARs are modified
|
// 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);
|
uint16 pcicmd = ReadPciConfig(dev->domain, 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));
|
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_command, 2, pcicmd & ~(PCI_command_io | PCI_command_memory));
|
||||||
|
|
||||||
// get BAR size infos
|
// get BAR size infos
|
||||||
GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, &dev->info.u.h0.rom_size);
|
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
|
// 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);
|
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++) {
|
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.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.cardbus_cis = ReadPciConfig(dev->domain, 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_id = ReadPciConfig(dev->domain, 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.subsystem_vendor_id = ReadPciConfig(dev->domain, 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_line = ReadPciConfig(dev->domain, 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.interrupt_pin = ReadPciConfig(dev->domain, 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.min_grant = ReadPciConfig(dev->domain, 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.max_latency = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_max_latency, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PCI_header_type_PCI_to_PCI_bridge:
|
case PCI_header_type_PCI_to_PCI_bridge:
|
||||||
{
|
{
|
||||||
// disable PCI device address decoding (io and memory) while BARs are modified
|
// 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);
|
uint16 pcicmd = ReadPciConfig(dev->domain, 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));
|
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);
|
GetRomBarInfo(dev, PCI_bridge_rom_base, &dev->info.u.h1.rom_base_pci);
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@@ -307,56 +451,56 @@ PCI::ReadPciHeaderInfo(PCIDev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore PCI device address decoding
|
// 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);
|
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++) {
|
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.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.primary_bus = ReadPciConfig(dev->domain, 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.secondary_bus = ReadPciConfig(dev->domain, 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.subordinate_bus = ReadPciConfig(dev->domain, 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.secondary_latency = ReadPciConfig(dev->domain, 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_base = ReadPciConfig(dev->domain, 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.io_limit = ReadPciConfig(dev->domain, 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.secondary_status = ReadPciConfig(dev->domain, 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_base = ReadPciConfig(dev->domain, 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.memory_limit = ReadPciConfig(dev->domain, 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_base = ReadPciConfig(dev->domain, 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_limit = ReadPciConfig(dev->domain, 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_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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2);
|
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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit_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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1);
|
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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
|
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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_device_id_1, 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 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_sub_vendor_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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PCI_header_type_cardbus:
|
case PCI_header_type_cardbus:
|
||||||
{
|
{
|
||||||
// for testing only, not final:
|
// 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_id = ReadPciConfig(dev->domain, 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.subsystem_vendor_id = ReadPciConfig(dev->domain, 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.primary_bus = ReadPciConfig(dev->domain, 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.secondary_bus = ReadPciConfig(dev->domain, 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.subordinate_bus = ReadPciConfig(dev->domain, 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.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.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_base = ReadPciConfig(dev->domain, 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_limit = ReadPciConfig(dev->domain, 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_base_upper32 = ReadPciConfig(dev->domain, 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.memory_limit_upper32 = ReadPciConfig(dev->domain, 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_base = ReadPciConfig(dev->domain, 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_limit = ReadPciConfig(dev->domain, 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_base_upper32 = ReadPciConfig(dev->domain, 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.io_limit_upper32 = ReadPciConfig(dev->domain, 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.secondary_status = ReadPciConfig(dev->domain, 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.bridge_control = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control_2, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,4 +520,75 @@ PCI::RefreshDeviceInfo(PCIBus *bus)
|
|||||||
if (dev->child)
|
if (dev->child)
|
||||||
RefreshDeviceInfo(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 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -7,8 +8,7 @@
|
|||||||
#ifndef __PCI_H__
|
#ifndef __PCI_H__
|
||||||
#define __PCI_H__
|
#define __PCI_H__
|
||||||
|
|
||||||
|
#include "pci_controller.h"
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_PCI
|
#define TRACE_PCI
|
||||||
@@ -21,38 +21,69 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
struct PCIBus;
|
|
||||||
struct PCIDev;
|
struct PCIDev;
|
||||||
|
|
||||||
struct PCIBus {
|
struct PCIBus {
|
||||||
|
PCIBus *next;
|
||||||
PCIDev *parent;
|
PCIDev *parent;
|
||||||
uint8 bus;
|
|
||||||
PCIDev *child;
|
PCIDev *child;
|
||||||
|
int domain;
|
||||||
|
uint8 bus;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PCIDev {
|
struct PCIDev {
|
||||||
PCIDev *next;
|
PCIDev *next;
|
||||||
PCIBus *parent;
|
PCIBus *parent;
|
||||||
PCIBus *child;
|
PCIBus *child;
|
||||||
|
int domain;
|
||||||
uint8 bus;
|
uint8 bus;
|
||||||
uint8 dev;
|
uint8 dev;
|
||||||
uint8 func;
|
uint8 func;
|
||||||
pci_info info;
|
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 {
|
class PCI {
|
||||||
public:
|
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:
|
private:
|
||||||
|
|
||||||
void DiscoverBus(PCIBus *bus);
|
void DiscoverBus(PCIBus *bus);
|
||||||
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func);
|
void DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func);
|
||||||
|
|
||||||
PCIDev *CreateDevice(PCIBus *parent, 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);
|
status_t GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo);
|
||||||
void ReadPciBasicInfo(PCIDev *dev);
|
void ReadPciBasicInfo(PCIDev *dev);
|
||||||
@@ -63,9 +94,19 @@ class PCI {
|
|||||||
uint32 BarSize(uint32 bits, uint32 mask);
|
uint32 BarSize(uint32 bits, uint32 mask);
|
||||||
void GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size = 0, uint8 *flags = 0);
|
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);
|
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:
|
private:
|
||||||
PCIBus fRootBus;
|
PCIBus * fRootBus;
|
||||||
|
|
||||||
|
enum { MAX_PCI_DOMAINS = 8 };
|
||||||
|
|
||||||
|
domain_data fDomainData[MAX_PCI_DOMAINS];
|
||||||
|
int fDomainCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
@@ -75,10 +116,13 @@ class PCI {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
status_t pci_init(void);
|
status_t pci_init(void);
|
||||||
void pci_uninit(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
|
#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.
|
** Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -151,7 +151,9 @@ print_capabilities(const pci_info *info)
|
|||||||
static void
|
static void
|
||||||
print_info_basic(const pci_info *info, bool verbose)
|
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));
|
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",
|
TRACE(("PCI: class_base %02x, class_function %02x, class_api %02x\n",
|
||||||
info->class_base, info->class_sub, info->class_api));
|
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
|
static status_t
|
||||||
pci_module_register_device(device_node_handle parent)
|
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_resource resources[2] = {
|
||||||
{ IO_PORT, PCI_CONFIG_ADDRESS, 8 },
|
{ 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
|
static status_t
|
||||||
pci_module_init(device_node_handle node, void *user_cookie, void **_cookie)
|
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
|
NULL, // rescan bus
|
||||||
},
|
},
|
||||||
|
|
||||||
pci_module_read_config,
|
&pci_read_config,
|
||||||
pci_module_write_config
|
&pci_write_config
|
||||||
};
|
};
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
|
|||||||
@@ -16,11 +16,6 @@
|
|||||||
// name of PCI device modules
|
// name of PCI device modules
|
||||||
#define PCI_DEVICE_MODULE_NAME "bus_managers/pci/device_v1"
|
#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;
|
extern device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
@@ -42,30 +37,10 @@ typedef struct pci_root_info {
|
|||||||
extern pci_device_module_info gPCIDeviceModule;
|
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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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);
|
void *pci_ram_address(const void *physical_address_in_system_memory);
|
||||||
|
|
||||||
status_t pci_io_init(void);
|
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);
|
uint32 pci_read_io_32(int mapped_io_addr);
|
||||||
void pci_write_io_32(int mapped_io_addr, uint32 value);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user