Buggy screen driver.
This commit is contained in:
parent
21c97f509d
commit
ad43ca56b1
2
Makefile
2
Makefile
@ -5,7 +5,7 @@ CC=gcc
|
||||
LD=ld
|
||||
LDFLAGS=-melf_i386 -Ttext 0x1000 --oformat binary
|
||||
|
||||
OBJ=kernel/kernel_entry.o kernel/kernel.o kernel/ports.o
|
||||
OBJ=kernel/kernel_entry.o kernel/kernel.o kernel/ports.o kernel/util.o drivers/screen.o
|
||||
|
||||
all: os-image
|
||||
|
||||
|
@ -1,6 +1,67 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include "../kernel/ports.h"
|
||||
#include "../kernel/util.h"
|
||||
|
||||
int get_screen_offset(int col, int row) {
|
||||
return (row * MAX_COLS + col) * 2;
|
||||
}
|
||||
|
||||
int get_cursor() {
|
||||
/*
|
||||
* screens use their control register as an index to
|
||||
* select their internal registers of which:
|
||||
* - 14: high byte of the cursor's offset
|
||||
* - 15: low byte of the cursor's offset
|
||||
*/
|
||||
port_byte_out(REG_SCREEN_CTRL, 14);
|
||||
/* get the high byte and shift it a byte */
|
||||
int offset = port_byte_in(REG_SCREEN_DATA) << 8;
|
||||
port_byte_out(REG_SCREEN_CTRL, 15);
|
||||
/* now add the low byte with the free space from before */
|
||||
offset += port_byte_in(REG_SCREEN_DATA);
|
||||
|
||||
/* remember: each cell is two bytes, not one */
|
||||
return offset * 2;
|
||||
}
|
||||
|
||||
void set_cursor(int offset) {
|
||||
/* convert from cell offset to char offset */
|
||||
offset /= 2;
|
||||
|
||||
port_byte_out(REG_SCREEN_CTRL, 14);
|
||||
port_byte_out(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
|
||||
port_byte_out(REG_SCREEN_CTRL, 15);
|
||||
}
|
||||
|
||||
int handle_scrolling(int cursor_offset) {
|
||||
/* if within the screen then don't modify */
|
||||
if(cursor_offset < MAX_ROWS * MAX_COLS * 2)
|
||||
return cursor_offset;
|
||||
|
||||
/* translate rows back by one */
|
||||
unsigned int i;
|
||||
for(i = 1; i < MAX_ROWS; ++i)
|
||||
{
|
||||
memory_copy((char*)get_screen_offset(0, i) + VIDEO_ADDRESS,
|
||||
(char*)get_screen_offset(0, i - 1) + VIDEO_ADDRESS,
|
||||
MAX_COLS * 2);
|
||||
}
|
||||
|
||||
/* set last line to blank */
|
||||
char *last_line = (char*)get_screen_offset(0, MAX_ROWS - 1) + VIDEO_ADDRESS;
|
||||
for(i = 0; i < MAX_COLS * 2; ++i)
|
||||
last_line[i] = 0;
|
||||
|
||||
/*
|
||||
* move the cursor offset to the last row instead of
|
||||
* off the screen
|
||||
*/
|
||||
cursor_offset -= MAX_COLS * 2;
|
||||
|
||||
/* updated cursor position */
|
||||
return cursor_offset;
|
||||
}
|
||||
|
||||
void print_char(char c, int col, int row, char attr_byte) {
|
||||
unsigned char *vidmem = (unsigned char*) VIDEO_ADDRESS;
|
||||
@ -44,3 +105,30 @@ void print_char(char c, int col, int row, char attr_byte) {
|
||||
/* update the cursor position */
|
||||
set_cursor(offset);
|
||||
}
|
||||
|
||||
void print_at(const char *msg, int col, int row) {
|
||||
if(col >= 0 && row >= 0)
|
||||
set_cursor(get_screen_offset(col, row));
|
||||
|
||||
int i;
|
||||
for(i = 0; msg[i] != 0; ++i)
|
||||
print_char(msg[i], col, row, WHITE_ON_BLACK);
|
||||
}
|
||||
|
||||
void print(const char *msg) {
|
||||
print_at(msg, -1, -1);
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
int row, col;
|
||||
|
||||
for(row = 0; row < MAX_ROWS; ++row)
|
||||
{
|
||||
for(col = 0; col < MAX_COLS; ++col)
|
||||
{
|
||||
print_char(' ', col, row, WHITE_ON_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
set_cursor(get_screen_offset(0, 0));
|
||||
}
|
||||
|
@ -9,5 +9,6 @@
|
||||
#define REG_SCREEN_CTRL 0x3d4
|
||||
#define REG_SCREEN_DATA 0x3d5
|
||||
|
||||
void print_char(char c, int col, int row, char attr_byte);
|
||||
int get_screen_offset(int col, int row);
|
||||
void print_at(const char *msg, int col, int row);
|
||||
void print(const char *msg);
|
||||
void clear_screen();
|
||||
|
@ -1,10 +1,6 @@
|
||||
#include "../drivers/screen.h"
|
||||
|
||||
void main() {
|
||||
/*
|
||||
* point to first text cell of the video memory
|
||||
*/
|
||||
char *video_memory = (char*) 0xb8000;
|
||||
/*
|
||||
* store the character 'X' there
|
||||
*/
|
||||
*video_memory = 'X';
|
||||
/*clear_screen();
|
||||
print_at("This is a test.", 0, 0);*/
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
unsigned char port_byte_in(unsigned char port) {
|
||||
unsigned char port_byte_in(unsigned short port) {
|
||||
unsigned char res;
|
||||
/*
|
||||
* `"=a" (res)' means: put result of `al' into `res' variable
|
||||
@ -8,7 +8,7 @@ unsigned char port_byte_in(unsigned char port) {
|
||||
return res;
|
||||
}
|
||||
|
||||
void port_byte_out(unsigned char port, unsigned char data) {
|
||||
void port_byte_out(unsigned short port, unsigned char data) {
|
||||
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,11 @@
|
||||
/*
|
||||
* return a byte from a port.
|
||||
*/
|
||||
unsigned char port_byte_in(unsigned char port);
|
||||
unsigned char port_byte_in(unsigned short port);
|
||||
/*
|
||||
* write a byte of data to a port.
|
||||
*/
|
||||
void port_byte_out(unsigned char port, unsigned char data);
|
||||
void port_byte_out(unsigned short port, unsigned char data);
|
||||
/*
|
||||
* return a word of data from a port.
|
||||
*/
|
||||
|
7
kernel/util.c
Normal file
7
kernel/util.c
Normal file
@ -0,0 +1,7 @@
|
||||
void memory_copy(char *src, char *dest, unsigned int n) {
|
||||
unsigned int i;
|
||||
for(i = 0; i < n; ++i)
|
||||
{
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
2
kernel/util.h
Normal file
2
kernel/util.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
void memory_copy(char *src, char *dest, unsigned int n);
|
Loading…
Reference in New Issue
Block a user