Orion
Barry Keyboard/Mouse drivers + POSIX names for structs 1628fcf (3 years, 1 month ago)
diff --git a/drivers/drivers.c b/drivers/drivers.c
index 5ae8c4b..1a2fa8d 100644
--- a/drivers/drivers.c
+++ b/drivers/drivers.c
@@ -29,6 +29,9 @@ Device devices[] = {
{0x10ec, 0x8139, "Realtek RTL8139 10/100 NIC", rtl8139_init},
{0x8086, 0x100e, "Intel Pro 1000/MT NIC", NULL},
+ /* Virtual devices */
+ {0x1b36, 0x000d, "QEMU XHCI Host Adapter", xhci_init},
+
/* VGA devices */
{0x1234, 0x1111, "QEMU/Bochs VBE Framebuffer", bga_init},
};
@@ -76,6 +79,7 @@ init_drivers(void)
{
uint16_t bus, slot, func;
uint16_t vendor, device;
+ uint8_t class, subclass;
uint32_t dev;
kprintf("Enumerating PCI devices");
for (bus = 0; bus < 256; bus++)
@@ -95,8 +99,11 @@ init_drivers(void)
}
if (devices[dev].vendor != vendor
|| devices[dev].device != device) {
- kprintf(" PCI(%d,%d,%d) = %#x:%#x",
- bus, slot, func, vendor, device);
+ class = pci_read_byte(bus, slot, func, 11);
+ subclass = pci_read_byte(bus, slot, func, 10);
+ kprintf(" PCI(%d,%d,%d) = %#.4x:%#.4x (%#.2x, %#.2x)",
+ bus, slot, func, vendor, device,
+ class, subclass);
}
}
}
diff --git a/drivers/drivers.h b/drivers/drivers.h
index 47cd243..be7e396 100644
--- a/drivers/drivers.h
+++ b/drivers/drivers.h
@@ -25,6 +25,10 @@ void register_driver(Driver *driver);
/* Drivers */
void ide_init(uint8_t bus, uint8_t slot, uint8_t func);
void rtl8139_init(uint8_t bus, uint8_t dev, uint8_t func);
+void xhci_init(uint8_t bus, uint8_t slot, uint8_t func);
void bga_init(uint8_t bus, uint8_t slot, uint8_t func);
+void init_tty(void);
+void init_kbd(void);
+void init_mouse(void);
#endif
diff --git a/drivers/keyboard/keyboard.c b/drivers/keyboard/keyboard.c
new file mode 100644
index 0000000..5ef3c6f
--- /dev/null
+++ b/drivers/keyboard/keyboard.c
@@ -0,0 +1,108 @@
+/*
+ * This file implements a keyboard driver. It generates the /dev/kbd device
+ * file, which can be read and returns a structure of the keyboard data. This
+ * driver produces raw keyboard data, not parsed text.
+ */
+
+#include <sys/kbd.h>
+#include "../drivers.h"
+#include "../../task/task.h"
+#include "../../proc/proc.h"
+#include "../../io.h"
+
+void tty_keypress(unsigned char key);
+size_t kbd_read(File *file, char *buf, size_t size, off_t offset);
+
+FileOps kbdFileOps = {
+ .read = kbd_read,
+};
+
+Driver kbdDriver = {
+ .major = 10,
+ .ops = &kbdFileOps,
+ .next = NULL,
+};
+
+TaskQueue keyWait;
+
+/* Ring buffer for keys */
+struct KeyBuffer {
+ int start, end;
+ char key[1024];
+} keyBuf;
+
+/* Add a key to the key buffer */
+static void
+add_to_buf(char key)
+{
+ /* No more space in buffer */
+ int start = (keyBuf.start + sizeof(keyBuf.key) - 1)
+ % sizeof(keyBuf.key);
+ if (keyBuf.end == start)
+ return;
+
+ keyBuf.key[keyBuf.end] = key;
+ keyBuf.end++;
+ keyBuf.end %= sizeof(keyBuf.key);
+}
+
+/* Get a key from the key buffer */
+static char
+get_from_buf(void)
+{
+ /* Nothing to read */
+ if (keyBuf.start == keyBuf.end)
+ return 0x00;
+
+ char key = keyBuf.key[keyBuf.start];
+ keyBuf.start++;
+ keyBuf.start %= sizeof(keyBuf.key);
+ return key;
+}
+
+/* Handle the keyboard interrupt */
+static void
+keyboard_handler(InterruptFrame *frame)
+{
+ unsigned char key;
+ int i;
+ for (i = 0; i < 1000; i++) {
+ if ((inb(0x64) & 1) == 0)
+ continue;
+ key = inb(0x60);
+ break;
+ }
+ if (i == 1000)
+ return;
+ add_to_buf(key);
+ tty_keypress(key);
+
+ for (Task *tmp = keyWait.start; tmp; tmp = tmp->next)
+ unblock_task(pop_from_queue(&keyWait));
+}
+
+/* Initialise the keyboard */
+void
+init_kbd(void)
+{
+ register_driver(&kbdDriver);
+ mknod("/dev/kbd", S_IFCHR | 0666, MKDEV(kbdDriver.major, 0));
+ register_interrupt(1, keyboard_handler);
+}
+
+size_t
+kbd_read(File *file, char *buf, size_t size, off_t offset)
+{
+ char c;
+ size_t count = 0;
+ while (count < size) {
+ c = get_from_buf();
+ if (!c) {
+ add_to_queue(&keyWait, current);
+ block_task(WAITING_FOR_IO);
+ }
+ *(buf + count) = c;
+ count++;
+ }
+ return count;
+}
diff --git a/drivers/mouse/mouse.c b/drivers/mouse/mouse.c
new file mode 100644
index 0000000..f32264e
--- /dev/null
+++ b/drivers/mouse/mouse.c
@@ -0,0 +1,116 @@
+/*
+ * This file contains the mouse driver. It generates the /dev/mouse device
+ * file, which can be read and returns a structure of the mouse data.
+ */
+
+#include <sys/mouse.h>
+#include "../drivers.h"
+#include "../../proc/proc.h"
+#include "../../io.h"
+
+size_t mouse_read(File *file, char *buf, size_t size, off_t offset);
+
+FileOps mouseFileOps = {
+ .read = mouse_read,
+};
+
+Driver mouseDriver = {
+ .major = 11,
+ .ops = &mouseFileOps,
+ .next = NULL,
+};
+
+unsigned char mouseCycle = 0;
+char mouseByte[3], mouseX = 0, mouseY = 0;
+
+/* Handle the mouse interrupt */
+static void
+mouse_handler(InterruptFrame *frame)
+{
+ mouseByte[mouseCycle++] = inb(0x60);
+ if (mouseCycle < 3)
+ return;
+ mouseCycle = 0;
+ mouseX = mouseByte[1];
+ mouseY = mouseByte[2];
+
+// kprintf("Mouse at [%d,%d]", mouseX, mouseY);
+}
+
+/* Wait on the mouse */
+static inline void
+mouse_io_wait(int type)
+{
+ int time = 100000;
+ if (!type) {
+ while (time--)
+ if ((inb(0x64) & 1) == 1)
+ return;
+ } else {
+ while (time--)
+ if ((inb(0x64) & 2) == 0)
+ return;
+ }
+}
+
+/* Write to the mouse */
+static inline void
+mouse_io_write(char byte)
+{
+ mouse_io_wait(1);
+ outb(0x64, 0xD4);
+ mouse_io_wait(1);
+ outb(0x60, byte);
+}
+
+/* Read from the mouse */
+static inline char
+mouse_io_read(void)
+{
+ mouse_io_wait(0);
+ return inb(0x60);
+}
+
+/* Initialise the mouse */
+void
+init_mouse(void)
+{
+ register_driver(&mouseDriver);
+ mknod("/dev/mouse", S_IFCHR | 0666, MKDEV(mouseDriver.major, 0));
+ register_interrupt(12, mouse_handler);
+
+ char status;
+ mouse_io_wait(1);
+ outb(0x64, 0xA8);
+
+ /* Enable interrupts */
+ mouse_io_wait(1);
+ outb(0x64, 0x20);
+ mouse_io_wait(0);
+ status = inb(0x60) | 2;
+ mouse_io_wait(1);
+ outb(0x64, 0x60);
+ mouse_io_wait(1);
+ outb(0x60, status);
+
+ /* Use default settings */
+ mouse_io_write(0xF6);
+ mouse_io_read();
+
+ /* Enable the mouse */
+ mouse_io_write(0xF4);
+ mouse_io_read();
+}
+
+/* Read the mouse device */
+size_t
+mouse_read(File *file, char *buf, size_t size, off_t offset)
+{
+ size_t count = 0;
+ while (count < size) {
+ *(buf + count++) = mouseByte[0];
+ *(buf + count++) = mouseX;
+ *(buf + count++) = mouseY;
+ }
+ return count;
+}
diff --git a/drivers/tty/tty.c b/drivers/tty/tty.c
index c65aeaf..94b3fb3 100644
--- a/drivers/tty/tty.c
+++ b/drivers/tty/tty.c
@@ -1,5 +1,5 @@
/*
- * This file contains the implementation of the TTY Device. Generates a device
+ * This file contains the implementation of the TTY Device, generates a device
* /dev/tty, which displays to the default text video output. This file handles
* all the formatting required for a TTY.
*/
@@ -230,7 +230,7 @@ print_char(char c)
draw_char(' ', ttyX*8, ttyY*16, 0xFFFFFF, 0x000000);
/* Characters */
- if (!(tty.lflag & ECHO) && c != '\n')
+ if (!(tty.c_lflag & ECHO) && c != '\n')
goto curctl;
switch (c) {
case '\r':
@@ -294,17 +294,9 @@ curctl:
/* Handle the keyboard interrupt */
void
-keyboard_handler(InterruptFrame *frame)
+tty_keypress(unsigned char key)
{
char c;
- unsigned char key;
- int i;
- for (i = 0; i < 1000; i++) {
- if ((inb(0x64) & 1) == 0)
- continue;
- key = inb(0x60);
- break;
- }
if (key == 0x1D)
ctrl = 128;
if (key == 0x9D)
@@ -323,6 +315,11 @@ keyboard_handler(InterruptFrame *frame)
if (!c)
return;
+ if (ctrl && c == 'c') {
+ kprintf("Killing foreground process");
+ return;
+ }
+
if (c == '\b' && lineBufLen == 0)
return;
if (c == '\b')
@@ -347,7 +344,7 @@ init_tty(void)
register_driver(&ttyDriver);
mknod("/dev/tty", S_IFCHR | 0666, MKDEV(ttyDriver.major, 0));
- tty.lflag = ICANON | ECHO;
+ tty.c_lflag = ICANON | ECHO;
int fd = open("/dev/fb", O_RDWR);
if (fd < 0) {
@@ -375,7 +372,6 @@ init_tty(void)
lineBuf = kmalloc(4096);
line = kmalloc(4096);
- register_interrupt(1, keyboard_handler);
}
/* Read from the TTY */
@@ -384,7 +380,7 @@ tty_read(File *file, char *buf, size_t size, off_t offset)
{
if (!lineLen) {
add_to_queue(&ttyWait, current);
- block_task(WAITING_FOR_READ);
+ block_task(WAITING_FOR_IO);
}
size_t count = (size < lineLen) ? size : lineLen;
memcpy(buf, line, count);
diff --git a/drivers/usb/xhci.c b/drivers/usb/xhci.c
new file mode 100644
index 0000000..715c3e6
--- /dev/null
+++ b/drivers/usb/xhci.c
@@ -0,0 +1,74 @@
+/*
+ * This file implements the driver for the Bochs Graphics Adapter video card.
+ * It is a simple card available in virtual machines. It creates a framebuffer
+ * device node, and handles the reading/writing to it, and also mapping the
+ * framebuffer into memory.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/fb.h>
+#include "../drivers.h"
+#include "../pci.h"
+#include "../../mem/paging.h"
+#include "../../vfs/vfs.h"
+#include "../../io.h"
+
+size_t xhci_read(File *file, char *buf, size_t size, off_t offset);
+size_t xhci_write(File *file, char *buf, size_t size, off_t offset);
+int xhci_ioctl(File *file, unsigned long request, uintptr_t argp);
+
+FileOps xhciFileOps = {
+ .read = xhci_read,
+ .write = xhci_write,
+ .ioctl = xhci_ioctl,
+};
+
+Driver xhciDriver = {
+ .major = 9,
+ .ops = &xhciFileOps,
+ .next = NULL,
+};
+
+/* Initialise the USB driver */
+void
+xhci_init(uint8_t bus, uint8_t slot, uint8_t func)
+{
+ register_driver(&xhciDriver);
+
+ uint8_t intf, class, subclass;
+ intf = pci_read_byte(bus, slot, func, 9);
+ subclass = pci_read_byte(bus, slot, func, 10);
+ class = pci_read_byte(bus, slot, func, 11);
+ kprintf(" Initialising USB (%#.2x, %#.2x, %#.2x)",
+ class, subclass, intf);
+
+ /* Map MMIO registers */
+ uint32_t bar0, bar1;
+ bar0 = pci_read_dword(bus, slot, func, 0x10);
+ bar1 = pci_read_dword(bus, slot, func, 0x14);
+ *get_page((void *) bar0) = bar0 | PTE_PRESENT | PTE_WRITE | PTE_GLOBAL;
+
+
+}
+
+/* Read from a USB device */
+size_t
+xhci_read(File *file, char *buf, size_t size, off_t offset)
+{
+ return 0;
+}
+
+/* Write to a USB device */
+size_t
+xhci_write(File *file, char *buf, size_t size, off_t offset)
+{
+ return 0;
+}
+
+/* Control a USB device */
+int
+xhci_ioctl(File *file, unsigned long request, uintptr_t argp)
+{
+ return 0;
+}
diff --git a/drivers/usb/xhci.h b/drivers/usb/xhci.h
new file mode 100644
index 0000000..250abf6
--- /dev/null
+++ b/drivers/usb/xhci.h
@@ -0,0 +1,6 @@
+#ifndef DRIVERS_USB_XHCI_H
+#define DRIVERS_USB_XHCI_H
+
+
+
+#endif
diff --git a/drivers/vga/bga.c b/drivers/vga/bga.c
index aff91aa..4548593 100644
--- a/drivers/vga/bga.c
+++ b/drivers/vga/bga.c
@@ -16,10 +16,12 @@
size_t bga_write(File *file, char *buf, size_t size, off_t offset);
int bga_ioctl(File *file, unsigned long request, uintptr_t argp);
+void bga_mmap(File *file, void *addr, size_t len, off_t offset);
FileOps bgaFileOps = {
.write = bga_write,
.ioctl = bga_ioctl,
+ .mmap = bga_mmap,
};
Driver bgaDriver = {
@@ -129,3 +131,25 @@ bga_ioctl(File *file, unsigned long request, uintptr_t argp)
return 0;
}
}
+
+/* Map the linear frame buffer into memory */
+void
+bga_mmap(File *file, void *addr, size_t len, off_t offset)
+{
+ if (offset >= bgaWidth*bgaHeight*(bgaBpp/8))
+ return;
+ if (len + offset > bgaWidth*bgaHeight*(bgaBpp/8))
+ len = (bgaWidth*bgaHeight*(bgaBpp/8)) - offset;
+
+ page_t *pg, new;
+ size_t max, count = 0;
+ while (len) {
+ max = (len < 0x1000) ? len : 0x1000;
+ pg = get_page(addr + count);
+ new = PG_ATTR(*pg);
+ free_page(pg);
+ alloc_page(pg, PG_ATTR(new), 0xFD000000 + offset + count);
+ count += max;
+ len -= max;
+ }
+}