mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Update files
This commit is contained in:
parent
32b44a50d4
commit
4b6683823f
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@
|
||||
*.map
|
||||
*.fsys
|
||||
*.log
|
||||
files/*.psf
|
||||
Files/*.psf
|
||||
|
@ -78,6 +78,20 @@ namespace CPU
|
||||
#endif
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
asmv("cli");
|
||||
asmv("hlt");
|
||||
#elif defined(__aarch64__)
|
||||
asmv("msr daifset, #2");
|
||||
asmv("wfe");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Halt()
|
||||
{
|
||||
#if defined(__amd64__) || defined(__i386__)
|
@ -4,7 +4,7 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include "HeapAllocators/Xalloc.hpp"
|
||||
#include "../lib/liballoc_1_1.h"
|
||||
#include "../Library/liballoc_1_1.h"
|
||||
|
||||
using namespace Memory;
|
||||
|
844
Core/PeripheralComponentInterconnect.cpp
Normal file
844
Core/PeripheralComponentInterconnect.cpp
Normal file
@ -0,0 +1,844 @@
|
||||
#include <pci.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
|
||||
namespace PCI
|
||||
{
|
||||
namespace Descriptors
|
||||
{
|
||||
char HexToStringOutput8[128];
|
||||
const char *u8ToHexString(uint8_t Value)
|
||||
{
|
||||
uint8_t *ValuePtr = &Value;
|
||||
uint8_t *Ptr;
|
||||
uint8_t Temp;
|
||||
uint8_t Size = 1 * 2 - 1;
|
||||
for (uint8_t i = 0; i < Size; i++)
|
||||
{
|
||||
Ptr = ((uint8_t *)ValuePtr + i);
|
||||
Temp = ((*Ptr & 0xF0) >> 4);
|
||||
HexToStringOutput8[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
|
||||
Temp = ((*Ptr & 0x0F));
|
||||
HexToStringOutput8[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
|
||||
}
|
||||
HexToStringOutput8[Size + 1] = 0;
|
||||
return HexToStringOutput8;
|
||||
}
|
||||
|
||||
char HexToStringOutput32[128];
|
||||
const char *u32ToHexString(uint32_t Value)
|
||||
{
|
||||
uint32_t *ValuePtr = &Value;
|
||||
uint8_t *Ptr;
|
||||
uint8_t Temp;
|
||||
uint8_t Size = 4 * 2 - 1;
|
||||
for (uint8_t i = 0; i < Size; i++)
|
||||
{
|
||||
Ptr = ((uint8_t *)ValuePtr + i);
|
||||
Temp = ((*Ptr & 0xF0) >> 4);
|
||||
HexToStringOutput32[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
|
||||
Temp = ((*Ptr & 0x0F));
|
||||
HexToStringOutput32[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
|
||||
}
|
||||
HexToStringOutput32[Size + 1] = 0;
|
||||
return HexToStringOutput32;
|
||||
}
|
||||
|
||||
const char *MassStorageControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "SCSI Bus Controller";
|
||||
case 0x01:
|
||||
return "IDE Controller";
|
||||
case 0x02:
|
||||
return "Floppy Disk Controller";
|
||||
case 0x03:
|
||||
return "IPI Bus Controller";
|
||||
case 0x04:
|
||||
return "RAID Controller";
|
||||
case 0x05:
|
||||
return "ATA Controller";
|
||||
case 0x06:
|
||||
return "Serial ATA";
|
||||
case 0x07:
|
||||
return "Serial Attached SCSI Controller";
|
||||
case 0x08:
|
||||
return "Non-Volatile Memory Controller";
|
||||
case 0x80:
|
||||
return "Mass Storage Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown mass storage controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *NetworkControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "Ethernet Controller";
|
||||
case 0x01:
|
||||
return "Token Ring Controller";
|
||||
case 0x02:
|
||||
return "FDDI Controller";
|
||||
case 0x03:
|
||||
return "ATM Controller";
|
||||
case 0x04:
|
||||
return "ISDN Controller";
|
||||
case 0x05:
|
||||
return "WorldFip Controller";
|
||||
case 0x06:
|
||||
return "PICMG HyperCard Controller";
|
||||
case 0x07:
|
||||
return "Infiniband Controller";
|
||||
case 0x08:
|
||||
return "Fabric Controller";
|
||||
case 0x80:
|
||||
return "Network Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown network controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *DisplayControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "VGA Compatible Controller";
|
||||
case 0x01:
|
||||
return "XGA Controller";
|
||||
case 0x02:
|
||||
return "3D Controller";
|
||||
case 0x80:
|
||||
return "Display Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown display controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *CommunicationControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "Serial Controller";
|
||||
case 0x01:
|
||||
return "Parallel Controller";
|
||||
case 0x02:
|
||||
return "Multi-Serial Controller";
|
||||
case 0x03:
|
||||
return "IEEE-1284 Controller";
|
||||
case 0x04:
|
||||
return "ATM Controller";
|
||||
case 0x05:
|
||||
return "Object Storage Controller";
|
||||
case 0x80:
|
||||
return "Communication controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown communication controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
// not sure if it's right
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "Unclassified";
|
||||
case 0x01:
|
||||
return "Keyboard";
|
||||
case 0x02:
|
||||
return "Pointing Device";
|
||||
case 0x03:
|
||||
return "Mouse";
|
||||
case 0x04:
|
||||
return "Scanner";
|
||||
case 0x05:
|
||||
return "Gameport";
|
||||
case 0x80:
|
||||
return "Unclassified";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown base system peripheral %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *SerialBusControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "FireWire (IEEE 1394) Controller";
|
||||
case 0x01:
|
||||
return "ACCESS Bus Controller";
|
||||
case 0x02:
|
||||
return "SSA Controller";
|
||||
case 0x03:
|
||||
return "USB Controller";
|
||||
case 0x04:
|
||||
return "Fibre Channel Controller";
|
||||
case 0x05:
|
||||
return "SMBus Controller";
|
||||
case 0x06:
|
||||
return "Infiniband Controller";
|
||||
case 0x07:
|
||||
return "IPMI Interface Controller";
|
||||
case 0x08:
|
||||
return "SERCOS Interface (IEC 61491) Controller";
|
||||
case 0x09:
|
||||
return "CANbus Controller";
|
||||
case 0x80:
|
||||
return "Serial Bus Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown serial bus controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *BridgeDeviceSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "Host Bridge";
|
||||
case 0x01:
|
||||
return "ISA Bridge";
|
||||
case 0x02:
|
||||
return "EISA Bridge";
|
||||
case 0x03:
|
||||
return "MCA Bridge";
|
||||
case 0x04:
|
||||
return "PCI-to-PCI Bridge";
|
||||
case 0x05:
|
||||
return "PCMCIA Bridge";
|
||||
case 0x06:
|
||||
return "NuBus Bridge";
|
||||
case 0x07:
|
||||
return "CardBus Bridge";
|
||||
case 0x08:
|
||||
return "RACEway Bridge";
|
||||
case 0x09:
|
||||
return "PCI-to-PCI Bridge";
|
||||
case 0x0A:
|
||||
return "InfiniBand-to-PCI Host Bridge";
|
||||
case 0x80:
|
||||
return "Bridge Device";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown bridge device %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *WirelessControllerSubclassName(uint8_t SubclassCode)
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x11:
|
||||
return "Bluetooth";
|
||||
case 0x20:
|
||||
return "802.1a controller";
|
||||
case 0x21:
|
||||
return "802.1b controller";
|
||||
case 0x80:
|
||||
return "Wireless controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown wireless controller %02x", SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *GetVendorName(uint32_t VendorID)
|
||||
{
|
||||
switch (VendorID)
|
||||
{
|
||||
case 0x1000:
|
||||
return "Symbios Logic";
|
||||
case 0x1B36:
|
||||
case 0x1AF4:
|
||||
return "Red Hat, Inc.";
|
||||
case 0x10EC:
|
||||
return "Realtek Semiconductor Co., Ltd.";
|
||||
case 0x80EE:
|
||||
return "VirtualBox";
|
||||
case 0x1274:
|
||||
return "Ensoniq";
|
||||
case 0x1234:
|
||||
return "QEMU";
|
||||
case 0x15AD:
|
||||
return "VMware";
|
||||
case 0x8086:
|
||||
return "Intel Corporation";
|
||||
case 0x1022:
|
||||
return "Advanced Micro Devices, Inc.";
|
||||
case 0x10DE:
|
||||
return "NVIDIA Corporation";
|
||||
case 0x1AE0:
|
||||
return "Google, Inc.";
|
||||
case 0x1a58:
|
||||
return "Razer USA Ltd.";
|
||||
case 0x1414:
|
||||
return "Microsoft Corporation";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown vendor %04x", VendorID);
|
||||
return u32ToHexString(VendorID);
|
||||
}
|
||||
|
||||
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID)
|
||||
{
|
||||
switch (VendorID)
|
||||
{
|
||||
case SymbiosLogic:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x30:
|
||||
return "53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI";
|
||||
case 0x1000:
|
||||
return "63C815";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RedHat:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x1000:
|
||||
case 0x1041:
|
||||
return "Virtio network device";
|
||||
case 0x1001:
|
||||
case 0x1042:
|
||||
return "Virtio block device";
|
||||
case 0x1002:
|
||||
case 0x1045:
|
||||
return "Virtio memory balloon";
|
||||
case 0x1003:
|
||||
case 0x1043:
|
||||
return "Virtio console";
|
||||
case 0x1004:
|
||||
case 0x1048:
|
||||
return "Virtio SCSI";
|
||||
case 0x1005:
|
||||
case 0x1044:
|
||||
return "Virtio RNG";
|
||||
case 0x1009:
|
||||
case 0x1049:
|
||||
case 0x105a:
|
||||
return "Virtio filesystem";
|
||||
case 0x1050:
|
||||
return "Virtio GPU";
|
||||
case 0x1052:
|
||||
return "Virtio input";
|
||||
case 0x1053:
|
||||
return "Virtio socket";
|
||||
case 1110:
|
||||
return "Inter-VM shared memory";
|
||||
case 0x1af41100:
|
||||
return "QEMU Virtual Machine";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REDHat2:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x0001:
|
||||
return "QEMU PCI-PCI bridge";
|
||||
case 0x0002:
|
||||
return "QEMU PCI 16550A Adapter";
|
||||
case 0x0003:
|
||||
return "QEMU PCI Dual-port 16550A Adapter";
|
||||
case 0x0004:
|
||||
return "QEMU PCI Quad-port 16550A Adapter";
|
||||
case 0x0005:
|
||||
return "QEMU PCI Test Device";
|
||||
case 0x0006:
|
||||
return "PCI Rocker Ethernet switch device";
|
||||
case 0x0007:
|
||||
return "PCI SD Card Host Controller Interface";
|
||||
case 0x0008:
|
||||
return "QEMU PCIe Host bridge";
|
||||
case 0x0009:
|
||||
return "QEMU PCI Expander bridge";
|
||||
case 0x000A:
|
||||
return "PCI-PCI bridge (multiseat)";
|
||||
case 0x000B:
|
||||
return "QEMU PCIe Expander bridge";
|
||||
case 0x000C:
|
||||
return "QEMU PCIe Root port";
|
||||
case 0x000D:
|
||||
return "QEMU XHCI Host Controller";
|
||||
case 0x0010:
|
||||
return "QEMU NVM Express Controller";
|
||||
case 0x0100:
|
||||
return "QXL paravirtual graphic card";
|
||||
case 0x1AF41100:
|
||||
return "QEMU Virtual Machine";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Realtek:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x8029:
|
||||
return "RTL-8029(AS)";
|
||||
case 0x8139:
|
||||
return "RTL-8139/8139C/8139C+ Ethernet Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VirtualBox:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0xCAFE:
|
||||
return "VirtualBox Guest Service";
|
||||
case 0xBEEF:
|
||||
return "VirtualBox Graphics Adapter";
|
||||
case 0x0021:
|
||||
return "USB Tablet";
|
||||
case 0x0022:
|
||||
return "Multitouch tablet";
|
||||
case 0x4E56:
|
||||
return "NVM Express";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Ensoniq:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x5000:
|
||||
return "ES1370 [AudioPCI]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEMU:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x1111:
|
||||
return "QEMU Display";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VMware:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x0740:
|
||||
return "Virtual Machine Communication Interface";
|
||||
case 0x0405:
|
||||
return "SVGA II Adapter";
|
||||
case 0x0790:
|
||||
return "PCI bridge";
|
||||
case 0x07A0:
|
||||
return "PCI Express Root Port";
|
||||
case 0x0774:
|
||||
return "USB1.1 UHCI Controller";
|
||||
case 0x0770:
|
||||
return "USB2 EHCI Controller";
|
||||
case 0x0779:
|
||||
return "USB3 xHCI 1.0 Controller";
|
||||
case 0x07F0:
|
||||
return "NVM Express";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IntelCorporation:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x1229:
|
||||
return "82557/8/9/0/1 Ethernet Pro 100";
|
||||
case 0x1209:
|
||||
return "8255xER/82551IT Fast Ethernet Controller";
|
||||
case 0x100E:
|
||||
return "82540EM Gigabit Ethernet Controller";
|
||||
case 0x7190:
|
||||
return "440BX/ZX/DX - 82443BX/ZX/DX Host bridge";
|
||||
case 0x7191:
|
||||
return "440BX/ZX/DX - 82443BX/ZX/DX AGP bridge";
|
||||
case 0x7110:
|
||||
return "82371AB/EB/MB PIIX4 ISA";
|
||||
case 0x7111:
|
||||
return "82371AB/EB/MB PIIX4 IDE";
|
||||
case 0x7113:
|
||||
return "82371AB/EB/MB PIIX4 ACPI";
|
||||
case 0x1e31:
|
||||
return "7 Series/C210 Series Chipset Family USB xHCI Host Controller";
|
||||
case 0x100F:
|
||||
return "82545EM Gigabit Ethernet Controller (Copper)";
|
||||
case 0x1371:
|
||||
return "ES1371/ES1373 / Creative Labs CT2518";
|
||||
case 0x27b9:
|
||||
return "82801GBM (ICH7-M) LPC Interface Bridge";
|
||||
case 0x07E0:
|
||||
return "SATA AHCI controller";
|
||||
case 0x293E:
|
||||
return "82801I (ICH9 Family) HD Audio Controller";
|
||||
case 0x2935:
|
||||
return "82801I (ICH9 Family) USB UHCI Controller #2";
|
||||
case 0x2936:
|
||||
return "82801I (ICH9 Family) USB UHCI Controller #3";
|
||||
case 0x293A:
|
||||
return "82801I (ICH9 Family) USB2 EHCI Controller #1";
|
||||
case 0x2934:
|
||||
return "82801I (ICH9 Family) USB UHCI Controller #1";
|
||||
case 0x2668:
|
||||
return "82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller";
|
||||
case 0x2415:
|
||||
return "82801AA AC'97 Audio Controller";
|
||||
case 0x10D3:
|
||||
return "82574L Gigabit Network Connection";
|
||||
case 0x29C0:
|
||||
return "82G33/G31/P35/P31 Express DRAM Controller";
|
||||
case 0x2918:
|
||||
return "82801IB (ICH9) LPC Interface Controller";
|
||||
case 0x2829:
|
||||
return "82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode]";
|
||||
case 0x2922:
|
||||
return "82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]";
|
||||
case 0x2930:
|
||||
return "82801I (ICH9 Family) SMBus Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AdvancedMicroDevices:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x2000:
|
||||
return "79C970 [PCnet32 LANCE]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fixme("Unknown device %04x:%04x", VendorID, DeviceID);
|
||||
return u32ToHexString(DeviceID);
|
||||
}
|
||||
|
||||
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode)
|
||||
{
|
||||
switch (ClassCode)
|
||||
{
|
||||
case 0x00:
|
||||
return "Unclassified";
|
||||
case 0x01:
|
||||
return MassStorageControllerSubclassName(SubclassCode);
|
||||
case 0x02:
|
||||
return NetworkControllerSubclassName(SubclassCode);
|
||||
case 0x03:
|
||||
return DisplayControllerSubclassName(SubclassCode);
|
||||
case 0x04:
|
||||
return "Multimedia controller";
|
||||
case 0x05:
|
||||
return "Memory Controller";
|
||||
case 0x06:
|
||||
return BridgeDeviceSubclassName(SubclassCode);
|
||||
case 0x07:
|
||||
return CommunicationControllerSubclassName(SubclassCode);
|
||||
case 0x08:
|
||||
return BaseSystemPeripheralSubclassName(SubclassCode);
|
||||
case 0x09:
|
||||
return "Input device controller";
|
||||
case 0x0A:
|
||||
return "Docking station";
|
||||
case 0x0B:
|
||||
return "Processor";
|
||||
case 0x0C:
|
||||
return SerialBusControllerSubclassName(SubclassCode);
|
||||
case 0x0D:
|
||||
return WirelessControllerSubclassName(SubclassCode);
|
||||
case 0x0E:
|
||||
return "Intelligent controller";
|
||||
case 0x0F:
|
||||
return "Satellite communication controller";
|
||||
case 0x10:
|
||||
return "Encryption controller";
|
||||
case 0x11:
|
||||
return "Signal processing accelerators";
|
||||
case 0x12:
|
||||
return "Processing accelerators";
|
||||
case 0x13:
|
||||
return "Non-Essential Instrumentation";
|
||||
case 0x40:
|
||||
return "Coprocessor";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fixme("Unknown subclass name %02x:%02x", ClassCode, SubclassCode);
|
||||
return u8ToHexString(SubclassCode);
|
||||
}
|
||||
|
||||
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF)
|
||||
{
|
||||
switch (ClassCode)
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x06:
|
||||
{
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0:
|
||||
return "Vendor Specific SATA Controller";
|
||||
case 1:
|
||||
return "AHCI SATA Controller";
|
||||
case 2:
|
||||
return "Serial Storage Bus SATA Controller";
|
||||
default:
|
||||
return "SATA controller";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x08:
|
||||
{
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0x01:
|
||||
return "NVMHCI Controller";
|
||||
case 0x02:
|
||||
return "NVM Express Controller";
|
||||
default:
|
||||
return "Non-Volatile Memory Controller";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0x00:
|
||||
return "VGA Controller";
|
||||
case 0x01:
|
||||
return "8514-Compatible Controller";
|
||||
default:
|
||||
return "VGA Compatible Controller";
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x07:
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
{
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0x00:
|
||||
return "Serial controller <8250>";
|
||||
case 0x01:
|
||||
return "Serial controller <16450>";
|
||||
case 0x02:
|
||||
return "Serial controller <16550>";
|
||||
case 0x03:
|
||||
return "Serial controller <16650>";
|
||||
case 0x04:
|
||||
return "Serial controller <16750>";
|
||||
case 0x05:
|
||||
return "Serial controller <16850>";
|
||||
case 0x06:
|
||||
return "Serial controller <16950";
|
||||
default:
|
||||
return "Serial controller";
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0C:
|
||||
{
|
||||
switch (SubclassCode)
|
||||
{
|
||||
case 0x00:
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0x00:
|
||||
return "Generic FireWire (IEEE 1394) Controller";
|
||||
case 0x10:
|
||||
return "OHCI FireWire (IEEE 1394) Controller";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
switch (ProgIF)
|
||||
{
|
||||
case 0x00:
|
||||
return "UHCI (USB1) Controller";
|
||||
case 0x10:
|
||||
return "OHCI (USB1) Controller";
|
||||
case 0x20:
|
||||
return "EHCI (USB2) Controller";
|
||||
case 0x30:
|
||||
return "XHCI (USB3) Controller";
|
||||
case 0x80:
|
||||
return "Unspecified";
|
||||
case 0xFE:
|
||||
return "USB Device";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// not really a fixme
|
||||
// fixme("Unknown prog IF name %02x:%02x:%02x", ClassCode, SubclassCode, ProgIF);
|
||||
return u8ToHexString(ProgIF);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void e(PCIDeviceHeader *hdr)
|
||||
{
|
||||
debug("%s / %s / %s / %s / %s",
|
||||
Descriptors::GetVendorName(hdr->VendorID),
|
||||
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
|
||||
Descriptors::DeviceClasses[hdr->Class],
|
||||
Descriptors::GetSubclassName(hdr->Class, hdr->Subclass),
|
||||
Descriptors::GetProgIFName(hdr->Class, hdr->Subclass, hdr->ProgIF));
|
||||
}
|
||||
#endif
|
||||
|
||||
void PCI::EnumerateFunction(uint64_t DeviceAddress, uint64_t Function)
|
||||
{
|
||||
uint64_t Offset = Function << 12;
|
||||
uint64_t FunctionAddress = DeviceAddress + Offset;
|
||||
Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
|
||||
if (PCIDeviceHdr->DeviceID == 0)
|
||||
return;
|
||||
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
||||
return;
|
||||
Devices.push_back(PCIDeviceHdr);
|
||||
#ifdef DEBUG
|
||||
e(PCIDeviceHdr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PCI::EnumerateDevice(uint64_t BusAddress, uint64_t Device)
|
||||
{
|
||||
uint64_t Offset = Device << 15;
|
||||
uint64_t DeviceAddress = BusAddress + Offset;
|
||||
Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
|
||||
if (PCIDeviceHdr->DeviceID == 0)
|
||||
return;
|
||||
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
||||
return;
|
||||
for (uint64_t Function = 0; Function < 8; Function++)
|
||||
EnumerateFunction(DeviceAddress, Function);
|
||||
}
|
||||
|
||||
void PCI::EnumerateBus(uint64_t BaseAddress, uint64_t Bus)
|
||||
{
|
||||
uint64_t Offset = Bus << 20;
|
||||
uint64_t BusAddress = BaseAddress + Offset;
|
||||
Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
|
||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
|
||||
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
|
||||
{
|
||||
if (PCIDeviceHdr->DeviceID == 0)
|
||||
return;
|
||||
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
||||
return;
|
||||
}
|
||||
trace("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
|
||||
PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST,
|
||||
PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command,
|
||||
PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF,
|
||||
PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass);
|
||||
for (uint64_t Device = 0; Device < 32; Device++)
|
||||
EnumerateDevice(BusAddress, Device);
|
||||
}
|
||||
|
||||
Vector<PCIDeviceHeader *> PCI::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF)
|
||||
{
|
||||
Vector<PCIDeviceHeader *> DeviceFound;
|
||||
for (auto var : Devices)
|
||||
if (var->Class == Class && var->Subclass == Subclass && var->ProgIF == ProgIF)
|
||||
DeviceFound.push_back(var);
|
||||
return DeviceFound;
|
||||
}
|
||||
|
||||
Vector<PCIDeviceHeader *> PCI::FindPCIDevice(int VendorID, int DeviceID)
|
||||
{
|
||||
Vector<PCIDeviceHeader *> DeviceFound;
|
||||
for (auto var : Devices)
|
||||
if (var->VendorID == VendorID && var->DeviceID == DeviceID)
|
||||
DeviceFound.push_back(var);
|
||||
return DeviceFound;
|
||||
}
|
||||
|
||||
PCI::PCI()
|
||||
{
|
||||
// int Entries = ((MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig);
|
||||
// for (int t = 0; t < Entries; t++)
|
||||
// {
|
||||
// DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
||||
// Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
||||
// trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
||||
// NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
||||
// for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
||||
// EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
|
||||
// }
|
||||
}
|
||||
|
||||
PCI::~PCI()
|
||||
{
|
||||
}
|
||||
}
|
81
Core/Power.cpp
Normal file
81
Core/Power.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include <power.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include "../kernel.h"
|
||||
#include <debug.h>
|
||||
|
||||
#if defined(__amd64__)
|
||||
#include "../arch/amd64/acpi.hpp"
|
||||
|
||||
namespace Power
|
||||
{
|
||||
void Power::Reboot()
|
||||
{
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
Power::Power()
|
||||
{
|
||||
this->acpi = new ACPI::ACPI(bInfo);
|
||||
this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi);
|
||||
this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT);
|
||||
trace("Power manager initialized");
|
||||
}
|
||||
|
||||
Power::~Power()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
namespace Power
|
||||
{
|
||||
void Power::Reboot()
|
||||
{
|
||||
warn("Reboot not implemented for i386");
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
warn("Shutdown not implemented for i386");
|
||||
}
|
||||
|
||||
Power::Power()
|
||||
{
|
||||
error("Power not implemented for i386");
|
||||
}
|
||||
|
||||
Power::~Power()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
namespace Power
|
||||
{
|
||||
void Power::Reboot()
|
||||
{
|
||||
warn("Reboot not implemented for aarch64");
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
warn("Shutdown not implemented for aarch64");
|
||||
}
|
||||
|
||||
Power::Power()
|
||||
{
|
||||
error("Power not implemented for aarch64");
|
||||
}
|
||||
|
||||
Power::~Power()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -4,6 +4,9 @@
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
|
||||
Vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
|
||||
|
||||
namespace UniversalAsynchronousReceiverTransmitter
|
||||
{
|
||||
#define SERIAL_ENABLE_DLAB 0x80
|
||||
@ -11,10 +14,6 @@ namespace UniversalAsynchronousReceiverTransmitter
|
||||
#define SERIAL_RATE_38400_HI 0x00
|
||||
#define SERIAL_BUFFER_EMPTY 0x20
|
||||
|
||||
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
|
||||
|
||||
Vector<Events *> RegisteredEvents;
|
||||
|
||||
UART::UART(SerialPorts Port)
|
||||
{
|
||||
#if defined(__amd64__) || defined(__i386__)
|
@ -2,9 +2,9 @@
|
||||
#include <lock.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
extern uint64_t _binary_files_ter_powerline_v12n_psf_start;
|
||||
extern uint64_t _binary_files_ter_powerline_v12n_psf_end;
|
||||
extern uint64_t _binary_files_ter_powerline_v12n_psf_size;
|
||||
extern uint64_t _binary_Files_ter_powerline_v12n_psf_start;
|
||||
extern uint64_t _binary_Files_ter_powerline_v12n_psf_end;
|
||||
extern uint64_t _binary_Files_ter_powerline_v12n_psf_size;
|
||||
|
||||
NEWLOCK(PrintLock);
|
||||
|
||||
@ -105,7 +105,7 @@ namespace Video
|
||||
this->framebuffer = Info;
|
||||
if (LoadDefaultFont)
|
||||
{
|
||||
this->CurrentFont = new Font(&_binary_files_ter_powerline_v12n_psf_start, &_binary_files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
|
||||
this->CurrentFont = new Font(&_binary_Files_ter_powerline_v12n_psf_start, &_binary_Files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
|
||||
FontInfo Info = this->CurrentFont->GetInfo();
|
||||
debug("Font loaded: %dx%d %s",
|
||||
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
|
@ -4,6 +4,7 @@
|
||||
#include <display.hpp>
|
||||
#include <symbols.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <power.hpp>
|
||||
#include <string.h>
|
||||
#include <printf.h>
|
||||
#include <time.hpp>
|
||||
@ -12,6 +13,7 @@
|
||||
BootInfo *bInfo = nullptr;
|
||||
Video::Display *Display = nullptr;
|
||||
SymbolResolver::Symbols *KernelSymbolTable = nullptr;
|
||||
Power::Power *PowerManager = nullptr;
|
||||
|
||||
// For the Display class. Printing on first buffer.
|
||||
extern "C" void putchar(char c) { Display->Print(c, 0); }
|
||||
@ -33,14 +35,14 @@ void KPrint(const char *format, ...)
|
||||
Display->SetBuffer(0);
|
||||
}
|
||||
|
||||
EXTERNC void kernel_aarch64_entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||
EXTERNC void aarch64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
while (1)
|
||||
CPU::Halt();
|
||||
}
|
||||
|
||||
EXTERNC void kernel_entry(BootInfo *Info)
|
||||
EXTERNC void Entry(BootInfo *Info)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
InitializeMemoryManagement(Info);
|
||||
@ -54,6 +56,8 @@ EXTERNC void kernel_entry(BootInfo *Info)
|
||||
Interrupts::Initialize();
|
||||
KPrint("Loading kernel symbols");
|
||||
KernelSymbolTable = new SymbolResolver::Symbols((uint64_t)Info->Kernel.FileBase);
|
||||
KPrint("Initializing Power Manager");
|
||||
PowerManager = new Power::Power;
|
||||
while (1)
|
||||
CPU::Halt();
|
||||
}
|
||||
|
6
Makefile
6
Makefile
@ -100,9 +100,9 @@ default:
|
||||
$(error Please specify a target)
|
||||
|
||||
prepare:
|
||||
rm -f ./files/ter-powerline-v12n.psf
|
||||
wget https://raw.githubusercontent.com/powerline/fonts/master/Terminus/PSF/ter-powerline-v12n.psf.gz -P files
|
||||
gzip -d files/ter-powerline-v12n.psf.gz
|
||||
rm -f ./Files/ter-powerline-v12n.psf
|
||||
wget https://raw.githubusercontent.com/powerline/fonts/master/Terminus/PSF/ter-powerline-v12n.psf.gz -P Files
|
||||
gzip -d Files/ter-powerline-v12n.psf.gz
|
||||
|
||||
build: $(KERNEL_FILENAME)
|
||||
$(OBJDUMP) -D -d $(KERNEL_FILENAME) > kernel_dump.map
|
||||
|
@ -11,7 +11,7 @@ _start:
|
||||
str xzr, [x5], #8
|
||||
sub w6, w6, #1
|
||||
cbnz w6, 1b
|
||||
2: bl kernel_aarch64_entry
|
||||
2: bl aarch64Entry
|
||||
Halt:
|
||||
wfe
|
||||
b Halt
|
||||
|
127
arch/amd64/AdvancedConfigurationandPowerInterface.cpp
Normal file
127
arch/amd64/AdvancedConfigurationandPowerInterface.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature)
|
||||
{
|
||||
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
|
||||
{
|
||||
// Should I be concerned about unaligned memory access?
|
||||
ACPI::ACPIHeader *SDTHdr = nullptr;
|
||||
if (XSDTSupported)
|
||||
SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8)));
|
||||
else
|
||||
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
|
||||
|
||||
for (uint64_t i = 0; i < 4; i++)
|
||||
{
|
||||
if (SDTHdr->Signature[i] != Signature[i])
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
trace("%s found!", Signature);
|
||||
return SDTHdr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// warn("%s not found!", Signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ACPI::SearchTables(ACPIHeader *Header)
|
||||
{
|
||||
if (!Header)
|
||||
return;
|
||||
|
||||
HPET = (HPETHeader *)FindTable(XSDT, (char *)"HPET");
|
||||
FADT = (FADTHeader *)FindTable(XSDT, (char *)"FACP");
|
||||
MCFG = (MCFGHeader *)FindTable(XSDT, (char *)"MCFG");
|
||||
BGRT = (BGRTHeader *)FindTable(XSDT, (char *)"BGRT");
|
||||
SRAT = (SRATHeader *)FindTable(XSDT, (char *)"SRAT");
|
||||
TPM2 = (TPM2Header *)FindTable(XSDT, (char *)"TPM2");
|
||||
TCPA = (TCPAHeader *)FindTable(XSDT, (char *)"TCPA");
|
||||
WAET = (WAETHeader *)FindTable(XSDT, (char *)"WAET");
|
||||
MADT = (MADTHeader *)FindTable(XSDT, (char *)"APIC");
|
||||
HEST = (HESTHeader *)FindTable(XSDT, (char *)"HEST");
|
||||
FindTable(XSDT, (char *)"BERT");
|
||||
FindTable(XSDT, (char *)"CPEP");
|
||||
FindTable(XSDT, (char *)"DSDT");
|
||||
FindTable(XSDT, (char *)"ECDT");
|
||||
FindTable(XSDT, (char *)"EINJ");
|
||||
FindTable(XSDT, (char *)"ERST");
|
||||
FindTable(XSDT, (char *)"FACS");
|
||||
FindTable(XSDT, (char *)"MSCT");
|
||||
FindTable(XSDT, (char *)"MPST");
|
||||
FindTable(XSDT, (char *)"OEMx");
|
||||
FindTable(XSDT, (char *)"PMTT");
|
||||
FindTable(XSDT, (char *)"PSDT");
|
||||
FindTable(XSDT, (char *)"RASF");
|
||||
FindTable(XSDT, (char *)"RSDT");
|
||||
FindTable(XSDT, (char *)"SBST");
|
||||
FindTable(XSDT, (char *)"SLIT");
|
||||
FindTable(XSDT, (char *)"SSDT");
|
||||
FindTable(XSDT, (char *)"XSDT");
|
||||
FindTable(XSDT, (char *)"DRTM");
|
||||
FindTable(XSDT, (char *)"FPDT");
|
||||
FindTable(XSDT, (char *)"GTDT");
|
||||
FindTable(XSDT, (char *)"PCCT");
|
||||
FindTable(XSDT, (char *)"S3PT");
|
||||
FindTable(XSDT, (char *)"MATR");
|
||||
FindTable(XSDT, (char *)"MSDM");
|
||||
FindTable(XSDT, (char *)"WPBT");
|
||||
FindTable(XSDT, (char *)"OSDT");
|
||||
FindTable(XSDT, (char *)"RSDP");
|
||||
FindTable(XSDT, (char *)"NFIT");
|
||||
FindTable(XSDT, (char *)"ASF!");
|
||||
FindTable(XSDT, (char *)"BOOT");
|
||||
FindTable(XSDT, (char *)"CSRT");
|
||||
FindTable(XSDT, (char *)"DBG2");
|
||||
FindTable(XSDT, (char *)"DBGP");
|
||||
FindTable(XSDT, (char *)"DMAR");
|
||||
FindTable(XSDT, (char *)"IBFT");
|
||||
FindTable(XSDT, (char *)"IORT");
|
||||
FindTable(XSDT, (char *)"IVRS");
|
||||
FindTable(XSDT, (char *)"LPIT");
|
||||
FindTable(XSDT, (char *)"MCHI");
|
||||
FindTable(XSDT, (char *)"MTMR");
|
||||
FindTable(XSDT, (char *)"SLIC");
|
||||
FindTable(XSDT, (char *)"SPCR");
|
||||
FindTable(XSDT, (char *)"SPMI");
|
||||
FindTable(XSDT, (char *)"UEFI");
|
||||
FindTable(XSDT, (char *)"VRTC");
|
||||
FindTable(XSDT, (char *)"WDAT");
|
||||
FindTable(XSDT, (char *)"WDDT");
|
||||
FindTable(XSDT, (char *)"WDRT");
|
||||
}
|
||||
|
||||
ACPI::ACPI(BootInfo *Info)
|
||||
{
|
||||
trace("Initializing ACPI");
|
||||
if (Info->RSDP->Revision >= 2 && Info->RSDP->XSDTAddress)
|
||||
{
|
||||
debug("XSDT supported");
|
||||
XSDTSupported = true;
|
||||
XSDT = (ACPIHeader *)(Info->RSDP->XSDTAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("RSDT supported");
|
||||
XSDT = (ACPIHeader *)(uintptr_t)Info->RSDP->RSDTAddress;
|
||||
}
|
||||
|
||||
this->SearchTables(XSDT);
|
||||
|
||||
outb(FADT->SMI_CommandPort, FADT->AcpiEnable);
|
||||
while (!(inw(FADT->PM1aControlBlock) & 1))
|
||||
;
|
||||
}
|
||||
|
||||
ACPI::~ACPI()
|
||||
{
|
||||
}
|
||||
}
|
225
arch/amd64/DifferentiatedSystemDescriptionTable.cpp
Normal file
225
arch/amd64/DifferentiatedSystemDescriptionTable.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <time.hpp>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
// #include "../timer.h"
|
||||
// #include "apic.hpp"
|
||||
// #include "smp.hpp"
|
||||
|
||||
#define ACPI_TIMER 0x0001
|
||||
#define ACPI_BUSMASTER 0x0010
|
||||
#define ACPI_GLOBAL 0x0020
|
||||
#define ACPI_POWER_BUTTON 0x0100
|
||||
#define ACPI_SLEEP_BUTTON 0x0200
|
||||
#define ACPI_RTC_ALARM 0x0400
|
||||
#define ACPI_PCIE_WAKE 0x4000
|
||||
#define ACPI_WAKE 0x8000
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
__attribute__((always_inline)) inline bool IsCanonical(uint64_t Address)
|
||||
{
|
||||
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
|
||||
}
|
||||
|
||||
#define ACPI_ENABLED 0x0001
|
||||
#define ACPI_SLEEP 0x2000
|
||||
|
||||
#define ACPI_GAS_MMIO 0
|
||||
#define ACPI_GAS_IO 1
|
||||
#define ACPI_GAS_PCI 2
|
||||
|
||||
void DSDT::SCIHandler(CPU::x64::TrapFrame *regs)
|
||||
{
|
||||
debug("SCI Handle Triggered");
|
||||
uint16_t event = this->GetSCIevent();
|
||||
debug("SCI Event: %#llx", event);
|
||||
if (event & ACPI_TIMER)
|
||||
event &= ~ACPI_TIMER; // Remove the ACPI timer flag.
|
||||
switch (event)
|
||||
{
|
||||
case ACPI_POWER_BUTTON:
|
||||
{
|
||||
this->Shutdown();
|
||||
Time tm = ReadClock();
|
||||
while (tm.Second == ReadClock().Second)
|
||||
;
|
||||
outw(0xB004, 0x2000);
|
||||
outw(0x604, 0x2000);
|
||||
outw(0x4004, 0x3400);
|
||||
CPU::Stop();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("unknown event 0x%04p", event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
UNUSED(regs);
|
||||
}
|
||||
|
||||
void DSDT::Shutdown()
|
||||
{
|
||||
trace("Shutting down...");
|
||||
if (!ACPIShutdownSupported)
|
||||
{
|
||||
outl(0xB004, 0x2000); // for qemu
|
||||
outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu
|
||||
outl(0x4004, 0x3400); // virtual box
|
||||
}
|
||||
else if (SCI_EN == 1)
|
||||
{
|
||||
outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP));
|
||||
if (acpi->FADT->PM1bControlBlock)
|
||||
outw(acpi->FADT->PM1bControlBlock, (inw(acpi->FADT->PM1bControlBlock) & 0xE3FF) | ((SLP_TYPb << 10) | ACPI_SLEEP));
|
||||
outw(PM1a_CNT, SLP_TYPa | SLP_EN);
|
||||
if (PM1b_CNT)
|
||||
outw(PM1b_CNT, SLP_TYPb | SLP_EN);
|
||||
}
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
void DSDT::Reboot()
|
||||
{
|
||||
trace("Rebooting...");
|
||||
if (!ACPIShutdownSupported)
|
||||
{
|
||||
uint8_t val = 0x02;
|
||||
while (val & 0x02)
|
||||
val = inb(0x64);
|
||||
outb(0x64, 0xFE);
|
||||
|
||||
warn("Executing the second attempt to reboot...");
|
||||
|
||||
// second attempt to reboot
|
||||
// https://wiki.osdev.org/Reboot
|
||||
uint8_t temp;
|
||||
asm volatile("cli");
|
||||
do
|
||||
{
|
||||
temp = inb(0x64);
|
||||
if (((temp) & (1 << (0))) != 0)
|
||||
inb(0x60);
|
||||
} while (((temp) & (1 << (1))) != 0);
|
||||
outb(0x64, 0xFE);
|
||||
|
||||
CPU::Stop();
|
||||
}
|
||||
switch (acpi->FADT->ResetReg.AddressSpace)
|
||||
{
|
||||
case ACPI_GAS_MMIO:
|
||||
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
|
||||
break;
|
||||
case ACPI_GAS_IO:
|
||||
outb(acpi->FADT->ResetReg.Address, acpi->FADT->ResetValue);
|
||||
break;
|
||||
case ACPI_GAS_PCI:
|
||||
fixme("ACPI_GAS_PCI not supported.");
|
||||
/*
|
||||
seg - 0
|
||||
bus - 0
|
||||
dev - (FADT->ResetReg.Address >> 32) & 0xFFFF
|
||||
function - (FADT->ResetReg.Address >> 16) & 0xFFFF
|
||||
offset - FADT->ResetReg.Address & 0xFFFF
|
||||
value - FADT->ResetValue
|
||||
*/
|
||||
break;
|
||||
}
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
uint16_t DSDT::GetSCIevent()
|
||||
{
|
||||
uint16_t a = 0, b = 0;
|
||||
if (acpi->FADT->PM1aEventBlock)
|
||||
{
|
||||
a = inw(acpi->FADT->PM1aEventBlock);
|
||||
outw(acpi->FADT->PM1aEventBlock, a);
|
||||
}
|
||||
if (acpi->FADT->PM1bEventBlock)
|
||||
{
|
||||
b = inw(acpi->FADT->PM1bEventBlock);
|
||||
outw(acpi->FADT->PM1bEventBlock, b);
|
||||
}
|
||||
return a | b;
|
||||
}
|
||||
|
||||
void DSDT::SetSCIevent(uint16_t value)
|
||||
{
|
||||
uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2);
|
||||
uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2);
|
||||
if (acpi->FADT->PM1aEventBlock)
|
||||
outw(a, value);
|
||||
if (acpi->FADT->PM1bEventBlock)
|
||||
outw(b, value);
|
||||
}
|
||||
|
||||
void DSDT::RegisterSCIEvents()
|
||||
{
|
||||
this->SetSCIevent(ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE);
|
||||
GetSCIevent();
|
||||
}
|
||||
|
||||
void DSDT::InitSCI()
|
||||
{
|
||||
// this should be done for all CPUs
|
||||
if (ACPIShutdownSupported)
|
||||
{
|
||||
debug("Registering SCI Handler to vector IRQ%d", acpi->FADT->SCI_Interrupt);
|
||||
this->RegisterSCIEvents();
|
||||
// RegisterInterrupt(this->SCIHandler, acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
DSDT::DSDT(ACPI *acpi)
|
||||
{
|
||||
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
|
||||
uint8_t *S5Address = (uint8_t *)(Address) + 36;
|
||||
ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address;
|
||||
uint64_t Length = Header->Length;
|
||||
Address *= 2;
|
||||
while (Length-- > 0)
|
||||
{
|
||||
if (!memcmp(S5Address, "_S5_", 4))
|
||||
break;
|
||||
S5Address++;
|
||||
}
|
||||
if (Length <= 0)
|
||||
{
|
||||
warn("_S5 not present in ACPI");
|
||||
return;
|
||||
}
|
||||
if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12)
|
||||
{
|
||||
S5Address += 5;
|
||||
S5Address += ((*S5Address & 0xC0) >> 6) + 2;
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
SLP_TYPa = *(S5Address) << 10;
|
||||
S5Address++;
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
SLP_TYPb = *(S5Address) << 10;
|
||||
SMI_CMD = acpi->FADT->SMI_CommandPort;
|
||||
ACPI_ENABLE = acpi->FADT->AcpiEnable;
|
||||
ACPI_DISABLE = acpi->FADT->AcpiDisable;
|
||||
PM1a_CNT = acpi->FADT->PM1aControlBlock;
|
||||
PM1b_CNT = acpi->FADT->PM1bControlBlock;
|
||||
PM1_CNT_LEN = acpi->FADT->PM1ControlLength;
|
||||
SLP_EN = 1 << 13;
|
||||
SCI_EN = 1;
|
||||
trace("ACPI Shutdown is supported");
|
||||
ACPIShutdownSupported = true;
|
||||
return;
|
||||
}
|
||||
warn("Failed to parse _S5 in ACPI");
|
||||
SCI_EN = 0;
|
||||
}
|
||||
|
||||
DSDT::~DSDT()
|
||||
{
|
||||
}
|
||||
}
|
@ -230,5 +230,5 @@ void init_limine()
|
||||
strcpy(binfo.Bootloader.Version, BootloaderInfoResponse->version);
|
||||
|
||||
// Call kernel entry point
|
||||
kernel_entry(&binfo);
|
||||
Entry(&binfo);
|
||||
}
|
||||
|
64
arch/amd64/MultipleAPICDescriptionTable.cpp
Normal file
64
arch/amd64/MultipleAPICDescriptionTable.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "acpi.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
MADT::MADT(ACPI::MADTHeader *madt)
|
||||
{
|
||||
LAPICAddr = (LAPIC *)(uintptr_t)madt->LocalControllerAddress;
|
||||
for (uint8_t *ptr = (uint8_t *)(madt->Entries);
|
||||
(uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length;
|
||||
ptr += *(ptr + 1))
|
||||
{
|
||||
switch (*(ptr))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (ptr[4] & 1)
|
||||
{
|
||||
lapic.push_back((LocalAPIC *)ptr);
|
||||
trace("Local APIC %#llx (APIC %#llx) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
CPUCores++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
ioapic.push_back((MADTIOApic *)ptr);
|
||||
trace("I/O APIC %#llx (Address %#llx) found.", ioapic.back()->APICID, ioapic.back()->addr);
|
||||
Memory::Virtual().Map((void *)(uintptr_t)ioapic.back()->addr, (void *)(uintptr_t)ioapic.back()->addr, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
iso.push_back((MADTIso *)ptr);
|
||||
trace("ISO (IRQ:%#llx, BUS:%#llx, GSI:%#llx, %s/%s) found.",
|
||||
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
|
||||
iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low",
|
||||
iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
nmi.push_back((MADTNmi *)ptr);
|
||||
trace("NMI %#llx (lint:%#llx) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
LAPICAddr = (LAPIC *)ptr;
|
||||
trace("APIC found at %#llx", LAPICAddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Memory::Virtual().Map((void *)LAPICAddr, (void *)LAPICAddr, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
|
||||
}
|
||||
trace("Total CPU cores: %d", CPUCores);
|
||||
}
|
||||
|
||||
MADT::~MADT()
|
||||
{
|
||||
}
|
||||
}
|
282
arch/amd64/acpi.hpp
Normal file
282
arch/amd64/acpi.hpp
Normal file
@ -0,0 +1,282 @@
|
||||
#ifndef __FENNIX_KERNEL_ACPI_H__
|
||||
#define __FENNIX_KERNEL_ACPI_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <boot/binfo.h>
|
||||
#include <interrupts.hpp>
|
||||
#include <vector.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
class ACPI
|
||||
{
|
||||
public:
|
||||
struct ACPIHeader
|
||||
{
|
||||
unsigned char Signature[4];
|
||||
uint32_t Length;
|
||||
uint8_t Revision;
|
||||
uint8_t Checksum;
|
||||
uint8_t OEMID[6];
|
||||
uint8_t OEMTableID[8];
|
||||
uint32_t OEMRevision;
|
||||
uint32_t CreatorID;
|
||||
uint32_t CreatorRevision;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct GenericAddressStructure
|
||||
{
|
||||
uint8_t AddressSpace;
|
||||
uint8_t BitWidth;
|
||||
uint8_t BitOffset;
|
||||
uint8_t AccessSize;
|
||||
uint64_t Address;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MCFGHeader
|
||||
{
|
||||
struct ACPIHeader Header;
|
||||
uint64_t Reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HPETHeader
|
||||
{
|
||||
ACPIHeader header;
|
||||
uint8_t hardware_rev_id;
|
||||
uint8_t comparator_count : 5;
|
||||
uint8_t counter_size : 1;
|
||||
uint8_t reserved : 1;
|
||||
uint8_t legacy_replacement : 1;
|
||||
uint16_t pci_vendor_id;
|
||||
struct GenericAddressStructure address;
|
||||
uint8_t hpet_number;
|
||||
uint16_t minimum_tick;
|
||||
uint8_t page_protection;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct FADTHeader
|
||||
{
|
||||
ACPIHeader header;
|
||||
uint32_t FirmwareCtrl;
|
||||
uint32_t Dsdt;
|
||||
uint8_t Reserved;
|
||||
uint8_t PreferredPowerManagementProfile;
|
||||
uint16_t SCI_Interrupt;
|
||||
uint32_t SMI_CommandPort;
|
||||
uint8_t AcpiEnable;
|
||||
uint8_t AcpiDisable;
|
||||
uint8_t S4BIOS_REQ;
|
||||
uint8_t PSTATE_Control;
|
||||
uint32_t PM1aEventBlock;
|
||||
uint32_t PM1bEventBlock;
|
||||
uint32_t PM1aControlBlock;
|
||||
uint32_t PM1bControlBlock;
|
||||
uint32_t PM2ControlBlock;
|
||||
uint32_t PMTimerBlock;
|
||||
uint32_t GPE0Block;
|
||||
uint32_t GPE1Block;
|
||||
uint8_t PM1EventLength;
|
||||
uint8_t PM1ControlLength;
|
||||
uint8_t PM2ControlLength;
|
||||
uint8_t PMTimerLength;
|
||||
uint8_t GPE0Length;
|
||||
uint8_t GPE1Length;
|
||||
uint8_t GPE1Base;
|
||||
uint8_t CStateControl;
|
||||
uint16_t WorstC2Latency;
|
||||
uint16_t WorstC3Latency;
|
||||
uint16_t FlushSize;
|
||||
uint16_t FlushStride;
|
||||
uint8_t DutyOffset;
|
||||
uint8_t DutyWidth;
|
||||
uint8_t DayAlarm;
|
||||
uint8_t MonthAlarm;
|
||||
uint8_t Century;
|
||||
uint16_t BootArchitectureFlags;
|
||||
uint8_t Reserved2;
|
||||
uint32_t Flags;
|
||||
struct GenericAddressStructure ResetReg;
|
||||
uint8_t ResetValue;
|
||||
uint8_t Reserved3[3];
|
||||
uint64_t X_FirmwareControl;
|
||||
uint64_t X_Dsdt;
|
||||
struct GenericAddressStructure X_PM1aEventBlock;
|
||||
struct GenericAddressStructure X_PM1bEventBlock;
|
||||
struct GenericAddressStructure X_PM1aControlBlock;
|
||||
struct GenericAddressStructure X_PM1bControlBlock;
|
||||
struct GenericAddressStructure X_PM2ControlBlock;
|
||||
struct GenericAddressStructure X_PMTimerBlock;
|
||||
struct GenericAddressStructure X_GPE0Block;
|
||||
struct GenericAddressStructure X_GPE1Block;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct BGRTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Version;
|
||||
uint8_t Status;
|
||||
uint8_t ImageType;
|
||||
uint64_t ImageAddress;
|
||||
uint32_t ImageOffsetX;
|
||||
uint32_t ImageOffsetY;
|
||||
};
|
||||
|
||||
struct SRATHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t TableRevision; // Must be value 1
|
||||
uint64_t Reserved; // Reserved, must be zero
|
||||
};
|
||||
|
||||
struct TPM2Header
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
uint64_t ControlAddress;
|
||||
uint32_t StartMethod;
|
||||
};
|
||||
|
||||
struct TCPAHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Reserved;
|
||||
uint32_t MaxLogLength;
|
||||
uint64_t LogAddress;
|
||||
};
|
||||
|
||||
struct WAETHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
};
|
||||
|
||||
struct HESTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t ErrorSourceCount;
|
||||
};
|
||||
|
||||
struct MADTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t LocalControllerAddress;
|
||||
uint32_t Flags;
|
||||
char Entries[];
|
||||
} __attribute__((packed));
|
||||
|
||||
ACPIHeader *XSDT = nullptr;
|
||||
MCFGHeader *MCFG = nullptr;
|
||||
HPETHeader *HPET = nullptr;
|
||||
FADTHeader *FADT = nullptr;
|
||||
BGRTHeader *BGRT = nullptr;
|
||||
SRATHeader *SRAT = nullptr;
|
||||
TPM2Header *TPM2 = nullptr;
|
||||
TCPAHeader *TCPA = nullptr;
|
||||
WAETHeader *WAET = nullptr;
|
||||
MADTHeader *MADT = nullptr;
|
||||
HESTHeader *HEST = nullptr;
|
||||
bool XSDTSupported = false;
|
||||
|
||||
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
|
||||
void SearchTables(ACPIHeader *Header);
|
||||
ACPI(BootInfo *Info);
|
||||
~ACPI();
|
||||
};
|
||||
|
||||
class MADT
|
||||
{
|
||||
public:
|
||||
struct APICHeader
|
||||
{
|
||||
uint8_t Type;
|
||||
uint8_t Length;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MADTIOApic
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t APICID;
|
||||
uint8_t reserved;
|
||||
uint32_t addr;
|
||||
uint32_t gsib;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MADTIso
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t BuSSource;
|
||||
uint8_t IRQSource;
|
||||
uint32_t GSI;
|
||||
uint16_t Flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct MADTNmi
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t processor;
|
||||
uint16_t flags;
|
||||
uint8_t lint;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct LocalAPIC
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t ACPIProcessorId;
|
||||
uint8_t APICId;
|
||||
uint32_t Flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct LAPIC
|
||||
{
|
||||
uint8_t id;
|
||||
uintptr_t PhysicalAddress;
|
||||
void *VirtualAddress;
|
||||
};
|
||||
|
||||
Vector<MADTIOApic *> ioapic;
|
||||
Vector<MADTIso *> iso;
|
||||
Vector<MADTNmi *> nmi;
|
||||
Vector<LocalAPIC *> lapic;
|
||||
struct LAPIC *LAPICAddr;
|
||||
uint8_t CPUCores;
|
||||
|
||||
MADT(ACPI::MADTHeader *madt);
|
||||
~MADT();
|
||||
};
|
||||
|
||||
class DSDT
|
||||
{
|
||||
private:
|
||||
uint32_t SMI_CMD = 0;
|
||||
uint8_t ACPI_ENABLE = 0;
|
||||
uint8_t ACPI_DISABLE = 0;
|
||||
uint32_t PM1a_CNT = 0;
|
||||
uint32_t PM1b_CNT = 0;
|
||||
uint16_t SLP_TYPa = 0;
|
||||
uint16_t SLP_TYPb = 0;
|
||||
uint16_t SLP_EN = 0;
|
||||
uint16_t SCI_EN = 0;
|
||||
uint8_t PM1_CNT_LEN = 0;
|
||||
|
||||
ACPI *acpi;
|
||||
|
||||
public:
|
||||
bool ACPIShutdownSupported = false;
|
||||
|
||||
void SCIHandler(CPU::x64::TrapFrame *regs);
|
||||
void RegisterSCIEvents();
|
||||
void SetSCIevent(uint16_t value);
|
||||
uint16_t GetSCIevent();
|
||||
|
||||
void Reboot();
|
||||
void Shutdown();
|
||||
|
||||
void InitSCI();
|
||||
DSDT(ACPI *acpi);
|
||||
~DSDT();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ACPI_H__
|
@ -1,7 +1,7 @@
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
ENTRY(kernel_entry)
|
||||
ENTRY(Entry)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
@ -36,10 +36,4 @@ SECTIONS
|
||||
}
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
OUTPUT_ARCH(i386)
|
||||
|
||||
ENTRY(kernel_entry)
|
||||
ENTRY(Entry)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
293
include/cpu.hpp
293
include/cpu.hpp
@ -53,6 +53,11 @@ namespace CPU
|
||||
*/
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief Stop the CPU (infinite loop)
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* @brief Halt the CPU
|
||||
*/
|
||||
@ -127,6 +132,294 @@ namespace CPU
|
||||
|
||||
namespace x64
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
DivideByZero = 0x0,
|
||||
Debug = 0x1,
|
||||
NonMaskableInterrupt = 0x2,
|
||||
Breakpoint = 0x3,
|
||||
Overflow = 0x4,
|
||||
BoundRange = 0x5,
|
||||
InvalidOpcode = 0x6,
|
||||
DeviceNotAvailable = 0x7,
|
||||
DoubleFault = 0x8,
|
||||
CoprocessorSegmentOverrun = 0x9,
|
||||
InvalidTSS = 0xa,
|
||||
SegmentNotPresent = 0xb,
|
||||
StackSegmentFault = 0xc,
|
||||
GeneralProtectionFault = 0xd,
|
||||
PageFault = 0xe,
|
||||
x87FloatingPoint = 0x10,
|
||||
AlignmentCheck = 0x11,
|
||||
MachineCheck = 0x12,
|
||||
SIMDFloatingPoint = 0x13,
|
||||
Virtualization = 0x14,
|
||||
Security = 0x1e
|
||||
} ISRExceptions;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ISR0 = 0x0, // Divide-by-zero Error
|
||||
ISR1 = 0x1, // Debug
|
||||
ISR2 = 0x2, // Non-maskable Interrupt
|
||||
ISR3 = 0x3, // Breakpoint
|
||||
ISR4 = 0x4, // Overflow
|
||||
ISR5 = 0x5, // Bound Range Exceeded
|
||||
ISR6 = 0x6, // Invalid Opcode
|
||||
ISR7 = 0x7, // Device Not Available
|
||||
ISR8 = 0x8, // Double Fault
|
||||
ISR9 = 0x9, // Coprocessor Segment Overrun
|
||||
ISR10 = 0xa, // Invalid TSS
|
||||
ISR11 = 0xb, // Segment Not P
|
||||
ISR12 = 0xc, // Stack-Segment Fault
|
||||
ISR13 = 0xd, // General Protection Fault
|
||||
ISR14 = 0xe, // Page Fault
|
||||
ISR15 = 0xf, // Reserved
|
||||
ISR16 = 0x10, // x87 Floating-Point Exception
|
||||
ISR17 = 0x11, // Alignment Check
|
||||
ISR18 = 0x12, // Machine Check
|
||||
ISR19 = 0x13, // SIMD Floating-Point Exception
|
||||
ISR20 = 0x14, // Virtualization Exception
|
||||
ISR21 = 0x15, // Reserved
|
||||
ISR22 = 0x16, // Reserved
|
||||
ISR23 = 0x17, // Reserved
|
||||
ISR24 = 0x18, // Reserved
|
||||
ISR25 = 0x19, // Reserved
|
||||
ISR26 = 0x1a, // Reserved
|
||||
ISR27 = 0x1b, // Reserved
|
||||
ISR28 = 0x1c, // Reserved
|
||||
ISR29 = 0x1d, // Reserved
|
||||
ISR30 = 0x1e, // Security Exception
|
||||
ISR31 = 0x1f, // Reserved
|
||||
|
||||
IRQ0 = 0x20, // Programmable Interrupt Timer Interrupt
|
||||
IRQ1 = 0x21, // Keyboard Interrupt
|
||||
IRQ2 = 0x22, // Cascade (used internally by the two PICs. never raised)
|
||||
IRQ3 = 0x23, // COM2 (if enabled)
|
||||
IRQ4 = 0x24, // COM1 (if enabled)
|
||||
IRQ5 = 0x25, // LPT2 (if enabled)
|
||||
IRQ6 = 0x26, // Floppy Disk
|
||||
IRQ7 = 0x27, // LPT1 / Unreliable "spurious" interrupt (usually)
|
||||
IRQ8 = 0x28, // CMOS real-time clock (if enabled)
|
||||
IRQ9 = 0x29, // Free for peripherals / legacy SCSI / NIC
|
||||
IRQ10 = 0x2a, // Free for peripherals / SCSI / NIC
|
||||
IRQ11 = 0x2b, // Free for peripherals / SCSI / NIC
|
||||
IRQ12 = 0x2c, // PS2 Mouse
|
||||
IRQ13 = 0x2d, // FPU / Coprocessor / Inter-processor
|
||||
IRQ14 = 0x2e, // Primary ATA Hard Disk
|
||||
IRQ15 = 0x2f, // Secondary ATA Hard Disk
|
||||
|
||||
IRQ16 = 0x30, // Reserved for multitasking
|
||||
IRQ17 = 0x31, // Reserved for monotasking
|
||||
|
||||
IRQ18 = 0x32,
|
||||
IRQ19 = 0x33,
|
||||
IRQ20 = 0x34,
|
||||
IRQ21 = 0x35,
|
||||
IRQ22 = 0x36,
|
||||
IRQ23 = 0x37,
|
||||
IRQ24 = 0x38,
|
||||
IRQ25 = 0x39,
|
||||
IRQ26 = 0x3a,
|
||||
IRQ27 = 0x3b,
|
||||
IRQ28 = 0x3c,
|
||||
IRQ29 = 0x3d,
|
||||
IRQ30 = 0x3e,
|
||||
IRQ31 = 0x3f,
|
||||
IRQ32 = 0x40,
|
||||
IRQ33 = 0x41,
|
||||
IRQ34 = 0x42,
|
||||
IRQ35 = 0x43,
|
||||
IRQ36 = 0x44,
|
||||
IRQ37 = 0x45,
|
||||
IRQ38 = 0x46,
|
||||
IRQ39 = 0x47,
|
||||
IRQ40 = 0x48,
|
||||
IRQ41 = 0x49,
|
||||
IRQ42 = 0x4a,
|
||||
IRQ43 = 0x4b,
|
||||
IRQ44 = 0x4c,
|
||||
IRQ45 = 0x4d,
|
||||
IRQ46 = 0x4e,
|
||||
IRQ47 = 0x4f,
|
||||
IRQ48 = 0x50,
|
||||
IRQ49 = 0x51,
|
||||
IRQ50 = 0x52,
|
||||
IRQ51 = 0x53,
|
||||
IRQ52 = 0x54,
|
||||
IRQ53 = 0x55,
|
||||
IRQ54 = 0x56,
|
||||
IRQ55 = 0x57,
|
||||
IRQ56 = 0x58,
|
||||
IRQ57 = 0x59,
|
||||
IRQ58 = 0x5a,
|
||||
IRQ59 = 0x5b,
|
||||
IRQ60 = 0x5c,
|
||||
IRQ61 = 0x5d,
|
||||
IRQ62 = 0x5e,
|
||||
IRQ63 = 0x5f,
|
||||
IRQ64 = 0x60,
|
||||
IRQ65 = 0x61,
|
||||
IRQ66 = 0x62,
|
||||
IRQ67 = 0x63,
|
||||
IRQ68 = 0x64,
|
||||
IRQ69 = 0x65,
|
||||
IRQ70 = 0x66,
|
||||
IRQ71 = 0x67,
|
||||
IRQ72 = 0x68,
|
||||
IRQ73 = 0x69,
|
||||
IRQ74 = 0x6a,
|
||||
IRQ75 = 0x6b,
|
||||
IRQ76 = 0x6c,
|
||||
IRQ77 = 0x6d,
|
||||
IRQ78 = 0x6e,
|
||||
IRQ79 = 0x6f,
|
||||
IRQ80 = 0x70,
|
||||
IRQ81 = 0x71,
|
||||
IRQ82 = 0x72,
|
||||
IRQ83 = 0x73,
|
||||
IRQ84 = 0x74,
|
||||
IRQ85 = 0x75,
|
||||
IRQ86 = 0x76,
|
||||
IRQ87 = 0x77,
|
||||
IRQ88 = 0x78,
|
||||
IRQ89 = 0x79,
|
||||
IRQ90 = 0x7a,
|
||||
IRQ91 = 0x7b,
|
||||
IRQ92 = 0x7c,
|
||||
IRQ93 = 0x7d,
|
||||
IRQ94 = 0x7e,
|
||||
IRQ95 = 0x7f,
|
||||
IRQ96 = 0x80,
|
||||
IRQ97 = 0x81,
|
||||
IRQ98 = 0x82,
|
||||
IRQ99 = 0x83,
|
||||
IRQ100 = 0x84,
|
||||
IRQ101 = 0x85,
|
||||
IRQ102 = 0x86,
|
||||
IRQ103 = 0x87,
|
||||
IRQ104 = 0x88,
|
||||
IRQ105 = 0x89,
|
||||
IRQ106 = 0x8a,
|
||||
IRQ107 = 0x8b,
|
||||
IRQ108 = 0x8c,
|
||||
IRQ109 = 0x8d,
|
||||
IRQ110 = 0x8e,
|
||||
IRQ111 = 0x8f,
|
||||
IRQ112 = 0x90,
|
||||
IRQ113 = 0x91,
|
||||
IRQ114 = 0x92,
|
||||
IRQ115 = 0x93,
|
||||
IRQ116 = 0x94,
|
||||
IRQ117 = 0x95,
|
||||
IRQ118 = 0x96,
|
||||
IRQ119 = 0x97,
|
||||
IRQ120 = 0x98,
|
||||
IRQ121 = 0x99,
|
||||
IRQ122 = 0x9a,
|
||||
IRQ123 = 0x9b,
|
||||
IRQ124 = 0x9c,
|
||||
IRQ125 = 0x9d,
|
||||
IRQ126 = 0x9e,
|
||||
IRQ127 = 0x9f,
|
||||
IRQ128 = 0xa0,
|
||||
IRQ129 = 0xa1,
|
||||
IRQ130 = 0xa2,
|
||||
IRQ131 = 0xa3,
|
||||
IRQ132 = 0xa4,
|
||||
IRQ133 = 0xa5,
|
||||
IRQ134 = 0xa6,
|
||||
IRQ135 = 0xa7,
|
||||
IRQ136 = 0xa8,
|
||||
IRQ137 = 0xa9,
|
||||
IRQ138 = 0xaa,
|
||||
IRQ139 = 0xab,
|
||||
IRQ140 = 0xac,
|
||||
IRQ141 = 0xad,
|
||||
IRQ142 = 0xae,
|
||||
IRQ143 = 0xaf,
|
||||
IRQ144 = 0xb0,
|
||||
IRQ145 = 0xb1,
|
||||
IRQ146 = 0xb2,
|
||||
IRQ147 = 0xb3,
|
||||
IRQ148 = 0xb4,
|
||||
IRQ149 = 0xb5,
|
||||
IRQ150 = 0xb6,
|
||||
IRQ151 = 0xb7,
|
||||
IRQ152 = 0xb8,
|
||||
IRQ153 = 0xb9,
|
||||
IRQ154 = 0xba,
|
||||
IRQ155 = 0xbb,
|
||||
IRQ156 = 0xbc,
|
||||
IRQ157 = 0xbd,
|
||||
IRQ158 = 0xbe,
|
||||
IRQ159 = 0xbf,
|
||||
IRQ160 = 0xc0,
|
||||
IRQ161 = 0xc1,
|
||||
IRQ162 = 0xc2,
|
||||
IRQ163 = 0xc3,
|
||||
IRQ164 = 0xc4,
|
||||
IRQ165 = 0xc5,
|
||||
IRQ166 = 0xc6,
|
||||
IRQ167 = 0xc7,
|
||||
IRQ168 = 0xc8,
|
||||
IRQ169 = 0xc9,
|
||||
IRQ170 = 0xca,
|
||||
IRQ171 = 0xcb,
|
||||
IRQ172 = 0xcc,
|
||||
IRQ173 = 0xcd,
|
||||
IRQ174 = 0xce,
|
||||
IRQ175 = 0xcf,
|
||||
IRQ176 = 0xd0,
|
||||
IRQ177 = 0xd1,
|
||||
IRQ178 = 0xd2,
|
||||
IRQ179 = 0xd3,
|
||||
IRQ180 = 0xd4,
|
||||
IRQ181 = 0xd5,
|
||||
IRQ182 = 0xd6,
|
||||
IRQ183 = 0xd7,
|
||||
IRQ184 = 0xd8,
|
||||
IRQ185 = 0xd9,
|
||||
IRQ186 = 0xda,
|
||||
IRQ187 = 0xdb,
|
||||
IRQ188 = 0xdc,
|
||||
IRQ189 = 0xdd,
|
||||
IRQ190 = 0xde,
|
||||
IRQ191 = 0xdf,
|
||||
IRQ192 = 0xe0,
|
||||
IRQ193 = 0xe1,
|
||||
IRQ194 = 0xe2,
|
||||
IRQ195 = 0xe3,
|
||||
IRQ196 = 0xe4,
|
||||
IRQ197 = 0xe5,
|
||||
IRQ198 = 0xe6,
|
||||
IRQ199 = 0xe7,
|
||||
IRQ200 = 0xe8,
|
||||
IRQ201 = 0xe9,
|
||||
IRQ202 = 0xea,
|
||||
IRQ203 = 0xeb,
|
||||
IRQ204 = 0xec,
|
||||
IRQ205 = 0xed,
|
||||
IRQ206 = 0xee,
|
||||
IRQ207 = 0xef,
|
||||
IRQ208 = 0xf0,
|
||||
IRQ209 = 0xf1,
|
||||
IRQ210 = 0xf2,
|
||||
IRQ211 = 0xf3,
|
||||
IRQ212 = 0xf4,
|
||||
IRQ213 = 0xf5,
|
||||
IRQ214 = 0xf6,
|
||||
IRQ215 = 0xf7,
|
||||
IRQ216 = 0xf8,
|
||||
IRQ217 = 0xf9,
|
||||
IRQ218 = 0xfa,
|
||||
IRQ219 = 0xfb,
|
||||
IRQ220 = 0xfc,
|
||||
IRQ221 = 0xfd,
|
||||
IRQ222 = 0xfe,
|
||||
IRQ223 = 0xff,
|
||||
} Interrupts;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
|
156
include/pci.hpp
Normal file
156
include/pci.hpp
Normal file
@ -0,0 +1,156 @@
|
||||
#ifndef __FENNIX_KERNEL_PCI_H__
|
||||
#define __FENNIX_KERNEL_PCI_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <vector.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
namespace PCI
|
||||
{
|
||||
namespace Descriptors
|
||||
{
|
||||
enum PCIVendors
|
||||
{
|
||||
SymbiosLogic = 0x1000,
|
||||
RedHat = 0x1AF4,
|
||||
REDHat2 = 0x1B36,
|
||||
Realtek = 0x10EC,
|
||||
VirtualBox = 0x80EE,
|
||||
Ensoniq = 0x1274,
|
||||
QEMU = 0x1234,
|
||||
VMware = 0x15AD,
|
||||
IntelCorporation = 0x8086,
|
||||
AdvancedMicroDevices = 0x1022,
|
||||
NVIDIACorporation = 0x10DE
|
||||
};
|
||||
|
||||
const char *const DeviceClasses[]{
|
||||
"Unclassified",
|
||||
"Mass Storage Controller",
|
||||
"Network Controller",
|
||||
"Display Controller",
|
||||
"Multimedia Controller",
|
||||
"Memory Controller",
|
||||
"Bridge Device",
|
||||
"Simple Communication Controller",
|
||||
"Base System Peripheral",
|
||||
"Input Device Controller",
|
||||
"Docking Station",
|
||||
"Processor",
|
||||
"Serial Bus Controller",
|
||||
"Wireless Controller",
|
||||
"Intelligent Controller",
|
||||
"Satellite Communication Controller",
|
||||
"Encryption Controller",
|
||||
"Signal Processing Controller",
|
||||
"Processing Accelerator",
|
||||
"Non Essential Instrumentation"};
|
||||
|
||||
const char *MassStorageControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *NetworkControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *DisplayControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *CommunicationControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode);
|
||||
const char *SerialBusControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *BridgeDeviceSubclassName(uint8_t SubclassCode);
|
||||
const char *WirelessControllerSubclassName(uint8_t SubclassCode);
|
||||
const char *GetVendorName(uint32_t VendorID);
|
||||
const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID);
|
||||
const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode);
|
||||
const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF);
|
||||
}
|
||||
|
||||
/* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */
|
||||
enum PCICommands
|
||||
{
|
||||
/** @brief Enable response in I/O space */
|
||||
PCI_COMMAND_IO = 0x1,
|
||||
/** @brief Enable response in Memory space */
|
||||
PCI_COMMAND_MEMORY = 0x2,
|
||||
/** @brief Enable bus mastering */
|
||||
PCI_COMMAND_MASTER = 0x4,
|
||||
/** @brief Enable response to special cycles */
|
||||
PCI_COMMAND_SPECIAL = 0x8,
|
||||
/** @brief Use memory write and invalidate */
|
||||
PCI_COMMAND_INVALIDATE = 0x10,
|
||||
/** @brief Enable palette snooping */
|
||||
PCI_COMMAND_VGA_PALETTE = 0x20,
|
||||
/** @brief Enable parity checking */
|
||||
PCI_COMMAND_PARITY = 0x40,
|
||||
/** @brief Enable address/data stepping */
|
||||
PCI_COMMAND_WAIT = 0x80,
|
||||
/** @brief Enable SERR */
|
||||
PCI_COMMAND_SERR = 0x100,
|
||||
/** @brief Enable back-to-back writes */
|
||||
PCI_COMMAND_FAST_BACK = 0x200,
|
||||
/** @brief INTx Emulation Disable */
|
||||
PCI_COMMAND_INTX_DISABLE = 0x400
|
||||
};
|
||||
|
||||
struct PCIDeviceHeader
|
||||
{
|
||||
uint16_t VendorID;
|
||||
uint16_t DeviceID;
|
||||
uint16_t Command;
|
||||
uint16_t Status;
|
||||
uint8_t RevisionID;
|
||||
uint8_t ProgIF;
|
||||
uint8_t Subclass;
|
||||
uint8_t Class;
|
||||
uint8_t CacheLineSize;
|
||||
uint8_t LatencyTimer;
|
||||
uint8_t HeaderType;
|
||||
uint8_t BIST;
|
||||
};
|
||||
|
||||
struct PCIHeader0
|
||||
{
|
||||
PCIDeviceHeader Header;
|
||||
uint32_t BAR0;
|
||||
uint32_t BAR1;
|
||||
uint32_t BAR2;
|
||||
uint32_t BAR3;
|
||||
uint32_t BAR4;
|
||||
uint32_t BAR5;
|
||||
uint32_t CardbusCISPtr;
|
||||
uint16_t SubsystemVendorID;
|
||||
uint16_t SubsystemID;
|
||||
uint32_t ExpansionROMBaseAddr;
|
||||
uint8_t CapabilitiesPtr;
|
||||
uint8_t Rsv0;
|
||||
uint16_t Rsv1;
|
||||
uint32_t Rsv2;
|
||||
uint8_t InterruptLine;
|
||||
uint8_t InterruptPin;
|
||||
uint8_t MinGrant;
|
||||
uint8_t MaxLatency;
|
||||
};
|
||||
|
||||
struct DeviceConfig
|
||||
{
|
||||
uint64_t BaseAddress;
|
||||
uint16_t PCISegGroup;
|
||||
uint8_t StartBus;
|
||||
uint8_t EndBus;
|
||||
uint32_t Reserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
class PCI
|
||||
{
|
||||
private:
|
||||
Vector<PCIDeviceHeader *> Devices;
|
||||
|
||||
public:
|
||||
void EnumerateFunction(uint64_t DeviceAddress, uint64_t Function);
|
||||
void EnumerateDevice(uint64_t BusAddress, uint64_t Device);
|
||||
void EnumerateBus(uint64_t BaseAddress, uint64_t Bus);
|
||||
Vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
|
||||
Vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
|
||||
|
||||
PCI();
|
||||
~PCI();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_PCI_H__
|
24
include/power.hpp
Normal file
24
include/power.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __FENNIX_KERNEL_POWER_H__
|
||||
#define __FENNIX_KERNEL_POWER_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
namespace Power
|
||||
{
|
||||
class Power
|
||||
{
|
||||
private:
|
||||
// specific for 64 and 32 bit
|
||||
void *acpi;
|
||||
void *dsdt;
|
||||
void *madt;
|
||||
|
||||
public:
|
||||
void Reboot();
|
||||
void Shutdown();
|
||||
Power();
|
||||
~Power();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_POWER_H__
|
Loading…
x
Reference in New Issue
Block a user