feat(kernel/drivers): migrate drivers to the kernel

make the drivers builtin

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-03-02 21:37:01 +00:00
parent f824df9aad
commit bf1e3432d7
22 changed files with 7078 additions and 1 deletions

View File

@ -0,0 +1,210 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp>
#include <cpu.hpp>
#include <pci.hpp>
#include "hda.hpp"
extern Driver::Manager *DriverManager;
extern PCI::Manager *PCIManager;
namespace Driver::HighDefinitionAudio
{
dev_t DriverID;
class HDADevice
{
private:
PCI::PCIHeader0 *Header;
bool Initialized = false;
ControllerRegisters *CTL;
uint32_t *CORB;
uint64_t *RIRB;
public:
bool IsInitialized() { return Initialized; }
size_t write(uint8_t *, size_t Size)
{
return Size;
}
int ioctl(AudioIoctl, void *)
{
return 0;
}
void OnInterruptReceived(CPU::TrapFrame *)
{
}
void Panic()
{
}
HDADevice(PCI::PCIHeader0 *_Header)
: Header(_Header),
CORB((uint32_t *)(uintptr_t)DriverManager->AllocateMemory(DriverID, 1)),
RIRB((uint64_t *)DriverManager->AllocateMemory(DriverID, 1))
{
CTL = (ControllerRegisters *)(uintptr_t)Header->BAR0;
fixme("Unimplemented HDA driver");
return;
Initialized = true;
}
~HDADevice()
{
if (!Initialized)
return;
}
};
std::unordered_map<dev_t, HDADevice *> Drivers;
int Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
return Drivers[Node->GetMinor()]->ioctl((AudioIoctl)Request, Argp);
}
ssize_t Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
return Drivers[Node->GetMinor()]->write((uint8_t *)Buffer, Size);
}
const struct InodeOperations ops = {
.Lookup = nullptr,
.Create = nullptr,
.Remove = nullptr,
.Rename = nullptr,
.Read = nullptr,
.Write = Write,
.Truncate = nullptr,
.Open = nullptr,
.Close = nullptr,
.Ioctl = Ioctl,
.ReadDir = nullptr,
.MkDir = nullptr,
.RmDir = nullptr,
.SymLink = nullptr,
.ReadLink = nullptr,
.Seek = nullptr,
.Stat = nullptr,
};
std::list<PCI::PCIDevice> Devices;
int Entry()
{
for (auto &&dev : Devices)
{
PCI::PCIHeader0 *hdr0 = (PCI::PCIHeader0 *)dev.Header;
uint8_t type = hdr0->BAR0 & 1;
if (type == 1)
{
debug("Device %x:%x.%d BAR0 is I/O.",
hdr0->Header.VendorID,
hdr0->Header.DeviceID,
hdr0->Header.ProgIF);
continue;
}
PCIManager->InitializeDevice(dev, KernelPageTable);
HDADevice *driver = new HDADevice((PCI::PCIHeader0 *)dev.Header);
if (driver->IsInitialized())
{
dev_t ret = v0::RegisterDevice(DriverID, AUDIO_TYPE_PCM, &ops);
Drivers[ret] = driver;
}
}
if (Drivers.empty())
{
debug("No valid HDA device found.");
return -EINVAL;
}
return 0;
}
int Final()
{
for (auto &&dev : Drivers)
{
dev_t ret = dev.first;
v0::UnregisterDevice(DriverID, ret);
delete dev.second;
}
return 0;
}
int Panic()
{
for (auto &&i : Drivers)
i.second->Panic();
return 0;
}
int Probe()
{
Devices = PCIManager->FindPCIDevice(
{
0x8086, /* Intel */
0x15AD, /* VMware */
},
{
0x9D71, /* Sunrise Point-LP HD Audio */
0x2668, /* ICH6 */
0x293E, /* ICH9 */
});
if (Devices.empty())
{
trace("No HDA device found.");
return -ENODEV;
}
for (auto &&dev : Devices)
{
PCI::PCIHeader0 *PCIBaseAddress = (PCI::PCIHeader0 *)dev.Header;
uint32_t PCIBAR0 = PCIBaseAddress->BAR0;
uint8_t Type = PCIBAR0 & 1;
if (Type == 1)
{
debug("Device %x:%x.%d BAR0 is I/O.",
PCIBaseAddress->Header.VendorID,
PCIBaseAddress->Header.DeviceID,
PCIBaseAddress->Header.ProgIF);
continue;
}
}
return 0;
}
REGISTER_BUILTIN_DRIVER(hda,
"Intel High Definition Audio Driver",
"enderice2",
1, 0, 0,
Entry,
Final,
Panic,
Probe);
}

View File

@ -0,0 +1,627 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <types.h>
struct StreamDescriptor
{
/** Control */
uint32_t CTL : 24;
/** Status */
uint8_t STS;
/** Link Position in Current Buffer */
uint32_t LPIB;
/** Cyclic Buffer Length */
uint32_t CBL;
/** Last Valid Index */
uint16_t LVI;
/** Reserved */
uint8_t Rsvd0[2];
/** FIFO Size */
uint16_t FIFOD;
/** Format */
uint16_t FMT;
/** Reserved */
uint8_t Rsvd1[4];
/** Buffer Descriptor List Pointer - Lower */
uint32_t BDPL;
/** Buffer Descriptor List Pointer - Upper */
uint32_t BDPU;
} __attribute__((packed));
struct ControllerRegisters
{
uint16_t GCAP;
uint8_t VMIN;
uint8_t VMJ;
uint16_t OUTPAY;
uint16_t INPAY;
uint32_t GCTL;
uint16_t WAKEEN;
uint16_t WAKESTS;
uint16_t GSTS;
uint8_t Rsvd0[6];
uint16_t OUTSTRMPAY;
uint16_t INSTRMPAY;
uint8_t Rsvd1[4];
uint32_t INTCTL;
uint32_t INTSTS;
uint8_t Rsvd2[8];
uint32_t WALCLK;
uint8_t Rsvd3[4];
uint32_t SSYNC;
uint8_t Rsvd4[4];
uint32_t CORBLBASE;
uint32_t CORBUBASE;
uint16_t CORBWP;
uint16_t CORBRP;
uint8_t CORBCTL;
uint8_t CORBSTS;
uint8_t CORBSIZE;
uint8_t Rsvd5;
uint32_t RIRBLBASE;
uint32_t RIRBUBASE;
uint16_t RIRBWP;
uint16_t RINTCNT;
uint8_t RIRBCTL;
uint8_t RIRBSTS;
uint8_t RIRBSIZE;
uint8_t Rsvd6;
uint32_t ICOI;
uint32_t ICII;
uint16_t ICIS;
uint8_t Rsvd7[6];
uint32_t DPIBLBASE;
uint32_t DPIBUBASE;
uint8_t Rsvd8[8];
StreamDescriptor SD[];
} __attribute__((packed));
/* Not working as expected */
struct __ControllerRegisters
{
/** Global Capabilities */
union
{
struct
{
/** 64 Bit Address Supported
*
* 0 = 32-bit addressing
* 1 = 64-bit addressing
*/
uint16_t _64OK : 1;
/** Number of Serial Data Out Signals
*
* 00 = 1 SDO
* 01 = 2 SDOs
* 10 = 4 SDOs
* 11 = Reserved
*/
uint16_t NSDO : 2;
/** Number of Bidirectional Streams Supported
*
* 00000b = No bidirectional streams supported
* 00001b = 1 bidirectional stream supported
* ...
* 11110b = 30 bidirectional streams supported
*/
uint16_t BSS : 5;
/** Number of Input Streams Supported
*
* 0000b = No input streams supported
* 0001b = 1 input stream supported
* ...
* 1111b = 15 input streams supported
*/
uint16_t ISS : 4;
/** Number of Output Streams Supported
*
* 0000b = No output streams supported
* 0001b = 1 output stream supported
* ...
* 1111b = 15 output streams supported
*/
uint16_t OSS : 4;
} __attribute__((packed));
uint16_t Raw;
} GCAP;
/** Minor Version */
uint8_t VMIN;
/** Major Version */
uint8_t VMJ;
/** Output Payload Capability
*
* 00h = 0 Words
* 01h = 1 Word payload
* ...
* FFh = 255h Word payload
*/
uint16_t OUTPAY;
/** Input Payload Capability
*
* 00h = 0 Words
* 01h = 1 Word payload
* ...
* FFh = 255h Word payload
*/
uint16_t INPAY;
/** Global Control */
union
{
struct
{
/** Controller Reset
*
* 0 = Reset
* 1 = Normal Operation
*/
uint32_t CRST : 1;
/** Flush Control
*
* 0 = Idle
* 1 = Flush
*/
uint32_t FCNTRL : 1;
/** Reserved */
uint32_t RsvdP0 : 6;
/** Accept Unsolicited Response Enable
*
* 0 = Disabled
* 1 = Enabled
*/
uint32_t UNSOL : 1;
/** Reserved */
uint32_t RsvdP1 : 23;
} __attribute__((packed));
uint32_t Raw;
} GCTL;
/** Wake Enable */
union
{
struct
{
/** SDIN Wake Enable Flags */
uint16_t SDIWEN : 15;
/** Reserved */
uint16_t RsvdP0 : 1;
} __attribute__((packed));
uint16_t Raw;
} WAKEEN;
/** Wake Status */
union
{
struct
{
/** SDIN State Change Status Flags */
uint16_t SDIWAKE : 15;
/** Reserved */
uint16_t RsvdZ0 : 1;
} __attribute__((packed));
uint16_t Raw;
} WAKESTS;
/** Global Status */
union
{
struct
{
uint16_t RsvdZ0 : 1;
uint16_t FSTS : 1;
uint16_t RsvdZ1 : 14;
} __attribute__((packed));
uint16_t Raw;
} GSTS;
/** Reserved */
uint8_t Rsvd0[6];
/** Output Stream Payload Capability */
uint16_t OUTSTRMPAY;
/** Input Stream Payload Capability */
uint16_t INSTRMPAY;
/** Reserved */
uint8_t Rsvd1[4];
/** Interrupt Control */
union
{
struct
{
/** Stream Interrupt Enable
*
* Bit 0 = Input Stream 0
* Bit 1 = Input Stream 1
* Bit 2 = Output Stream 0
* Bit 3 = Output Stream 1
* Bit 4 = Output Stream 2
* Bit 5 = Bidirectional Stream 0
* Bits 6-28 = Reserved
*/
uint32_t SIE : 30;
/** Controller Interrupt Enable */
uint32_t CIE : 1;
/** Global Interrupt Enable */
uint32_t GIE : 1;
} __attribute__((packed));
uint32_t Raw;
} INTCTL;
/** Interrupt Status */
union
{
struct
{
/** Stream Interrupt Status */
uint32_t SIS : 30;
/** Controller Interrupt Status */
uint32_t CIS : 1;
/** Global Interrupt Status */
uint32_t GIS : 1;
} __attribute__((packed));
uint32_t Raw;
} INTSTS;
/** Reserved */
uint8_t Rsvd2[8];
/** Wall Clock Counter */
uint32_t WALCLK;
/** Reserved */
uint8_t Rsvd3[4];
/** Stream Synchronization */
union
{
struct
{
/** Stream Synchronization Bits */
uint32_t SSYNC : 30;
/** Reserved */
uint32_t RsvdP0 : 2;
} __attribute__((packed));
uint32_t Raw;
} SSYNC;
/** Reserved */
uint8_t Rsvd4[4];
/** CORB Lower Base Address */
union
{
struct
{
/** CORB Lower Base Unimplemented Bits */
uint32_t Unimplemented : 7;
/** CORB Lower Base Address */
uint32_t CORBLBASE : 25;
} __attribute__((packed));
uint32_t Raw;
} CORBLBASE;
/** CORB Upper Base Address */
uint32_t CORBUBASE;
/** CORB Write Pointer */
union
{
struct
{
/** CORB Write Pointer */
uint16_t CORBWP : 8;
/** Reserved */
uint16_t RsvdP0 : 8;
} __attribute__((packed));
uint16_t Raw;
} CORBWP;
/** CORB Read Pointer */
union
{
struct
{
/** CORB Read Pointer */
uint16_t CORBRP : 8;
/** Reserved */
uint16_t RsvdP0 : 7;
/** CORB Read Pointer Reset */
uint16_t CORBRPRST : 1;
} __attribute__((packed));
uint16_t Raw;
} CORBRP;
/** CORB Control */
union
{
struct
{
/** CORB Memory Error Interrupt Enable */
uint8_t CMEIE : 1;
/** Enable CORB DMA Engine
*
* 0 = DMA Stop
* 1 = DMA Run
*
* @note Must read the value back.
*/
uint8_t CORBRUN : 1;
/** Reserved */
uint8_t RsvdP0 : 6;
} __attribute__((packed));
uint8_t Raw;
} CORBCTL;
/** CORB Status */
union
{
struct
{
/** CORB Memory Error Indication */
uint8_t CMEI : 1;
/** Reserved */
uint8_t RsvdZ0 : 7;
} __attribute__((packed));
uint8_t Raw;
} CORBSTS;
/** CORB Size */
union
{
struct
{
/** CORB Size
*
* 00b = 2 entries
* 01b = 16 entries
* 10b = 256 entries
* 11b = Reserved
*/
uint8_t CORBSIZE : 2;
/** Reserved */
uint8_t RsvdP0 : 2;
/** CORB Size Capability
*
* 0001b = 2 entries
* 0010b = 16 entries
* 0100b = 256 entries
* 1000b = Reserved
*/
uint8_t CORBSZCAP : 4;
} __attribute__((packed));
uint8_t Raw;
} CORBSIZE;
/** Reserved */
uint8_t Rsvd5;
/** RIRB Lower Base Address */
union
{
struct
{
/** RIRB Lower Base Unimplemented Bits */
uint32_t Unimplemented : 7;
/** RIRB Lower Base Address */
uint32_t RIRBLBASE : 25;
} __attribute__((packed));
uint32_t Raw;
} RIRBLBASE;
/** RIRB Upper Base Address */
uint32_t RIRBUBASE;
/** RIRB Write Pointer */
union
{
struct
{
/** RIRB Write Pointer */
uint16_t RIRBWP : 8;
/** Reserved */
uint16_t RsvdP0 : 7;
/** RIRB Write Pointer Reset */
uint16_t RIRBWPRST : 1;
} __attribute__((packed));
uint16_t Raw;
} RIRBWP;
/** Response Interrupt Count */
union
{
struct
{
/** N Response Interrupt Count
*
* 00000001b = 1 Response sent to RIRB
* ...
* 11111111b = 255 Responses sent to RIRB
* 00000000b = 256 Response sent to RIRB
*/
uint16_t RINTCNT : 8;
/** Reserved */
uint16_t RsvdP0 : 8;
} __attribute__((packed));
uint16_t Raw;
} RINTCNT;
/** RIRB Control */
union
{
struct
{
/** Response Interrupt Control
*
* 0 = Disable Interrupt
* 1 = Generate an interrupt after N responses are sent to the RIRB
*/
uint8_t RINTCTL : 1;
/** RIRB DMA Enable
*
* 0 = DMA Stop
* 1 = DMA Run
*/
uint8_t RIRBDMAEN : 1;
/** Response Overrun Interrupt Control */
uint8_t RIRBOIC : 1;
/** Reserved */
uint8_t RsvdP0 : 5;
} __attribute__((packed));
uint8_t Raw;
} RIRBCTL;
/** RIRB Status */
union
{
struct
{
/** Response Interrupt */
uint8_t RINTFL : 1;
/** Reserved */
uint8_t RsvdZ0 : 1;
/** Response Overrun Interrupt Status */
uint8_t RIRBOIS : 1;
/** Reserved */
uint8_t RsvdZ1 : 5;
} __attribute__((packed));
uint8_t Raw;
} RIRBSTS;
/** RIRB Size */
union
{
struct
{
/** RIRB Size
*
* 00b = 2 entries
* 01b = 16 entries
* 10b = 256 entries
* 11b = Reserved
*/
uint8_t RIRBSIZE : 2;
/** Reserved */
uint8_t RsvdP0 : 2;
/** RIRB Size Capability
*
* 0001b = 2 entries
* 0010b = 16 entries
* 0100b = 256 entries
* 1000b = Reserved
*/
uint8_t RIRBSZCAP : 4;
} __attribute__((packed));
uint8_t Raw;
} RIRBSIZE;
/** Reserved */
uint8_t Rsvd6;
/** Immediate Command Output Interface */
uint32_t ICOI;
/** Immediate Command Input Interface */
uint32_t ICII;
/** Immediate Command Status */
uint16_t ICIS;
/** Reserved */
uint8_t Rsvd7[6];
/** DMA Position Buffer Lower Base */
union
{
struct
{
/** DMA Position Buffer Enable */
uint32_t DPBEN : 1;
/** Reserved */
uint32_t RsvdZ0 : 6;
/** DMA Position Lower Base Address */
uint32_t DPLBASE : 25;
} __attribute__((packed));
uint32_t Raw;
} DPIBLBASE;
/** DMA Position Buffer Upper Base */
uint32_t DPIBUBASE;
/** Reserved */
uint8_t Rsvd8[8];
StreamDescriptor SD[];
} __attribute__((packed));