1
0
mirror of https://github.com/EnderIce2/Fennix.git synced 2025-07-23 21:21:41 +00:00
Files
.devcontainer
.github
.vscode
Bootloader
Drivers
Kernel
.vscode
arch
core
drivers
audio
fs
misc
aip
aip.hpp
ata.cpp
keyboard.cpp
main.cpp
mouse.cpp
scancodes.c
uart.cpp
mem
pty
vmware
net
storage
video
trusted.c
exec
files
include
include_std
kshell
library
network
profiling
storage
subsystem
syscalls
tasking
tests
tty
virtualization
.editorconfig
.gdbinit
.gitignore
ISSUES.md
Makefile
README.md
TODO.md
dump.sh
kernel.cpp
kernel.h
kernel_config.cpp
kernel_note.cpp
kernel_thread.cpp
kernel_vfs.cpp
Userspace
rootfs
tools
.editorconfig
.gitignore
.gitlab-ci.yml
CHANGELOG.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CREDITS.md
Doxyfile
Fennix Bootloader.code-workspace
Fennix Drivers.code-workspace
Fennix Kernel.code-workspace
Fennix Userspace.code-workspace
Fennix Website.code-workspace
Fennix.code-workspace
INSTALL.md
LICENSE.md
LICENSES.md
Makefile
README.md
SECURITY.md
STYLE_GUIDE.md
cliff.toml
config.mk
Fennix/Kernel/drivers/misc/aip/main.cpp
2025-03-05 23:19:02 +00:00

265 lines
6.0 KiB
C++

/*
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/>.
*/
#if defined(__amd64__) || defined(__i386__)
#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);
}
#endif