Orion
Barry Keyboard/Mouse drivers + POSIX names for structs 1628fcf (2 years, 4 months 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; + } +} diff --git a/main.c b/main.c index d4e1421..d25b7e8 100644 --- a/main.c +++ b/main.c @@ -9,6 +9,7 @@ #include <stdint.h> #include <fcntl.h> #include <unistd.h> +#include <sys/mount.h> #include "mem/frame.h" #include "mem/paging.h" #include "mem/heap.h" @@ -23,10 +24,6 @@ #include "spinlock.h" #include "multiboot.h" -#include <sys/mount.h> - -void init_tty(void); - extern char _bss[], _end[]; uintptr_t initialStack; @@ -101,6 +98,8 @@ kmain(uint32_t esp, struct MultibootInfo *mbinfo) /* Search for devices */ init_drivers(); init_tty(); + init_kbd(); +// init_mouse(); /* Initialise Networking */ // init_net(); diff --git a/vfs/devfs/file.c b/vfs/devfs/file.c index d2da4e4..95d8aeb 100644 --- a/vfs/devfs/file.c +++ b/vfs/devfs/file.c @@ -53,32 +53,32 @@ devfs_readdir(File *file, DirEnt *dent, off_t index) DirEntry *de; if (!index--) { - dent->ino = file->inode->ino; - dent->type = DT_DIR; - dent->namelen = 2; - strncpy(dent->name, ".", dent->namelen); + dent->d_ino = file->inode->ino; + dent->d_type = DT_DIR; + dent->d_namelen = 2; + strncpy(dent->d_name, ".", dent->d_namelen); return 0; } for (de = file->inode->dirEntries; de && index; de = de->next, index--); if (!de) return -ENOENT; - dent->ino = de->inode->ino; + dent->d_ino = de->inode->ino; if (S_ISBLK(de->inode->mode)) - dent->type = DT_BLK; + dent->d_type = DT_BLK; if (S_ISCHR(de->inode->mode)) - dent->type = DT_CHR; + dent->d_type = DT_CHR; if (S_ISDIR(de->inode->mode)) - dent->type = DT_DIR; + dent->d_type = DT_DIR; if (S_ISFIFO(de->inode->mode)) - dent->type = DT_FIFO; + dent->d_type = DT_FIFO; if (S_ISLNK(de->inode->mode)) - dent->type = DT_LNK; + dent->d_type = DT_LNK; if (S_ISREG(de->inode->mode)) - dent->type = DT_REG; + dent->d_type = DT_REG; if (S_ISSOCK(de->inode->mode)) - dent->type = DT_SOCK; - dent->namelen = strnlen(de->name, NAME_MAX) + 1; - strncpy(dent->name, de->name, NAME_MAX); + dent->d_type = DT_SOCK; + dent->d_namelen = strnlen(de->name, NAME_MAX) + 1; + strncpy(dent->d_name, de->name, NAME_MAX); return 0; } diff --git a/vfs/ext2fs/file.c b/vfs/ext2fs/file.c index d0caa35..9701e37 100644 --- a/vfs/ext2fs/file.c +++ b/vfs/ext2fs/file.c @@ -71,10 +71,10 @@ ext2fs_readdir(File *file, DirEnt *dent, off_t index) } if (!de->ino) return -ENOENT; - dent->ino = de->ino; - dent->type = de->type; - dent->namelen = de->nameLen + 1; - strncpy(dent->name, de->name, de->size); + dent->d_ino = de->ino; + dent->d_type = de->type; + dent->d_namelen = de->nameLen + 1; + strncpy(dent->d_name, de->name, de->size); return 0; } diff --git a/vfs/procfs/file.c b/vfs/procfs/file.c index b292cf4..979c2c9 100644 --- a/vfs/procfs/file.c +++ b/vfs/procfs/file.c @@ -88,33 +88,33 @@ procfs_readdir(File *file, DirEnt *dent, off_t index) DirEntry *de; if (!index--) { - dent->ino = file->inode->ino; - dent->type = DT_DIR; - dent->namelen = 2; - strncpy(dent->name, ".", dent->namelen); + dent->d_ino = file->inode->ino; + dent->d_type = DT_DIR; + dent->d_namelen = 2; + strncpy(dent->d_name, ".", dent->d_namelen); return 0; } for (de = file->inode->dirEntries; de && index; de = de->next, index--); if (!de) return -ENOENT; - dent->ino = de->inode->ino; + dent->d_ino = de->inode->ino; if (S_ISBLK(de->inode->mode)) - dent->type = DT_BLK; + dent->d_type = DT_BLK; if (S_ISCHR(de->inode->mode)) - dent->type = DT_CHR; + dent->d_type = DT_CHR; if (S_ISDIR(de->inode->mode)) - dent->type = DT_DIR; + dent->d_type = DT_DIR; if (S_ISFIFO(de->inode->mode)) - dent->type = DT_FIFO; + dent->d_type = DT_FIFO; if (S_ISLNK(de->inode->mode)) - dent->type = DT_LNK; + dent->d_type = DT_LNK; if (S_ISREG(de->inode->mode)) - dent->type = DT_REG; + dent->d_type = DT_REG; if (S_ISSOCK(de->inode->mode)) - dent->type = DT_SOCK; - dent->namelen = strnlen(de->name, NAME_MAX) + 1; - strncpy(dent->name, de->name, NAME_MAX); + dent->d_type = DT_SOCK; + dent->d_namelen = strnlen(de->name, NAME_MAX) + 1; + strncpy(dent->d_name, de->name, NAME_MAX); return 0; } diff --git a/vfs/tmpfs/file.c b/vfs/tmpfs/file.c index bc320ed..275e77c 100644 --- a/vfs/tmpfs/file.c +++ b/vfs/tmpfs/file.c @@ -90,33 +90,33 @@ tmpfs_readdir(File *file, DirEnt *dent, off_t index) DirEntry *de; if (!index--) { - dent->ino = file->inode->ino; - dent->type = DT_DIR; - dent->namelen = 2; - strncpy(dent->name, ".", dent->namelen); + dent->d_ino = file->inode->ino; + dent->d_type = DT_DIR; + dent->d_namelen = 2; + strncpy(dent->d_name, ".", dent->d_namelen); return 0; } for (de = file->inode->dirEntries; de && index; de = de->next, index--); if (!de) return -ENOENT; - dent->ino = de->inode->ino; + dent->d_ino = de->inode->ino; if (S_ISBLK(de->inode->mode)) - dent->type = DT_BLK; + dent->d_type = DT_BLK; if (S_ISCHR(de->inode->mode)) - dent->type = DT_CHR; + dent->d_type = DT_CHR; if (S_ISDIR(de->inode->mode)) - dent->type = DT_DIR; + dent->d_type = DT_DIR; if (S_ISFIFO(de->inode->mode)) - dent->type = DT_FIFO; + dent->d_type = DT_FIFO; if (S_ISLNK(de->inode->mode)) - dent->type = DT_LNK; + dent->d_type = DT_LNK; if (S_ISREG(de->inode->mode)) - dent->type = DT_REG; + dent->d_type = DT_REG; if (S_ISSOCK(de->inode->mode)) - dent->type = DT_SOCK; - dent->namelen = strnlen(de->name, NAME_MAX) + 1; - strncpy(dent->name, de->name, NAME_MAX); + dent->d_type = DT_SOCK; + dent->d_namelen = strnlen(de->name, NAME_MAX) + 1; + strncpy(dent->d_name, de->name, NAME_MAX); return 0; } diff --git a/vfs/vfs.c b/vfs/vfs.c index c4784f2..396fd8f 100644 --- a/vfs/vfs.c +++ b/vfs/vfs.c @@ -475,7 +475,7 @@ getdents(int fd, void *buf, size_t count) err = file_readdir(file, dent, i); if (err < 0) goto out; - size += sizeof(DirEnt) + dent->namelen; + size += sizeof(DirEnt) + dent->d_namelen; *((char *) buf + size - 1) = '\0'; dent = (void *) ((char *) buf + size); }