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:
260
Kernel/drivers/misc/aip/main.cpp
Normal file
260
Kernel/drivers/misc/aip/main.cpp
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
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 <interface/aip.h>
|
||||
#include <cpu.hpp>
|
||||
#include <pci.hpp>
|
||||
|
||||
#include "aip.hpp"
|
||||
|
||||
extern Driver::Manager *DriverManager;
|
||||
extern PCI::Manager *PCIManager;
|
||||
EXTERNC void KPrint(const char *Format, ...);
|
||||
namespace Driver::AdvancedIntegratedPeripheral
|
||||
{
|
||||
dev_t DriverID;
|
||||
|
||||
bool IsATAPresent()
|
||||
{
|
||||
outb(0x1F0 + 2, 0);
|
||||
outb(0x1F0 + 3, 0);
|
||||
outb(0x1F0 + 4, 0);
|
||||
outb(0x1F0 + 5, 0);
|
||||
outb(0x1F0 + 7, 0xEC);
|
||||
if (inb(0x1F0 + 7) == 0 || inb(0x1F0 + 1) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsKeyboard(uint8_t ID)
|
||||
{
|
||||
/* Common keyboard IDs */
|
||||
return ID == 0xAB || ID == 0xAC || ID == 0x5D ||
|
||||
ID == 0x2B || ID == 0x47 || ID == 0x60;
|
||||
}
|
||||
|
||||
bool IsMouse(uint8_t ID)
|
||||
{
|
||||
/* Common mouse IDs */
|
||||
return ID == 0x00 || ID == 0x03 || ID == 0x04;
|
||||
}
|
||||
|
||||
const char *GetPS2DeviceName(uint8_t ID, uint8_t SubID)
|
||||
{
|
||||
switch (ID)
|
||||
{
|
||||
case 0x00:
|
||||
return "Standard PS/2 Mouse";
|
||||
case 0x03:
|
||||
return "Mouse with scroll wheel";
|
||||
case 0x04:
|
||||
return "Mouse 5 buttons";
|
||||
case 0xAB:
|
||||
{
|
||||
switch (SubID)
|
||||
{
|
||||
case 0x83: /* Normal */
|
||||
case 0x41: /* Translated */
|
||||
case 0xC1: /* Normal + Translated */
|
||||
return "Standard PS/2 Keyboard";
|
||||
case 0x84:
|
||||
case 0x54:
|
||||
return "IBM Thinkpad/Spacesaver Keyboard";
|
||||
case 0x85:
|
||||
return "NCD N-97/122-Key Host Connect(ed) Keyboard";
|
||||
case 0x86:
|
||||
return "122-Key Keyboard";
|
||||
case 0x90:
|
||||
return "Japanese \"G\" Keyboard";
|
||||
case 0x91:
|
||||
return "Japanese \"P\" Keyboard";
|
||||
case 0x92:
|
||||
return "Japanese \"A\" Keyboard";
|
||||
default:
|
||||
return "Unknown PS/2 Keyboard";
|
||||
}
|
||||
}
|
||||
case 0xAC:
|
||||
{
|
||||
switch (SubID)
|
||||
{
|
||||
case 0xA1:
|
||||
return "NCD Sun Keyboard";
|
||||
default:
|
||||
return "Unknown NCD Sun Keyboard";
|
||||
}
|
||||
}
|
||||
case 0x5D:
|
||||
case 0x2B:
|
||||
return "Trust Keyboard";
|
||||
case 0x47:
|
||||
case 0x60:
|
||||
return "NMB SGI Keyboard";
|
||||
default:
|
||||
return "Unknown PS/2 Device";
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Device1ID[2] = {0x00, 0x00};
|
||||
uint8_t Device2ID[2] = {0x00, 0x00};
|
||||
bool DualChannel = false;
|
||||
bool ATAPresent = false;
|
||||
|
||||
int Entry()
|
||||
{
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_1);
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_2);
|
||||
v0::PS2ClearOutputBuffer(DriverID);
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_READ_CONFIG);
|
||||
PS2_CONFIGURATION cfg = {.Raw = v0::PS2ReadData(DriverID)};
|
||||
|
||||
DualChannel = cfg.Port2Clock;
|
||||
if (DualChannel)
|
||||
trace("Dual channel PS/2 controller detected");
|
||||
cfg.Port1Interrupt = 1;
|
||||
cfg.Port2Interrupt = 1;
|
||||
cfg.Port1Translation = 1;
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_WRITE_CONFIG);
|
||||
v0::PS2WriteData(DriverID, cfg.Raw);
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_TEST_CONTROLLER);
|
||||
uint8_t test = v0::PS2ReadData(DriverID);
|
||||
if (test != PS2_TEST_PASSED)
|
||||
{
|
||||
trace("PS/2 controller self test failed (%#x)", test);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_WRITE_CONFIG);
|
||||
v0::PS2WriteData(DriverID, cfg.Raw);
|
||||
|
||||
// bool port2avail = false;
|
||||
// if (DualChannel)
|
||||
// {
|
||||
// v0::PS2WriteCommand(DriverID, PS2_CMD_ENABLE_PORT_1);
|
||||
// v0::PS2WriteCommand(DriverID, PS2_CMD_READ_CONFIG);
|
||||
// cfg.Raw = v0::PS2ReadData(DriverID);
|
||||
// port2avail = cfg.Port2Clock;
|
||||
// v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_1);
|
||||
// }
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_TEST_PORT_1);
|
||||
test = v0::PS2ReadData(DriverID);
|
||||
if (test != 0x00)
|
||||
{
|
||||
trace("PS/2 Port 1 self test failed (%#x)", test);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (DualChannel)
|
||||
{
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_TEST_PORT_2);
|
||||
test = v0::PS2ReadData(DriverID);
|
||||
if (test != 0x00)
|
||||
{
|
||||
trace("PS/2 Port 2 self test failed (%#x)", test);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_ENABLE_PORT_1);
|
||||
if (DualChannel)
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_ENABLE_PORT_2);
|
||||
|
||||
int errK = InitializeKeyboard();
|
||||
|
||||
int errM = 0;
|
||||
if (DualChannel)
|
||||
errM = InitializeMouse();
|
||||
|
||||
ATAPresent = IsATAPresent();
|
||||
|
||||
if (errK != 0 && errM != 0 && ATAPresent == false)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Final()
|
||||
{
|
||||
FinalizeKeyboard();
|
||||
FinalizeMouse();
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_1);
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Panic()
|
||||
{
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_1);
|
||||
v0::PS2WriteCommand(DriverID, PS2_CMD_DISABLE_PORT_2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __intStub() {}
|
||||
int Probe()
|
||||
{
|
||||
v0::RegisterInterruptHandler(DriverID, 1, (void *)__intStub);
|
||||
v0::RegisterInterruptHandler(DriverID, 12, (void *)__intStub);
|
||||
|
||||
int kbd = DetectPS2Keyboard();
|
||||
int mouse = DetectPS2Mouse();
|
||||
int uart = DetectUART();
|
||||
|
||||
v0::UnregisterAllInterruptHandlers(DriverID, (void *)__intStub);
|
||||
|
||||
if (kbd != 0 && mouse != 0 && uart != 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (kbd == 0)
|
||||
{
|
||||
if (!IsKeyboard(Device1ID[0]))
|
||||
{
|
||||
trace("PS/2 Port 1 is not a keyboard");
|
||||
// return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse == 0)
|
||||
{
|
||||
if (!IsMouse(Device2ID[0]))
|
||||
{
|
||||
trace("PS/2 Port 2 is not a mouse");
|
||||
// return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
KPrint("PS/2 Port 1: %s (0x%X 0x%X)",
|
||||
GetPS2DeviceName(Device1ID[0], Device1ID[1]),
|
||||
Device1ID[0], Device1ID[1]);
|
||||
KPrint("PS/2 Port 2: %s (0x%X 0x%X)",
|
||||
GetPS2DeviceName(Device2ID[0], Device2ID[1]),
|
||||
Device2ID[0], Device2ID[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_BUILTIN_DRIVER(aip,
|
||||
"Advanced Integrated Peripheral Driver",
|
||||
"enderice2",
|
||||
1, 0, 0,
|
||||
Entry,
|
||||
Final,
|
||||
Panic,
|
||||
Probe);
|
||||
}
|
Reference in New Issue
Block a user