Initial commit

This commit is contained in:
2021-10-10 14:39:17 +08:00
commit d25da95e1e
135 changed files with 19184 additions and 0 deletions

View File

@ -0,0 +1,64 @@
#pragma once
#include "../../../../main.h"
#include "ps2.h"
#include "../internal.h"
#ifdef __cplusplus
extern "C" {
#endif
SYSV_ABI void irq_pic_ps2_IRQHandlerK(); // keyboard IRQ1
SYSV_ABI void irq_pic_ps2_IRQHandlerM(); // mouse IRQ12
// waits until the Output Buffer Status (bit 0) of the Status Register is set
// and port 0x60 is ready for data read
static inline void __ps2_PollWait_ReadReady() {
while ((inb(IRQ_PIC_PS2_STATUSPORT) & IRQ_PIC_PS2_STATUS_OUTPUT_BUFFER) == 0)
asm("pause");
}
// waits until the Input Buffer Status (bit 1) of the Status Register is clear
// and ports 0x60/0x64 are ready for data write
static inline void __ps2_PollWait_WriteReady() {
while ((inb(IRQ_PIC_PS2_STATUSPORT) & IRQ_PIC_PS2_STATUS_INPUT_BUFFER) != 0)
asm("pause");
}
// waits until port 0x60 is ready and reads the byte in it
static inline uint8_t __ps2_ReadData() {
__ps2_PollWait_ReadReady();
return inb(IRQ_PIC_PS2_IOPORT);
}
// waits until port 0x64 is ready for write, OUTB to it.
static inline void __ps2_WriteCommand(uint8_t cmd) {
__ps2_PollWait_WriteReady();
outb(IRQ_PIC_PS2_CMDPORT, cmd);
}
// waits until port 0x64 is ready, OUTB to it, OUTB to 0x60 for data byte.
static inline void __ps2_WriteCommandData(uint8_t cmd, uint8_t data) {
__ps2_PollWait_WriteReady();
outb(IRQ_PIC_PS2_CMDPORT, cmd);
__ps2_PollWait_WriteReady();
outb(IRQ_PIC_PS2_IOPORT, data);
}
static inline void __ps2_ReadACK() {
while (__ps2_ReadData() != IRQ_PIC_PS2_ACK) {}
}
// sets the sample rate of the mouse
static inline void __ps2_SetMouseRate(uint8_t rate) {
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_SEND_MOUSE, 0xf3); // command to the mouse
__ps2_ReadACK(); // read the ACK
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_SEND_MOUSE, rate); // send the rate
__ps2_ReadACK(); // read the ACK
}
#ifdef __cplusplus
}
#endif

80
driver/irq/pic/ps2/ps2.c Normal file
View File

@ -0,0 +1,80 @@
#include "ps2.h"
#include "../pic.h"
#include "../internal.h"
#include "internal.h"
#include "../../../../interrupt/interrupt.h"
#include "../../../../runtime/panic_assert.h"
#include "../../../../runtime/stdio.h"
#include "../../../../graphics/graphics.h"
bool irq_pic_ps2_Mouse4Bytes; // the mouse has 4-byte data packages instead of 3
queue irq_pic_ps2_QueueKeyboard, irq_pic_ps2_QueueMouse;
uint8_t __irq_pic_ps2_QueueBufferK[IRQ_PIC_PS2_QUEUESIZE_KEYBOARD], __irq_pic_ps2_QueueBufferM[IRQ_PIC_PS2_QUEUESIZE_MOUSE];
void irq_pic_ps2_Init() {
assert(irq_pic_Enabled && "irq_pic_ps2_Init() requires PIC to be enabled");
// init the Keyboard and Mouse queues
queue_InitBuffered(&irq_pic_ps2_QueueKeyboard, __irq_pic_ps2_QueueBufferK, IRQ_PIC_PS2_QUEUESIZE_KEYBOARD);
queue_InitBuffered(&irq_pic_ps2_QueueMouse, __irq_pic_ps2_QueueBufferM, IRQ_PIC_PS2_QUEUESIZE_MOUSE);
uint8_t data;
INTERRUPT_DISABLE;
irq_pic_IRQHandler[IRQ_PIC_PS2_KEYBOARD] = irq_pic_ps2_IRQHandlerK;
irq_pic_IRQHandler[IRQ_PIC_PS2_MOUSE] = irq_pic_ps2_IRQHandlerM;
irq_pic_Mask(IRQ_PIC_PS2_KEYBOARD, false);
irq_pic_Mask(IRQ_PIC_PS2_MOUSE, false);
// enable second PS/2 port
io_Printf("ENABLE_MOUSE... ");
__ps2_WriteCommand(IRQ_PIC_PS2_CMD_ENABLE_MOUSE);
// write controller mode (EnablePort1Int | EnablePort2Int | SystemPOSTOk | Port1Translation)
io_Printf("CONTROLLER_WRITE_CONFIGBYTE... ");
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_WRITE_CONFIGBYTE, 0x47);
// reset mouse
io_Printf("DEVICE_RESET... ");
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_SEND_MOUSE, IRQ_PIC_PS2_CMD_DEVICE_RESET);
while ((data = __ps2_ReadData()) != IRQ_PIC_PS2_RESET_OK) {
io_Printf("%X ", data);
}
io_Printf("%X ", data);
// enable mouse reporting
io_Printf("MOUSE_ENABLE_REPORTING... ");
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_SEND_MOUSE, IRQ_PIC_PS2_CMD_DEVICE_MOUSE_ENABLE_REPORTING);
__ps2_ReadACK(); // receive ACK
// enable 4-byte mode for mouse, pure magic!
irq_pic_ps2_Mouse4Bytes = false;
__ps2_SetMouseRate(200);
__ps2_SetMouseRate(100);
__ps2_SetMouseRate(80);
io_Printf("SEND_MOUSE(PS2_DEVICE_ID)");
__ps2_WriteCommandData(IRQ_PIC_PS2_CMD_SEND_MOUSE, 0xf2); // get device ID
__ps2_ReadACK();
uint8_t id = __ps2_ReadData(); // receive device ID
io_Printf(", MOUSE PS/2 ID=%d\n", id);
if (id == 3) // Z-axis is enabled
irq_pic_ps2_Mouse4Bytes = true;
// set the actual mouse sample rate
__ps2_SetMouseRate(IRQ_PIC_PS2_MOUSE_SAMPLERATE);
INTERRUPT_RESTORE;
}
SYSV_ABI void irq_pic_ps2_IRQHandlerK() {
queue_PushByte(&irq_pic_ps2_QueueKeyboard, inb(IRQ_PIC_PS2_IOPORT));
}
SYSV_ABI void irq_pic_ps2_IRQHandlerM() {
queue_PushByte(&irq_pic_ps2_QueueMouse, inb(IRQ_PIC_PS2_IOPORT));
}

