mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Refactor PCI BAR support.
This commit is contained in:
parent
a133a7717e
commit
34dbc4d515
3 changed files with 110 additions and 33 deletions
|
@ -84,6 +84,12 @@ const uint16_t VBE_MAX_POS_VERSION = 0xB0CF;
|
|||
const size_t VBE_BANK_SIZE = 64UL * 1024UL;
|
||||
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()
|
||||
{
|
||||
uint32_t devaddr;
|
||||
|
@ -94,7 +100,7 @@ addr_t DetectBGAFramebuffer()
|
|||
pcifind.vendorid = 0x1234;
|
||||
pcifind.deviceid = 0x1111;
|
||||
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
||||
return PCI::ParseDevBar0(devaddr);
|
||||
return ParseDevBar0(devaddr);
|
||||
|
||||
// Search for a generic VGA compatible device.
|
||||
memset(&pcifind, 255, sizeof(pcifind));
|
||||
|
@ -102,7 +108,7 @@ addr_t DetectBGAFramebuffer()
|
|||
pcifind.subclassid = 0x00;
|
||||
pcifind.progif = 0x00;
|
||||
if ( (devaddr = PCI::SearchForDevice(pcifind)) )
|
||||
return PCI::ParseDevBar0(devaddr);
|
||||
return ParseDevBar0(devaddr);
|
||||
|
||||
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.
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
|||
#ifndef SORTIX_PCI_H
|
||||
#define SORTIX_PCI_H
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
typedef struct
|
||||
|
@ -52,6 +55,30 @@ typedef struct
|
|||
uint8_t revid;
|
||||
} 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 {
|
||||
|
||||
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);
|
||||
pcitype_t GetDeviceType(uint32_t devaddr);
|
||||
uint32_t SearchForDevice(pcifind_t pcifind);
|
||||
addr_t ParseDevBar0(uint32_t devaddr);
|
||||
bool IsIOSpaceBar(uint32_t devaddr, uint8_t bar);
|
||||
bool Is64BitBar(uint32_t devaddr, uint8_t bar);
|
||||
uint64_t GetPCIBAR(uint32_t devaddr, uint8_t bar);
|
||||
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar);
|
||||
pcibar_t GetExpansionROM(uint32_t devaddr);
|
||||
void EnableExpansionROM(uint32_t devaddr);
|
||||
void DisableExpansionROM(uint32_t devaddr);
|
||||
bool IsExpansionROMEnabled(uint32_t devaddr);
|
||||
|
||||
} // namespace PCI
|
||||
} // 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.
|
||||
|
||||
|
@ -27,11 +27,14 @@
|
|||
|
||||
#include <sortix/kernel/cpu.h>
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/pci.h>
|
||||
|
||||
namespace Sortix {
|
||||
namespace PCI {
|
||||
|
||||
static kthread_mutex_t pci_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
const uint16_t CONFIG_ADDRESS = 0xCF8;
|
||||
const uint16_t CONFIG_DATA = 0xCFC;
|
||||
|
||||
|
@ -166,45 +169,85 @@ uint32_t SearchForDevice(pcifind_t pcifind)
|
|||
return SearchForDeviceOnBus(0, pcifind);
|
||||
}
|
||||
|
||||
// TODO: This is just a hack but will do for now.
|
||||
addr_t ParseDevBar0(uint32_t devaddr)
|
||||
pcibar_t GetBAR(uint32_t devaddr, uint8_t bar)
|
||||
{
|
||||
uint32_t bar0 = Read32(devaddr, 0x10);
|
||||
if ( bar0 & 0x1 ) // IO Space
|
||||
return bar0 & ~0x7UL;
|
||||
else // Memory Space
|
||||
ScopedLock lock(&pci_lock);
|
||||
|
||||
uint32_t low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||
|
||||
pcibar_t result;
|
||||
result.addr_raw = low;
|
||||
result.size_raw = 0;
|
||||
if ( result.is_64bit() )
|
||||
{
|
||||
//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;
|
||||
uint32_t high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
||||
result.addr_raw |= (uint64_t) high << 32;
|
||||
PCI::Write32(devaddr, 0x10 + 4 * (bar+0), 0xFFFFFFFF);
|
||||
PCI::Write32(devaddr, 0x10 + 4 * (bar+1), 0xFFFFFFFF);
|
||||
uint32_t size_low = PCI::Read32(devaddr, 0x10 + 4 * (bar+0));
|
||||
uint32_t size_high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
||||
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);
|
||||
return val & 0x1;
|
||||
const uint32_t ROM_ADDRESS_MASK = ~UINT32_C(0x7FF);
|
||||
|
||||
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);
|
||||
return (val & 0x3 << 1) == 0x2 << 1;
|
||||
ScopedLock lock(&pci_lock);
|
||||
|
||||
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));
|
||||
if ( (low & (0x3 << 1)) != (0x2 << 1) )
|
||||
return low & 0xFFFFFFF0ULL;
|
||||
uint64_t high = PCI::Read32(devaddr, 0x10 + 4 * (bar+1));
|
||||
return (low & 0xFFFFFFF0ULL) | high << 32ULL;
|
||||
ScopedLock lock(&pci_lock);
|
||||
|
||||
PCI::Write32(devaddr, 0x30, PCI::Read32(devaddr, 0x30) & ~UINT32_C(0x1));
|
||||
}
|
||||
|
||||
bool IsExpansionROMEnabled(uint32_t devaddr)
|
||||
{
|
||||
ScopedLock lock(&pci_lock);
|
||||
|
||||
return PCI::Read32(devaddr, 0x30) & 0x1;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue