From c1711d4318b8069972fe83517a4af957ce91dd96 Mon Sep 17 00:00:00 2001 From: Sam Tebbs Date: Thu, 23 May 2019 18:30:42 +0100 Subject: [PATCH] Revert "Add TTY and VGA interface (#20)" This reverts commit 7bcccd648edfa775e1da912bcd546b119d5a7901. --- build.zig | 1 - src/kernel/arch.zig | 30 - src/kernel/arch/x86/arch.zig | 69 +- src/kernel/kmain.zig | 94 +- src/kernel/tty.zig | 2475 ---------------------------------- src/kernel/vga.zig | 413 ------ test/kernel/arch_mock.zig | 32 - 7 files changed, 98 insertions(+), 3016 deletions(-) delete mode 100644 src/kernel/tty.zig delete mode 100644 src/kernel/vga.zig delete mode 100644 test/kernel/arch_mock.zig diff --git a/build.zig b/build.zig index 1c5934b..a4f867d 100644 --- a/build.zig +++ b/build.zig @@ -53,7 +53,6 @@ fn buildTest(b: *Builder, src_path: []const u8) void { var file_src = concat(b.allocator, src_path2.toSlice(), file) catch unreachable; file_src.append(".zig") catch unreachable; const tst = b.addTest(file_src.toSlice()); - tst.setMainPkgPath("."); step.dependOn(&tst.step); } } diff --git a/src/kernel/arch.zig b/src/kernel/arch.zig index 2949827..6f9f2cd 100644 --- a/src/kernel/arch.zig +++ b/src/kernel/arch.zig @@ -1,32 +1,2 @@ -// Zig version: 0.4.0 - -/// /// Initialise the architecture -/// pub extern fn init() void; - -/// -/// Inline assembly to write to a given port with a byte of data. -/// -/// Arguments: -/// IN port: u16 - The port to write to. -/// IN data: u8 - The byte of data that will be sent. -/// -pub extern fn outb(port: u16, data: u8) void; - -/// -/// Inline assembly that reads data from a given port and returns its value. -/// -/// Arguments: -/// IN port: u16 - The port to read data from. -/// -/// Return: -/// The data that the port returns. -/// -pub extern fn inb(port: u16) u8; - -/// -/// A simple way of waiting for I/O event to happen by doing an I/O event to flush the I/O -/// event being waited. -/// -pub extern fn ioWait() void; diff --git a/src/kernel/arch/x86/arch.zig b/src/kernel/arch/x86/arch.zig index bf9981b..5aaee35 100644 --- a/src/kernel/arch/x86/arch.zig +++ b/src/kernel/arch/x86/arch.zig @@ -1,17 +1,3 @@ -// Zig version: 0.4.0 - -const is_test = @import("builtin").is_test; - -const ALIGN = 1 << 0; -const MEMINFO = 1 << 1; -const MAGIC = 0x1BADB002; -const FLAGS = ALIGN | MEMINFO; - -const KERNEL_ADDR_OFFSET = 0xC0000000; -const KERNEL_PAGE_NUMBER = KERNEL_ADDR_OFFSET >> 22; -// The number of pages occupied by the kernel, will need to be increased as we add a heap etc. -const KERNEL_NUM_PAGES = 1; - extern fn kmain() void; const MultiBoot = packed struct { @@ -20,12 +6,22 @@ const MultiBoot = packed struct { checksum: i32, }; -export var multiboot align(4) linksection(".rodata.boot") = MultiBoot { +const ALIGN = 1 << 0; +const MEMINFO = 1 << 1; +const MAGIC = 0x1BADB002; +const FLAGS = ALIGN | MEMINFO; + +export var multiboot align(4) linksection(".rodata.boot") = MultiBoot{ .magic = MAGIC, .flags = FLAGS, .checksum = -(MAGIC + FLAGS), }; +const KERNEL_ADDR_OFFSET = 0xC0000000; +const KERNEL_PAGE_NUMBER = KERNEL_ADDR_OFFSET >> 22; +// The number of pages occupied by the kernel, will need to be increased as we add a heap etc. +const KERNEL_NUM_PAGES = 1; + // The initial page directory used for booting into the higher half. Should be overwritten later export var boot_page_directory: [1024]u32 align(4096) linksection(".rodata.boot") = init: { // Increase max number of branches done by comptime evaluator @@ -39,7 +35,7 @@ export var boot_page_directory: [1024]u32 align(4096) linksection(".rodata.boot" var i = 0; var idx = 1; - // Fill preceding pages with zeroes. May be unnecessary but incurs no runtime cost + // Fill preceding pages with zeroes. May be unecessary but incurs no runtime cost while (i < KERNEL_PAGE_NUMBER - 1) : ({ i += 1; idx += 1; @@ -55,7 +51,7 @@ export var boot_page_directory: [1024]u32 align(4096) linksection(".rodata.boot" }) { dir[idx] = 0x00000083 | (i << 22); } - // Fill succeeding pages with zeroes. May be unnecessary but incurs no runtime cost + // Fill suceeding pages with zeroes. May be unecessary but incurs no runtime cost i = 0; while (i < 1024 - KERNEL_PAGE_NUMBER - KERNEL_NUM_PAGES) : ({ i += 1; @@ -111,43 +107,4 @@ export nakedcc fn start_higher_half() noreturn { while (true) {} } -/// -/// Initialise the architecture -/// export fn init() void {} - -/// -/// Inline assembly to write to a given port with a byte of data. -/// -/// Arguments: -/// IN port: u16 - The port to write to. -/// IN data: u8 - The byte of data that will be sent. -/// -export fn outb(port: u16, data: u8) void { - asm volatile ("outb %[data], %[port]" - : - : [port] "{dx}" (port), [data] "{al}" (data)); -} - -/// -/// Inline assembly that reads data from a given port and returns its value. -/// -/// Arguments: -/// IN port: u16 - The port to read data from. -/// -/// Return: -/// The data that the port returns. -/// -export fn inb(port: u16) u8 { - return asm volatile ("inb %[port], %[result]" - : [result] "={al}" (-> u8) - : [port] "N{dx}" (port)); -} - -/// -/// A simple way of waiting for I/O event to happen by doing an I/O event to flush the I/O -/// event being waited. -/// -export fn ioWait() void { - outb(0x80, 0); -} diff --git a/src/kernel/kmain.zig b/src/kernel/kmain.zig index a75270e..4659112 100644 --- a/src/kernel/kmain.zig +++ b/src/kernel/kmain.zig @@ -1,14 +1,17 @@ -// Zig version: 0.4.0 - +// +// kmain +// Zig version: +// Author: DrDeano +// Date: 2019-03-30 +// const builtin = @import("builtin"); -const arch = if (builtin.is_test) @import("../../test/kernel/arch_mock.zig") else @import("arch.zig"); +const arch = @import("arch.zig"); const multiboot = @import("multiboot.zig"); -const tty = @import("tty.zig"); -const vga = @import("vga.zig"); pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { @setCold(true); - tty.print("\nKERNEL PANIC: {}\n", msg); + terminal.write("KERNEL PANIC: "); + terminal.write(msg); while (true) {} } @@ -16,8 +19,81 @@ pub export fn kmain(mb_info: *multiboot.multiboot_info_t, mb_magic: u32) void { if (mb_magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC) { // Booted with compatible bootloader arch.init(); - vga.init(); - tty.init(); - tty.print("\nHello Pluto from kernel :)\n"); + terminal.initialize(); + terminal.write("Hello, kernel World!"); } } + +// Hardware text mode color constants +const VGA_COLOUR = enum(u8) { + VGA_COLOUR_BLACK, + VGA_COLOUR_BLUE, + VGA_COLOUR_GREEN, + VGA_COLOUR_CYAN, + VGA_COLOUR_RED, + VGA_COLOUR_MAGENTA, + VGA_COLOUR_BROWN, + VGA_COLOUR_LIGHT_GREY, + VGA_COLOUR_DARK_GREY, + VGA_COLOUR_LIGHT_BLUE, + VGA_COLOUR_LIGHT_GREEN, + VGA_COLOUR_LIGHT_CYAN, + VGA_COLOUR_LIGHT_RED, + VGA_COLOUR_LIGHT_MAGENTA, + VGA_COLOUR_LIGHT_BROWN, + VGA_COLOUR_WHITE, +}; + +fn vga_entry_colour(fg: VGA_COLOUR, bg: VGA_COLOUR) u8 { + return @enumToInt(fg) | (@enumToInt(bg) << 4); +} + +fn vga_entry(uc: u8, colour: u8) u16 { + return u16(uc) | (u16(colour) << 8); +} + +const VGA_WIDTH = 80; +const VGA_HEIGHT = 25; + +const terminal = struct { + var row = usize(0); + var column = usize(0); + var colour = vga_entry_colour(VGA_COLOUR.VGA_COLOUR_LIGHT_GREY, VGA_COLOUR.VGA_COLOUR_BLACK); + + const buffer = @intToPtr([*]volatile u16, 0xC00B8000); + + fn initialize() void { + var y = usize(0); + while (y < VGA_HEIGHT) : (y += 1) { + var x = usize(0); + while (x < VGA_WIDTH) : (x += 1) { + putCharAt(' ', colour, x, y); + } + } + } + + fn setColour(new_colour: u8) void { + colour = new_colour; + } + + fn putCharAt(c: u8, new_colour: u8, x: usize, y: usize) void { + const index = y * VGA_WIDTH + x; + buffer[index] = vga_entry(c, new_colour); + } + + fn putChar(c: u8) void { + putCharAt(c, colour, column, row); + column += 1; + if (column == VGA_WIDTH) { + column = 0; + row += 1; + if (row == VGA_HEIGHT) + row = 0; + } + } + + fn write(data: []const u8) void { + for (data) |c| + putChar(c); + } +}; diff --git a/src/kernel/tty.zig b/src/kernel/tty.zig deleted file mode 100644 index 9e879ed..0000000 --- a/src/kernel/tty.zig +++ /dev/null @@ -1,2475 +0,0 @@ -// Zig version: 0.4.0 - -const vga = @import("vga.zig"); - -const expectEqual = @import("std").testing.expectEqual; -const expectError = @import("std").testing.expectError; -const expect = @import("std").testing.expect; -const warn = @import("std").debug.warn; -const fmt = @import("std").fmt; - -/// The number of rows down from the top (row 0) where the displayable region starts. Above is -/// where the logo and time is printed -const ROW_MIN: u16 = 7; - -/// The total number of rows in the displayable region -const ROW_TOTAL: u16 = vga.HEIGHT - ROW_MIN; - -/// The total number of pages (static) that the terminal will remember. In the future, this can -/// move to a more dynamic allocation when a kheap is implemented. -const TOTAL_NUM_PAGES: u16 = 5; - -/// The total number of VGA (or characters) elements are on a page -const TOTAL_CHAR_ON_PAGE: u16 = vga.WIDTH * ROW_TOTAL; - -/// The start of the displayable region in the video buffer memory -const START_OF_DISPLAYABLE_REGION: u16 = vga.WIDTH * ROW_MIN; - -/// The total number of VGA elements (or characters) the video buffer can display -const VIDEO_BUFFER_SIZE: u16 = vga.WIDTH * vga.HEIGHT; - -const PrintError = error { - OutOfBounds, -}; - -/// The current x position of the cursor. -var column: u8 = 0; - -/// The current y position of the cursor. -var row: u8 = 0; - -/// The current colour of the display with foreground and background colour. -var colour: u8 = undefined; - -/// The buffer starting from the beginning of the video memory location that contains all data -/// written to the display. -var video_buffer: []volatile u16 = undefined; - -/// The blank VGA entry to be used to clear the screen. -var blank: u16 = undefined; - -/// A total of TOTAL_NUM_PAGES pages that can be saved and restored to from and to the video buffer -var pages: [TOTAL_NUM_PAGES][TOTAL_CHAR_ON_PAGE]u16 = init: { - //@setEvalBranchQuota(TOTAL_NUM_PAGES * TOTAL_CHAR_ON_PAGE + TOTAL_CHAR_ON_PAGE); - var p: [TOTAL_NUM_PAGES][TOTAL_CHAR_ON_PAGE]u16 = undefined; - - for (p) |*page| { - page.* = []u16{0} ** TOTAL_CHAR_ON_PAGE; - } - - break :init p; -}; - -/// The current page index. -var page_index: u8 = 0; - -/// -/// Copies data into the video buffer. This is used for copying a page into the video buffer. -/// -/// Global changes: -/// video_buffer -/// -/// Arguments: -/// IN video_buf_offset: u16 - The offset into the video buffer to start copying to. -/// IN data: []const u16 - The data to copy into the video buffer. -/// IN size: u16 - The amount to copy. -/// -/// Errors: -/// PrintError.OutOfBounds - If offset or the size to copy is greater than the size of the -/// video buffer or data to copy. -/// -fn videoCopy(video_buf_offset: u16, data: []const u16, size: u16) PrintError!void { - // Secure programming ;) - if (video_buf_offset >= video_buffer.len and - size > video_buffer.len - video_buf_offset and - size > data.len) { - return PrintError.OutOfBounds; - } - - var i: usize = 0; - while (i < size) : (i += 1) { - video_buffer[video_buf_offset + i] = data[i]; - } -} - -/// -/// Moves data with a page without overriding itself. -/// -/// Arguments: -/// IN dest: []u16 - The destination position to copy into. -/// IN src: []u16 - The source position to copy from. -/// IN size: u16 - The amount to copy. -/// -/// Errors: -/// PrintError.OutOfBounds - If the size to copy is greater than the size of -/// pages. -/// -fn pageMove(dest: []u16, src: []u16, size: usize) PrintError!void { - if (dest.len < size or src.len < size) { - return PrintError.OutOfBounds; - } - - // Not an error is size is zero, nothing will be copied - if (size == 0) return; - - // Make sure we don't override the values we want to copy - if (@ptrToInt(&dest[0]) < @ptrToInt(&src[0])) { - var i: usize = 0; - while (i != size) : (i += 1) { - dest[i] = src[i]; - } - } else { - var i: usize = size; - while (i != 0) { - i -= 1; - dest[i] = src[i]; - } - } -} - -/// -/// Clears a region of the video buffer to a VGA entry from the beginning. -/// -/// Global changes: -/// video_buffer -/// -/// Arguments: -/// IN c: u16 - VGA entry to set the video buffer to. -/// IN size: u16 - The number to VGA entries to set from the beginning of the video buffer. -/// -fn setVideoBuffer(c: u16, size: u16) void { - for (video_buffer[0..size]) |*b| { - b.* = c; - } -} - -/// -/// Updated the hardware cursor to the current column and row (x, y). -/// -fn updateCursor() void { - vga.updateCursor(column, row); -} - -/// -/// Get the hardware cursor to set the current column and row (x, y). -/// -/// Global changes: -/// column -/// row -/// -fn getCursor() void { - var cursor: u16 = vga.getCursor(); - - row = @truncate(u8, cursor / vga.WIDTH); - column = @truncate(u8, cursor % vga.WIDTH); -} - -/// -/// Display the current page number at the bottom right corner. -/// -/// Global changes: -/// video_buffer -/// pages -/// -fn displayPageNumber() void { - const column_temp: u8 = column; - const row_temp: u8 = row; - - // A bit hard coded as the kprintf below is 11 characters long. - // Once got a ksnprintf, then can use that value to set how far from the end to print. - column = vga.WIDTH - 11; - row = ROW_MIN - 1; - - print("Page {} of {}", page_index, TOTAL_NUM_PAGES - 1); - - column = column_temp; - row = row_temp; -} - -/// -/// Put a character at a specific column and row position on the screen. This will use the current -/// colour. -/// -/// Global changes: -/// video_buffer -/// pages -/// page_index -/// -/// Arguments: -/// IN char: u8 - The character to print. This will be combined with the current colour. -/// IN x: u8 - The x position (column) to put the character at. -/// IN y: u8 - The y position (row) to put the character at. -/// -/// Errors: -/// PrintError.OutOfBounds - If trying to print outside the video buffer -/// -fn putEntryAt(char: u8, x: u8, y: u8) PrintError!void { - const index: u16 = y * vga.WIDTH + x; - - // Bounds check - if (index >= VIDEO_BUFFER_SIZE) { - return PrintError.OutOfBounds; - } - - const char_entry: u16 = vga.entry(char, colour); - - if (index >= START_OF_DISPLAYABLE_REGION) { - // If not at page zero, (bottom of page), then display that page - // The user has move up a number of pages and then typed a letter, so need to move to the - // 0'th page - if (page_index != 0) { - // This isn't out of bounds - page_index = 0; - videoCopy(START_OF_DISPLAYABLE_REGION, pages[page_index][0..TOTAL_CHAR_ON_PAGE], TOTAL_CHAR_ON_PAGE) catch unreachable; - displayPageNumber(); - - // If not on page 0, then the cursor would have been disabled - vga.enableCursor(); - updateCursor(); - } - pages[page_index][index - START_OF_DISPLAYABLE_REGION] = char_entry; - } - video_buffer[index] = char_entry; -} - -/// Move rows up pages across multiple pages leaving the last rows blank. -/// -/// Global changes: -/// pages -/// -/// Arguments: -/// IN rows: u16 - The number of rows to move up. -/// -/// Errors: -/// PrintError.OutOfBounds - If trying to move up more rows on a page -/// -fn pagesMoveRowsUp(rows: u16) PrintError!void { - // Out of bounds check, also no need to move 0 rows - if (rows > ROW_TOTAL) { - return PrintError.OutOfBounds; - } - - // Not an error to move 0 rows, but is pointless - if (rows == 0) return; - - // Move up rows in last page up by "rows" - const row_length: u16 = rows * vga.WIDTH; - const chars_to_move: u16 = (ROW_TOTAL - rows) * vga.WIDTH; - pageMove(pages[TOTAL_NUM_PAGES - 1][0..chars_to_move], pages[TOTAL_NUM_PAGES - 1][row_length..], chars_to_move) catch unreachable; - - // Loop for the other pages - var i = TOTAL_NUM_PAGES - 1; - while (i > 0) : (i -= 1) { - pageMove(pages[i][chars_to_move..], pages[i - 1][0..row_length], row_length) catch unreachable; - pageMove(pages[i - 1][0..chars_to_move], pages[i - 1][row_length..], chars_to_move) catch unreachable; - } - - // Clear the last lines - for (pages[0][chars_to_move..]) |*p| { - p.* = blank; - } -} - -/// -/// When the text/terminal gets to the bottom of the screen, then move all line up by the amount -/// that are below the bottom of the screen. Usually moves up by one line. -/// -/// Global changes: -/// pages -/// video_buffer -/// row -/// -fn scroll() void { - // Added the condition in the if from pagesMoveRowsUp as don't need to move all rows - if (row >= vga.HEIGHT and (row - vga.HEIGHT + 1) <= ROW_TOTAL) { - var rows_to_move: u16 = row - vga.HEIGHT + 1; - - // Move rows up pages by temp, will usually be one. - // Can't return an error - pagesMoveRowsUp(rows_to_move) catch unreachable; - - // Move all rows up by rows_to_move - var i: u16 = 0; - while (i < (ROW_TOTAL - rows_to_move) * vga.WIDTH) : (i += 1) { - video_buffer[START_OF_DISPLAYABLE_REGION + i] = video_buffer[(rows_to_move * vga.WIDTH) + START_OF_DISPLAYABLE_REGION + i]; - } - - // Set the last rows to blanks - i = 0; - while (i < vga.WIDTH * rows_to_move) : (i += 1) { - video_buffer[(vga.HEIGHT - rows_to_move) * vga.WIDTH + i] = blank; - } - - row = vga.HEIGHT - 1; - } -} - -/// -/// Print a character without updating the cursor. For speed when printing a string as only need to -/// update the cursor once. This will also print the special characters: \n, \r, \t and \b. (\b is -/// not a valid character so use \x08 which is the hex value). -/// -/// Global changes: -/// pages -/// video_buffer -/// row -/// column -/// -/// Arguments: -/// IN char: u8 - The character to print. -/// -/// Errors: -/// PrintError.OutOfBounds - If trying to scroll more rows on a page/displayable region or -/// print beyond the video buffer. -/// -fn putChar(char: u8) PrintError!void { - const column_temp: u8 = column; - const row_temp: u8 = row; - - // If there was an error, then set the row and column back to where is was - // Like nothing happened - errdefer column = column_temp; - errdefer row = row_temp; - - switch (char) { - '\n' => { - column = 0; - row += 1; - scroll(); - }, - '\t' => { - column += 4; - if (column >= vga.WIDTH) { - column -= @truncate(u8, vga.WIDTH); - row += 1; - scroll(); - } - }, - '\r' => { - column = 0; - }, - // \b - '\x08' => { - if (column == 0) { - if (row != 0) { - column = vga.WIDTH - 1; - row -= 1; - } - } else { - column -= 1; - } - }, - else => { - try putEntryAt(char, column, row); - column += 1; - if (column == vga.WIDTH) { - column = 0; - row += 1; - scroll(); - } - }, - } -} - -/// -/// Print a string to the TTY. This also updates to hardware cursor. -/// -/// Global changes: -/// video_buffer -/// pages -/// column -/// row -/// -/// Arguments: -/// IN str: []const u8 - The string to print. -/// -/// Errors: -/// PrintError.OutOfBounds - If trying to print beyond the video buffer. -/// -fn writeString(str: []const u8) PrintError!void { - // Make sure we update the cursor to the last character - defer updateCursor(); - for (str) |char| { - try putChar(char); - } -} - -/// -/// A call back function for use in the formation of a string. This calls writeString normally. -/// -/// Global changes: -/// video_buffer -/// pages -/// column -/// row -/// -/// Arguments: -/// IN context: void - The context of the printing. This will be empty. -/// IN string: []const u8 - The string to print. -/// -/// Errors: -/// PrintError.OutOfBounds - If trying to print beyond the video buffer. -/// -fn printCallback(context: void, string: []const u8) PrintError!void { - try writeString(string); -} - -/// -/// Print a character without updating the cursor. For speed when printing a string as only need to -/// update the cursor once. This will also print the special characters: \n, \r, \t and \b -/// -/// Global changes: -/// video_buffer -/// -/// Arguments: -/// IN char: u8 - The character to print. -/// -fn printLogo() void { - const column_temp = column; - const row_temp = row; - - column = 0; - row = 0; - - writeString(" _____ _ _ _ _______ ____ \n") catch unreachable; - writeString(" | __ \\ | | | | | | |__ __| / __ \\ \n") catch unreachable; - writeString(" | |__) | | | | | | | | | | | | |\n") catch unreachable; - writeString(" | ___/ | | | | | | | | | | | |\n") catch unreachable; - writeString(" | | | |____ | |__| | | | | |__| |\n") catch unreachable; - writeString(" |_| |______| \\____/ |_| \\____/ \n") catch unreachable; - - column = column_temp; - row = row_temp; -} - -/// -/// Print a formatted string to the terminal in the current colour. This used the standard zig -/// formatting. -/// -/// Global changes: -/// pages -/// video_buffer -/// column -/// row -/// -/// Arguments: -/// IN format: []const u8 - The format string to print -/// IN args: ... - The arguments to be used in the formatted string -/// -pub fn print(comptime format: []const u8, args: ...) void { - // Printing can't error because of the scrolling, if it does, we have a big problem - fmt.format({}, PrintError, printCallback, format, args) catch unreachable; -} - -/// -/// Move up a page. This will copy the page above to the video buffer. Will keep trace of which -/// page is being displayed. -/// -/// Global changes: -/// video_buffer -/// pages -/// page_index -/// -pub fn pageUp() void { - if (page_index < TOTAL_NUM_PAGES - 1) { - // Copy page to display - page_index += 1; - videoCopy(START_OF_DISPLAYABLE_REGION, pages[page_index][0..TOTAL_CHAR_ON_PAGE], TOTAL_CHAR_ON_PAGE) catch unreachable; - displayPageNumber(); - vga.disableCursor(); - } -} - -/// -/// Move down a page. This will copy the page bellow to the video buffer. Will keep trace of which -/// page is being displayed. -/// -/// Global changes: -/// video_buffer -/// pages -/// page_index -/// -pub fn pageDown() void { - if (page_index > 0) { - // Copy page to display - page_index -= 1; - videoCopy(START_OF_DISPLAYABLE_REGION, pages[page_index][0..TOTAL_CHAR_ON_PAGE], TOTAL_CHAR_ON_PAGE) catch unreachable; - displayPageNumber(); - if(page_index == 0) { - vga.enableCursor(); - updateCursor(); - } else { - vga.disableCursor(); - } - } -} - -/// -/// This clears the entire screen with blanks using the current colour. This will also save the -/// screen to the pages so can scroll back down. -/// -/// Global changes: -/// video_buffer -/// -pub fn clearScreen() void { - // Move all the rows up - //row = ROW_MIN - 1 + vga.HEIGHT; // 42 - pagesMoveRowsUp(ROW_TOTAL) catch unreachable; - - // Clear the screen - var i: u16 = START_OF_DISPLAYABLE_REGION; - while (i < VIDEO_BUFFER_SIZE) : (i += 1) { - video_buffer[i] = blank; - } - column = 0; - row = ROW_MIN; - updateCursor(); -} - -/// -/// This moves the software and hardware cursor to the left by one. -/// -/// Global changes: -/// column -/// row -/// -pub fn moveCursorLeft() void { - if (column == 0) { - if (row != 0) { - column = vga.WIDTH - 1; - row -= 1; - } - } else { - column -= 1; - } - updateCursor(); -} - -/// -/// This moves the software and hardware cursor to the right by one. -/// -/// Global changes: -/// column -/// row -/// -pub fn moveCursorRight() void { - if (column == (vga.WIDTH - 1)) { - if (row != (vga.HEIGHT - 1)) { - column = 0; - row += 1; - } - } else { - column += 1; - } - updateCursor(); -} - -/// -/// This will set a new colour for the screen. It will only become effective when printing new -/// characters. Use vga.colourEntry and the colour enums to set the colour. -/// -/// Global changes: -/// colour -/// blank -/// -/// Arguments: -/// new_colour: u8 - The new foreground and background colour of the screen. -/// -pub fn setColour(new_colour: u8) void { - colour = new_colour; - blank = vga.entry(0, colour); -} - -/// -/// Initialise the tty. This will keep the bootloaders output and set the software cursor to where -/// the bootloader left it. Will copy the current screen to the pages, set the colour and blank -/// entry, print the logo and display the 0'th page. -/// -/// Global changes: -/// pages -/// video_buffer -/// column -/// row -/// colour -/// blank -/// -pub fn init() void { - // Video buffer in higher half - video_buffer = @intToPtr([*]volatile u16, 0xC00B8000)[0..VIDEO_BUFFER_SIZE]; - setColour(vga.entryColour(vga.COLOUR_LIGHT_GREY, vga.COLOUR_BLACK)); - - // Enable and get the hardware cursor to set the software cursor - vga.enableCursor(); - getCursor(); - - if (row != 0 or column != 0) { - // Copy rows 7 down to make room for logo - // If there isn't enough room, only take the bottom rows - var row_offset: u16 = 0; - if(vga.HEIGHT - 1 - row < ROW_MIN) { - row_offset = u16(ROW_MIN - (vga.HEIGHT - 1 - row)); - } - - // Make a copy into the terminal_pages - // Assuming that there is only one page - var i: u16 = 0; - while (i < row * vga.WIDTH) : (i += 1) { - pages[0][i] = video_buffer[i]; - } - - // Move terminal_row rows down 7 - i = 0; - if (@ptrToInt(&video_buffer[ROW_MIN * vga.WIDTH]) < @ptrToInt(&video_buffer[row_offset * vga.WIDTH])) { - while (i != row * vga.WIDTH) : (i += 1) { - video_buffer[i + (ROW_MIN * vga.WIDTH)] = video_buffer[i + (row_offset * vga.WIDTH)]; - } - } else { - i = row * vga.WIDTH; - while (i != 0) { - i -= 1; - video_buffer[i + (ROW_MIN * vga.WIDTH)] = video_buffer[i + (row_offset * vga.WIDTH)]; - } - } - - // Set the top 7 rows blank - setVideoBuffer(blank, START_OF_DISPLAYABLE_REGION); - row += @truncate(u8, row_offset + ROW_MIN); - } else { - // Clear the screen - setVideoBuffer(blank, VIDEO_BUFFER_SIZE); - } - - printLogo(); - displayPageNumber(); -} - -fn resetGlobals() void { - column = 0; - row = 0; - page_index = 0; - colour = undefined; - video_buffer = @intToPtr([*]volatile u16, 0xB8000)[0..VIDEO_BUFFER_SIZE]; - blank = undefined; - - pages = init: { - var p: [TOTAL_NUM_PAGES][TOTAL_CHAR_ON_PAGE]u16 = undefined; - - for (p) |*page| { - page.* = []u16{0} ** TOTAL_CHAR_ON_PAGE; - } - - break :init p; - }; -} - -const test_colour: u8 = vga.entryColour(vga.COLOUR_LIGHT_GREY, vga.COLOUR_BLACK); -var test_video_buffer = []volatile u16{0} ** VIDEO_BUFFER_SIZE; - -fn _setVideoBuffer() void { - // Change to a stack location - video_buffer = test_video_buffer[0..VIDEO_BUFFER_SIZE]; - - expectEqual(@ptrToInt(video_buffer.ptr), @ptrToInt(&test_video_buffer[0])); - expect(@typeOf(video_buffer) == []volatile u16); - - setColour(test_colour); - - // Set pages to blank - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - pages[i][j] = blank; - } - } -} - -fn setVideoBufferBlankPages() void { - _setVideoBuffer(); - for (video_buffer) |*b| { - b.* = blank; - } -} - -fn setVideoBufferIncrementingBlankPages() void { - _setVideoBuffer(); - var i: u16 = 0; - while (i < VIDEO_BUFFER_SIZE) : (i += 1) { - video_buffer[i] = i; - } -} - -fn setPagesIncrementing() void { - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - pages[i][j] = i * TOTAL_CHAR_ON_PAGE + j; - } - } -} - -fn defaultVariablesTesting(p_i: u8, r: u8, c: u8) void { - expectEqual(test_colour, colour); - expectEqual(vga.entry(0, test_colour), blank); - expectEqual(p_i, page_index); - expectEqual(r, row); - expectEqual(c, column); -} - -fn incrementingPagesTesting() void { - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - expectEqual(i * TOTAL_CHAR_ON_PAGE + j, pages[i][j]); - } - } -} - -fn blankPagesTesting() void { - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - expectEqual(blank, pages[i][j]); - } - } -} - -fn incrementingVideoBufferTesting() void { - var i: u16 = 0; - while (i < VIDEO_BUFFER_SIZE) : (i += 1) { - expectEqual(i, video_buffer[i]); - } -} - -fn defaultVideoBufferTesting() void { - for (video_buffer) |b| { - expectEqual(vga.entry(0, test_colour), b); - } -} - -fn defaultAllTesting(p_i: u8, r: u8, c: u8) void { - defaultVariablesTesting(p_i, r, c); - blankPagesTesting(); - defaultVideoBufferTesting(); -} - -test "updateCursor" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - updateCursor(); - - // - // Post test - // - - defaultAllTesting(0, 0, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "getCursor all" { - warn(" Waiting for mocking "); -} - -test "displayPageNumber column and row is reset" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - row = 6; - defaultAllTesting(0, 6, 5); - - // - // Call function - // - - displayPageNumber(); - - // - // Post test - // - - defaultVariablesTesting(0, 6, 5); - - const text: [11]u8 = "Page 0 of 4"; - - // Test both video and pages for page number 0 - for (video_buffer) |b, i| { - if (i < START_OF_DISPLAYABLE_REGION - 11) { - expectEqual(blank, b); - } else if (i < START_OF_DISPLAYABLE_REGION) { - expectEqual(vga.entry(text[i + 11 - START_OF_DISPLAYABLE_REGION], colour), b); - } else { - expectEqual(blank, b); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "putEntryAt out of bounds" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - expectError(PrintError.OutOfBounds, putEntryAt('A', 100, 100)); - - // - // Post test - // - - defaultAllTesting(0, 0, 0); - - // - // Tear down (resets globals) - // - - resetGlobals(); -} - -test "putEntryAt not in displayable region" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - const x: u8 = 0; - const y: u8 = 0; - const char: u8 = 'A'; - putEntryAt(char, x, y) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - blankPagesTesting(); - - for (video_buffer) |b, i| { - if (i == y * vga.WIDTH + x) { - expectEqual(vga.entry(char, test_colour), b); - } else { - expectEqual(vga.entry(0, test_colour), b); - } - } - - // - // Tear down (resets globals) - // - - resetGlobals(); -} - -test "putEntryAt in displayable region page_index is 0" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - const x: u16 = 0; - const y: u16 = ROW_MIN; - const char: u8 = 'A'; - putEntryAt(char, x, y) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - for (pages) |page, i| { - for (page) |c, j| { - if ((i == page_index) and (j == (y * vga.WIDTH + x) - START_OF_DISPLAYABLE_REGION)) { - expectEqual(vga.entry(char, test_colour), c); - } else { - expectEqual(blank, c); - } - } - } - - for (video_buffer) |b, i| { - if (i == y * vga.WIDTH + x) { - expectEqual(vga.entry(char, test_colour), b); - } else { - expectEqual(vga.entry(0, test_colour), b); - } - } - - // - // Tear down (resets globals) - // - - resetGlobals(); -} - -test "putEntryAt in displayable region page_index is not 0" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // Fill the 1'nd page (index 1) will all 1's - const ones: u16 = vga.entry('1', test_colour); - for (pages) |*page, i| { - for (page) |*char| { - if (i == 0) { - char.* = ones; - } else { - char.* = 0; - } - } - } - - page_index = 1; - - // - // Pre testing - // - - defaultVariablesTesting(1, 0, 0); - defaultVideoBufferTesting(); - - for (pages) |page, i| { - for (page) |char| { - if (i == 0) { - expectEqual(ones, char); - } else { - expectEqual(u16(0), char); - } - } - } - - // - // Call function - // - - const x: u16 = 0; - const y: u16 = ROW_MIN; - const char: u8 = 'A'; - putEntryAt(char, x, y) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - - const text: []const u8 = "Page 0 of 4"; - - for (pages) |page, i| { - for (page) |c, j| { - if (i == 0 and j == 0) { - expectEqual(vga.entry(char, test_colour), c); - } else if (i == 0) { - expectEqual(ones, c); - } else { - expectEqual(u16(0), c); - } - } - } - - // The top 7 rows won't be copied - for (video_buffer) |b, i| { - if (i < START_OF_DISPLAYABLE_REGION - 11) { - expectEqual(blank, b); - } else if (i < START_OF_DISPLAYABLE_REGION) { - expectEqual(vga.entry(text[i + 11 - START_OF_DISPLAYABLE_REGION], colour), b); - } else if (i == y * vga.WIDTH + x) { - expectEqual(vga.entry(char, test_colour), b); - } else { - expectEqual(ones, b); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "pagesMoveRowsUp out of bounds" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - const rows_to_move: u16 = ROW_TOTAL + 1; - expectError(PrintError.OutOfBounds, pagesMoveRowsUp(rows_to_move)); - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Tear down - // - - resetGlobals(); -} - -test "pagesMoveRowsUp 0 rows" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - const rows_to_move: u16 = 0; - pagesMoveRowsUp(rows_to_move) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Tear down - // - - resetGlobals(); -} - -test "pagesMoveRowsUp 1 rows" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - const rows_to_move: u16 = 1; - pagesMoveRowsUp(rows_to_move) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - - var i: u16 = 0; - const to_add: u16 = rows_to_move * vga.WIDTH; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (j >= TOTAL_CHAR_ON_PAGE - to_add) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + (j + to_add - TOTAL_CHAR_ON_PAGE), pages[i][j]); - } - } else { - // All rows moved up one, so add vga.WIDTH - expectEqual(i * TOTAL_CHAR_ON_PAGE + j + to_add, pages[i][j]); - } - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "pagesMoveRowsUp ROW_TOTAL - 1 rows" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - const rows_to_move: u16 = ROW_TOTAL - 1; - pagesMoveRowsUp(rows_to_move) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - - var i: u16 = 0; - const to_add: u16 = rows_to_move * vga.WIDTH; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (j >= TOTAL_CHAR_ON_PAGE - to_add) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + (j + to_add - TOTAL_CHAR_ON_PAGE), pages[i][j]); - } - } else { - // All rows moved up one, so add vga.WIDTH - expectEqual(i * TOTAL_CHAR_ON_PAGE + j + to_add, pages[i][j]); - } - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "pagesMoveRowsUp ROW_TOTAL rows" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - const rows_to_move: u16 = ROW_TOTAL; - pagesMoveRowsUp(rows_to_move) catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + j, pages[i][j]); - } - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "scroll row is less then max height" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - scroll(); - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - defaultVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Tear down - // - - resetGlobals(); -} - -test "scroll row is equal to height" { - // - // Set up - // - - setVideoBufferIncrementingBlankPages(); - setPagesIncrementing(); - - const row_test: u16 = vga.HEIGHT; - row = row_test; - - // - // Pre testing - // - - defaultVariablesTesting(0, row_test, 0); - incrementingPagesTesting(); - incrementingVideoBufferTesting(); - - // - // Call function - // - - // Rows move up one - scroll(); - - // - // Post test - // - - defaultVariablesTesting(0, vga.HEIGHT - 1, 0); - - var i: u16 = 0; - const to_add: u16 = (row_test - vga.HEIGHT + 1) * vga.WIDTH; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (j >= TOTAL_CHAR_ON_PAGE - to_add) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + (j + to_add - TOTAL_CHAR_ON_PAGE), pages[i][j]); - } - } else { - // All rows moved up one, so add vga.WIDTH - expectEqual(i * TOTAL_CHAR_ON_PAGE + j + to_add, pages[i][j]); - } - } - } - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k < START_OF_DISPLAYABLE_REGION) { - expectEqual(k, video_buffer[k]); - } else if (k >= VIDEO_BUFFER_SIZE - to_add) { - expectEqual(blank, video_buffer[k]); - } else { - expectEqual(k + to_add, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "scroll row is more than height" { - // - // Set up - // - - setVideoBufferIncrementingBlankPages(); - setPagesIncrementing(); - - const row_test: u16 = vga.HEIGHT + 5; - row = row_test; - - // - // Pre testing - // - - defaultVariablesTesting(0, row_test, 0); - incrementingPagesTesting(); - incrementingVideoBufferTesting(); - - // - // Call function - // - - // Rows move up 5 - scroll(); - - // - // Post test - // - - defaultVariablesTesting(0, vga.HEIGHT - 1, 0); - - var i: u16 = 0; - const to_add: u16 = (row_test - vga.HEIGHT + 1) * vga.WIDTH; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (j >= TOTAL_CHAR_ON_PAGE - to_add) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + (j + to_add - TOTAL_CHAR_ON_PAGE), pages[i][j]); - } - } else { - // All rows moved up one, so add vga.WIDTH - expectEqual(i * TOTAL_CHAR_ON_PAGE + j + to_add, pages[i][j]); - } - } - } - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k < START_OF_DISPLAYABLE_REGION) { - expectEqual(k, video_buffer[k]); - } else if (k >= VIDEO_BUFFER_SIZE - to_add) { - expectEqual(blank, video_buffer[k]); - } else { - expectEqual(k + to_add, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar new line within screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - row = 5; - defaultAllTesting(0, 5, 5); - - // - // Call function - // - - putChar('\n') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 6, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar new line outside screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - row = vga.HEIGHT - 1; - defaultAllTesting(0, vga.HEIGHT - 1, 5); - - // - // Call function - // - - putChar('\n') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, vga.HEIGHT - 1, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar tab within line" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - row = 6; - defaultAllTesting(0, 6, 5); - - // - // Call function - // - - putChar('\t') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 6, 9); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar tab end of line" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = vga.WIDTH - 1; - row = 6; - defaultAllTesting(0, 6, vga.WIDTH - 1); - - // - // Call function - // - - putChar('\t') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 7, 3); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar tab end of screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = vga.WIDTH - 1; - row = vga.HEIGHT - 1; - defaultAllTesting(0, vga.HEIGHT - 1, vga.WIDTH - 1); - - // - // Call function - // - - putChar('\t') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, vga.HEIGHT - 1, 3); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar line feed" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = vga.WIDTH - 1; - row = vga.HEIGHT - 1; - defaultAllTesting(0, vga.HEIGHT - 1, vga.WIDTH - 1); - - // - // Call function - // - - putChar('\r') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, vga.HEIGHT - 1, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar back char top left of screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - putChar('\x08') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 0, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar back char top row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 8; - defaultAllTesting(0, 0, 8); - - // - // Call function - // - - putChar('\x08') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 0, 7); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar back char beginning of row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - row = 1; - defaultAllTesting(0, 1, 0); - - // - // Call function - // - - putChar('\x08') catch unreachable; - - // - // Post test - // - - defaultAllTesting(0, 0, vga.WIDTH - 1); - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar any char in row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - putChar('A') catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 0, 1); - blankPagesTesting(); - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k == 0) { - expectEqual(vga.entry('A', colour), video_buffer[k]); - } else { - expectEqual(blank, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar any char end of row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = vga.WIDTH - 1; - defaultAllTesting(0, 0, vga.WIDTH - 1); - - // - // Call function - // - - putChar('A') catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, 1, 0); - blankPagesTesting(); - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k == vga.WIDTH - 1) { - expectEqual(vga.entry('A', colour), video_buffer[k]); - } else { - expectEqual(blank, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "putChar any char end of screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - row = vga.HEIGHT - 1; - column = vga.WIDTH - 1; - defaultAllTesting(0, vga.HEIGHT - 1, vga.WIDTH - 1); - - // - // Call function - // - - putChar('A') catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, vga.HEIGHT - 1, 0); - for (pages) |page, i| { - for (page) |c, j| { - if ((i == 0) and (j == TOTAL_CHAR_ON_PAGE - vga.WIDTH - 1)) { - expectEqual(vga.entry('A', colour), c); - } else { - expectEqual(blank, c); - } - } - } - - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k == VIDEO_BUFFER_SIZE - vga.WIDTH - 1) { - expectEqual(vga.entry('A', colour), video_buffer[k]); - } else { - expectEqual(blank, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "printLogo all" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 0; - row = ROW_MIN; - - defaultAllTesting(0, ROW_MIN, 0); - - // - // Call function - // - - printLogo(); - - // - // Post test - // - - defaultVariablesTesting(0, ROW_MIN, 0); - blankPagesTesting(); - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k < START_OF_DISPLAYABLE_REGION) { - // This is where the logo will be, but is a complex string so no testing - // Just take my word it works :P - } else { - expectEqual(blank, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "pageUp top page" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - page_index = TOTAL_NUM_PAGES - 1; - - defaultVariablesTesting(TOTAL_NUM_PAGES - 1, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Call function - // - - pageUp(); - - // - // Post test - // - - defaultVariablesTesting(TOTAL_NUM_PAGES - 1, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Tear down - // - - resetGlobals(); -} - -test "pageUp bottom page" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Call function - // - - pageUp(); - - // - // Post test - // - - defaultVariablesTesting(1, 0, 0); - incrementingPagesTesting(); - - const text: []const u8 = "Page 1 of 4"; - - for (video_buffer) |b, i| { - // Ignore the ROW_MIN row as this is where the page number is printed and is already - // tested, page number is printed 11 from the end - if (i < START_OF_DISPLAYABLE_REGION - 11) { - expectEqual(blank, b); - } else if (i < START_OF_DISPLAYABLE_REGION) { - expectEqual(vga.entry(text[i + 11 - START_OF_DISPLAYABLE_REGION], colour), b); - } else { - expectEqual(i - START_OF_DISPLAYABLE_REGION + TOTAL_CHAR_ON_PAGE, b); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "pageDown bottom page" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Call function - // - - pageDown(); - - // - // Post test - // - - defaultVariablesTesting(0, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Tear down - // - - resetGlobals(); -} - -test "pageDown top page" { - // - // Set up - // - - setVideoBufferBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - page_index = TOTAL_NUM_PAGES - 1; - - defaultVariablesTesting(TOTAL_NUM_PAGES - 1, 0, 0); - incrementingPagesTesting(); - defaultVideoBufferTesting(); - - // - // Call function - // - - pageDown(); - - // - // Post test - // - - defaultVariablesTesting(TOTAL_NUM_PAGES - 2, 0, 0); - incrementingPagesTesting(); - - const text: []const u8 = "Page 3 of 4"; - - for (video_buffer) |b, i| { - // Ignore the ROW_MIN row as this is where the page number is printed and is already - // tested, page number is printed 11 from the end - if (i < START_OF_DISPLAYABLE_REGION - 11) { - expectEqual(blank, b); - } else if (i < START_OF_DISPLAYABLE_REGION) { - expectEqual(vga.entry(text[i + 11 - START_OF_DISPLAYABLE_REGION], colour), b); - } else { - expectEqual((i - START_OF_DISPLAYABLE_REGION) + (TOTAL_CHAR_ON_PAGE * page_index), b); - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "clearScreen all" { - // - // Set up - // - - setVideoBufferIncrementingBlankPages(); - setPagesIncrementing(); - - // - // Pre testing - // - - defaultVariablesTesting(0, 0, 0); - incrementingVideoBufferTesting(); - incrementingPagesTesting(); - - // - // Call function - // - - clearScreen(); - - // - // Post test - // - - defaultVariablesTesting(0, ROW_MIN, 0); - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k < START_OF_DISPLAYABLE_REGION) { - expectEqual(k, video_buffer[k]); - } else { - expectEqual(blank, video_buffer[k]); - } - } - - var i: u16 = 0; - while (i < TOTAL_NUM_PAGES) : (i += 1) { - var j: u16 = 0; - while (j < TOTAL_CHAR_ON_PAGE) : (j += 1) { - if (i == 0) { - // The last rows will be blanks - expectEqual(blank, pages[i][j]); - } else { - expectEqual((i - 1) * TOTAL_CHAR_ON_PAGE + j, pages[i][j]); - } - } - } - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorLeft top left of screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - defaultAllTesting(0, 0, 0); - - // - // Call function - // - - moveCursorLeft(); - - // - // Post test - // - - defaultAllTesting(0, 0, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorLeft top screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - defaultAllTesting(0, 0, 5); - - // - // Call function - // - - moveCursorLeft(); - - // - // Post test - // - - defaultAllTesting(0, 0, 4); - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorLeft start of row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - row = 5; - defaultAllTesting(0, 5, 0); - - // - // Call function - // - - moveCursorLeft(); - - // - // Post test - // - - defaultAllTesting(0, 4, vga.WIDTH - 1); - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorRight bottom right of screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - row = vga.HEIGHT - 1; - column = vga.WIDTH - 1; - defaultAllTesting(0, vga.HEIGHT - 1, vga.WIDTH - 1); - - // - // Call function - // - - moveCursorRight(); - - // - // Post test - // - - defaultAllTesting(0, vga.HEIGHT - 1, vga.WIDTH - 1); - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorRight top screen" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - column = 5; - defaultAllTesting(0, 0, 5); - - // - // Call function - // - - moveCursorRight(); - - // - // Post test - // - - defaultAllTesting(0, 0, 6); - - // - // Tear down - // - - resetGlobals(); -} - -test "moveCursorRight end of row" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - - row = 5; - column = vga.WIDTH - 1; - defaultAllTesting(0, 5, vga.WIDTH - 1); - - // - // Call function - // - - moveCursorRight(); - - // - // Post test - // - - defaultAllTesting(0, 6, 0); - - // - // Tear down - // - - resetGlobals(); -} - -test "setColour all" { - // - // Set up - // - - // - // Pre testing - // - - // - // Call function - // - - const new_colour: u8 = vga.entryColour(vga.COLOUR_WHITE, vga.COLOUR_WHITE); - setColour(new_colour); - - // - // Post test - // - - expectEqual(new_colour, colour); - expectEqual(vga.entry(0, new_colour), blank); - - // - // Tear down - // - resetGlobals(); -} - -test "writeString all" { - // - // Set up - // - - setVideoBufferBlankPages(); - - // - // Pre testing - // - row = ROW_MIN; - defaultAllTesting(0, ROW_MIN, 0); - - // - // Call function - // - - writeString("ABC") catch unreachable; - - // - // Post test - // - - defaultVariablesTesting(0, ROW_MIN, 3); - for (pages) |page, i| { - for (page) |c, j| { - if ((i == 0) and (j == 0)) { - expectEqual(vga.entry('A', colour), c); - } else if ((i == 0) and (j == 1)) { - expectEqual(vga.entry('B', colour), c); - } else if ((i == 0) and (j == 2)) { - expectEqual(vga.entry('C', colour), c); - } else { - expectEqual(blank, c); - } - } - } - - - var k: u16 = 0; - while (k < VIDEO_BUFFER_SIZE) : (k += 1) { - if (k == START_OF_DISPLAYABLE_REGION) { - expectEqual(vga.entry('A', colour), video_buffer[k]); - } else if (k == START_OF_DISPLAYABLE_REGION + 1) { - expectEqual(vga.entry('B', colour), video_buffer[k]); - } else if (k == START_OF_DISPLAYABLE_REGION + 2) { - expectEqual(vga.entry('C', colour), video_buffer[k]); - } else { - expectEqual(blank, video_buffer[k]); - } - } - - // - // Tear down - // - - resetGlobals(); -} diff --git a/src/kernel/vga.zig b/src/kernel/vga.zig deleted file mode 100644 index e778655..0000000 --- a/src/kernel/vga.zig +++ /dev/null @@ -1,413 +0,0 @@ -// Zig version: 0.4.0 - -const builtin = @import("builtin"); -const arch = if (builtin.is_test) @import("../../test/kernel/arch_mock.zig") - else @import("arch.zig"); - -const expectEqual = @import("std").testing.expectEqual; -const warn = @import("std").debug.warn; - -/// The port address for the VGA register selection. -const PORT_ADDRESS: u16 = 0x03D4; - -/// The port address for the VGA data. -const PORT_DATA: u16 = 0x03D5; - -// The indexes that is passed to the address port to select the register for the data to be -// read or written to. - -const REG_HORIZONTAL_TOTAL: u8 = 0x00; -const REG_HORIZONTAL_DISPLAY_ENABLE_END: u8 = 0x01; -const REG_START_HORIZONTAL_BLINKING: u8 = 0x02; -const REG_END_HORIZONTAL_BLINKING: u8 = 0x03; -const REG_START_HORIZONTAL_RETRACE_PULSE: u8 = 0x04; -const REG_END_HORIZONTAL_RETRACE_PULSE: u8 = 0x05; -const REG_VERTICAL_TOTAL: u8 = 0x06; -const REG_OVERFLOW: u8 = 0x07; -const REG_PRESET_ROW_SCAN: u8 = 0x08; -const REG_MAXIMUM_SCAN_LINE: u8 = 0x09; - -/// The command for setting the start of the cursor scan line. -const REG_CURSOR_START: u8 = 0x0A; - -/// The command for setting the end of the cursor scan line. -const REG_CURSOR_END: u8 = 0x0B; -const REG_START_ADDRESS_HIGH: u8 = 0x0C; -const REG_START_ADDRESS_LOW: u8 = 0x0D; - -/// The command for setting the upper byte of the cursor's linear location. -const REG_CURSOR_LOCATION_HIGH: u8 = 0x0E; - -/// The command for setting the lower byte of the cursor's linear location. -const REG_CURSOR_LOCATION_LOW: u8 = 0x0F; -const REG_VERTICAL_RETRACE_START: u8 = 0x10; -const REG_VERTICAL_RETRACE_END: u8 = 0x11; -const REG_VERTICAL_DISPLAY_ENABLE_END: u8 = 0x12; -const REG_OFFSET: u8 = 0x13; -const REG_UNDERLINE_LOCATION: u8 = 0x14; -const REG_START_VERTICAL_BLINKING: u8 = 0x15; -const REG_END_VERTICAL_BLINKING: u8 = 0x16; -const REG_CRT_MODE_CONTROL: u8 = 0x17; -const REG_LINE_COMPARE: u8 = 0x18; - - -///The start of the cursor scan line, the very beginning. -const CURSOR_SCANLINE_START: u8 = 0x0; - -///The scan line for use in the underline cursor shape. -const CURSOR_SCANLINE_MIDDLE: u8 = 0xE; - -///The end of the cursor scan line, the very end. -const CURSOR_SCANLINE_END: u8 = 0xF; - -/// If set, disables the cursor. -const CURSOR_DISABLE: u8 = 0x20; - -pub const WIDTH: u16 = 80; -pub const HEIGHT: u16 = 25; - -// The set of colours that VGA supports and can display for the foreground and background. -pub const COLOUR_BLACK: u4 = 0x00; -pub const COLOUR_BLUE: u4 = 0x01; -pub const COLOUR_GREEN: u4 = 0x02; -pub const COLOUR_CYAN: u4 = 0x03; -pub const COLOUR_RED: u4 = 0x04; -pub const COLOUR_MAGENTA: u4 = 0x05; -pub const COLOUR_BROWN: u4 = 0x06; -pub const COLOUR_LIGHT_GREY: u4 = 0x07; -pub const COLOUR_DARK_GREY: u4 = 0x08; -pub const COLOUR_LIGHT_BLUE: u4 = 0x09; -pub const COLOUR_LIGHT_GREEN: u4 = 0x0A; -pub const COLOUR_LIGHT_CYAN: u4 = 0x0B; -pub const COLOUR_LIGHT_RED: u4 = 0x0C; -pub const COLOUR_LIGHT_MAGENTA: u4 = 0x0D; -pub const COLOUR_LIGHT_BROWN: u4 = 0x0E; -pub const COLOUR_WHITE: u4 = 0x0F; - -/// The set of shapes that can be displayed. -pub const CursorShape = enum(u1) { - /// The cursor has the underline shape. - UNDERLINE, - - /// The cursor has the block shape. - BLOCK, -}; - -/// The cursor scan line start so to know whether is in block or underline mode. -var cursor_scanline_start: u8 = undefined; - -/// The cursor scan line end so to know whether is in block or underline mode. -var cursor_scanline_end: u8 = undefined; - -/// -/// Takes two 4 bit values that represent the foreground and background colour of the text and -/// returns a 8 bit value that gives both to be displayed. -/// -/// Arguments: -/// IN fg: u4 - The foreground colour. -/// IN bg: u4 - The background colour. -/// -/// Return: -/// Both combined into 1 byte for the colour to be displayed. -/// -pub fn entryColour(fg: u4, bg: u4) u8 { - return u8(fg) | u8(bg) << 4; -} - -/// -/// Create the 2 bytes entry that the VGA used to display a character with a foreground and -/// background colour. -/// -/// Arguments: -/// IN uc: u8 - The character. -/// IN colour: u8 - The foreground and background colour. -/// -/// Return: -/// The VGA entry. -/// -pub fn entry(uc: u8, colour: u8) u16 { - return u16(uc) | u16(colour) << 8; -} - -/// -/// Update the hardware on screen cursor. -/// -/// Arguments: -/// IN x: u16 - The horizontal position of the cursor. -/// IN y: u16 - The vertical position of the cursor. -/// -/// Return: -/// The VGA entry. -/// -pub fn updateCursor(x: u16, y: u16) void { - var pos: u16 = undefined; - var pos_upper: u16 = undefined; - var pos_lower: u16 = undefined; - - // Make sure new cursor position is within the screen - if (x < HEIGHT and y < WIDTH) { - pos = y * WIDTH + x; - } else { - // If not within the screen, then just put the cursor at the very end - pos = (HEIGHT - 1) * WIDTH + (WIDTH - 1); - } - - pos_upper = (pos >> 8) & 0x00FF; - pos_lower = pos & 0x00FF; - - // Set the cursor position - arch.outb(PORT_ADDRESS, REG_CURSOR_LOCATION_LOW); - arch.outb(PORT_DATA, @truncate(u8, pos_lower)); - - arch.outb(PORT_ADDRESS, REG_CURSOR_LOCATION_HIGH); - arch.outb(PORT_DATA, @truncate(u8, pos_upper)); -} - -/// -/// Get the hardware cursor position. -/// -/// Return: -/// The linear cursor position. -/// -pub fn getCursor() u16 { - var cursor: u16 = 0; - - arch.outb(PORT_ADDRESS, REG_CURSOR_LOCATION_LOW); - cursor |= u16(arch.inb(PORT_DATA)); - - arch.outb(PORT_ADDRESS, REG_CURSOR_LOCATION_HIGH); - cursor |= u16(arch.inb(PORT_DATA)) << 8; - - return cursor; -} - -/// -/// Enables the blinking cursor to that is is visible. -/// -pub fn enableCursor() void { - arch.outb(PORT_ADDRESS, REG_CURSOR_START); - arch.outb(PORT_DATA, cursor_scanline_start); - - arch.outb(PORT_ADDRESS, REG_CURSOR_END); - arch.outb(PORT_DATA, cursor_scanline_end); -} - -/// -/// Disables the blinking cursor to that is is visible. -/// -pub fn disableCursor() void { - arch.outb(PORT_ADDRESS, REG_CURSOR_START); - arch.outb(PORT_DATA, CURSOR_DISABLE); -} - -/// -/// Set the shape of the cursor. This can be and underline or block shape. -/// -/// Arguments: -/// IN shape: CURSOR_SHAPE - The enum CURSOR_SHAPE that selects which shape to use. -/// -pub fn setCursorShape(shape: CursorShape) void { - switch(shape) { - CursorShape.UNDERLINE => { - arch.outb(PORT_ADDRESS, REG_CURSOR_START); - arch.outb(PORT_DATA, CURSOR_SCANLINE_MIDDLE); - - arch.outb(PORT_ADDRESS, REG_CURSOR_END); - arch.outb(PORT_DATA, CURSOR_SCANLINE_END); - - cursor_scanline_start = CURSOR_SCANLINE_MIDDLE; - cursor_scanline_end = CURSOR_SCANLINE_END; - }, - CursorShape.BLOCK => { - arch.outb(PORT_ADDRESS, REG_CURSOR_START); - arch.outb(PORT_DATA, CURSOR_SCANLINE_START); - - arch.outb(PORT_ADDRESS, REG_CURSOR_END); - arch.outb(PORT_DATA, CURSOR_SCANLINE_END); - - cursor_scanline_start = CURSOR_SCANLINE_START; - cursor_scanline_end = CURSOR_SCANLINE_END; - }, - } -} - -/// -/// Initialise the VGA text mode. This sets the cursor and underline shape. -/// -pub fn init() void { - // Set the maximum scan line to 0x0F - arch.outb(PORT_ADDRESS, REG_MAXIMUM_SCAN_LINE); - arch.outb(PORT_DATA, CURSOR_SCANLINE_END); - - // Set by default the underline cursor - setCursorShape(CursorShape.UNDERLINE); - cursor_scanline_start = CURSOR_SCANLINE_MIDDLE; - cursor_scanline_end = CURSOR_SCANLINE_END; -} - -test "entryColour" { - var fg: u4 = COLOUR_BLACK; - var bg: u4 = COLOUR_BLACK; - var res: u8 = entryColour(fg, bg); - expectEqual(u8(0x00), res); - - fg = COLOUR_LIGHT_GREEN; - bg = COLOUR_BLACK; - res = entryColour(fg, bg); - expectEqual(u8(0x0A), res); - - fg = COLOUR_BLACK; - bg = COLOUR_LIGHT_GREEN; - res = entryColour(fg, bg); - expectEqual(u8(0xA0), res); - - fg = COLOUR_BROWN; - bg = COLOUR_LIGHT_GREEN; - res = entryColour(fg, bg); - expectEqual(u8(0xA6), res); -} - -test "entry" { - var colour: u8 = entryColour(COLOUR_BROWN, COLOUR_LIGHT_GREEN); - expectEqual(u8(0xA6), colour); - - // Character '0' is 0x30 - var video_entry: u16 = entry('0', colour); - expectEqual(u16(0xA630), video_entry); - - video_entry = entry(0x55, colour); - expectEqual(u16(0xA655), video_entry); -} - -fn testOutOfBounds(x: u16, y: u16) bool { - if(x < HEIGHT and y < WIDTH) { - return true; - } - return false; -} - -fn testUpperVal(x: u16, y: u16) u16 { - const pos: u16 = x * WIDTH + y; - const pos_upper: u16 = (pos >> 8) & 0x00FF; - return pos_upper; -} - -fn testLowerVal(x: u16, y: u16) u16 { - const pos: u16 = x * WIDTH + y; - const pos_lower: u16 = pos & 0x00FF; - return pos_lower; -} - -test "updateCursor out of bounds" { - var x: u16 = 0; - var y: u16 = 0; - var res: bool = testOutOfBounds(x, y); - expectEqual(true, res); - - x = HEIGHT - 1; - res = testOutOfBounds(x, y); - expectEqual(true, res); - - y = WIDTH - 1; - res = testOutOfBounds(x, y); - expectEqual(true, res); - - x = HEIGHT; - y = WIDTH; - res = testOutOfBounds(x, y); - expectEqual(false, res); - - x = HEIGHT - 1; - y = WIDTH; - res = testOutOfBounds(x, y); - expectEqual(false, res); - - x = HEIGHT; - y = WIDTH - 1; - res = testOutOfBounds(x, y); - expectEqual(false, res); -} - -test "updateCursor lower values" { - var x: u16 = 0x0000; - var y: u16 = 0x0000; - var res: u16 = testLowerVal(x, y); - var expected: u16 = 0x0000; - expectEqual(expected, res); - - x = 0x0000; - y = 0x000A; - res = testLowerVal(x, y); - expected = 0x000A; - expectEqual(expected, res); - - x = 0x000A; - y = 0x0000; - res = testLowerVal(x, y); - expected = 0x0020; - expectEqual(expected, res); - - x = 0x000A; - y = 0x000A; - res = testLowerVal(x, y); - expected = 0x002A; - expectEqual(expected, res); -} - -test "updateCursor upper values" { - var x: u16 = 0x0000; - var y: u16 = 0x0000; - var res: u16 = testUpperVal(x, y); - var expected: u16 = 0x0000; - expectEqual(expected, res); - - x = 0x0000; - y = 0x000A; - res = testUpperVal(x, y); - expected = 0x0000; - expectEqual(expected, res); - - x = 0x000A; - y = 0x0000; - res = testUpperVal(x, y); - expected = 0x0003; - expectEqual(expected, res); - - x = 0x000A; - y = 0x000A; - res = testUpperVal(x, y); - expected = 0x0003; - expectEqual(expected, res); -} - -test "getCursor all" { - warn(" Waiting for mocking "); - var res = getCursor(); -} - -test "enableCursor all" { - warn(" Waiting for mocking "); - enableCursor(); -} - -test "disableCursor all" { - warn(" Waiting for mocking "); - disableCursor(); -} - -test "setCursorShape all" { - setCursorShape(CursorShape.UNDERLINE); - expectEqual(CURSOR_SCANLINE_MIDDLE, cursor_scanline_start); - expectEqual(CURSOR_SCANLINE_END, cursor_scanline_end); - - setCursorShape(CursorShape.BLOCK); - expectEqual(CURSOR_SCANLINE_START, cursor_scanline_start); - expectEqual(CURSOR_SCANLINE_END, cursor_scanline_end); -} - -test "init all" { - warn(" Waiting for mocking "); - init(); - expectEqual(CURSOR_SCANLINE_MIDDLE, cursor_scanline_start); - expectEqual(CURSOR_SCANLINE_END, cursor_scanline_end); -} \ No newline at end of file diff --git a/test/kernel/arch_mock.zig b/test/kernel/arch_mock.zig deleted file mode 100644 index 30dcaa6..0000000 --- a/test/kernel/arch_mock.zig +++ /dev/null @@ -1,32 +0,0 @@ -// Zig version: 0.4.0 - -/// -/// Initialise the architecture -/// -pub fn init() void {} - -/// -/// Inline assembly to write to a given port with a byte of data. -/// -/// Arguments: -/// IN port: u16 - The port to write to. -/// IN data: u8 - The byte of data that will be sent. -/// -pub fn outb(port: u16, data: u8) void {} - -/// -/// Inline assembly that reads data from a given port and returns its value. -/// -/// Arguments: -/// IN port: u16 - The port to read data from. -/// -/// Return: -/// The data that the port returns. -/// -pub fn inb(port: u16) u8 {return 0;} - -/// -/// A simple way of waiting for I/O event to happen by doing an I/O event to flush the I/O -/// event being waited. -/// -pub fn ioWait() void {}