1
0
Fork 0
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:
Jonas 'Sortie' Termansen 2012-07-28 01:40:25 +02:00
parent 5f6ca5e729
commit 19b5451f3b
4 changed files with 244 additions and 307 deletions

View 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

View file

@ -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.

View file

@ -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

View file

@ -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