add keyboard buffer and shell-like interface
This commit is contained in:
parent
de59d0d549
commit
e5f54a0cfb
2
Makefile
2
Makefile
|
@ -13,7 +13,7 @@ NASMFLAGS += -felf32
|
|||
BIN = sysroot/boot/hhhos.bin
|
||||
ISO = build/HhhOS.iso
|
||||
|
||||
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ahci build/drivers/ide
|
||||
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ide
|
||||
|
||||
OBJS = build/boot/boot.o build/boot/kernel.o build/std/string.o build/drivers/terminal/terminal.o build/drivers/idt/idt.o \
|
||||
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o build/drivers/ide/ide.o
|
||||
|
|
|
@ -6,28 +6,61 @@
|
|||
#include <drivers/device/device.h>
|
||||
#include <drivers/ide/ide.h>
|
||||
|
||||
/* Check if the compiler thinks you are targeting the wrong operating system. */
|
||||
#if defined(__linux__)
|
||||
#error "You are not using a cross-compiler, you will most certainly run into trouble"
|
||||
#endif
|
||||
|
||||
/* This operating system will only work for the 32-bit ix86 targets. */
|
||||
#if !defined(__i386__)
|
||||
#error "This operating system needs to be compiled with a ix86-elf compiler"
|
||||
#endif
|
||||
|
||||
uint8_t is_running = 1;
|
||||
int keyboard_descriptor = 0;
|
||||
int terminal_descriptor = 0;
|
||||
|
||||
void shell() {
|
||||
terminal_writestring("hello yes");
|
||||
|
||||
while (is_running) {
|
||||
terminal_writestring("\n> ");
|
||||
|
||||
while (true) {
|
||||
unsigned char scancode = read(keyboard_descriptor, NULL);
|
||||
if (!scancode) continue;
|
||||
|
||||
bool special = true;
|
||||
bool finished = false;
|
||||
|
||||
switch (scancode) {
|
||||
case 72:
|
||||
terminal_row--;
|
||||
break;
|
||||
case 75:
|
||||
terminal_column--;
|
||||
break;
|
||||
case 77:
|
||||
terminal_column++;
|
||||
break;
|
||||
case 80:
|
||||
terminal_row++;
|
||||
break;
|
||||
case 0x1C:
|
||||
finished = true;
|
||||
break;
|
||||
default:
|
||||
special = false;
|
||||
}
|
||||
|
||||
if (finished) break;
|
||||
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
|
||||
terminal_updatecursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kmain() {
|
||||
terminal_initialize();
|
||||
terminal_writeline("Initializing terminal... done");
|
||||
terminal_descriptor = terminal_initialize();
|
||||
terminal_writestring("Initializing terminal... done, descriptor: ");
|
||||
terminal_writeline(itoa(terminal_descriptor));
|
||||
terminal_writestring("Preparing interrupts... ");
|
||||
pic_init();
|
||||
isr_install();
|
||||
terminal_writeline("done");
|
||||
|
||||
terminal_writestring("Preparing keyboard... ");
|
||||
int keyboard_descriptor = keyboard_init();
|
||||
keyboard_descriptor = keyboard_init();
|
||||
terminal_writestring("done, descriptor: ");
|
||||
terminal_writeline(itoa(keyboard_descriptor));
|
||||
|
||||
|
@ -41,20 +74,10 @@ void kmain() {
|
|||
} else {
|
||||
terminal_writeline("no");
|
||||
}
|
||||
terminal_writestring("Is keyboard enabled? ");
|
||||
if (are_interrupts_enabled() == 1) {
|
||||
terminal_writeline("yes");
|
||||
} else {
|
||||
terminal_writeline("no");
|
||||
}
|
||||
|
||||
terminal_writestring("kmain memory address: ");
|
||||
terminal_writeline(itoa(kmain));
|
||||
|
||||
terminal_writeline("----------");
|
||||
|
||||
terminal_writeline("hello yes");
|
||||
terminal_writestring("> ");
|
||||
|
||||
while (is_running);
|
||||
shell();
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <drivers/ahci/ahci.h>
|
||||
#include <drivers/terminal/terminal.h>
|
||||
#include <std/util.h>
|
||||
#include <std/string.h>
|
||||
#include <std/inline.h>
|
||||
|
||||
// AHCI driver, source: https://wiki.osdev.org/AHCI
|
||||
|
||||
static void trace_ahci(const char* message, int i) {
|
||||
terminal_writestring(message);
|
||||
terminal_writeline(itoa(i));
|
||||
}
|
||||
|
||||
// Check device type
|
||||
static int check_type(HBA_PORT *port) {
|
||||
uint32_t ssts = port->ssts;
|
||||
|
||||
uint8_t ipm = (ssts >> 8) & 0x0F;
|
||||
uint8_t det = ssts & 0x0F;
|
||||
|
||||
if (det != HBA_PORT_DET_PRESENT) // Check drive status
|
||||
return AHCI_DEV_NULL;
|
||||
if (ipm != HBA_PORT_IPM_ACTIVE)
|
||||
return AHCI_DEV_NULL;
|
||||
|
||||
switch (port->sig)
|
||||
{
|
||||
case SATA_SIG_ATAPI:
|
||||
return AHCI_DEV_SATAPI;
|
||||
case SATA_SIG_SEMB:
|
||||
return AHCI_DEV_SEMB;
|
||||
case SATA_SIG_PM:
|
||||
return AHCI_DEV_PM;
|
||||
default:
|
||||
return AHCI_DEV_SATA;
|
||||
}
|
||||
}
|
||||
|
||||
void probe_port(HBA_MEM *abar) {
|
||||
// Search disk in implemented ports
|
||||
uint32_t pi = abar->pi;
|
||||
int i = 0;
|
||||
while (i<32)
|
||||
{
|
||||
if (pi & 1)
|
||||
{
|
||||
int dt = check_type(&abar->ports[i]);
|
||||
if (dt == AHCI_DEV_SATA)
|
||||
{
|
||||
trace_ahci("SATA drive found at port: ", i);
|
||||
}
|
||||
else if (dt == AHCI_DEV_SATAPI)
|
||||
{
|
||||
trace_ahci("SATAPI drive found at port: ", i);
|
||||
}
|
||||
else if (dt == AHCI_DEV_SEMB)
|
||||
{
|
||||
trace_ahci("SEMB drive found at port: ", i);
|
||||
}
|
||||
else if (dt == AHCI_DEV_PM)
|
||||
{
|
||||
trace_ahci("PM drive found at port: ", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
//trace_ahci("No drive found at port: ", i);
|
||||
}
|
||||
}
|
||||
|
||||
pi >>= 1;
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pci_config_read_word(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
|
||||
uint32_t address;
|
||||
uint32_t lbus = (uint32_t)bus;
|
||||
uint32_t lslot = (uint32_t)slot;
|
||||
uint32_t lfunc = (uint32_t)func;
|
||||
uint64_t tmp = 0;
|
||||
|
||||
/* create configuration address as per Figure 1 */
|
||||
address = (uint32_t)((lbus << 16) | (lslot << 11) |
|
||||
(lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
|
||||
|
||||
/* write out the address */
|
||||
outportl(0xCF8, address);
|
||||
/* read in the data */
|
||||
/* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */
|
||||
if (offset == 0x24)
|
||||
tmp = inportb(0xCFC) ;
|
||||
else
|
||||
tmp = (uint16_t)( (inportb(0xCFC) >> ((offset & 2) * 8) ) & 0xffff);
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
uint16_t get_vendor_id(uint8_t bus, uint8_t slot)
|
||||
{
|
||||
return pci_config_read_word(bus, slot, 0, 0);
|
||||
}
|
||||
|
||||
uint16_t get_device_id(uint8_t bus, uint8_t slot)
|
||||
{
|
||||
return pci_config_read_word(bus, slot, 0, 2);
|
||||
}
|
||||
|
||||
uint64_t check_device(uint8_t bus, uint8_t device) {
|
||||
//uint8_t function = 0;
|
||||
|
||||
uint16_t vendorID = get_vendor_id(bus, device);
|
||||
if(vendorID == 0xFFFF) return 0; // Device doesn't exist
|
||||
uint16_t deviceID = get_device_id(bus, device);
|
||||
|
||||
return pci_config_read_word(bus, device, 0, 0x24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t check_all_buses(void)
|
||||
{
|
||||
uint16_t bus;
|
||||
uint8_t device;
|
||||
uint64_t bar5;
|
||||
|
||||
for(bus = 0; bus < 256; bus++)
|
||||
{
|
||||
for(device = 0; device < 32; device++)
|
||||
{
|
||||
bar5 = check_device(bus, device);
|
||||
if (bar5 == 0) return 0;
|
||||
probe_port((HBA_MEM*)bar5);
|
||||
return bar5;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start command engine
|
||||
void start_cmd(HBA_PORT *port)
|
||||
{
|
||||
// Wait until CR (bit15) is cleared
|
||||
while (port->cmd & HBA_PxCMD_CR);
|
||||
|
||||
// Set FRE (bit4) and ST (bit0)
|
||||
port->cmd |= HBA_PxCMD_FRE;
|
||||
port->cmd |= HBA_PxCMD_ST;
|
||||
}
|
||||
|
||||
// Stop command engine
|
||||
void stop_cmd(HBA_PORT *port)
|
||||
{
|
||||
// Clear ST (bit0)
|
||||
port->cmd &= ~HBA_PxCMD_ST;
|
||||
|
||||
// Clear FRE (bit4)
|
||||
port->cmd &= ~HBA_PxCMD_FRE;
|
||||
|
||||
// Wait until FR (bit14), CR (bit15) are cleared
|
||||
while(1)
|
||||
{
|
||||
if (port->cmd & HBA_PxCMD_FR)
|
||||
continue;
|
||||
if (port->cmd & HBA_PxCMD_CR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void port_rebase(HBA_PORT *port, int portno)
|
||||
{
|
||||
stop_cmd(port); // Stop command engine
|
||||
|
||||
// Command list offset: 1K*portno
|
||||
// Command list entry size = 32
|
||||
// Command list entry maxim count = 32
|
||||
// Command list maxim size = 32*32 = 1K per port
|
||||
port->clb = AHCI_BASE + (portno<<10);
|
||||
port->clbu = 0;
|
||||
memset((void*)(port->clb), 0, 1024);
|
||||
|
||||
// FIS offset: 32K+256*portno
|
||||
// FIS entry size = 256 bytes per port
|
||||
port->fb = AHCI_BASE + (32<<10) + (portno<<8);
|
||||
port->fbu = 0;
|
||||
memset((void*)(port->fb), 0, 256);
|
||||
|
||||
// Command table offset: 40K + 8K*portno
|
||||
// Command table size = 256*32 = 8K per port
|
||||
HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER*)(port->clb);
|
||||
for (int i=0; i<32; i++)
|
||||
{
|
||||
cmdheader[i].prdtl = 8; // 8 prdt entries per command table
|
||||
// 256 bytes per command table, 64+16+48+16*8
|
||||
// Command table offset: 40K + 8K*portno + cmdheader_index*256
|
||||
cmdheader[i].ctba = AHCI_BASE + (40<<10) + (portno<<13) + (i<<8);
|
||||
cmdheader[i].ctbau = 0;
|
||||
memset((void*)cmdheader[i].ctba, 0, 256);
|
||||
}
|
||||
|
||||
start_cmd(port); // Start command engine
|
||||
}
|
||||
|
||||
void ahci_init(void) {
|
||||
uint64_t bar5 = check_all_buses();
|
||||
if (bar5 == 0) {
|
||||
terminal_writeline("Error: Could not find AHCI device");
|
||||
return;
|
||||
}
|
||||
|
||||
terminal_writestring("Found AHCI device at: ");
|
||||
terminal_writeline(itoa(bar5));
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,8 @@
|
|||
#include <drivers/keyboard/keyboard.h>
|
||||
#include <drivers/device/device.h>
|
||||
|
||||
unsigned char kbdbuf[KBD_BUF_SIZE];
|
||||
|
||||
unsigned char kbdus[128] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||
'9', '0', '-', '=', '\b', /* Backspace */
|
||||
|
@ -45,6 +47,18 @@ unsigned char kbdus[128] = {
|
|||
uint8_t lastkey = 0;
|
||||
uint8_t __kbd_enabled = 0;
|
||||
|
||||
void keyboard_buffer_push_key(unsigned char scancode) {
|
||||
kbdbuf[lastkey++] = scancode;
|
||||
}
|
||||
|
||||
unsigned char keyboard_buffer_pop_key() {
|
||||
uint8_t index = lastkey--;
|
||||
unsigned char scancode = kbdbuf[index];
|
||||
kbdbuf[index] = 0;
|
||||
return scancode;
|
||||
}
|
||||
|
||||
|
||||
unsigned char keyboard_get_key_from_scancode(unsigned char scancode) {
|
||||
return kbdus[scancode];
|
||||
}
|
||||
|
@ -52,34 +66,14 @@ unsigned char keyboard_get_key_from_scancode(unsigned char scancode) {
|
|||
__attribute__((interrupt)) static void keyboard_irq(struct interrupt_frame* frame) {
|
||||
unsigned char scancode = inportb(0x60);
|
||||
|
||||
bool special = true;
|
||||
|
||||
switch (scancode) {
|
||||
case 72:
|
||||
terminal_row--;
|
||||
break;
|
||||
case 75:
|
||||
terminal_column--;
|
||||
break;
|
||||
case 77:
|
||||
terminal_column++;
|
||||
break;
|
||||
case 80:
|
||||
terminal_row++;
|
||||
break;
|
||||
default:
|
||||
special = false;
|
||||
}
|
||||
|
||||
if (scancode & 128) {
|
||||
// This is a release scancode, just ignore it
|
||||
pic_send_eoi(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
|
||||
terminal_updatecursor();
|
||||
pic_send_eoi(1);
|
||||
keyboard_buffer_push_key(scancode);
|
||||
pic_send_eoi(1);
|
||||
}
|
||||
|
||||
uint8_t keyboard_enabled(void) {
|
||||
|
@ -87,11 +81,7 @@ uint8_t keyboard_enabled(void) {
|
|||
}
|
||||
|
||||
void* keyboard_read(void* data) {
|
||||
if (inportb(0x64) & 1) {
|
||||
return keyboard_get_key_from_scancode(inportb(0x60));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return keyboard_buffer_pop_key();
|
||||
}
|
||||
|
||||
void* keyboard_write(void* data) {
|
||||
|
@ -109,7 +99,5 @@ int keyboard_init(void) {
|
|||
read: &keyboard_read
|
||||
};
|
||||
|
||||
int keyboard_descriptor = push_device(keyboard_device);
|
||||
|
||||
return keyboard_descriptor;
|
||||
return push_device(keyboard_device);
|
||||
}
|
18
arch/i386/drivers/tar/tar.c
Normal file
18
arch/i386/drivers/tar/tar.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <drivers/tar/tar.h>
|
||||
#include <std/util.h>
|
||||
#include <drivers/device/device.h>
|
||||
|
||||
struct tar_header* tar_seek(int fd, char filename[100]) {
|
||||
unsigned int i;
|
||||
unsigned int addr;
|
||||
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
struct tar_header *header = (struct tar_header *)read(fd, addr);
|
||||
if (header->filename == filename) return header;
|
||||
|
||||
unsigned int size = getsize(header->size);
|
||||
addr += ((size / 512) + 1);
|
||||
if (size % 512) addr++;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include <drivers/terminal/terminal.h>
|
||||
#include <drivers/device/device.h>
|
||||
|
||||
size_t terminal_row;
|
||||
size_t terminal_column;
|
||||
|
@ -14,12 +15,39 @@ void terminal_clear(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void terminal_initialize(void) {
|
||||
/*
|
||||
static inline void terminal_writestring(const char* data) {
|
||||
terminal_write(data, strlen(data));
|
||||
}
|
||||
|
||||
static inline void terminal_writeline(const char* data) {
|
||||
terminal_writestring(data);
|
||||
terminal_putchar('\n');
|
||||
}
|
||||
*/
|
||||
|
||||
void* terminal_devread(void* data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* terminal_devwrite(void* data) {
|
||||
terminal_putchar(*((char*)data));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int terminal_initialize(void) {
|
||||
terminal_row = 0;
|
||||
terminal_column = 0;
|
||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||
terminal_buffer = (uint16_t*) 0xB8000;
|
||||
terminal_clear();
|
||||
|
||||
struct device terminal_device = {
|
||||
write: &terminal_devwrite,
|
||||
read: &terminal_devread
|
||||
};
|
||||
|
||||
return push_device(terminal_device);
|
||||
}
|
||||
|
||||
void terminal_setcolor(uint8_t color) {
|
||||
|
|
|
@ -36,4 +36,16 @@ char* itoa(int res) {
|
|||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int atoi(const char *in)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
unsigned int j;
|
||||
unsigned int count = 1;
|
||||
|
||||
for (j = 11; j > 0; j--, count *= 8)
|
||||
size += ((in[j - 1] - '0') * count);
|
||||
|
||||
return size;
|
||||
}
|
|
@ -104,7 +104,6 @@ extern "C" {
|
|||
|
||||
void ide_init();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KBD_BUF_SIZE 256
|
||||
|
||||
int keyboard_init(void);
|
||||
uint8_t keyboard_enabled(void);
|
||||
|
||||
|
|
27
include/drivers/tar/tar.h
Normal file
27
include/drivers/tar/tar.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef _TAR_H
|
||||
#define _TAR_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct tar_header
|
||||
{
|
||||
char filename[100];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag[1];
|
||||
char padding[355];
|
||||
};
|
||||
|
||||
struct tar_header* tar_seek(int fd, char filename[100]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TAR_H */
|
|
@ -47,7 +47,7 @@ extern uint8_t terminal_color;
|
|||
extern uint16_t* terminal_buffer;
|
||||
|
||||
void terminal_clear(void);
|
||||
void terminal_initialize(void);
|
||||
int terminal_initialize(void);
|
||||
void terminal_setcolor(uint8_t color);
|
||||
void terminal_clearline(size_t line);
|
||||
void terminal_clearlines(size_t from, size_t to);
|
||||
|
|
|
@ -15,6 +15,7 @@ void* malloc(size_t amount);
|
|||
int rand(void);
|
||||
void srand(size_t seed);
|
||||
char* itoa(int res);
|
||||
unsigned int atoi(const char *in);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue