mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-03 11:29:17 +00:00
feat(kernel/drivers): migrate drivers to the kernel
make the drivers builtin Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
210
Kernel/drivers/audio/hda/hda.cpp
Normal file
210
Kernel/drivers/audio/hda/hda.cpp
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user