Added PCI device detection and a start script.
This commit is contained in:
253
targets/_any/include/drivers/pci.hpp
Normal file
253
targets/_any/include/drivers/pci.hpp
Normal file
@@ -0,0 +1,253 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_DRIVERS_PCI_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_DRIVERS_PCI_HPP_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace baos::pci
|
||||
{
|
||||
enum class BaseClass : std::uint8_t
|
||||
{
|
||||
UNCLASSIFIED = 0x0,
|
||||
MASS_STORAGE_CONTROLLER = 0x1,
|
||||
NETWORK_CONTROLLER = 0x2,
|
||||
DISPLAY_CONTROLLER = 0x3,
|
||||
MULTIMEDIA_CONTROLLER = 0x4,
|
||||
MEMORY_CONTROLLER = 0x5,
|
||||
BRIDGE = 0x6,
|
||||
SIMPLE_COMMUNICATION_CONTROLLER = 0x7,
|
||||
BASE_SYSTEM_PERIPHERAL = 0x8,
|
||||
INPUT_DEVICE_CONTROLLER = 0x9,
|
||||
DOCKING_STATION = 0xA,
|
||||
PROCESSOR = 0xB,
|
||||
SERIAL_BUS_CONTROLLER = 0xC,
|
||||
WIRELESS_CONTROLLER = 0xD,
|
||||
INTELLIGENT_CONTROLLER = 0xE,
|
||||
SATELLITE_COMMUNICATION_CONTROLLER = 0xF,
|
||||
ENCRYPTION_CONTROLLER = 0x10,
|
||||
SIGNAL_PROCESSING_CONTROLLER = 0x11,
|
||||
PROCESSING_ACCELERATOR = 0x12,
|
||||
NON_ESSENTIAL_INSTRUMENTATION = 0x13,
|
||||
CO_PROCESSOR = 0x40,
|
||||
UNASSIGNED = 0xFF
|
||||
};
|
||||
|
||||
enum class SubClass : std::uint8_t
|
||||
{
|
||||
// for 0x1 - Mass Storage Controller
|
||||
IDE_CONTROLLER = 0x1,
|
||||
FLOPPY_DISK_CONTROLLER = 0x2,
|
||||
IPI_BUS_CONTROLLER = 0x3,
|
||||
RAID_CONTROLLER = 0x4,
|
||||
ATA_CONTROLLER = 0x5,
|
||||
SERIAL_ATA_CONTROLLER = 0x6,
|
||||
SERIAL_ATTACHED_SCSI_CONTROLLER = 0x7,
|
||||
NON_VOLATILE_MEMORY_CONTROLLER = 0x8,
|
||||
OTHER = 0x80,
|
||||
|
||||
// for 0x2 - Network Controller
|
||||
ETHERNET_CONTROLLER = 0x0,
|
||||
TOKEN_RING_CONTROLLER = 0x1,
|
||||
FDDI_CONTROLLER = 0x2,
|
||||
ATM_CONTROLLER = 0x3,
|
||||
ISDN_CONTROLLER = 0x4,
|
||||
WORLDFIP_CONTROLLER = 0x5,
|
||||
PICMG_CONTROLLER = 0x6,
|
||||
INFIBAND_CONTROLLER = 0x7,
|
||||
FABRIC_CONTROLLER = 0x8,
|
||||
|
||||
// for 0x3 - Display Controller
|
||||
VGA_COMPATIBLE_CONTROLLER = 0x0,
|
||||
XGA_CONTROLLER = 0x1,
|
||||
NOT_VGA_COMPATIBLE_3D_CONTROLLER = 0x2,
|
||||
|
||||
// for 0x4 - Multimedia Controller
|
||||
MULTIMEDIA_VIDEO_CONTROLLER = 0x0,
|
||||
MULTIMEDIA_AUDIO_CONTROLLER = 0x1,
|
||||
COMPUTER_TELEPHONY_DEVICE = 0x2,
|
||||
AUDIO_DEVICE = 0x3,
|
||||
|
||||
// for 0x5 - Memory Controller
|
||||
RAM_CONTROLLER = 0x0,
|
||||
FLASH_CONTROLLER = 0x1,
|
||||
|
||||
// for 0x6 - Bridge
|
||||
HOST_BRIDGE = 0x0,
|
||||
ISA_BRIDGE = 0x1,
|
||||
EISA_BRIDGE = 0x2,
|
||||
MCA_BRIDGE = 0x3,
|
||||
PCI_TO_PCI_BRIDGE = 0x4,
|
||||
PCMCIA_BRIDGE = 0x5,
|
||||
NUBUS_BRIDGE = 0x6,
|
||||
CARDBUS_BRIDGE = 0x7,
|
||||
RACEWAY_BRIDGE = 0x8,
|
||||
PCI_TO_PCI_BRIDGE_2 = 0x9,
|
||||
INFINIBAND_TO_PCI_HOST_BRIDGE = 0xA,
|
||||
|
||||
// for 0x7 - Simple Communication Controller
|
||||
SERIAL_CONTROLLER = 0x0,
|
||||
PARALLEL_CONTROLLER = 0x1,
|
||||
MULTIPORT_SERIAL_CONTROLLER = 0x2,
|
||||
MODEM = 0x3,
|
||||
IEEE488_CONTROLLER = 0x4,
|
||||
SMART_CARD_CONTROLLER = 0x5,
|
||||
|
||||
// for 0x8 - Base System Peripheral
|
||||
PIC = 0x1,
|
||||
DMA_CONTROLLER = 0x1,
|
||||
TIMER = 0x2,
|
||||
RTC_CONTROLLER = 0x3,
|
||||
PCI_HOT_PLUG_CONTROLLER = 0x4,
|
||||
SD_HOST_CONTROLLER = 0x5,
|
||||
IOMMU = 0x6,
|
||||
|
||||
// for 0x9 - Input Device Controller
|
||||
KEYBOARD_CONTROLLER = 0x0,
|
||||
DIGITIZER_PEN = 0x1,
|
||||
MOUSE_CONTROLLER = 0x2,
|
||||
SCANNER_CONTROLLER = 0x3,
|
||||
GAMEPORT_CONTROLLER = 0x4,
|
||||
|
||||
// for 0xA - Docking Station
|
||||
GENERIC = 0x0,
|
||||
|
||||
// for 0xB - Processor
|
||||
_386 = 0x0,
|
||||
_486 = 0x1,
|
||||
PENTIUM = 0x2,
|
||||
PENTIUM_PRO = 0x3,
|
||||
ALPHA = 0x10,
|
||||
POWERPC = 0x20,
|
||||
MIPS = 0x30,
|
||||
CO_PROCESSOR = 0x40,
|
||||
|
||||
// for 0xC - Serial Bus Controller
|
||||
FIREWIRE_CONTROLLER = 0x0,
|
||||
ACCESS_BUS_CONTROLLER = 0x1,
|
||||
SSA = 0x2,
|
||||
USB_CONTROLLER = 0x3,
|
||||
FIBRE_CHANNEL = 0x4,
|
||||
SMBUS_CONTROLLER = 0x5,
|
||||
INFINIBAND_CONTROLLER = 0x6,
|
||||
IPMI_INTERFACE = 0x7,
|
||||
SERCOS_INTERFACE = 0x8,
|
||||
CANBUS_CONTROLLER = 0x9,
|
||||
|
||||
// for 0xD - Wireless Controller
|
||||
IRDA_COMPATIBLE_CONTROLLER = 0xD,
|
||||
CONSUMER_IR_CONTROLLER = 0x1,
|
||||
RF_CONTROLLER = 0x10,
|
||||
BLUETOOTH_CONTROLLER = 0x11,
|
||||
BROADBAND_CONTROLLER = 0x12,
|
||||
ETHERNET_CONTROLLER_8021A = 0x20,
|
||||
ETHERNET_CONTROLLER_8021B = 0x21,
|
||||
|
||||
// for 0xE - Intelligent Controller
|
||||
I20 = 0x0,
|
||||
|
||||
// for 0xF - Satellite Communication Controller
|
||||
SATELLITE_TV_CONTROLLER = 0x1,
|
||||
SATELLITE_AUDIO_CONTROLLER = 0x2,
|
||||
SATELLITE_VOICE_CONTROLLER = 0x3,
|
||||
SATELLITE_DATA_CONTROLLER = 0x4,
|
||||
|
||||
// for 0x10 - Encryption Controller
|
||||
NETWORK_AND_COMPUTING_EN_DECRYPTION = 0x0,
|
||||
ENTERTAINMENT_EN_DECRYPTION = 0x10,
|
||||
|
||||
// for 0x11 - Signal Processing Controller
|
||||
DPIO_MODULE = 0x0,
|
||||
PERFORMANCE_COUNTER = 0x1,
|
||||
COMMUNICATION_SYNCHRONIZER = 0x10,
|
||||
SIGNAL_PROCESSING_MANAGEMENT = 0x20
|
||||
};
|
||||
|
||||
enum class HeaderType : std::uint8_t
|
||||
{
|
||||
GENERAL_DEVICE = 0x0,
|
||||
PCI_TO_PCI_BRIDGE = 0x1,
|
||||
PCI_TO_CARDBUS_BRIDGE = 0x2
|
||||
};
|
||||
|
||||
struct Header
|
||||
{
|
||||
std::uint8_t bus;
|
||||
std::uint8_t device;
|
||||
std::uint8_t function;
|
||||
std::uint8_t pad_;
|
||||
|
||||
std::uint16_t vendorID;
|
||||
std::uint16_t deviceID;
|
||||
std::uint16_t command;
|
||||
std::uint16_t status;
|
||||
std::uint8_t revisionID;
|
||||
std::uint8_t progIf;
|
||||
SubClass subClass;
|
||||
BaseClass baseClass;
|
||||
std::uint8_t cacheLineSize;
|
||||
std::uint8_t latencyTimer;
|
||||
HeaderType headerType : 7;
|
||||
bool multiFunction : 1;
|
||||
std::uint8_t builtinSelfTest;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct GeneralDeviceHeader : Header
|
||||
{
|
||||
std::uint32_t bar0;
|
||||
std::uint32_t bar1;
|
||||
std::uint32_t bar2;
|
||||
std::uint32_t bar3;
|
||||
std::uint32_t bar4;
|
||||
std::uint32_t bar5;
|
||||
std::uint32_t cardbusCISPointer;
|
||||
std::uint16_t subsystemVendorID;
|
||||
std::uint16_t subsystemID;
|
||||
std::uint32_t expansionROMBaseAddress;
|
||||
std::uint8_t capabilitiesPointer;
|
||||
std::uint64_t reserved : 56;
|
||||
std::uint8_t interruptLine;
|
||||
std::uint8_t interruptPIN;
|
||||
std::uint8_t minGrant;
|
||||
std::uint8_t maxLatency;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PCIToPCIBridgeHeader : Header
|
||||
{
|
||||
std::uint32_t bar0;
|
||||
std::uint32_t bar1;
|
||||
std::uint8_t primaryBusNumber;
|
||||
std::uint8_t secondaryBusNumber;
|
||||
std::uint8_t subordinateBusNumber;
|
||||
std::uint8_t secondaryLatencyTimer;
|
||||
std::uint8_t ioBase;
|
||||
std::uint8_t ioLimit;
|
||||
std::uint16_t secondaryStatus;
|
||||
std::uint16_t memoryBase;
|
||||
std::uint16_t memoryLimit;
|
||||
std::uint16_t prefetchableMemoryBase;
|
||||
std::uint16_t prefetchableMemoryLimit;
|
||||
std::uint32_t prefetchableBaseUpper32;
|
||||
std::uint32_t prefetchableLimitUpper32;
|
||||
std::uint16_t ioBaseUpper16;
|
||||
std::uint16_t ioLimitUpper16;
|
||||
std::uint8_t capbiliityPointer;
|
||||
std::uint32_t reserved : 24;
|
||||
std::uint32_t expansionRomBaseAddress;
|
||||
std::uint8_t interruptLine;
|
||||
std::uint8_t interruptPin;
|
||||
std::uint16_t bridgeControl;
|
||||
} __attribute__((packed));
|
||||
|
||||
[[nodiscard]] std::vector<Header> enumerateDevices() noexcept;
|
||||
[[nodiscard]] bool getGeneralDeviceHeader(std::uint8_t bus, std::uint8_t device, std::uint8_t function, GeneralDeviceHeader& outHeader) noexcept;
|
||||
|
||||
[[nodiscard]] inline bool getGeneralDeviceHeader(const Header& header, GeneralDeviceHeader& outHeader) noexcept
|
||||
{
|
||||
return getGeneralDeviceHeader(header.bus, header.device, header.function, outHeader);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_DRIVERS_PCI_HPP_INCLUDED)
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define writePortByte(port, value) \
|
||||
#define writePort8(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outb %0, %1" \
|
||||
@@ -16,7 +16,7 @@
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPortByte(port) \
|
||||
#define readPort8(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint8_t value = 0; \
|
||||
@@ -28,9 +28,53 @@
|
||||
return value; \
|
||||
}()
|
||||
|
||||
#define writePort16(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outw %0, %1" \
|
||||
: \
|
||||
: "a"(static_cast<std::uint16_t>(value)), \
|
||||
"Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPort16(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint16_t value = 0; \
|
||||
__asm__ __volatile__( \
|
||||
"inw %1, %0" \
|
||||
: "=a"(value) \
|
||||
: "Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
return value; \
|
||||
}()
|
||||
|
||||
#define writePort32(port, value) \
|
||||
{ \
|
||||
__asm__ __volatile__( \
|
||||
"outl %0, %1" \
|
||||
: \
|
||||
: "a"(static_cast<std::uint32_t>(value)), \
|
||||
"Nd"(static_cast<std::uint16_t>(port)) \
|
||||
); \
|
||||
}
|
||||
|
||||
#define readPort32(port) \
|
||||
[&]() \
|
||||
{ \
|
||||
std::uint32_t value = 0; \
|
||||
__asm__ __volatile__( \
|
||||
"inl %1, %0" \
|
||||
: "=a"(value) \
|
||||
: "Nd"(static_cast<std::uint32_t>(port)) \
|
||||
); \
|
||||
return value; \
|
||||
}()
|
||||
|
||||
inline void ioWait() noexcept
|
||||
{
|
||||
writePortByte(0x80, 0);
|
||||
writePort8(0x80, 0);
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_PORT_HPP_INCLUDED)
|
||||
|
||||
@@ -19,31 +19,31 @@ inline constexpr std::uint16_t PORT_COM8 = 0x4E8;
|
||||
|
||||
[[nodiscard]] inline bool initSerialPort(std::uint16_t port) noexcept
|
||||
{
|
||||
writePortByte(port + 1, 0x00); // Disable all interrupts
|
||||
writePortByte(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
writePortByte(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
writePortByte(port + 1, 0x00); // (hi byte)
|
||||
writePortByte(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
writePortByte(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
writePortByte(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
writePortByte(port + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
writePortByte(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
writePort8(port + 1, 0x00); // Disable all interrupts
|
||||
writePort8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
|
||||
writePort8(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||
writePort8(port + 1, 0x00); // (hi byte)
|
||||
writePort8(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
writePort8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
writePort8(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
writePort8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||
writePort8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||
|
||||
// Check if serial is faulty (i.e: not same byte as sent)
|
||||
if(readPortByte(port + 0) != 0xAE) {
|
||||
if(readPort8(port + 0) != 0xAE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If serial is not faulty set it in normal operation mode
|
||||
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||
writePortByte(port + 4, 0x0F);
|
||||
writePort8(port + 4, 0x0F);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void serialWrite(std::uint16_t port, std::uint8_t data) noexcept
|
||||
{
|
||||
while ((readPortByte(port + 5) & 0x20) == 0);
|
||||
writePortByte(port, data);
|
||||
while ((readPort8(port + 5) & 0x20) == 0);
|
||||
writePort8(port, data);
|
||||
}
|
||||
|
||||
inline void serialWriteString(std::uint16_t port, const char* str) noexcept
|
||||
|
||||
Reference in New Issue
Block a user