mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactored the PCI code to become a library of utility functions.
This commit is contained in:
parent
5f6ca5e729
commit
19b5451f3b
4 changed files with 244 additions and 307 deletions
75
sortix/include/sortix/kernel/pci.h
Normal file
75
sortix/include/sortix/kernel/pci.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pci.h
|
||||
Functions for handling PCI devices.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_PCI_H
|
||||
#define SORTIX_PCI_H
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t deviceid;
|
||||
uint16_t vendorid;
|
||||
} pciid_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t classid;
|
||||
uint8_t subclassid;
|
||||
uint8_t progif;
|
||||
uint8_t revid;
|
||||
} pcitype_t;
|
||||
|
||||
// memset(&pcifind, 255, sizeof(pcifind)) and fill out rest.
|
||||
typedef struct
|
||||
{
|
||||
uint16_t deviceid;
|
||||
uint16_t vendorid;
|
||||
uint8_t classid;
|
||||
uint8_t subclassid;
|
||||
uint8_t progif;
|
||||
uint8_t revid;
|
||||
} pcifind_t;
|
||||
|
||||
namespace PCI {
|
||||
|
||||
void Init();
|
||||
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func);
|
||||
void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */);
|
||||
uint8_t Read8(uint32_t devaddr, uint8_t off); // Host endian
|
||||
uint16_t Read16(uint32_t devaddr, uint8_t off); // Host endian
|
||||
uint32_t Read32(uint32_t devaddr, uint8_t off); // Host endian
|
||||
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off); // PCI endian
|
||||
void Write32(uint32_t devaddr, uint8_t off, uint32_t val); // Host endian
|
||||
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val); // PCI endian
|
||||
pciid_t GetDeviceId(uint32_t devaddr);
|
||||
pcitype_t GetDeviceType(uint32_t devaddr);
|
||||
uint32_t SearchForDevice(pcifind_t pcifind);
|
||||
addr_t ParseDevBar0(uint32_t devaddr);
|
||||
|
||||
} // namespace PCI
|
||||
} // namespace Sortix
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/textbuffer.h>
|
||||
#include <sortix/kernel/pci.h>
|
||||
#include <libmaxsi/memory.h>
|
||||
#include <libmaxsi/string.h>
|
||||
#include <libmaxsi/format.h>
|
||||
|
@ -42,7 +43,7 @@
|
|||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "syscall.h"
|
||||
#include "pci.h"
|
||||
#include "ata.h"
|
||||
#include "com.h"
|
||||
#include "uart.h"
|
||||
#include "vgatextbuffer.h"
|
||||
|
@ -218,6 +219,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
|||
// Search for PCI devices and load their drivers.
|
||||
PCI::Init();
|
||||
|
||||
// Initialize ATA devices.
|
||||
ATA::Init();
|
||||
|
||||
// Alright, now the system's drivers are loaded and initialized. It is
|
||||
// time to load the initial user-space programs and start execution of
|
||||
// the actual operating system.
|
||||
|
|
423
sortix/pci.cpp
423
sortix/pci.cpp
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
/*******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -14,283 +14,180 @@
|
|||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pci.h
|
||||
Handles basic PCI bus stuff.
|
||||
pci.cpp
|
||||
Functions for handling PCI devices.
|
||||
|
||||
******************************************************************************/
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/kernel/platform.h>
|
||||
#include "cpu.h"
|
||||
#include <libmaxsi/error.h>
|
||||
#include "pci.h"
|
||||
#include <sortix/kernel/log.h>
|
||||
#include "ata.h"
|
||||
#include <sortix/kernel/endian.h>
|
||||
#include <sortix/kernel/pci.h>
|
||||
#include "cpu.h" // TODO: Put this in some <sortix/kernel/cpu.h>
|
||||
|
||||
using namespace Maxsi;
|
||||
// TODO: Verify that the endian conversions in this file actually works. I have
|
||||
// a sneaking suspicion that they won't work on non-little endian platforms.
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace PCI
|
||||
{
|
||||
const uint16_t Config_Address = 0xCF8;
|
||||
const uint16_t Config_Data = 0xCFC;
|
||||
namespace Sortix {
|
||||
namespace PCI {
|
||||
|
||||
uint32_t SwapBytes(uint32_t I)
|
||||
const uint16_t CONFIG_ADDRESS = 0xCF8;
|
||||
const uint16_t CONFIG_DATA = 0xCFC;
|
||||
|
||||
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func)
|
||||
{
|
||||
return (I >> 24) | ((I >> 8) & 0x0000FF00) | ((I << 8) & 0x00FF0000) | (I << 24);
|
||||
//ASSERT(bus < 1UL<<8UL); // bus is 8 bit anyways.
|
||||
ASSERT(slot < 1UL<<5UL);
|
||||
ASSERT(func < 1UL<<3UL);
|
||||
return func << 8U | slot << 11U | bus << 16U | 1 << 31U;
|
||||
}
|
||||
|
||||
const char* ToDeviceDesc(uint32_t ProductInfo, uint32_t DeviceType)
|
||||
void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */)
|
||||
{
|
||||
uint32_t Class = (DeviceType) >> 24;
|
||||
uint32_t SubClass = (DeviceType >> 16) & 0xFF;
|
||||
uint32_t ProgIF = (DeviceType >> 8) & 0xFF;
|
||||
uint32_t RevisionID = (DeviceType) & 0xFF;
|
||||
|
||||
if ( Class == 0x00 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Any device except for VGA-Compatible devices"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "VGA-Compatible Device"; }
|
||||
}
|
||||
if ( Class == 0x01 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "SCSI Bus Controller"; }
|
||||
if ( SubClass == 0x01 ) { return "IDE Controller"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Floppy Disk Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "IPI Bus Controller"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "RAID Controller"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x20 ) { return "ATA Controller (Single DMA)"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x30 ) { return "ATA Controller (Chained DMA)"; }
|
||||
if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "Serial ATA (Direct Port Access)"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Mass Storage Controller"; }
|
||||
}
|
||||
if ( Class == 0x02 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Ethernet Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Token Ring Controller"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "FDDI Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "ATM Controller"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "ISDN Controller"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "WorldFip Controller"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "ATA Controller (Chained DMA)"; }
|
||||
if ( SubClass == 0x06 ) { return "PICMG 2.14 Multi Computing"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Network Controller"; }
|
||||
}
|
||||
if ( Class == 0x03 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "VGA-Compatible Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "8512-Compatible Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "XGA Controller"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "3D Controller (Not VGA-Compatible)"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Display Controller"; }
|
||||
}
|
||||
if ( Class == 0x04 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Video Device"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Audio Device"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Computer Telephony Device"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Multimedia Device"; }
|
||||
}
|
||||
if ( Class == 0x05 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "RAM Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Flash Controller"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Memory Controller"; }
|
||||
}
|
||||
if ( Class == 0x06 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Host Bridge"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "ISA Bridge"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "EISA Bridge"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "MCA Bridge"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "PCI-to-PCI Bridge"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x01 ) { return "PCI-to-PCI Bridge (Subtractive Decode)"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "PCMCIA Bridge"; }
|
||||
if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "NuBus Bridge"; }
|
||||
if ( SubClass == 0x07 && ProgIF == 0x00 ) { return "CardBus Bridge"; }
|
||||
if ( SubClass == 0x08 ) { return "RACEway Bridge"; }
|
||||
if ( SubClass == 0x09 && ProgIF == 0x40 ) { return "PCI-to-PCI Bridge (Semi-Transparent, Primary)"; }
|
||||
if ( SubClass == 0x09 && ProgIF == 0x80 ) { return "PCI-to-PCI Bridge (Semi-Transparent, Secondary)"; }
|
||||
if ( SubClass == 0x0A && ProgIF == 0x00 ) { return "InfiniBrand-to-PCI Host Bridge"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Bridge Device"; }
|
||||
}
|
||||
if ( Class == 0x07 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic XT-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "16450-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x02 ) { return "16550-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x03 ) { return "16650-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x04 ) { return "16750-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x05 ) { return "16850-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x06 ) { return "16950-Compatible Serial Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Parallel Port"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x01 ) { return "Bi-Directional Parallel Port"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x02 ) { return "ECP 1.X Compliant Parallel Port"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x03 ) { return "IEEE 1284 Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0xFE ) { return "IEEE 1284 Target Device"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Multiport Serial Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Generic Modem"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x01 ) { return "Hayes Compatible Modem (16450-Compatible Interface)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x02 ) { return "Hayes Compatible Modem (16550-Compatible Interface)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x03 ) { return "Hayes Compatible Modem (16650-Compatible Interface)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x04 ) { return "Hayes Compatible Modem (16750-Compatible Interface)"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "IEEE 488.1/2 (GPIB) Controller"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "Smart Card"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Communications Device"; }
|
||||
}
|
||||
if ( Class == 0x08 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic 8259 PIC"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "ISA PIC"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x02 ) { return "EISA PIC"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x10 ) { return "I/O APIC Interrupt Controller"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x20 ) { return "I/O(x) APIC Interrupt Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Generic 8237 DMA Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x01 ) { return "ISA DMA Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x02 ) { return "EISA DMA Controller"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Generic 8254 System Timer"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x01 ) { return "ISA System Timer"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x02 ) { return "EISA System Timer"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Generic RTC Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x01 ) { return "ISA RTC Controller"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x01 ) { return "Generic PCI Hot-Plug Controller"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other System Peripheral"; }
|
||||
}
|
||||
if ( Class == 0x09 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Keyboard Controller"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Digitizer"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Mouse Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Scanner Controller"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Gameport Controller (Generic)"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x10 ) { return "Gameport Controller (Legacy)"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Input Controller"; }
|
||||
}
|
||||
if ( Class == 0x0A )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic Docking Station"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Docking Station"; }
|
||||
}
|
||||
if ( Class == 0x0B )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "386 Processor"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "486 Processor"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Pentium Processor"; }
|
||||
if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Alpha Processor"; }
|
||||
if ( SubClass == 0x20 && ProgIF == 0x00 ) { return "PowerPC Processor"; }
|
||||
if ( SubClass == 0x30 && ProgIF == 0x00 ) { return "MIPS Processor"; }
|
||||
if ( SubClass == 0x40 && ProgIF == 0x00 ) { return "Co-Processor"; }
|
||||
}
|
||||
if ( Class == 0x0C )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "IEEE 1394 Controller (FireWire)"; }
|
||||
if ( SubClass == 0x00 && ProgIF == 0x10 ) { return "IEEE 1394 Controller (1394 OpenHCI Spec)"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "ACCESS.bus"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "SSA"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "USB (Universal Host Controller Spec)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x10 ) { return "USB (Open Host Controller Spec)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x20 ) { return "USB2 Host Controller (Intel Enhanced Host Controller Interface)"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x80 ) { return "USB"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0xFE ) { return "USB (Not Host Controller)"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Fibre Channel"; }
|
||||
if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "SMBus"; }
|
||||
if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "InfiniBand"; }
|
||||
if ( SubClass == 0x07 && ProgIF == 0x00 ) { return "IPMI SMIC Interface"; }
|
||||
if ( SubClass == 0x07 && ProgIF == 0x01 ) { return "IPMI Kybd Controller Style Interface"; }
|
||||
if ( SubClass == 0x07 && ProgIF == 0x02 ) { return "IPMI Block Transfer Interface"; }
|
||||
if ( SubClass == 0x08 && ProgIF == 0x02 ) { return "SERCOS Interface Standard (IEC 61491)"; }
|
||||
if ( SubClass == 0x09 && ProgIF == 0x00 ) { return "CANbus"; }
|
||||
}
|
||||
if ( Class == 0x0E )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Message FIFO"; }
|
||||
if ( SubClass == 0x00 ) { return "I20 Architecture"; }
|
||||
}
|
||||
if ( Class == 0x0F )
|
||||
{
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "TV Controller"; }
|
||||
if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Audio Controller"; }
|
||||
if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Voice Controller"; }
|
||||
if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Data Controller"; }
|
||||
}
|
||||
if ( Class == 0x10 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Network and Computing Encryption/Decryption"; }
|
||||
if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Entertainment Encryption/Decryption"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Encryption/Decryption"; }
|
||||
}
|
||||
if ( Class == 0x11 )
|
||||
{
|
||||
if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "DPIO Modules"; }
|
||||
if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Performance Counters"; }
|
||||
if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Communications Syncrhonization Plus Time and Frequency Test/Measurment"; }
|
||||
if ( SubClass == 0x20 && ProgIF == 0x00 ) { return "Management Card"; }
|
||||
if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Data Acquisition/Signal Processing Controller"; }
|
||||
vals[0] = devaddr >> 16U & ((1UL<<8UL)-1);
|
||||
vals[1] = devaddr >> 11U & ((1UL<<3UL)-1);
|
||||
vals[2] = devaddr >> 8U & ((1UL<<5UL)-1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off)
|
||||
{
|
||||
CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
|
||||
return CPU::InPortL(CONFIG_DATA);
|
||||
}
|
||||
|
||||
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val)
|
||||
{
|
||||
CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
|
||||
CPU::OutPortL(CONFIG_DATA, val);
|
||||
}
|
||||
|
||||
uint32_t Read32(uint32_t devaddr, uint8_t off)
|
||||
{
|
||||
return LittleToHost(ReadRaw32(devaddr, off));
|
||||
}
|
||||
|
||||
void Write32(uint32_t devaddr, uint8_t off, uint32_t val)
|
||||
{
|
||||
WriteRaw32(devaddr, off, HostToLittle(val));
|
||||
}
|
||||
|
||||
uint16_t Read16(uint32_t devaddr, uint8_t off)
|
||||
{
|
||||
ASSERT((off & 0x1) == 0);
|
||||
uint8_t alignedoff = off & ~0x3;
|
||||
union { uint16_t val16[2]; uint32_t val32; };
|
||||
val32 = ReadRaw32(devaddr, alignedoff);
|
||||
uint16_t ret = off & 0x2 ? val16[0] : val16[1];
|
||||
return LittleToHost(ret);
|
||||
}
|
||||
|
||||
uint8_t Read8(uint32_t devaddr, uint8_t off)
|
||||
{
|
||||
uint8_t alignedoff = off & ~0x1;
|
||||
union { uint8_t val8[2]; uint32_t val16; };
|
||||
val16 = HostToLittle(Read16(devaddr, alignedoff));
|
||||
uint8_t ret = off & 0x1 ? val8[0] : val8[1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t CheckDevice(uint8_t bus, uint8_t slot, uint8_t func)
|
||||
{
|
||||
return Read32(MakeDevAddr(bus, slot, func), 0x0);
|
||||
}
|
||||
|
||||
pciid_t GetDeviceId(uint32_t devaddr)
|
||||
{
|
||||
pciid_t ret;
|
||||
ret.deviceid = Read16(devaddr, 0x00);
|
||||
ret.vendorid = Read16(devaddr, 0x02);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pcitype_t GetDeviceType(uint32_t devaddr)
|
||||
{
|
||||
pcitype_t ret;
|
||||
ret.classid = Read8(devaddr, 0x08);
|
||||
ret.subclassid = Read8(devaddr, 0x09);
|
||||
ret.progif = Read8(devaddr, 0x0A);
|
||||
ret.revid = Read8(devaddr, 0x0B);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool MatchesSearchCriteria(uint32_t devaddr, pcifind_t pcifind)
|
||||
{
|
||||
pciid_t id = GetDeviceId(devaddr);
|
||||
if ( id.vendorid == 0xFFFF && id.deviceid == 0xFFFF )
|
||||
return false;
|
||||
pcitype_t type = GetDeviceType(devaddr);
|
||||
if ( pcifind.vendorid != 0xFFFF && id.vendorid != pcifind.vendorid )
|
||||
return false;
|
||||
if ( pcifind.deviceid != 0xFFFF && id.deviceid != pcifind.deviceid )
|
||||
return false;
|
||||
if ( pcifind.classid != 0xFF && type.classid != pcifind.classid )
|
||||
return false;
|
||||
if ( pcifind.subclassid != 0xFF && type.subclassid != pcifind.subclassid )
|
||||
return false;
|
||||
if ( pcifind.progif != 0xFF && type.progif != pcifind.progif )
|
||||
return false;
|
||||
if ( pcifind.revid != 0xFF && type.revid != pcifind.revid )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t SearchForDeviceOnBus(uint8_t bus, pcifind_t pcifind)
|
||||
{
|
||||
for ( unsigned slot = 0; slot < 32; slot++ )
|
||||
{
|
||||
unsigned numfuncs = 1;
|
||||
for ( unsigned func = 0; func < numfuncs; func++ )
|
||||
{
|
||||
uint32_t devaddr = MakeDevAddr(bus, slot, func);
|
||||
if ( MatchesSearchCriteria(devaddr, pcifind) )
|
||||
return devaddr;
|
||||
uint8_t header = Read8(devaddr, 0x0D); // Secondary Bus Number.
|
||||
if ( header & 0x80 ) // Multi function device.
|
||||
numfuncs = 8;
|
||||
if ( (header & 0x7F) == 0x01 ) // PCI to PCI bus.
|
||||
{
|
||||
uint8_t subbusid = Read8(devaddr, 0x1A);
|
||||
uint32_t recret = SearchForDeviceOnBus(subbusid, pcifind);
|
||||
if ( recret )
|
||||
return recret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t SearchForDevice(pcifind_t pcifind)
|
||||
{
|
||||
// Search on bus 0 and recurse on other detected busses.
|
||||
return SearchForDeviceOnBus(0, pcifind);
|
||||
}
|
||||
|
||||
// TODO: This is just a hack but will do for now.
|
||||
addr_t ParseDevBar0(uint32_t devaddr)
|
||||
{
|
||||
uint32_t bar0 = Read32(devaddr, 0x10);
|
||||
if ( bar0 & 0x1 ) // IO Space
|
||||
return bar0 & ~0x7UL;
|
||||
else // Memory Space
|
||||
{
|
||||
//uint32_t type = bar0 >> 1 & 0x3;
|
||||
//uint32_t prefetchable = bar0 >> 3 & 0x1;
|
||||
//if ( type == 0x01 )
|
||||
// // TODO: Support 16-bit addresses here.
|
||||
//if ( type == 0x02 )
|
||||
// // TODO: Support 64-bit addresses here.
|
||||
return bar0 & ~0xFUL;
|
||||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
ATA::Init();
|
||||
#if 0
|
||||
Log::Print("PCI Devices: ");
|
||||
|
||||
for ( nat Bus = 0; Bus < 256; Bus++ )
|
||||
{
|
||||
for ( nat Slot = 0; Slot < 32; Slot++ )
|
||||
{
|
||||
for ( nat Function = 0; Function < 8; Function++ )
|
||||
{
|
||||
uint32_t ProductInfo = CheckDevice(Bus, Slot, Function);
|
||||
|
||||
if ( ProductInfo == 0xFFFFFFFF ) { continue; }
|
||||
|
||||
uint32_t DeviceType = ReadLong(Bus, Slot, Function, 0x08);
|
||||
|
||||
const char* DeviceDesc = ToDeviceDesc(ProductInfo, DeviceType);
|
||||
|
||||
if ( DeviceDesc != NULL )
|
||||
{
|
||||
Log::PrintF("%s, ", DeviceDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::PrintF("Unknown PCI Device @ %x:%x.%x (ProductInfo=0x%x, DeviceType=0x%x), ", Bus, Slot, Function, ProductInfo, DeviceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log::Print("\b\b\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t ReadLong(uint8_t Bus, uint8_t Slot, uint8_t Function, uint8_t Offset)
|
||||
{
|
||||
unsigned long LBus = (unsigned long) Bus;
|
||||
unsigned long LSlot = (unsigned long) Slot;
|
||||
unsigned long LFunc = (unsigned long) Function;
|
||||
|
||||
// create configuration address.
|
||||
unsigned long Address = (unsigned long) ( (LBus << 16) | (LSlot << 11) | (LFunc << 8) | (Offset & 0xFC) | ((uint32_t) 0x80000000));
|
||||
|
||||
// Write out the address.
|
||||
CPU::OutPortL(Config_Address, Address);
|
||||
|
||||
// Read in the data.
|
||||
return CPU::InPortL(Config_Data);
|
||||
|
||||
}
|
||||
|
||||
uint32_t CheckDevice(uint8_t Bus, uint8_t Slot, uint8_t Function)
|
||||
{
|
||||
return ReadLong(Bus, Slot, Function, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace PCI
|
||||
} // namespace Sortix
|
||||
|
|
39
sortix/pci.h
39
sortix/pci.h
|
@ -1,39 +0,0 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pci.h
|
||||
Handles basic PCI bus stuff.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_PCI_H
|
||||
#define SORTIX_PCI_H
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace PCI
|
||||
{
|
||||
void Init();
|
||||
uint32_t ReadLong(uint8_t Bus, uint8_t Slot, uint8_t Function, uint8_t Offset);
|
||||
uint32_t CheckDevice(uint8_t Bus, uint8_t Slot, uint8_t Function = 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in a new issue