separating: there will be libk and libc
This commit is contained in:
131
drivers/framebuffer.c
Normal file
131
drivers/framebuffer.c
Normal file
@@ -0,0 +1,131 @@
|
||||
// Framebuffer driver
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include "framebuffer.h"
|
||||
#include "serial.h"
|
||||
#include "../kernel/system.h"
|
||||
#include "../kernel/kheap.h"
|
||||
|
||||
extern char* framebuffer;
|
||||
|
||||
void psf_init()
|
||||
{
|
||||
uint16_t glyph = 0;
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
if (font->flags)
|
||||
{
|
||||
unicode = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
char* s = (char*)((unsigned char*)&FONT_START + font->headersize + font->numglyph * font->bytesperglyph);
|
||||
unicode = calloc(USHRT_MAX, 2);
|
||||
|
||||
while((uintptr_t)s>(uintptr_t)FONT_END){
|
||||
uint16_t uc = (uint16_t)((unsigned char)s[0]);
|
||||
if(uc == 0xFF) {
|
||||
glyph++;
|
||||
s++;
|
||||
continue;
|
||||
} else if(uc & 128) {
|
||||
/* UTF-8 to unicode */
|
||||
if((uc & 32) == 0 ) {
|
||||
uc = ((s[0] & 0x1F)<<6)+(s[1] & 0x3F);
|
||||
s++;
|
||||
} else
|
||||
if((uc & 16) == 0 ) {
|
||||
uc = ((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F);
|
||||
s+=2;
|
||||
} else
|
||||
if((uc & 8) == 0 ) {
|
||||
uc = ((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F);
|
||||
s+=3;
|
||||
} else
|
||||
uc = 0;
|
||||
}
|
||||
/* save translation */
|
||||
unicode[uc] = glyph;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
||||
{
|
||||
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
||||
*pixel_addr = color;
|
||||
}
|
||||
|
||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
int bytesperline=(font->width+7)/8;
|
||||
if (unicode != NULL) {
|
||||
c = unicode[c];
|
||||
}
|
||||
|
||||
unsigned char* glyph = (unsigned char*)&FONT_START + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
|
||||
|
||||
int offs =
|
||||
(cy * font->height * scanline) +
|
||||
(cx * (font->width) * sizeof(PIXEL));
|
||||
|
||||
unsigned int x, y;
|
||||
int line, mask;
|
||||
|
||||
for (y=0; y<font->height; y++)
|
||||
{
|
||||
line=offs;
|
||||
mask=1<<(font->width-1);
|
||||
|
||||
for (x=0; x<font->width; x++)
|
||||
{
|
||||
*((PIXEL*)(framebuffer + line)) = *((unsigned int*)glyph) & mask ? fg : bg;
|
||||
mask >>= 1;
|
||||
line += sizeof(PIXEL);
|
||||
}
|
||||
|
||||
glyph += bytesperline;
|
||||
offs += scanline;
|
||||
}
|
||||
}
|
||||
|
||||
void scroll()
|
||||
{
|
||||
serial_printf(3, "Scrolling...\r");
|
||||
uint32_t bg_color = 0x00000000;
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
|
||||
int line_size = font->height * scanline;
|
||||
int framebuffer_size = scanline * font->height * (1080/font->height);
|
||||
|
||||
// Erasing first line
|
||||
for (uint32_t y=0; y<font->height; y++)
|
||||
{
|
||||
for (uint32_t x=0; x<scanline/sizeof(PIXEL); x++)
|
||||
{
|
||||
*((PIXEL*)(framebuffer + y * scanline + x * sizeof(PIXEL))) = bg_color;
|
||||
}
|
||||
}
|
||||
|
||||
// Moving all lines up by 1 line
|
||||
for (int y=1; y<(framebuffer_size/line_size); y++)
|
||||
{
|
||||
void* src = framebuffer + y*line_size;
|
||||
void* dst = framebuffer + (y-1)*line_size;
|
||||
memmove(dst, src, line_size);
|
||||
}
|
||||
|
||||
// Erasing last line
|
||||
int last_line_start = (framebuffer_size/line_size-1) * line_size;
|
||||
for (uint32_t y=0; y<font->height; y++)
|
||||
{
|
||||
for (uint32_t x=0; x<scanline/sizeof(PIXEL); x++)
|
||||
{
|
||||
*((PIXEL*)(framebuffer + last_line_start + y * scanline + x * sizeof(PIXEL))) = bg_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
drivers/framebuffer.h
Normal file
48
drivers/framebuffer.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Framebuffer driver header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef FRAMEBUFFER_H
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int scanline;
|
||||
|
||||
#define FONT_START _binary_include_fonts_viscii10_8x16_psfu_start
|
||||
#define FONT_END _binary_include_fonts_viscii10_8x16_psfu_start
|
||||
|
||||
extern char FONT_START;
|
||||
extern char FONT_END;
|
||||
uint16_t* unicode;
|
||||
#define PIXEL uint32_t
|
||||
|
||||
#define USHRT_MAX 10000
|
||||
#define PSF1_FONT_MAGIC 0x0436
|
||||
|
||||
typedef struct {
|
||||
uint16_t magic; // Magic bytes for identification.
|
||||
uint8_t fontMode; // PSF font mode.
|
||||
uint8_t characterSize; // PSF character size.
|
||||
} PSF1_Header;
|
||||
|
||||
#define PSF_FONT_MAGIC 0x864ab572
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; /* magic bytes to identify PSF */
|
||||
uint32_t version; /* zero */
|
||||
uint32_t headersize; /* offset of bitmaps in file, 32 */
|
||||
uint32_t flags; /* 0 if there's no unicode table */
|
||||
uint32_t numglyph; /* number of glyphs */
|
||||
uint32_t bytesperglyph; /* size of each glyph */
|
||||
uint32_t height; /* height in pixels */
|
||||
uint32_t width; /* width in pixels */
|
||||
} PSF_font;
|
||||
|
||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color);
|
||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg);
|
||||
void scroll();
|
||||
void psf_init();
|
||||
|
||||
#endif
|
||||
286
drivers/serial.c
Normal file
286
drivers/serial.c
Normal file
@@ -0,0 +1,286 @@
|
||||
// Serial I/O driver
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../kernel/io.h"
|
||||
#include "serial.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
int init_serial()
|
||||
{
|
||||
outb(PORT+1, 0x00);
|
||||
outb(PORT+3, 0x80);
|
||||
outb(PORT+0, 0x03);
|
||||
outb(PORT+1, 0x00);
|
||||
|
||||
outb(PORT+3, 0x03);
|
||||
outb(PORT+2, 0xC7);
|
||||
outb(PORT+4, 0x0B);
|
||||
outb(PORT+4, 0x1E);
|
||||
outb(PORT+0, 0xAE);
|
||||
|
||||
if (inb(PORT+0) != 0xAE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
outb(PORT+4, 0x0F);
|
||||
puts("[serial] initialized i/o on port COM1\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_transmit_empty()
|
||||
{
|
||||
return inb(PORT+5) & 0x20;
|
||||
}
|
||||
|
||||
void write_serial(const char a)
|
||||
{
|
||||
while (is_transmit_empty() == 0);
|
||||
outb(PORT, a);
|
||||
}
|
||||
|
||||
void serial_puts(const char* str)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
write_serial(str[0]); // Transmit first byte 2 times
|
||||
while (*str++)
|
||||
{
|
||||
write_serial(str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void log(const char* str, const int errlevel)
|
||||
{
|
||||
switch (errlevel)
|
||||
{
|
||||
case 0:
|
||||
serial_puts("[ERROR] ");
|
||||
break;
|
||||
case 1:
|
||||
serial_puts("[WARNING] ");
|
||||
break;
|
||||
case 2:
|
||||
serial_puts("[INFO] ");
|
||||
break;
|
||||
case 3:
|
||||
serial_puts("[DEBUG] ");
|
||||
break;
|
||||
}
|
||||
serial_puts(str);
|
||||
}
|
||||
|
||||
const char serial_charset[] = "0123456789abcdef";
|
||||
|
||||
int* serial_printf_number(int* argp, int length, bool sign, int radix)
|
||||
{
|
||||
char buffer[32];
|
||||
unsigned long long number;
|
||||
int number_sign = 1;
|
||||
int pos = 0;
|
||||
|
||||
switch(length)
|
||||
{
|
||||
case PRINTF_LENGTH_SHORT_SHORT:
|
||||
case PRINTF_LENGTH_SHORT:
|
||||
case PRINTF_LENGTH_START:
|
||||
if (sign)
|
||||
{
|
||||
int n = *argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned int*) argp;
|
||||
}
|
||||
argp++;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long int n = *(long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long int*) argp;
|
||||
}
|
||||
argp += 2;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long long int n = *(long long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long long int*) argp;
|
||||
}
|
||||
argp += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
uint32_t rem;
|
||||
x86_div64_32(number, radix, &number, &rem);
|
||||
buffer[pos++] = serial_charset[rem];
|
||||
} while (number > 0);
|
||||
|
||||
if (sign && number_sign < 0)
|
||||
{
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
while (--pos >= 0)
|
||||
{
|
||||
write_serial(buffer[pos]);
|
||||
}
|
||||
|
||||
return argp;
|
||||
}
|
||||
void serial_printf(int errlevel, const char* fmt, ...)
|
||||
{
|
||||
switch (errlevel)
|
||||
{
|
||||
case 0:
|
||||
serial_puts("[ERROR] ");
|
||||
break;
|
||||
case 1:
|
||||
serial_puts("[WARNING] ");
|
||||
break;
|
||||
case 2:
|
||||
serial_puts("[INFO] ");
|
||||
break;
|
||||
case 3:
|
||||
serial_puts("[DEBUG] ");
|
||||
break;
|
||||
}
|
||||
|
||||
int* argp = (int*) &fmt;
|
||||
int state = PRINTF_STATE_START;
|
||||
int length = PRINTF_LENGTH_START;
|
||||
int radix = 10;
|
||||
bool sign = false;
|
||||
|
||||
argp++;
|
||||
while (*fmt)
|
||||
{
|
||||
switch(state) {
|
||||
case PRINTF_STATE_START:
|
||||
if (*fmt == '%')
|
||||
{
|
||||
state = PRINTF_STATE_LENGTH;
|
||||
}
|
||||
else {
|
||||
write_serial(*fmt);
|
||||
}
|
||||
break;
|
||||
case PRINTF_STATE_LENGTH:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT;
|
||||
state = PRINTF_STATE_SHORT;
|
||||
}
|
||||
else if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG;
|
||||
state = PRINTF_STATE_LONG;
|
||||
}
|
||||
else {
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
case PRINTF_STATE_SHORT:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else {
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
case PRINTF_STATE_LONG:
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG_LONG;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else {
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
case PRINTF_STATE_SPEC:
|
||||
PRINTF_STATE_SPEC_:
|
||||
switch(*fmt)
|
||||
{
|
||||
case 'c':
|
||||
serial_puts(*(const char **)argp);
|
||||
argp++;
|
||||
break;
|
||||
case 's':
|
||||
serial_puts(*(const char **)argp);
|
||||
argp++;
|
||||
break;
|
||||
case '%':
|
||||
putc('%');
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
radix = 10;
|
||||
sign = true;
|
||||
argp = serial_printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
sign = false;
|
||||
argp = serial_printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
case 'X':
|
||||
case 'x':
|
||||
case 'p':
|
||||
radix = 16;
|
||||
sign = false;
|
||||
argp = serial_printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
sign = false;
|
||||
argp = serial_printf_number(argp, length, sign, radix);
|
||||
break;
|
||||
case 'f': {
|
||||
// Handle floating-point numbers
|
||||
double* dargp = (double*)argp;
|
||||
double d = *(double*)dargp;
|
||||
char buffer[64];
|
||||
dtostrf(d, buffer, 6); // Default precision: 6
|
||||
serial_puts(buffer);
|
||||
argp += 2; // Incrementing by 2 to move past the double argument
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = PRINTF_STATE_START;
|
||||
length = PRINTF_LENGTH_START;
|
||||
radix = 10;
|
||||
sign = false;
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
serial_puts("\r\n");
|
||||
}
|
||||
18
drivers/serial.h
Normal file
18
drivers/serial.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Serial I/O driver header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
|
||||
#define PORT 0x3f8 //COM1
|
||||
|
||||
int init_serial();
|
||||
int is_transmit_empty();
|
||||
void write_serial(const char a);
|
||||
void serial_puts(const char* str);
|
||||
void log(const char* str, const int errlevel);
|
||||
void serial_printf(int errlevel, const char* fmt, ...);
|
||||
|
||||
#endif
|
||||
38
drivers/timer.c
Normal file
38
drivers/timer.c
Normal file
@@ -0,0 +1,38 @@
|
||||
// Programmable Interval Timer channel 0 driver
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../kernel/system.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
volatile unsigned long global_ticks = 0;
|
||||
|
||||
void timer_handler()
|
||||
{
|
||||
global_ticks++;
|
||||
if (global_ticks % 20 == 0)
|
||||
{
|
||||
draw_cursor(white);
|
||||
} else if (global_ticks % 20 == 10) {
|
||||
erase_cursor();
|
||||
}
|
||||
}
|
||||
|
||||
void timer_install()
|
||||
{
|
||||
irq_install_handler(0, timer_handler);
|
||||
printf("[timer] initialized, starting g_ticks...\n");
|
||||
}
|
||||
|
||||
void delay(int ticks)
|
||||
{
|
||||
unsigned long eticks;
|
||||
eticks = global_ticks + ticks;
|
||||
while (global_ticks < eticks);
|
||||
}
|
||||
|
||||
int uptime()
|
||||
{
|
||||
return global_ticks;
|
||||
}
|
||||
Reference in New Issue
Block a user