Refactor PCI BAR support.
This commit is contained in:
parent
a133a7717e
commit
34dbc4d515
|
@ -84,6 +84,12 @@ const uint16_t VBE_MAX_POS_VERSION = 0xB0CF;
|
||||||
const size_t VBE_BANK_SIZE = 64UL * 1024UL;
|
const size_t VBE_BANK_SIZE = 64UL * 1024UL;
|
||||||
volatile uint8_t* const VBE_VIDEO_MEM = (volatile uint8_t*) 0xA0000;
|
volatile uint8_t* const VBE_VIDEO_MEM = (volatile uint8_t*) 0xA0000;
|
||||||
|
|
||||||
|
static addr_t ParseDevBar0(uint32_t devaddr)
|
||||||
|
{
|
||||||
|
pcibar_t bar = PCI::GetBAR(devaddr, 0);
|
||||||
|
return bar.addr();
|
||||||
|
}
|
||||||
|
|
||||||
addr_t DetectBGAFramebuffer()
|
addr_t DetectBGAFramebuffer()
|
||||||
{
|
{
|
||||||
uint32_t devaddr;
|
uint32_t devaddr;
|
||||||
|
@ -94,7 +100,7 @@ addr_t DetectBGAFramebuffer()
|
||||||
pcifind.vendorid = 0x1234;
|
pcifind.vendorid = 0x1234;
|
||||||
pcifind.deviceid = 0x1111;
|
pcifind.deviceid = 0x1111;
|
||||||
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
||||||
return PCI::ParseDevBar0(devaddr);
|
return ParseDevBar0(devaddr);
|
||||||
|
|
||||||
// Search for a generic VGA compatible device.
|
// Search for a generic VGA compatible device.
|
||||||
memset(&pcifind, 255, sizeof(pcifind));
|
memset(&pcifind, 255, sizeof(pcifind));
|
||||||
|
@ -102,7 +108,7 @@ addr_t DetectBGAFramebuffer()
|
||||||
pcifind.subclassid = 0x00;
|
pcifind.subclassid = 0x00;
|
||||||
pcifind.progif = 0x00;
|
pcifind.progif = 0x00;
|
||||||
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
||||||
return PCI::ParseDevBar0(devaddr);
|
return ParseDevBar0(devaddr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -25,6 +25,9 @@
|
||||||
#ifndef SORTIX_PCI_H
|
#ifndef SORTIX_PCI_H
|
||||||
#define SORTIX_PCI_H
|
#define SORTIX_PCI_H
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -52,6 +55,30 @@ typedef struct
|
||||||
uint8_t revid;
|
uint8_t revid;
|
||||||
} pcifind_t;
|
} pcifind_t;
|
||||||
|
|
||||||
|
const uint8_t PCIBAR_TYPE_IOSPACE = 0x0 << 1 | 0x1 << 0;
|
||||||
|
const uint8_t PCIBAR_TYPE_16BIT = 0x1 << 1 | 0x0 << 0;
|
||||||
|
const uint8_t PCIBAR_TYPE_32BIT = 0x0 << 1 | 0x0 << 0;
|
||||||
|
const uint8_t PCIBAR_TYPE_64BIT = 0x2 << 1 | 0x0 << 0;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint64_t addr_raw;
|
||||||
|
uint64_t size_raw;
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint64_t addr() const { return addr_raw & 0xFFFFFFFFFFFFFFF0; }
|
||||||
|
uint64_t size() const { return size_raw & 0xFFFFFFFFFFFFFFFF; }
|
||||||
|
uint8_t type() const { return addr_raw & 0x7; }
|
||||||
|
uint32_t ioaddr() const { return addr_raw & 0xFFFFFFFC; };
|
||||||
|
bool is_prefetchable() const { return addr_raw & 0x8; }
|
||||||
|
bool is_iospace() const { return type() == PCIBAR_TYPE_IOSPACE; }
|
||||||
|
bool is_16bit() const { return type() == PCIBAR_TYPE_16BIT; }
|
||||||
|
bool is_32bit() const { return type() == PCIBAR_TYPE_32BIT; }
|
||||||
|
bool is_64bit() const { return type() == PCIBAR_TYPE_64BIT; }
|
||||||
|
bool is_mmio() const { return is_16bit() || is_32bit() || is_64bit(); }
|
||||||
|
} pcibar_t;
|
||||||
|
|
||||||
namespace PCI {
|
namespace PCI {
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
@ -66,10 +93,11 @@ void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val); // PCI endian
|
||||||
pciid_t GetDeviceId(uint32_t devaddr);
|
pciid_t GetDeviceId(uint32_t devaddr);
|
||||||
pcitype_t GetDeviceType(uint32_t devaddr);
|
pcitype_t GetDeviceType(uint32_t devaddr);
|
||||||
uint32_t SearchForDevice(pcifind_t pcifind);
|
uint32_t SearchForDevice(pcifind_t pcifind);
|
||||||
addr_t ParseDevBar0(uint32_t devaddr);
|
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar);
|
||||||
bool IsIOSpaceBar(uint32_t devaddr, uint8_t bar);
|
pcibar_t GetExpansionROM(uint32_t devaddr);
|
||||||
bool Is64BitBar(uint32_t devaddr, uint8_t bar);
|
void EnableExpansionROM(uint32_t devaddr);
|
||||||
uint64_t GetPCIBAR(uint32_t devaddr, uint8_t bar);
|
void DisableExpansionROM(uint32_t devaddr);
|
||||||
|
bool IsExpansionROMEnabled(uint32_t devaddr);
|
||||||
|
|
||||||
} // namespace PCI
|
} // namespace PCI
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,11 +27,14 @@
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/pci.h>
|
#include <sortix/kernel/pci.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
namespace PCI {
|
namespace PCI {
|
||||||
|
|
||||||
|
static kthread_mutex_t pci_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
const uint16_t CONFIG_ADDRESS = 0xCF8;
|
const uint16_t CONFIG_ADDRESS = 0xCF8;
|
||||||
const uint16_t CONFIG_DATA = 0xCFC;
|
const uint16_t CONFIG_DATA = 0xCFC;
|
||||||
|
|
||||||
|
@ -166,45 +169,85 @@ uint32_t SearchForDevice(pcifind_t pcifind)
|
||||||
return SearchForDeviceOnBus(0, pcifind);
|
return SearchForDeviceOnBus(0, pcifind);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is just a hack but will do for now.
|
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar)
|
||||||
addr_t ParseDevBar0(uint32_t devaddr)
|
|
||||||
{
|
{
|
||||||
uint32_t bar0 = Read32(devaddr, 0x10);
|
ScopedLock lock(&pci_lock);
|
||||||
if ( bar0 & 0x1 ) // IO Space
|
|
||||||
return bar0 & ~0x7UL;
|
uint32_t low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||||
else // Memory Space
|
|
||||||
|
pcibar_t result;
|
||||||
|
result.addr_raw = low;
|
||||||
|
result.size_raw = 0;
|
||||||
|
if ( result.is_64bit() )
|
||||||
{
|
{
|
||||||
//uint32_t type = bar0 >> 1 & 0x3;
|
uint32_t high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
||||||
//uint32_t prefetchable = bar0 >> 3 & 0x1;
|
result.addr_raw |= (uint64_t) high << 32;
|
||||||
//if ( type == 0x01 )
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), 0xFFFFFFFF);
|
||||||
// // TODO: Support 16-bit addresses here.
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+1), 0xFFFFFFFF);
|
||||||
//if ( type == 0x02 )
|
uint32_t size_low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||||
// // TODO: Support 64-bit addresses here.
|
uint32_t size_high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
||||||
return bar0 & ~0xFUL;
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), low);
|
||||||
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+1), high);
|
||||||
|
result.size_raw = (uint64_t) size_high << 32 | (uint64_t) size_low << 0;
|
||||||
|
result.size_raw = ~(result.size_raw & 0xFFFFFFFFFFFFFFF0) + 1;
|
||||||
}
|
}
|
||||||
|
else if ( result.is_32bit() )
|
||||||
|
{
|
||||||
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), 0xFFFFFFFF);
|
||||||
|
uint32_t size_low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||||
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), low);
|
||||||
|
result.size_raw = (uint64_t) size_low << 0;
|
||||||
|
result.size_raw = ~(result.size_raw & 0xFFFFFFF0) + 1;
|
||||||
|
}
|
||||||
|
else if ( result.is_iospace() )
|
||||||
|
{
|
||||||
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), 0xFFFFFFFF);
|
||||||
|
uint32_t size_low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||||
|
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), low);
|
||||||
|
result.size_raw = (uint64_t) size_low << 0;
|
||||||
|
result.size_raw = ~(result.size_raw & 0xFFFFFFFC) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsIOSpaceBar(uint32_t devaddr, uint8_t bar)
|
pcibar_t GetExpansionROM(uint32_t devaddr)
|
||||||
{
|
{
|
||||||
uint32_t val = PCI::Read32(devaddr, 0x10 + 4 * bar);
|
const uint32_t ROM_ADDRESS_MASK = ~UINT32_C(0x7FF);
|
||||||
return val & 0x1;
|
|
||||||
|
ScopedLock lock(&pci_lock);
|
||||||
|
|
||||||
|
uint32_t low = PCI::Read32(devaddr, 0x30);
|
||||||
|
PCI::Write32(devaddr, 0x30, ROM_ADDRESS_MASK | low);
|
||||||
|
uint32_t size_low = PCI::Read32(devaddr, 0x30);
|
||||||
|
PCI::Write32(devaddr, 0x30, low);
|
||||||
|
|
||||||
|
pcibar_t result;
|
||||||
|
result.addr_raw = (low & ROM_ADDRESS_MASK) | PCIBAR_TYPE_32BIT;
|
||||||
|
result.size_raw = ~(size_low & ROM_ADDRESS_MASK) + 1;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Is64BitBar(uint32_t devaddr, uint8_t bar)
|
void EnableExpansionROM(uint32_t devaddr)
|
||||||
{
|
{
|
||||||
uint32_t val = PCI::Read32(devaddr, 0x10 + 4 * bar);
|
ScopedLock lock(&pci_lock);
|
||||||
return (val & 0x3 << 1) == 0x2 << 1;
|
|
||||||
|
PCI::Write32(devaddr, 0x30, PCI::Read32(devaddr, 0x30) | 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetPCIBAR(uint32_t devaddr, uint8_t bar)
|
void DisableExpansionROM(uint32_t devaddr)
|
||||||
{
|
{
|
||||||
uint64_t low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
ScopedLock lock(&pci_lock);
|
||||||
if ( (low & (0x3 << 1)) != (0x2 << 1) )
|
|
||||||
return low & 0xFFFFFFF0ULL;
|
PCI::Write32(devaddr, 0x30, PCI::Read32(devaddr, 0x30) & ~UINT32_C(0x1));
|
||||||
uint64_t high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
|
||||||
return (low & 0xFFFFFFF0ULL) | high << 32ULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsExpansionROMEnabled(uint32_t devaddr)
|
||||||
|
{
|
||||||
|
ScopedLock lock(&pci_lock);
|
||||||
|
|
||||||
|
return PCI::Read32(devaddr, 0x30) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue