diff options
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/arch/amd64/cpu/cpu_mp.c | 3 | ||||
-rw-r--r-- | src/sys/arch/amd64/isa/i8042.c | 127 | ||||
-rw-r--r-- | src/sys/arch/amd64/os/os_proc.c | 17 | ||||
-rw-r--r-- | src/sys/conf/GENERIC | 4 | ||||
-rw-r--r-- | src/sys/include/arch/amd64/i8042var.h | 11 | ||||
-rw-r--r-- | src/sys/include/io/cons/cons.h | 2 | ||||
-rw-r--r-- | src/sys/include/sys/fbdev.h | 2 | ||||
-rw-r--r-- | src/sys/include/sys/spawn.h | 46 | ||||
-rw-r--r-- | src/sys/io/cons/cons.c | 78 |
9 files changed, 281 insertions, 9 deletions
diff --git a/src/sys/arch/amd64/cpu/cpu_mp.c b/src/sys/arch/amd64/cpu/cpu_mp.c index d95ba70..ae7b367 100644 --- a/src/sys/arch/amd64/cpu/cpu_mp.c +++ b/src/sys/arch/amd64/cpu/cpu_mp.c @@ -77,6 +77,9 @@ ap_entry(struct limine_smp_info *) corelist[ncores_up - 1] = pcore; atomic_inc_64(&ncores_up); spinlock_release(&lock); + + md_proc_yield(); + __builtin_unreachable(); for (;;); } diff --git a/src/sys/arch/amd64/isa/i8042.c b/src/sys/arch/amd64/isa/i8042.c index 9bbd85d..9417206 100644 --- a/src/sys/arch/amd64/isa/i8042.c +++ b/src/sys/arch/amd64/isa/i8042.c @@ -30,6 +30,7 @@ #include <sys/syslog.h> #include <sys/proc.h> #include <sys/errno.h> +#include <sys/ascii.h> #include <os/module.h> #include <os/clkdev.h> #include <os/iotap.h> @@ -58,6 +59,11 @@ struct keybuf { static struct iotap_ops tap_port0_ops; static struct iotap_desc tap_port0; +/* Key states */ +static bool shift_key = false; +static bool capslock = false; +static bool capslock_released = true; + static struct clkdev *clk; static struct spinlock lock; static struct keybuf buf = {0}; @@ -73,6 +79,26 @@ static char keytab[] = { 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0', ' ' }; +static char keytab_shift[] = { + '\0', '\0', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', 'D', 'F', 'G', 'H', + 'J', 'K', 'L', ':', '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', ' ' +}; + +static char keytab_caps[] = { + '\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-','=', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '[', ']', '\n', '\0', 'A', 'S', 'D', 'F', 'G', 'H', + 'J', 'K', 'L', ';', '\'', '`', '\0', '\\', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', ',', '.', '/', '\0', '\0', '\0', ' ' +}; + +static uint8_t i8042_read(void); +static void i8042_write(bool is_cmd, uint8_t v); +static int i8042_devsend(bool aux, uint8_t data); + /* * Compute the length of a kbp ring */ @@ -215,16 +241,111 @@ i8042_read(void) } /* + * Send data to an i8042 device + * + * @aux: If true, send data to the mouse + * @data: Byte to send to the bus + * + * Returns zero on success + */ +static int +i8042_devsend(bool aux, uint8_t data) +{ + if (aux) { + i8042_write(true, I8042_PORT1_SEND); + } + + i8042_write(false, data); + return i8042_read(); +} + +/* + * Send a keyboard LED mask to the controller + * + * @mask: Keyboard LED mask (I8042_LED_*) + */ +static void +i8042_kbdled(uint8_t mask) +{ + i8042_devsend(false, 0xED); + i8042_devsend(false, mask); +} + +/* + * Convert scancode to character + * + * @sc: Scancode + * @chr: Character output + * + * Returns 0 when a char is given back. + */ +static int +i8042_getc(uint8_t sc, char *chr) +{ + bool release = ISSET(sc, BIT(7)); + uint8_t led_mask; + + switch (sc) { + case 0x76: + *chr = ASCII_ESC; + return 0; + /* Caps lock [press] */ + case 0x3A: + if (!capslock_released) { + return -EAGAIN; + } + capslock_released = false; + capslock = !capslock; + i8042_kbdled(capslock << CAPS_LED_SHIFT); + return -EAGAIN; + /* Caps lock [release] */ + case 0xBA: + capslock_released = true; + return -EAGAIN; + /* Shift */ + case 0x36: + case 0xAA: + case 0x2A: + case 0xB6: + if (!release) { + shift_key = true; + } else { + shift_key = false; + } + return -EAGAIN; + } + + if (release) { + return -EAGAIN; + } + + if (capslock) { + *chr = keytab_caps[sc]; + return 0; + } + + if (shift_key) { + *chr = keytab_shift[sc]; + return 0; + } + + *chr = keytab[sc]; + return 0; +} + +/* * IRQ 1 handler */ static int i8042_irq(struct intr_hand *hp) { + char c; uint8_t scancode; + int error; scancode = i8042_read(); - if (!ISSET(scancode, 0x80)) { - keybuf_enter(&buf, scancode); + if (i8042_getc(scancode, &c) == 0) { + keybuf_enter(&buf, c); } return 1; } @@ -292,7 +413,7 @@ static struct iotap_ops tap_port0_ops = { }; static struct iotap_desc tap_port0 = { - .name = "i8042.port.0", + .name = "input.igkbd", .ops = &tap_port0_ops }; diff --git a/src/sys/arch/amd64/os/os_proc.c b/src/sys/arch/amd64/os/os_proc.c index d944f41..b8e7c99 100644 --- a/src/sys/arch/amd64/os/os_proc.c +++ b/src/sys/arch/amd64/os/os_proc.c @@ -137,11 +137,24 @@ md_proc_init(struct proc *procp, int flags) __dead void md_proc_yield(void) { - /* Clear pending interrupts and oneshot */ + struct proc *proc; + struct pcore *core = this_core(); + int error; + lapic_eoi(); - lapic_timer_oneshot_us(9000); + /* + * Set the oneshot timer and check if there is + * any procs in our runqueues. If not, wait for + * it to fire again. + */ for (;;) { + lapic_timer_oneshot_us(9000); + error = sched_deq(&core->scq, &proc); + if (error == 0) { + core->curproc = proc; + md_proc_kick(proc); + } __ASMV("sti; hlt"); } } diff --git a/src/sys/conf/GENERIC b/src/sys/conf/GENERIC index a667a78..a7321d8 100644 --- a/src/sys/conf/GENERIC +++ b/src/sys/conf/GENERIC @@ -2,3 +2,7 @@ option DUMP_MEMMAP yes // Dump memory map on boot // PCI switches and knobs setval PCI_MAX_BUS 8 // Max buses to scan on boot + +// Default console attributes +setval CONS_BG 0x000000 // Background color +setval CONS_FG 0xB57614 // Foreground color diff --git a/src/sys/include/arch/amd64/i8042var.h b/src/sys/include/arch/amd64/i8042var.h index ec2c36e..53f5029 100644 --- a/src/sys/include/arch/amd64/i8042var.h +++ b/src/sys/include/arch/amd64/i8042var.h @@ -67,10 +67,15 @@ #define I8042_AUX_DISABLE 0xF5 #define I8042_AUX_RESET 0xFF +/* LED shifts */ +#define SCROLL_LED_SHIFT 0 +#define NUM_LED_SHIFT 1 +#define CAPS_LED_SHIFT 2 + /* LED bits */ -#define I8042_LED_SCROLL BIT(0) -#define I8042_LED_NUM BIT(1) -#define I8042_LED_CAPS BIT(2) +#define I8042_LED_SCROLL (1 << SCROLL_LED_SHIFT) +#define I8042_LED_NUM (1 << NUM_LED_SHIFT) +#define I8042_LED_CAPS (1 << CAPS_LED_SHIFT) /* Extended scancode types */ #define I8042_XSC_ENDPR 0 /* End pressed */ diff --git a/src/sys/include/io/cons/cons.h b/src/sys/include/io/cons/cons.h index 4ae99a0..6b5c4f1 100644 --- a/src/sys/include/io/cons/cons.h +++ b/src/sys/include/io/cons/cons.h @@ -39,6 +39,8 @@ struct cons_scr { struct bootvar_fb fbvars; size_t text_x; size_t text_y; + size_t cursor_x; + size_t cursor_y; size_t max_col; size_t max_row; uint32_t scr_bg; diff --git a/src/sys/include/sys/fbdev.h b/src/sys/include/sys/fbdev.h index 2acddbf..e6f5d8f 100644 --- a/src/sys/include/sys/fbdev.h +++ b/src/sys/include/sys/fbdev.h @@ -35,7 +35,7 @@ #include <stdint.h> #endif /* !_KERNEL */ -#define FBDEV_NSO "video:attr" +#define FBDEV_NSO "output.fbdev.attr" struct fb_info { uint32_t width; diff --git a/src/sys/include/sys/spawn.h b/src/sys/include/sys/spawn.h new file mode 100644 index 0000000..d15439d --- /dev/null +++ b/src/sys/include/sys/spawn.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Ian Marco Moffett and L5 engineers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SPAWN_H_ +#define _SYS_SPAWN_H_ 1 + +#include <sys/types.h> + +/* + * Spawn a process + * + * @path: Path of program image to spawn + * @argv: Argument list + * + * Returns the PID on success, otherwise a less than + * zero value on failure. + */ +int spawn(const char *path, char **argv); + +#endif /* !_SYS_SPAWN_H_ */ diff --git a/src/sys/io/cons/cons.c b/src/sys/io/cons/cons.c index d9ebb5c..0543e89 100644 --- a/src/sys/io/cons/cons.c +++ b/src/sys/io/cons/cons.c @@ -37,11 +37,26 @@ #include <stdbool.h> #include <string.h> +/* kconf background color config */ +#if defined(__CONS_BG) +#define DEFAULT_BG __CONS_BG +#else #define DEFAULT_BG 0x000000 +#endif /* __CONS_BG */ + +/* kconf foreground color config */ +#if defined(__CONS_FG) +#define DEFAULT_FG __CONS_FG +#else #define DEFAULT_FG 0xB57614 +#endif /* !__CONS_FG */ + #define FONT_WIDTH 8 #define FONT_HEIGHT 20 +#define CURSOR_WIDTH FONT_WIDTH +#define CURSOR_HEIGHT 4 + struct cons_scr g_root_scr; /* Forward declarations */ @@ -64,6 +79,53 @@ fb_get_index(uint32_t pitch, uint32_t x, uint32_t y) } /* + * Invert an RGB color + * + * @rgb: Color to invert + * + * Returns inverted color code (RGB) + */ +__always_inline static inline uint32_t +rgb_invert(uint32_t rgb) +{ + return (0xFFFFFF - rgb); +} + +/* + * Draw the text cursor onto the screen + * + * @scr: Screen to draw onto + * @hide: True if it should be hidden + */ +static void +cons_draw_cursor(struct cons_scr *scr, bool hide) +{ + struct bootvar_fb *fbvars; + uint32_t *fbio, idx; + uint32_t color; + + if (scr == NULL) { + return; + } + + fbvars = &scr->fbvars; + fbio = fbvars->io; + + for (uint32_t cy = 0; cy < CURSOR_HEIGHT; ++cy) { + for (uint32_t cx = 0; cx < CURSOR_WIDTH; ++cx) { + idx = fb_get_index( + fbvars->pitch, + cx + scr->cursor_x, + (cy + scr->cursor_y) + FONT_HEIGHT / 2 + ); + + color = (hide) ? scr->scr_bg : rgb_invert(scr->scr_bg); + fbio[idx] = color; + } + } +} + +/* * Write a newline onto the console and handle * Y overflows * @@ -75,12 +137,22 @@ cons_newline(struct cons_scr *scr) scr->text_x = 0; scr->text_y += FONT_HEIGHT; + cons_draw_cursor(scr, true); + scr->cursor_y += FONT_HEIGHT; + scr->cursor_x = 0; + /* Handle console y overflow */ if (scr->text_y >= scr->max_row - FONT_HEIGHT) { scr->text_x = 0; scr->text_y = 0; + + scr->cursor_x = 0; + scr->cursor_y = 0; fill_screen(scr, scr->scr_bg); } + + /* Redraw the cursor */ + cons_draw_cursor(scr, false); } /* @@ -152,6 +224,10 @@ cons_putch(struct cons_scr *scr, struct cons_ch *ch) x = ch->x; y = ch->y; + /* Update the cursor */ + cons_draw_cursor(scr, true); + scr->cursor_x += FONT_WIDTH; + /* Begin the plotting */ for (int cy = 0; cy < hdr->csize; ++cy) { for (int cx = 0; cx < 8; ++cx) { @@ -162,6 +238,8 @@ cons_putch(struct cons_scr *scr, struct cons_ch *ch) fbio[idx] = color; } } + + cons_draw_cursor(scr, false); } /* |