499 lines
17 KiB
C
499 lines
17 KiB
C
/// @file pci.c
|
|
/// @brief Routines for PCI initialization.
|
|
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
|
/// See LICENSE.md for details.
|
|
///! @cond Doxygen_Suppress
|
|
|
|
// Include the kernel log levels.
|
|
#include "sys/kernel_levels.h"
|
|
/// Change the header.
|
|
#define __DEBUG_HEADER__ "[PCI ]"
|
|
/// Set the log level.
|
|
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
|
|
|
|
#include "devices/pci.h"
|
|
#include "io/debug.h"
|
|
#include "string.h"
|
|
#include "io/port_io.h"
|
|
|
|
void pci_write_field(uint32_t device, int field, int size, uint32_t value)
|
|
{
|
|
(void)size;
|
|
outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
|
|
#if 0
|
|
if (size == 4)
|
|
outportl(PCI_VALUE_PORT, value);
|
|
else if (size == 2)
|
|
outports(PCI_VALUE_PORT, value);
|
|
else if (size == 1)
|
|
outportb(PCI_VALUE_PORT, value);
|
|
#else
|
|
outportl(PCI_VALUE_PORT, value);
|
|
#endif
|
|
}
|
|
|
|
uint32_t pci_read_field(uint32_t device, int field, int size)
|
|
{
|
|
outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
|
|
|
|
if (size == 4) {
|
|
return inportl(PCI_VALUE_PORT);
|
|
} else if (size == 2) {
|
|
return inports(PCI_VALUE_PORT + (field & 2));
|
|
} else if (size == 1) {
|
|
return inportb(PCI_VALUE_PORT + (field & 3));
|
|
}
|
|
return 0xFFFF;
|
|
}
|
|
|
|
uint32_t pci_find_type(uint32_t device)
|
|
{
|
|
return pci_read_field(device, PCI_CLASS, 1) << 16 |
|
|
pci_read_field(device, PCI_SUBCLASS, 1) << 8 |
|
|
pci_read_field(device, PCI_PROG_IF, 1);
|
|
}
|
|
|
|
struct {
|
|
uint16_t id;
|
|
const char *name;
|
|
} _pci_vendors[] = {
|
|
{ 0x1022, "AMD" },
|
|
{ 0x106b, "Apple, Inc." },
|
|
{ 0x1234, "Bochs/QEMU" },
|
|
{ 0x1274, "Ensoniq" },
|
|
{ 0x15ad, "VMWare" },
|
|
{ 0x8086, "Intel Corporation" },
|
|
{ 0x80EE, "VirtualBox" },
|
|
};
|
|
|
|
struct {
|
|
uint16_t ven_id;
|
|
uint16_t dev_id;
|
|
const char *name;
|
|
} _pci_devices[] = {
|
|
{ 0x1022, 0x2000, "PCNet Ethernet Controller (pcnet)" },
|
|
{ 0x106b, 0x003f, "OHCI Controller" },
|
|
{ 0x1234, 0x1111, "VGA BIOS Graphics Extensions" },
|
|
{ 0x1274, 0x1371, "Creative Labs CT2518 (ensoniq audio)" },
|
|
{ 0x15ad, 0x0740, "VM Communication Interface" },
|
|
{ 0x15ad, 0x0405, "SVGA II Adapter" },
|
|
{ 0x15ad, 0x0790, "PCI bridge" },
|
|
{ 0x15ad, 0x07a0, "PCI Express Root Port" },
|
|
{ 0x8086, 0x100e, "Gigabit Ethernet Controller (e1000)" },
|
|
{ 0x8086, 0x100f, "Gigabit Ethernet Controller (e1000)" },
|
|
{ 0x8086, 0x1237, "PCI & Memory" },
|
|
{ 0x8086, 0x2415, "AC'97 Audio Chipset" },
|
|
{ 0x8086, 0x7000, "PCI-to-ISA Bridge" },
|
|
{ 0x8086, 0x7010, "IDE Interface" },
|
|
{ 0x8086, 0x7110, "PIIX4 ISA" },
|
|
{ 0x8086, 0x7111, "PIIX4 IDE" },
|
|
{ 0x8086, 0x7113, "Power Management Controller" },
|
|
{ 0x8086, 0x7190, "Host Bridge" },
|
|
{ 0x8086, 0x7191, "AGP Bridge" },
|
|
{ 0x80EE, 0xBEEF, "Bochs/QEMU-compatible Graphics Adapter" },
|
|
{ 0x80EE, 0xCAFE, "Guest Additions Device" },
|
|
};
|
|
|
|
struct {
|
|
uint32_t id;
|
|
const char *name;
|
|
} _pci_classes[] = {
|
|
{ 0x000000, "Legacy Device" },
|
|
{ 0x000100, "VGA-Compatible Device" },
|
|
|
|
{ 0x010000, "SCSI bus controller" },
|
|
{ 0x010100, "ISA Compatibility mode-only controller" },
|
|
{ 0x010105, "PCI native mode-only controller" },
|
|
{ 0x01010a, "ISA Compatibility mode controller, supports both channels "
|
|
"switched to PCI native mode" },
|
|
{ 0x01010f, "PCI native mode controller, supports both channels switched "
|
|
"to ISA compatibility mode" },
|
|
{ 0x010180,
|
|
"ISA Compatibility mode-only controller, supports bus mastering" },
|
|
{ 0x010185, "PCI native mode-only controller, supports bus mastering" },
|
|
{ 0x01018a, "ISA Compatibility mode controller, supports both channels "
|
|
"switched to PCI native mode, supports bus mastering" },
|
|
{ 0x01018f, "PCI native mode controller, supports both channels switched "
|
|
"\to ISA compatibility mode, supports bus mastering" },
|
|
|
|
{ 0x010200, "Floppy disk controller" },
|
|
{ 0x010300, "IPI bus controller" },
|
|
{ 0x010400, "RAID controller" },
|
|
{ 0x010520, "ATA controller, single stepping" },
|
|
{ 0x010530, "ATA controller, continuous" },
|
|
{ 0x010600, "Serial ATA controller - vendor specific interface" },
|
|
{ 0x010601, "Serial ATA controller - AHCI 1.0 interface" },
|
|
{ 0x010700, "Serial Attached SCSI controller" },
|
|
{ 0x018000, "Mass Storage controller" },
|
|
|
|
{ 0x020000, "Ethernet controller" },
|
|
{ 0x020100, "Token Ring controller" },
|
|
{ 0x020200, "FDDI controller" },
|
|
{ 0x020300, "ATM controller" },
|
|
{ 0x020400, "ISDN controller" },
|
|
{ 0x020500, "WorldFip controller" },
|
|
// { 0x0206xx , "PICMG 2.14 Multi Computing" },
|
|
{ 0x028000, "Network controller" },
|
|
|
|
{ 0x030000, "VGA Display controller" },
|
|
{ 0x030001, "8514-compatible Display controller" },
|
|
{ 0x030100, "XGA Display controller" },
|
|
{ 0x030200, "3D Display controller" },
|
|
{ 0x038000, "Display controller" },
|
|
|
|
{ 0x040000, "Video device" },
|
|
{ 0x040100, "Audio device" },
|
|
{ 0x040200, "Computer Telephony device" },
|
|
{ 0x048000, "Multimedia device" },
|
|
|
|
{ 0x050000, "RAM memory controller" },
|
|
{ 0x050100, "Flash memory controller" },
|
|
{ 0x058000, "Memory controller" },
|
|
|
|
{ 0x060000, "Host bridge" },
|
|
{ 0x060100, "ISA bridge" },
|
|
{ 0x060200, "EISA bridge" },
|
|
{ 0x060300, "MCA bridge" },
|
|
{ 0x060400, "PCI-to-PCI bridge" },
|
|
{ 0x060401, "PCI-to-PCI bridge (subtractive decoding)" },
|
|
{ 0x060500, "PCMCIA bridge" },
|
|
{ 0x060600, "NuBus bridge" },
|
|
{ 0x060700, "CardBus bridge" },
|
|
// { 0x0608xx , "RACEway bridge" },
|
|
{ 0x060940, "PCI-to-PCI bridge, Semi-transparent, primary facing Host" },
|
|
{ 0x060980, "PCI-to-PCI bridge, Semi-transparent, secondary facing Host" },
|
|
{ 0x060A00, "InfiniBand-to-PCI host bridge" },
|
|
{ 0x068000, "Bridge device" },
|
|
|
|
{ 0x070000, "Generic XT-compatible serial controller" },
|
|
{ 0x070001, "16450-compatible serial controller" },
|
|
{ 0x070002, "16550-compatible serial controller" },
|
|
{ 0x070003, "16650-compatible serial controller" },
|
|
{ 0x070004, "16750-compatible serial controller" },
|
|
{ 0x070005, "16850-compatible serial controller" },
|
|
{ 0x070006, "16950-compatible serial controller" },
|
|
|
|
{ 0x070100, "Parallel port" },
|
|
{ 0x070101, "Bi-directional parallel port" },
|
|
{ 0x070102, "ECP 1.X compliant parallel port" },
|
|
{ 0x070103, "IEEE1284 controller" },
|
|
{ 0x0701FE, "IEEE1284 target device" },
|
|
{ 0x070200, "Multiport serial controller" },
|
|
|
|
{ 0x070300, "Generic modem" },
|
|
{ 0x070301, "Hayes 16450-compatible modem" },
|
|
{ 0x070302, "Hayes 16550-compatible modem" },
|
|
{ 0x070303, "Hayes 16650-compatible modem" },
|
|
{ 0x070304, "Hayes 16750-compatible modem" },
|
|
{ 0x070400, "GPIB (IEEE 488.1/2) controller" },
|
|
{ 0x070500, "Smart Card" },
|
|
{ 0x078000, "Communications device" },
|
|
|
|
{ 0x080000, "Generic 8259 PIC" },
|
|
{ 0x080001, "ISA PIC" },
|
|
{ 0x080002, "EISA PIC" },
|
|
{ 0x080010, "I/O APIC interrupt controller" },
|
|
{ 0x080020, "I/O(x) APIC interrupt controller" },
|
|
|
|
{ 0x080100, "Generic 8237 DMA controller" },
|
|
{ 0x080101, "ISA DMA controller" },
|
|
{ 0x080102, "EISA DMA controller" },
|
|
|
|
{ 0x080200, "Generic 8254 system timer" },
|
|
{ 0x080201, "ISA system timer" },
|
|
{ 0x080202, "EISA system timer-pair" },
|
|
|
|
{ 0x080300, "Generic RTC controller" },
|
|
{ 0x080301, "ISA RTC controller" },
|
|
|
|
{ 0x080400, "Generic PCI Hot-Plug controller" },
|
|
{ 0x080500, "SD Host controller" },
|
|
{ 0x088000, "System peripheral" },
|
|
|
|
{ 0x090000, "Keyboard controller" },
|
|
{ 0x090100, "Digitizer (pen)" },
|
|
{ 0x090200, "Mouse controller" },
|
|
{ 0x090300, "Scanner controller" },
|
|
{ 0x090400, "Generic Gameport controller" },
|
|
{ 0x090410, "Legacy Gameport controller" },
|
|
{ 0x098000, "Input controller" },
|
|
|
|
{ 0x0a0000, "Generic docking station" },
|
|
{ 0x0a8000, "Docking station" },
|
|
|
|
{ 0x0b0000, "386 Processor" },
|
|
{ 0x0b0100, "486 Processor" },
|
|
{ 0x0b0200, "Pentium Processor" },
|
|
{ 0x0b1000, "Alpha Processor" },
|
|
{ 0x0b2000, "PowerPC Processor" },
|
|
{ 0x0b3000, "MIPS Processor" },
|
|
{ 0x0b4000, "Co-processor" },
|
|
|
|
{ 0x0c0000, "IEEE 1394 (FireWire)" },
|
|
{ 0x0c0010, "IEEE 1394 -- OpenHCI spec" },
|
|
{ 0x0c0100, "ACCESS.bus" },
|
|
{ 0x0c0200, "SSA" },
|
|
{ 0x0c0300, "Universal Serial Bus (UHC spec)" },
|
|
{ 0x0c0310, "Universal Serial Bus (Open Host spec)" },
|
|
{ 0x0c0320, "USB2 Host controller (Intel Enhanced HCI spec)" },
|
|
{ 0x0c0380, "Universal Serial Bus (no PI spec)" },
|
|
{ 0x0c03FE, "USB Target Device" },
|
|
{ 0x0c0400, "Fibre Channel" },
|
|
{ 0x0c0500, "System Management Bus" },
|
|
{ 0x0c0600, "InfiniBand" },
|
|
{ 0x0c0700, "IPMI SMIC Interface" },
|
|
{ 0x0c0701, "IPMI Kybd Controller Style Interface" },
|
|
{ 0x0c0702, "IPMI Block Transfer Interface" },
|
|
// { 0x0c08xx , "SERCOS Interface" },
|
|
{ 0x0c0900, "CANbus" },
|
|
|
|
{ 0x0d100, "iRDA compatible controller" },
|
|
{ 0x0d100, "Consumer IR controller" },
|
|
{ 0x0d100, "RF controller" },
|
|
{ 0x0d100, "Bluetooth controller" },
|
|
{ 0x0d100, "Broadband controller" },
|
|
{ 0x0d100, "Ethernet (802.11a 5 GHz) controller" },
|
|
{ 0x0d100, "Ethernet (802.11b 2.4 GHz) controller" },
|
|
{ 0x0d100, "Wireless controller" },
|
|
|
|
// { 0x0e00xx , "I2O Intelligent I/O, spec 1.0" },
|
|
{ 0x0e0000, "Message FIFO at offset 040h" },
|
|
|
|
{ 0x0f0100, "TV satellite comm. controller" },
|
|
{ 0x0f0200, "Audio satellite comm. controller" },
|
|
{ 0x0f0300, "Voice satellite comm. controller" },
|
|
{ 0x0f0400, "Data satellite comm. controller" },
|
|
|
|
{ 0x100000, "Network and computing en/decryption" },
|
|
{ 0x101000, "Entertainment en/decryption" },
|
|
{ 0x108000, "En/Decryption" },
|
|
|
|
{ 0x110000, "DPIO modules" },
|
|
{ 0x110100, "Perf. counters" },
|
|
{ 0x111000, "Comm. synch., time and freq. test" },
|
|
{ 0x112000, "Management card" },
|
|
{ 0x118000, "Data acq./Signal proc." },
|
|
};
|
|
|
|
const char *pci_vendor_lookup(unsigned short vendor_id)
|
|
{
|
|
for (int i = 0; i < sizeof(_pci_vendors) / sizeof(_pci_vendors[0]); ++i) {
|
|
if (_pci_vendors[i].id == vendor_id) {
|
|
return _pci_vendors[i].name;
|
|
}
|
|
}
|
|
|
|
return "Unknown";
|
|
}
|
|
|
|
const char *pci_device_lookup(unsigned short vendor_id, unsigned short device_id)
|
|
{
|
|
for (int i = 0; i < sizeof(_pci_devices) / sizeof(_pci_devices[0]); ++i) {
|
|
if (_pci_devices[i].ven_id == vendor_id &&
|
|
_pci_devices[i].dev_id == device_id) {
|
|
return _pci_devices[i].name;
|
|
}
|
|
}
|
|
|
|
return "Unknown";
|
|
}
|
|
|
|
const char *pci_class_lookup(uint32_t class_code)
|
|
{
|
|
for (int i = 0; i < sizeof(_pci_classes) / sizeof(_pci_classes[0]); ++i) {
|
|
if (_pci_classes[i].id == class_code) {
|
|
return _pci_classes[i].name;
|
|
}
|
|
}
|
|
|
|
return "Unknown";
|
|
}
|
|
|
|
void pci_scan_hit(pci_scan_func_t f, uint32_t device, void *extra)
|
|
{
|
|
uint16_t vendor_id = (uint16_t)pci_read_field(device, PCI_VENDOR_ID, 2);
|
|
uint16_t device_id = (uint16_t)pci_read_field(device, PCI_DEVICE_ID, 2);
|
|
f(device, vendor_id, device_id, extra);
|
|
}
|
|
|
|
void pci_scan_func(pci_scan_func_t f, int type, int bus, int slot, int func, void *extra)
|
|
{
|
|
uint32_t device = pci_box_device(bus, slot, func);
|
|
|
|
if ((type == -1) || (type == pci_find_type(device))) {
|
|
pci_scan_hit(f, device, extra);
|
|
}
|
|
if (pci_find_type(device) == PCI_TYPE_BRIDGE) {
|
|
pci_scan_bus(f, type, pci_read_field(device, PCI_SECONDARY_BUS, 1), extra);
|
|
}
|
|
}
|
|
|
|
void pci_scan_slot(pci_scan_func_t f, int type, int bus, int slot, void *extra)
|
|
{
|
|
uint32_t device = pci_box_device(bus, slot, 0);
|
|
|
|
if (pci_read_field(device, PCI_VENDOR_ID, 2) == PCI_NONE) {
|
|
return;
|
|
}
|
|
|
|
pci_scan_func(f, type, bus, slot, 0, extra);
|
|
|
|
if (!pci_read_field(device, PCI_HEADER_TYPE, 1)) {
|
|
return;
|
|
}
|
|
|
|
for (int func = 1; func < 8; func++) {
|
|
device = pci_box_device(bus, slot, func);
|
|
|
|
if (pci_read_field(device, PCI_VENDOR_ID, 2) != PCI_NONE) {
|
|
pci_scan_func(f, type, bus, slot, func, extra);
|
|
}
|
|
}
|
|
}
|
|
|
|
void pci_scan_bus(pci_scan_func_t f, int type, int bus, void *extra)
|
|
{
|
|
for (int slot = 0; slot < 32; ++slot) {
|
|
pci_scan_slot(f, type, bus, slot, extra);
|
|
}
|
|
}
|
|
|
|
void pci_scan(pci_scan_func_t f, int type, void *extra)
|
|
{
|
|
if ((pci_read_field(0, PCI_HEADER_TYPE, 1) & 0x80) == 0) {
|
|
pci_scan_bus(f, type, 0, extra);
|
|
return;
|
|
}
|
|
|
|
for (int func = 0; func < 8; ++func) {
|
|
uint32_t device = pci_box_device(0, 0, func);
|
|
|
|
if (pci_read_field(device, PCI_VENDOR_ID, 2) == PCI_NONE) {
|
|
break;
|
|
}
|
|
pci_scan_bus(f, type, func, extra);
|
|
}
|
|
}
|
|
|
|
static void find_isa_bridge(uint32_t device, uint16_t vendorid, uint16_t deviceid, void *extra)
|
|
{
|
|
if (vendorid == 0x8086 && (deviceid == 0x7000 || deviceid == 0x7110)) {
|
|
*((uint32_t *)extra) = device;
|
|
}
|
|
}
|
|
|
|
static uint32_t pci_isa = 0;
|
|
static uint32_t pci_remaps[4] = { 0 };
|
|
|
|
void pci_remap()
|
|
{
|
|
pci_scan(&find_isa_bridge, -1, &pci_isa);
|
|
|
|
if (pci_isa) {
|
|
pr_default("PCI-to-ISA interrupt mappings by line:\n");
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
pci_remaps[i] = pci_read_field(pci_isa, 0x60 + i, 1);
|
|
pr_default("\tLine %d: 0x%2x\n", i + 1, pci_remaps[i]);
|
|
}
|
|
|
|
uint32_t out = 0;
|
|
memcpy(&out, &pci_remaps, 4);
|
|
pci_write_field(pci_isa, 0x60, 4, out);
|
|
}
|
|
}
|
|
|
|
int pci_get_interrupt(uint32_t device)
|
|
{
|
|
if (pci_isa == 0) {
|
|
return pci_read_field(device, PCI_INTERRUPT_LINE, 1);
|
|
}
|
|
|
|
uint32_t irq_pin = pci_read_field(device, PCI_INTERRUPT_PIN, 1);
|
|
|
|
if (irq_pin == 0) {
|
|
pr_default("PCI device does not specific interrupt line\n");
|
|
return pci_read_field(device, PCI_INTERRUPT_LINE, 1);
|
|
}
|
|
|
|
int pirq = (irq_pin + pci_extract_slot(device) - 2) % 4;
|
|
|
|
uint32_t int_line = pci_read_field(device, PCI_INTERRUPT_LINE, 1);
|
|
|
|
pr_default("Slot is %d, irq pin is %d, so pirq is %d and that maps to %d?"
|
|
"int_line=%d\n",
|
|
pci_extract_slot(device), irq_pin, pirq, pci_remaps[pirq],
|
|
int_line);
|
|
|
|
if (pci_remaps[pirq] == 0x80) {
|
|
pr_default("Not mapped, remapping?\n");
|
|
pci_remaps[pirq] = int_line;
|
|
uint32_t out = 0;
|
|
memcpy(&out, &pci_remaps, 4);
|
|
pci_write_field(pci_isa, 0x60, 4, out);
|
|
return pci_read_field(device, PCI_INTERRUPT_LINE, 1);
|
|
}
|
|
|
|
return pci_remaps[pirq];
|
|
}
|
|
|
|
static void __scan_count(uint32_t device, uint16_t vendorid, uint16_t deviceid, void *extra)
|
|
{
|
|
(void)device;
|
|
(void)vendorid;
|
|
(void)deviceid;
|
|
size_t *count = extra;
|
|
++(*count);
|
|
}
|
|
|
|
static void __scan_hit_list(uint32_t device, uint16_t vendorid, uint16_t deviceid, void *extra)
|
|
{
|
|
(void)extra;
|
|
pr_default("%2x:%2x.%d\n", pci_extract_bus(device), pci_extract_slot(device), pci_extract_func(device), deviceid);
|
|
pr_default(" Vendor : [0x%06x] %s\n", vendorid, pci_vendor_lookup(vendorid));
|
|
pr_default(" Device : [0x%06x] %s\n", deviceid, pci_device_lookup(vendorid, deviceid));
|
|
pr_default(" Type : [0x%06x] %s\n", pci_find_type(device), pci_class_lookup(pci_find_type(device)));
|
|
pr_default(" Status : 0x%4x\n", pci_read_field(device, PCI_STATUS, 2));
|
|
pr_default(" Command : 0x%4x\n", pci_read_field(device, PCI_COMMAND, 2));
|
|
pr_default(" Revision : %2d\n", pci_read_field(device, PCI_REVISION_ID, 1));
|
|
pr_default(" Cache Line Size : %2d\n", pci_read_field(device, PCI_CACHE_LINE_SIZE, 1));
|
|
pr_default(" Latency Timer : %2d\n", pci_read_field(device, PCI_LATENCY_TIMER, 1));
|
|
pr_default(" Header Type : %2d\n", pci_read_field(device, PCI_HEADER_TYPE, 1));
|
|
pr_default(" BIST : %2d\n", pci_read_field(device, PCI_BIST, 1));
|
|
pr_default(" BAR0 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_0, 4));
|
|
pr_default(" BAR1 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_1, 4));
|
|
pr_default(" BAR2 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_2, 4));
|
|
pr_default(" BAR3 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_3, 4));
|
|
pr_default(" BAR4 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_4, 4));
|
|
pr_default(" BAR6 : 0x%08x\n", pci_read_field(device, PCI_BASE_ADDRESS_5, 4));
|
|
pr_default(" Cardbus CIS : 0x%08x\n", pci_read_field(device, PCI_CARDBUS_CIS, 4));
|
|
pr_default(" Subsystem V. ID : 0x%08x\n", pci_read_field(device, PCI_SUBSYSTEM_VENDOR_ID, 2));
|
|
pr_default(" Subsystem ID : 0x%08x\n", pci_read_field(device, PCI_SUBSYSTEM_ID, 2));
|
|
pr_default(" ROM Base Address: 0x%08x\n", pci_read_field(device, PCI_ROM_ADDRESS, 4));
|
|
pr_default(" PCI Cp. LinkList: 0x%08x\n", pci_read_field(device, PCI_CAPABILITY_LIST, 1));
|
|
pr_default(" Max Latency : 0x%08x\n", pci_read_field(device, PCI_MAX_LAT, 1));
|
|
pr_default(" Min Grant : 0x%08x\n", pci_read_field(device, PCI_MIN_GNT, 1));
|
|
pr_default(" Interrupt Pin : %2d\n", pci_read_field(device, PCI_INTERRUPT_PIN, 1));
|
|
pr_default(" Interrupt Line : %2d\n", pci_read_field(device, PCI_INTERRUPT_LINE, 1));
|
|
pr_default(" Interrupt Number: %2d\n", pci_get_interrupt(device));
|
|
pr_default("\n");
|
|
}
|
|
|
|
void pci_debug_scan()
|
|
{
|
|
pr_default("\n--------------------------------------------------\n");
|
|
pr_default("Counting PCI entities...\n");
|
|
size_t count = 0;
|
|
pci_scan(&__scan_count, -1, &count);
|
|
pr_default("Total PCI entities: %d\n", count);
|
|
|
|
pr_default("Scanning PCI entities...\n");
|
|
pci_scan(&__scan_hit_list, -1, NULL);
|
|
|
|
pr_default("Mapping PCI entities...\n");
|
|
pci_remap();
|
|
|
|
pr_default("--------------------------------------------------\n");
|
|
}
|
|
|
|
///! @endcond
|