58
driver/irq/pic/ps2/ps2.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include "../../../../util/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
#define IRQ_PIC_PS2_MOUSE_SAMPLERATE 60 // the sample rate of the mouse
#define IRQ_PIC_PS2_KEYBOARD 1 // Keyboard IRQ number
#define IRQ_PIC_PS2_MOUSE 12 // Mouse IRQ number
#define IRQ_PIC_PS2_IOPORT 0x0060
#define IRQ_PIC_PS2_STATUSPORT 0x0064
#define IRQ_PIC_PS2_CMDPORT 0x0064
#define IRQ_PIC_PS2_STATUS_OUTPUT_BUFFER (1 << 0)
#define IRQ_PIC_PS2_STATUS_INPUT_BUFFER (1 << 1)
#define IRQ_PIC_PS2_STATUS_SYSTEM_FLAG (1 << 2)
#define IRQ_PIC_PS2_STATUS_INPUT_BUFFER_IS_COMMAND (1 << 3) // (0 = data written to input buffer is data for PS/2 device, 1 = data written to input buffer is data for PS/2 controller command)
#define IRQ_PIC_PS2_STATUS_UNUSED_4 (1 << 4)
#define IRQ_PIC_PS2_STATUS_UNUSED_5 (1 << 5)
#define IRQ_PIC_PS2_STATUS_TIMEOUT_ERROR (1 << 6)
#define IRQ_PIC_PS2_STATUS_PARITY_ERROR (1 << 7)
#define IRQ_PIC_PS2_ACK 0xfa // ACK code for keyboard and mouse (controller cmds have no ack)
#define IRQ_PIC_PS2_RESET_OK 0xaa // the last output byte when a PS/2 device is reset
#define IRQ_PIC_PS2_CMD_READ_CONFIGBYTE 0x20 // Read byte 0 from controller RAM (configuration byte)
#define IRQ_PIC_PS2_CMD_WRITE_CONFIGBYTE 0x60 // Write byte 0 to controller RAM (config byte)
#define IRQ_PIC_PS2_CMD_DISABLE_MOUSE 0xa9 // Disable second PS/2 port (usually mouse)
#define IRQ_PIC_PS2_CMD_ENABLE_MOUSE 0xa8 // Enable second PS/2 port (usually mouse)
#define IRQ_PIC_PS2_CMD_SEND_MOUSE 0xd4 // Send a data byte to the second PS/2 port (usually mouse)
#define IRQ_PIC_PS2_CMD_DEVICE_GETID 0xf2
#define IRQ_PIC_PS2_CMD_DEVICE_RESET 0xff
#define IRQ_PIC_PS2_CMD_DEVICE_MOUSE_DISABLE_REPORTING 0xf5
#define IRQ_PIC_PS2_CMD_DEVICE_MOUSE_ENABLE_REPORTING 0xf4
void irq_pic_ps2_Init();
extern bool irq_pic_ps2_Mouse4Bytes; // the mouse has 4-byte data packages instead of 3; mouse wheel enabled
// size in bytes of the Keyboard/Mouse FIFO buffers
#define IRQ_PIC_PS2_QUEUESIZE_KEYBOARD 64
#define IRQ_PIC_PS2_QUEUESIZE_MOUSE 256
// data queue in bytes for the Keyboard and Mouse IRQs
extern queue irq_pic_ps2_QueueKeyboard, irq_pic_ps2_QueueMouse;
#ifdef __cplusplus
}
#endif