/*- * Copyright (c) 2002-2018 The UbixOS Project. * All rights reserved. * * This was developed by Christopher W. Olsen for the UbixOS Project. * * 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, the following disclaimer and the list of authors. * 2) Redistributions in binary form must reproduce the above copyright notice, this list of * conditions, the following disclaimer and the list of authors in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the UbixOS 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 AUTHOR 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. */ #include <ubixos/tty.h> #include <ubixos/kpanic.h> #include <ubixos/spinlock.h> #include <lib/kprintf.h> #include <lib/kmalloc.h> #include <sys/io.h> #include <string.h> static tty_term *terms = 0x0; tty_term *tty_foreground = 0x0; static struct spinLock tty_spinLock = SPIN_LOCK_INITIALIZER; int tty_init() { int i = 0x0; /* Allocate memory for terminals */ terms = (tty_term *) kmalloc(sizeof(tty_term) * TTY_MAX_TERMS); if (terms == 0x0) kpanic("tty_init: Failed to allocate memory. File: %s, Line: %i\n", __FILE__, __LINE__); /* Set up all default terminal information */ for (i = 0; i < TTY_MAX_TERMS; i++) { terms[i].tty_buffer = (char *) kmalloc(80 * 60 * 2); if (terms[i].tty_buffer == 0x0) kpanic("tty_init: Failed to allocate buffer memory. File: %s, Line: %i\n", __FILE__, __LINE__); terms[i].tty_pointer = terms[i].tty_buffer; /* Set up tty pointer to internal buffer */ terms[i].tty_x = 0x0; /* Set up default X position */ terms[i].tty_y = 0x0; /* Set up default Y position */ terms[i].tty_colour = 0x0A + i; /* Set up default tty text colour */ } /* Read tty0 current position (to migrate from kprintf). */ outportByte(0x3D4, 0x0e); terms[0].tty_y = inportByte(0x3D5); outportByte(0x3D4, 0x0f); terms[0].tty_x = inportByte(0x3D5); /* Set up pointer for the foreground tty */ tty_foreground = &terms[0]; /* Set up the foreground ttys information */ tty_foreground->tty_pointer = (char *) 0xB8000; /* Return to let kernel know initialization is complete */ kprintf("tty0 - Initialized\n"); return (0x0); } /* This will change the specified tty. It ultimately copies the screen to the foreground buffer copies the new ttys buffer to the screen and adjusts a couple pointers and we are good to go. */ int tty_change(uInt16 tty) { if (tty > TTY_MAX_TERMS) kpanic("Error: Changing to an invalid tty. File: %s, Line: %i\n", __FILE__, __LINE__); /* Copy display buffer to tty buffer */ memcpy(tty_foreground->tty_buffer, (char *) 0xB8000, (80 * 60 * 2)); /* Copy new tty buffer to display buffer */ memcpy((char *) 0xB8000, terms[tty].tty_buffer, (80 * 60 * 2)); /* Set the tty_pointer to the internal buffer so I can continue writing to what it believes is the screen */ tty_foreground->tty_pointer = tty_foreground->tty_buffer; terms[tty].tty_pointer = (char *) 0xB8000; /* set new foreground tty */ tty_foreground = &terms[tty]; /* Adjust cursor when we change consoles */ outportByte(0x3D4, 0x0F); outportByte(0x3D5, tty_foreground->tty_x); outportByte(0x3D4, 0x0E); outportByte(0x3D5, tty_foreground->tty_y); return (0x0); } int tty_print(char *string, tty_term *term) { unsigned int bufferOffset = 0x0, character = 0x0, i = 0x0; spinLock(&tty_spinLock); /* We Need To Get The Y Position */ bufferOffset = term->tty_y; bufferOffset <<= 8; /* Then We Need To Add The X Position */ bufferOffset += term->tty_x; bufferOffset <<= 1; while ((character = *string++)) { switch (character) { case '\n': bufferOffset = (bufferOffset / 160) * 160 + 160; break; default: term->tty_pointer[bufferOffset++] = character; term->tty_pointer[bufferOffset++] = term->tty_colour; break; } /* switch */ /* Check To See If We Are Out Of Bounds */ if (bufferOffset >= 160 * 25) { for (i = 0; i < 160 * 24; i++) { term->tty_pointer[i] = term->tty_pointer[i + 160]; } for (i = 0; i < 80; i++) { term->tty_pointer[(160 * 24) + (i * 2)] = 0x20; term->tty_pointer[(160 * 24) + (i * 2) + 1] = term->tty_colour; } bufferOffset -= 160; } } bufferOffset >>= 1; /* Set the new cursor position */ term->tty_x = (bufferOffset & 0xFF); term->tty_y = (bufferOffset >> 0x8); if (term == tty_foreground) { outportByte(0x3D4, 0x0f); outportByte(0x3D5, term->tty_x); outportByte(0x3D4, 0x0e); outportByte(0x3D5, term->tty_y); } spinUnlock(&tty_spinLock); return (0x0); } tty_term *tty_find(uInt16 tty) { return (&terms[tty]); } /*** END ***/