about summary refs log tree commit diff stats
path: root/tools/iso/kernel.soso/mouse.c
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-01-01 18:22:19 -0800
committerKartik Agaram <vc@akkartik.com>2020-01-01 18:42:48 -0800
commit65409d2312e702a48d3cf5b32479d25266bda3c3 (patch)
tree62a7262fce61f2302109246da4536ce6f8e9ef80 /tools/iso/kernel.soso/mouse.c
parenta6da50ad30d2e1825575ffef497ab450a8f26e94 (diff)
downloadmu-65409d2312e702a48d3cf5b32479d25266bda3c3.tar.gz
5858
Move script to create a Soso boot image into a sub-directory.

I'm trying to streamline newcomer attention to just a couple of use cases.
Diffstat (limited to 'tools/iso/kernel.soso/mouse.c')
-rw-r--r--tools/iso/kernel.soso/mouse.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/tools/iso/kernel.soso/mouse.c b/tools/iso/kernel.soso/mouse.c
new file mode 100644
index 00000000..235d931d
--- /dev/null
+++ b/tools/iso/kernel.soso/mouse.c
@@ -0,0 +1,187 @@
+#include "mouse.h"
+#include "isr.h"
+#include "common.h"
+#include "device.h"
+#include "alloc.h"
+#include "devfs.h"
+#include "list.h"
+#include "fifobuffer.h"
+#include "spinlock.h"
+
+static void handleMouseInterrupt(Registers *regs);
+
+static uint8 gMouseByteCounter = 0;
+
+static void prepareForRead();
+static void prepareForWrite();
+static void writeMouse(uint8 data);
+static void handleMouseInterrupt(Registers *regs);
+
+static BOOL mouse_open(File *file, uint32 flags);
+static void mouse_close(File *file);
+static int32 mouse_read(File *file, uint32 size, uint8 *buffer);
+
+#define MOUSE_PACKET_SIZE 3
+
+uint8 gMousePacket[MOUSE_PACKET_SIZE];
+
+static List* gReaders = NULL;
+
+static Spinlock gReadersLock;
+
+void initializeMouse() {
+    Device device;
+    memset((uint8*)&device, 0, sizeof(Device));
+    strcpy(device.name, "psaux");
+    device.deviceType = FT_CharacterDevice;
+    device.open = mouse_open;
+    device.close = mouse_close;
+    device.read = mouse_read;
+    registerInterruptHandler(IRQ12, handleMouseInterrupt);
+
+    registerDevice(&device);
+
+    memset(gMousePacket, 0, MOUSE_PACKET_SIZE);
+
+    gReaders = List_Create();
+
+    Spinlock_Init(&gReadersLock);
+
+    prepareForWrite();
+
+    outb(0x64, 0x20); //get status command
+
+    uint8 status = inb(0x60);
+    status = status | 2; //enable IRQ12
+
+    outb(0x64, 0x60); //set status command
+    outb(0x60, status);
+
+    outb(0x64, 0xA8); //enable Auxiliary Device command
+
+    writeMouse(0xF4); //0xF4: Enable Packet Streaming
+}
+
+static BOOL mouse_open(File *file, uint32 flags) {
+    FifoBuffer* fifo = FifoBuffer_create(60);
+
+    file->privateData = (void*)fifo;
+
+    Spinlock_Lock(&gReadersLock);
+
+    List_Append(gReaders, file);
+
+    Spinlock_Unlock(&gReadersLock);
+
+    return TRUE;
+}
+
+static void mouse_close(File *file) {
+    Spinlock_Lock(&gReadersLock);
+
+    List_RemoveFirstOccurrence(gReaders, file);
+
+    Spinlock_Unlock(&gReadersLock);
+
+    FifoBuffer* fifo = (FifoBuffer*)file->privateData;
+
+    FifoBuffer_destroy(fifo);
+}
+
+static int32 mouse_read(File *file, uint32 size, uint8 *buffer) {
+    FifoBuffer* fifo = (FifoBuffer*)file->privateData;
+
+    while (FifoBuffer_getSize(fifo) < MOUSE_PACKET_SIZE) {
+        file->thread->state = TS_WAITIO;
+        file->thread->state_privateData = mouse_read;
+        enableInterrupts();
+        halt();
+    }
+
+    disableInterrupts();
+
+
+    uint32 available = FifoBuffer_getSize(fifo);
+    uint32 smaller = MIN(available, size);
+
+    FifoBuffer_dequeue(fifo, buffer, smaller);
+
+    return smaller;
+}
+
+static void prepareForRead() {
+    //https://wiki.osdev.org/Mouse_Input
+    //Bytes cannot be read from port 0x60 until bit 0 (value=1) of port 0x64 is set
+
+    int32 tryCount = 1000;
+
+    uint8 data = 0;
+    do {
+        data = inb(0x64);
+    } while (((data & 0x01) == 0) && --tryCount > 0);
+}
+
+static void prepareForWrite() {
+    //https://wiki.osdev.org/Mouse_Input
+    //All output to port 0x60 or 0x64 must be preceded by waiting for bit 1 (value=2) of port 0x64 to become clear
+
+    int32 tryCount = 1000;
+
+    uint8 data = 0;
+    do {
+        data = inb(0x64);
+    } while (((data & 0x02) != 0) && --tryCount > 0);
+}
+
+static void writeMouse(uint8 data) {
+    prepareForWrite();
+
+    outb(0x64, 0xD4);
+
+    prepareForWrite();
+
+    outb(0x60, data);
+}
+
+static void handleMouseInterrupt(Registers *regs) {
+    uint8 status = 0;
+    //0x20 (5th bit is mouse bit)
+    //read from 0x64, if its mouse bit is 1 then data is available at 0x60!
+
+    int32 tryCount = 1000;
+    do {
+        status = inb(0x64);
+    } while (((status & 0x20) == 0) && --tryCount > 0);
+
+    uint8 data = inb(0x60);
+
+    gMousePacket[gMouseByteCounter] = data;
+
+    gMouseByteCounter += 1;
+
+    if (gMouseByteCounter == MOUSE_PACKET_SIZE) {
+        gMouseByteCounter = 0;
+
+        Spinlock_Lock(&gReadersLock);
+
+        //Wake readers
+        List_Foreach(n, gReaders) {
+            File* file = n->data;
+
+            FifoBuffer* fifo = (FifoBuffer*)file->privateData;
+
+            FifoBuffer_enqueue(fifo, gMousePacket, MOUSE_PACKET_SIZE);
+
+            if (file->thread->state == TS_WAITIO) {
+                if (file->thread->state_privateData == mouse_read) {
+                    file->thread->state = TS_RUN;
+                    file->thread->state_privateData = NULL;
+                }
+            }
+        }
+
+        Spinlock_Unlock(&gReadersLock);
+    }
+
+    //printkf("mouse:%d\n", data);
+}