réplica de
https://github.com/Arnau478/quark.git
synced 2024-11-23 12:58:07 +01:00
Floppy disk controller, new keyboard and PIT driver interface, many things
- Implemented basic FDC capable of reading floppy disc sectors - Now PIT timer can be used, as it counts the ticks - Now the keyboard is buffered, instead of being accessed only during the interrupt itself - HAL for sleep() - gets() - atoi() - Now shell is not called by the IRQ, but it's a procedure that reads the key buffer
This commit is contained in:
pare
109b5b17a1
commit
be55b8121c
S'han modificat 19 arxius amb 497 adicions i 47 eliminacions
240
src/kernel/arch/i686/fdc.c
Normal file
240
src/kernel/arch/i686/fdc.c
Normal file
|
@ -0,0 +1,240 @@
|
|||
#include <stdbool.h>
|
||||
#include "fdc.h"
|
||||
#include "isr.h"
|
||||
#include "io.h"
|
||||
#include "../../lib/time.h"
|
||||
|
||||
static volatile bool g_fdc_irq = false;
|
||||
static int g_curr_drive = 0;
|
||||
|
||||
static void i686_fdc_irq(registers *regs){
|
||||
g_fdc_irq = true;
|
||||
}
|
||||
|
||||
static inline void wait_irq(){
|
||||
while(!g_fdc_irq); // Wait until g_fdc_irq is true
|
||||
g_fdc_irq = false; // Then reset it to false
|
||||
}
|
||||
|
||||
void i686_fdc_initialize_dma(){
|
||||
i686_outb(0x0A, 0x06); // Mask DMA channel 2
|
||||
i686_outb(0xD8, 0xFF); // Reset master flip-flop
|
||||
i686_outw(0x04, 0x1000); // Address = 0x1000
|
||||
i686_outb(0xD8, 0xFF); // Reset master flip-flop
|
||||
i686_outb(0x05, 0xFF); // Count to 0x23FF (bytes in 2.5" floppy disk track)
|
||||
i686_outb(0x05, 0x23);
|
||||
i686_outb(0x80, 0x00); // External page register = 0
|
||||
i686_outb(0x0A, 0x02); // Unmask DMA channel 2
|
||||
}
|
||||
|
||||
void i686_fdc_dma_read(){
|
||||
i686_outb(0x0A, 0x06); // Mask DMA channel 2
|
||||
i686_outb(0x0B, 0x56); // single transfer, address increment, autoinit, read, channel 2
|
||||
i686_outb(0x0A, 0x02); // Unmask DMA channel 2
|
||||
}
|
||||
|
||||
void i686_fdc_dma_write(){
|
||||
i686_outb(0x0A, 0x06); // Mask DMA channel 2
|
||||
i686_outb(0x0B, 0x5A); // single transfer, address increment, autoinit, write, channel 2
|
||||
i686_outb(0x0A, 0x02); // Unmask DMA channel 2
|
||||
}
|
||||
|
||||
uint8_t i686_fdc_msr_read(){
|
||||
return i686_inb(i686_FDC_MSR);
|
||||
}
|
||||
|
||||
void i686_fdc_send_cmd(uint8_t cmd){
|
||||
while(!(i686_fdc_msr_read() & i686_FDC_MSR_DATAREG));
|
||||
i686_outb(i686_FDC_FIFO, cmd);
|
||||
}
|
||||
|
||||
uint8_t i686_fdc_read_data(){
|
||||
while(!(i686_fdc_msr_read() & i686_FDC_MSR_DATAREG));
|
||||
return i686_inb(i686_FDC_FIFO);
|
||||
}
|
||||
|
||||
void i686_fdc_write_ccr(uint8_t v){
|
||||
i686_outb(i686_FDC_CTRL, v);
|
||||
}
|
||||
|
||||
void i686_fdc_drive_data(uint32_t stepr, uint32_t loadt, uint32_t unloadt, bool dma){
|
||||
uint32_t data = 0;
|
||||
|
||||
i686_fdc_send_cmd(i686_FDC_CMD_SPECIFY);
|
||||
|
||||
data = ((stepr & 0xF) << 4) | (unloadt & 0xF);
|
||||
i686_fdc_send_cmd(data);
|
||||
|
||||
data = loadt << 1 | dma ? 1 : 0; // Ensure dma is a 0/1 bool
|
||||
i686_fdc_send_cmd(data);
|
||||
}
|
||||
|
||||
void i686_fdc_check_int(uint32_t *st0, uint32_t *cyl){
|
||||
i686_fdc_send_cmd(i686_FDC_CMD_CHECK_INT);
|
||||
*st0 = i686_fdc_read_data();
|
||||
*cyl = i686_fdc_read_data();
|
||||
}
|
||||
|
||||
int i686_fdc_motor(bool b){
|
||||
if(g_curr_drive > 3) return -2;
|
||||
|
||||
uint32_t motor = 0;
|
||||
switch(g_curr_drive){
|
||||
case 0: motor = i686_FDC_DOR_DRIVE0_MOTOR; break;
|
||||
case 1: motor = i686_FDC_DOR_DRIVE1_MOTOR; break;
|
||||
case 2: motor = i686_FDC_DOR_DRIVE2_MOTOR; break;
|
||||
case 3: motor = i686_FDC_DOR_DRIVE3_MOTOR; break;
|
||||
}
|
||||
|
||||
if(b) i686_outb(i686_FDC_DOR, g_curr_drive | motor | i686_FDC_DOR_RESET | i686_FDC_DOR_DMA);
|
||||
else i686_outb(i686_FDC_DOR, i686_FDC_DOR_RESET);
|
||||
|
||||
// Give the motor some time
|
||||
sleep(20);
|
||||
}
|
||||
|
||||
void i686_fdc_read_sector_imp(uint8_t head, uint8_t track, uint8_t sector){
|
||||
uint32_t st0, cyl;
|
||||
|
||||
// Set DMA for read
|
||||
i686_fdc_dma_read();
|
||||
|
||||
// Read a sector
|
||||
i686_fdc_send_cmd(i686_FDC_CMD_READ_SECT | i686_FDC_CMD_EXT_MULTITRACK | i686_FDC_CMD_EXT_SKIP | i686_FDC_CMD_EXT_DENSITY);
|
||||
i686_fdc_send_cmd(head << 2 | g_curr_drive);
|
||||
i686_fdc_send_cmd(track);
|
||||
i686_fdc_send_cmd(head);
|
||||
i686_fdc_send_cmd(sector);
|
||||
i686_fdc_send_cmd(i686_FDC_SECTOR_DTL_512);
|
||||
i686_fdc_send_cmd((sector + 1) >= i686_FDC_SECTORS_PER_TRACK ? i686_FDC_SECTORS_PER_TRACK : sector + 1);
|
||||
i686_fdc_send_cmd(i686_FDC_GAP3_3_5);
|
||||
i686_fdc_send_cmd(0xFF);
|
||||
|
||||
// Wait for IRQ
|
||||
wait_irq();
|
||||
|
||||
// Read output
|
||||
for(int i = 0; i < 7; i++) i686_fdc_read_data();
|
||||
|
||||
// Tell the FDC we are done
|
||||
i686_fdc_check_int(&st0, &cyl);
|
||||
}
|
||||
|
||||
static void lba_to_chs(int lba, int *head, int *track, int *sector){
|
||||
*head = (lba % (i686_FDC_SECTORS_PER_TRACK * 2)) / i686_FDC_SECTORS_PER_TRACK;
|
||||
*track = lba / (i686_FDC_SECTORS_PER_TRACK * 2);
|
||||
*sector = lba % i686_FDC_SECTORS_PER_TRACK + 1;
|
||||
}
|
||||
|
||||
uint8_t *i686_fdc_read_sector(int lba){
|
||||
if(g_curr_drive > 3) return 0;
|
||||
|
||||
// Convert LBA to CHS
|
||||
int head = 0, track = 0, sector = 1;
|
||||
lba_to_chs(lba, &head, &track, §or);
|
||||
|
||||
// Turn on motor and seek
|
||||
i686_fdc_motor(true);
|
||||
if(i686_fdc_seek(track, head) != 0) return 0;
|
||||
|
||||
// Read and turn off motor
|
||||
i686_fdc_read_sector_imp(head, track, sector);
|
||||
i686_fdc_motor(false);
|
||||
|
||||
return (uint8_t *)0x1000;
|
||||
}
|
||||
|
||||
int i686_fdc_calibrate(uint32_t drive){
|
||||
uint32_t st0, cyl;
|
||||
|
||||
if(drive > 3) return -2;
|
||||
|
||||
i686_fdc_motor(true);
|
||||
|
||||
for(int i = 0; i < 10; i++){
|
||||
// Send command
|
||||
i686_fdc_send_cmd(i686_FDC_CMD_CALIBRATE);
|
||||
i686_fdc_send_cmd(drive);
|
||||
wait_irq();
|
||||
i686_fdc_check_int(&st0, &cyl);
|
||||
|
||||
if(!cyl){
|
||||
i686_fdc_motor(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i686_fdc_motor(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i686_fdc_seek(uint32_t cyl, uint32_t head){
|
||||
uint32_t st0, cyl0;
|
||||
|
||||
if(g_curr_drive > 3) return -2;
|
||||
|
||||
for(int i = 0; i < 10; i++){
|
||||
// Send the command
|
||||
i686_fdc_send_cmd(i686_FDC_CMD_SEEK);
|
||||
i686_fdc_send_cmd(head << 2 | g_curr_drive);
|
||||
i686_fdc_send_cmd(cyl);
|
||||
|
||||
// Wait for the results
|
||||
wait_irq();
|
||||
i686_fdc_check_int(&st0, &cyl0);
|
||||
|
||||
// Found?
|
||||
if(cyl0 == cyl) return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void i686_fdc_disable(){
|
||||
i686_outb(i686_FDC_DOR, 0);
|
||||
}
|
||||
|
||||
void i686_fdc_enable(){
|
||||
i686_outb(i686_FDC_DOR, i686_FDC_DOR_RESET | i686_FDC_DOR_DMA);
|
||||
}
|
||||
|
||||
void i686_fdc_reset(){
|
||||
uint32_t st0, cyl;
|
||||
|
||||
// Reset the controller
|
||||
i686_fdc_disable();
|
||||
i686_fdc_enable();
|
||||
wait_irq();
|
||||
|
||||
// CHECK_INT to all drives
|
||||
for(int i = 0; i < 4; i++) i686_fdc_check_int(&st0, &cyl);
|
||||
|
||||
// 500kb/s
|
||||
i686_fdc_write_ccr(0);
|
||||
|
||||
// steprate = 3ms, unload time = 240ms, load time = 16ms, dma = true
|
||||
i686_fdc_drive_data(3, 16, 240, true);
|
||||
|
||||
// Calibrate the disk
|
||||
i686_fdc_calibrate(g_curr_drive);
|
||||
}
|
||||
|
||||
void i686_fdc_set_working_drive(int drive){
|
||||
if(drive < 4) g_curr_drive = drive;
|
||||
}
|
||||
|
||||
void i686_fdc_initialize(){
|
||||
debug_printf("[FDC] Initializing\n");
|
||||
// Setup IRQ
|
||||
i686_isr_register_handler(IRQ(6), i686_fdc_irq);
|
||||
|
||||
// Initialize DMA
|
||||
i686_fdc_initialize_dma();
|
||||
|
||||
// Reset FDC
|
||||
i686_fdc_reset();
|
||||
|
||||
// Set drive info
|
||||
i686_fdc_drive_data(13, 1, 0x0F, true);
|
||||
}
|
70
src/kernel/arch/i686/fdc.h
Normal file
70
src/kernel/arch/i686/fdc.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define i686_FDC_DOR 0x3F2
|
||||
#define i686_FDC_MSR 0x3F4
|
||||
#define i686_FDC_FIFO 0x3F5
|
||||
#define i686_FDC_CTRL 0x3F7
|
||||
#define i686_FDC_DOR_DRIVE0 0x00
|
||||
#define i686_FDC_DOR_DRIVE1 0x01
|
||||
#define i686_FDC_DOR_DRIVE2 0x02
|
||||
#define i686_FDC_DOR_DRIVE3 0x03
|
||||
#define i686_FDC_DOR_RESET 0x04
|
||||
#define i686_FDC_DOR_DMA 0x08
|
||||
#define i686_FDC_DOR_DRIVE0_MOTOR 0x10
|
||||
#define i686_FDC_DOR_DRIVE1_MOTOR 0x20
|
||||
#define i686_FDC_DOR_DRIVE2_MOTOR 0x40
|
||||
#define i686_FDC_DOR_DRIVE3_MOTOR 0x80
|
||||
#define i686_FDC_MSR_DRIVE0_POS_MODE 0x01
|
||||
#define i686_FDC_MSR_DRIVE1_POS_MODE 0x02
|
||||
#define i686_FDC_MSR_DRIVE2_POS_MODE 0x04
|
||||
#define i686_FDC_MSR_DRIVE3_POS_MODE 0x08
|
||||
#define i686_FDC_MSR_BUSY 0x10
|
||||
#define i686_FDC_MSR_DMA 0x20
|
||||
#define i686_FDC_MSR_DATAIO 0x40
|
||||
#define i686_FDC_MSR_DATAREG 0x80
|
||||
#define i686_FDC_CMD_READ_TRACK 0x02
|
||||
#define i686_FDC_CMD_SPECIFY 0x03
|
||||
#define i686_FDC_CMD_CHECK_STAT 0x04
|
||||
#define i686_FDC_CMD_WRITE_SECT 0x05
|
||||
#define i686_FDC_CMD_READ_SECT 0x06
|
||||
#define i686_FDC_CMD_CALIBRATE 0x07
|
||||
#define i686_FDC_CMD_CHECK_INT 0x08
|
||||
#define i686_FDC_CMD_WRITE_DEL_S 0x09
|
||||
#define i686_FDC_CMD_READ_ID_S 0x0A
|
||||
#define i686_FDC_CMD_READ_DEL_S 0x0C
|
||||
#define i686_FDC_CMD_FORMAT_TRACK 0x0D
|
||||
#define i686_FDC_CMD_SEEK 0x0F
|
||||
#define i686_FDC_CMD_EXT_SKIP 0x20
|
||||
#define i686_FDC_CMD_EXT_DENSITY 0x40
|
||||
#define i686_FDC_CMD_EXT_MULTITRACK 0x80
|
||||
#define i686_FDC_GAP3_STD 42
|
||||
#define i686_FDC_GAP3_5_14 32
|
||||
#define i686_FDC_GAP3_3_5 27
|
||||
#define i686_FDC_SECTOR_DTL_128 0
|
||||
#define i686_FDC_SECTOR_DTL_256 1
|
||||
#define i686_FDC_SECTOR_DTL_512 2
|
||||
#define i686_FDC_SECTOR_DTL_1024 4
|
||||
#define i686_FDC_SECTORS_PER_TRACK 18
|
||||
|
||||
void i686_fdc_initialize_dma();
|
||||
void i686_fdc_dma_read();
|
||||
void i686_fdc_dma_write();
|
||||
uint8_t i686_fdc_msr_read();
|
||||
void i686_fdc_send_cmd(uint8_t cmd);
|
||||
uint8_t i686_fdc_read_data();
|
||||
void i686_fdc_write_ccr(uint8_t v);
|
||||
void i686_fdc_drive_data(uint32_t stepr, uint32_t loadt, uint32_t unloadt, bool dma);
|
||||
void i686_fdc_check_int(uint32_t *st0, uint32_t *cyl);
|
||||
int i686_fdc_motor(bool b);
|
||||
void i686_fdc_read_sector_imp(uint8_t head, uint8_t track, uint8_t sector);
|
||||
uint8_t *i686_fdc_read_sector(int lba);
|
||||
int i686_fdc_calibrate(uint32_t drive);
|
||||
int i686_fdc_seek(uint32_t cyl, uint32_t head);
|
||||
void i686_fdc_disable();
|
||||
void i686_fdc_enable();
|
||||
void i686_fdc_reset();
|
||||
void i686_fdc_set_working_drive(int drive);
|
||||
void i686_fdc_initialize();
|
19
src/kernel/arch/i686/pit.c
Normal file
19
src/kernel/arch/i686/pit.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "pit.h"
|
||||
#include "isr.h"
|
||||
#include "../../lib/stdio.h"
|
||||
#include "../../lib/debug.h"
|
||||
|
||||
static volatile uint32_t g_tick_count = 0;
|
||||
|
||||
static void i686_pit_handler(registers *regs){
|
||||
g_tick_count++;
|
||||
}
|
||||
|
||||
void i686_pit_initialize(){
|
||||
debug_printf("[PIT] Initializing\n");
|
||||
i686_isr_register_handler(IRQ(0), i686_pit_handler);
|
||||
}
|
||||
|
||||
uint32_t i686_pit_get_tick_count(){
|
||||
return g_tick_count;
|
||||
}
|
6
src/kernel/arch/i686/pit.h
Normal file
6
src/kernel/arch/i686/pit.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void i686_pit_initialize();
|
||||
uint32_t i686_pit_get_tick_count();
|
|
@ -11,54 +11,66 @@
|
|||
static bool g_caps_lock = false;
|
||||
static bool g_shift = false;
|
||||
|
||||
static char g_key_buffer[256];
|
||||
static struct {
|
||||
char buffer[KEY_BUFFER_LENGTH];
|
||||
int base;
|
||||
int top;
|
||||
} g_key_buffer;
|
||||
|
||||
void keyboard_buffer_add(char c){
|
||||
g_key_buffer.buffer[g_key_buffer.top] = c;
|
||||
g_key_buffer.top++;
|
||||
g_key_buffer.top %= KEY_BUFFER_LENGTH;
|
||||
}
|
||||
|
||||
char keyboard_buffer_get(){
|
||||
char c = g_key_buffer.buffer[g_key_buffer.base];
|
||||
g_key_buffer.base++;
|
||||
g_key_buffer.base %= KEY_BUFFER_LENGTH;
|
||||
return c;
|
||||
}
|
||||
|
||||
int keyboard_buffer_length(){
|
||||
int base = g_key_buffer.base;
|
||||
int top = g_key_buffer.top;
|
||||
if(top < base) top += KEY_BUFFER_LENGTH;
|
||||
return top - base;
|
||||
}
|
||||
|
||||
static const char g_sc_ascii[128] = {
|
||||
'?', '?', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', '?', '?',
|
||||
'7', '8', '9', '0', '-', '=', '\b', '?',
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
'o', 'p', '[', ']', '?', '?', 'a', 's',
|
||||
'o', 'p', '[', ']', '\n', '?', 'a', 's',
|
||||
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
'\'', '`', '?', '\\', 'z', 'x', 'c', 'v',
|
||||
'b', 'n', 'm', ',', '.', '/', '?', '?',
|
||||
'?', ' '
|
||||
};
|
||||
|
||||
static void user_input(char *str){
|
||||
shell_run(str);
|
||||
}
|
||||
|
||||
static void keyboard_callback(){
|
||||
uint8_t scancode = i686_inb(0x60);
|
||||
if(scancode == 0x2A) g_shift = true; // Shift pressed
|
||||
else if(scancode == 0x2A + 128) g_shift = false; // Shift released
|
||||
else if(scancode == 0x3A) g_caps_lock = !g_caps_lock; // Caps lock pressed
|
||||
else if(scancode < 128){ // If it's a "pressed" event, not "released"
|
||||
if(scancode == 0x0E){ // Backspace
|
||||
putc('\b');
|
||||
g_key_buffer[strlen(g_key_buffer)-1] = '\0';
|
||||
}
|
||||
else if(scancode == 0x1C){ // Enter
|
||||
putc('\n');
|
||||
user_input(g_key_buffer);
|
||||
g_key_buffer[0] = '\0';
|
||||
}
|
||||
else{
|
||||
char c = g_sc_ascii[scancode];
|
||||
if(c >= 'a' && c <= 'z' && g_shift != g_caps_lock) c += 'A' - 'a';
|
||||
putc(c);
|
||||
char c = g_sc_ascii[scancode];
|
||||
if(c >= 'a' && c <= 'z' && g_shift != g_caps_lock) c += 'A' - 'a';
|
||||
|
||||
// strlen() works here because char[] is the same as
|
||||
// char*, and both are null-terminated, so they are
|
||||
// exactly the same
|
||||
int len = strlen(g_key_buffer);
|
||||
g_key_buffer[len] = c;
|
||||
g_key_buffer[len+1] = '\0';
|
||||
}
|
||||
// strlen() works here because char[] is the same as
|
||||
// char*, and both are null-terminated, so they are
|
||||
// exactly the same
|
||||
keyboard_buffer_add(c);
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_initialize(){
|
||||
debug_printf("[KEYBOARD] Initializing keyboard\n");
|
||||
debug_printf("[KEYBOARD] Initializing\n");
|
||||
|
||||
// Setup IRQ
|
||||
i686_isr_register_handler(IRQ(1), keyboard_callback);
|
||||
|
||||
// Initialize key buffer
|
||||
g_key_buffer.base = 0;
|
||||
g_key_buffer.top = 0;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define KEY_BUFFER_LENGTH 16
|
||||
|
||||
char keyboard_buffer_get();
|
||||
int keyboard_buffer_length();
|
||||
void keyboard_initialize();
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#include "timer.h"
|
||||
#include "../arch/i686/isr.h"
|
||||
#include "../lib/stdio.h"
|
||||
#include "../lib/debug.h"
|
||||
|
||||
static void timer_handler(registers *regs){
|
||||
//printf("TICK\n");
|
||||
}
|
||||
|
||||
void timer_initialize(){
|
||||
debug_printf("[TIMER] Initializing PIT\n");
|
||||
i686_isr_register_handler(IRQ(0), timer_handler);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
void timer_initialize();
|
|
@ -2,9 +2,15 @@
|
|||
#include "../arch/i686/gdt.h"
|
||||
#include "../arch/i686/idt.h"
|
||||
#include "../arch/i686/isr.h"
|
||||
#include "../arch/i686/pit.h"
|
||||
|
||||
void hal_initialize(){
|
||||
i686_gdt_initialize();
|
||||
i686_idt_initialize();
|
||||
i686_isr_initialize();
|
||||
i686_pit_initialize();
|
||||
}
|
||||
|
||||
uint32_t hal_get_tick_count(){
|
||||
return i686_pit_get_tick_count();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void hal_initialize();
|
||||
uint32_t hal_get_tick_count();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "stdio.h"
|
||||
#include "../drivers/vga.h"
|
||||
#include "../drivers/uart.h"
|
||||
#include "../drivers/keyboard.h"
|
||||
|
||||
typedef void (*print_callable_fn_t)(char);
|
||||
|
||||
|
@ -128,6 +129,34 @@ void serial_printf(char *fmt, ...){
|
|||
_vprintf(serial_putc, fmt, args);
|
||||
}
|
||||
|
||||
void gets(char *str, int max){
|
||||
int count = 0;
|
||||
str[0] = '\0';
|
||||
|
||||
for(;;){
|
||||
if(keyboard_buffer_length()){
|
||||
char c = keyboard_buffer_get();
|
||||
if(c == '\n'){
|
||||
putc(c);
|
||||
return;
|
||||
}
|
||||
else if(c == '\b'){
|
||||
if(count){
|
||||
putc(c);
|
||||
str[count--] = '\0';
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(count < max){
|
||||
putc(c);
|
||||
str[count] = c;
|
||||
str[++count] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_screen(){
|
||||
vga_fill_screen(' ', VGA_COLOR_BG_BLACK | VGA_COLOR_FG_WHITE);
|
||||
vga_set_cursor(0);
|
||||
|
|
|
@ -9,4 +9,5 @@ void vprintf(char *fmt, va_list args);
|
|||
void printf(char *fmt, ...);
|
||||
void serial_vprintf(char *fmt, va_list args);
|
||||
void serial_printf(char *fmt, ...);
|
||||
void gets(char *str, int max);
|
||||
void clear_screen();
|
||||
|
|
|
@ -17,3 +17,14 @@ void strcpy(char *dest, char *src){
|
|||
}
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
int atoi(char *str){
|
||||
int res = 0;
|
||||
|
||||
for(int i = 0; i < strlen(str); i++){
|
||||
res *= 10;
|
||||
res += str[i] - '0';
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
int strlen(char *s);
|
||||
int strcmp(char *s1, char *s2);
|
||||
void strcpy(char *dest, char *src);
|
||||
int atoi(char *str);
|
||||
|
|
8
src/kernel/lib/time.c
Normal file
8
src/kernel/lib/time.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <stdint.h>
|
||||
#include "time.h"
|
||||
#include "../hal/hal.h"
|
||||
|
||||
void sleep(int ms){
|
||||
uint32_t ticks = ms + hal_get_tick_count();
|
||||
while(ticks > hal_get_tick_count());
|
||||
}
|
3
src/kernel/lib/time.h
Normal file
3
src/kernel/lib/time.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void sleep(int ms);
|
|
@ -1,7 +1,6 @@
|
|||
#include <stdint.h>
|
||||
#include "lib/stdio.h"
|
||||
#include "hal/hal.h"
|
||||
#include "drivers/timer.h"
|
||||
#include "drivers/keyboard.h"
|
||||
#include "drivers/uart.h"
|
||||
#include "fs/vfs.h"
|
||||
|
@ -9,6 +8,7 @@
|
|||
#include "arch/i686/mm/vmm.h"
|
||||
#include "multiboot.h"
|
||||
#include "lib/debug.h"
|
||||
#include "arch/i686/fdc.h"
|
||||
|
||||
extern uint8_t end; // Kernel end
|
||||
|
||||
|
@ -23,7 +23,6 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
|||
uart_initialize(COM1, 2);
|
||||
|
||||
// Initialize drivers
|
||||
timer_initialize();
|
||||
keyboard_initialize();
|
||||
|
||||
// Initialize physical memory manager
|
||||
|
@ -31,6 +30,8 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
|||
|
||||
i686_pmm_initialize(mem_size, (int)(&end));
|
||||
|
||||
// Memory map
|
||||
debug_printf("= Memory map =\n");
|
||||
for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){
|
||||
multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i);
|
||||
debug_printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
||||
|
@ -45,8 +46,17 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
|||
// Initialize virtual memory
|
||||
i686_vmm_initialize();
|
||||
|
||||
// Floppy disk controller
|
||||
i686_fdc_set_working_drive(0);
|
||||
i686_fdc_initialize();
|
||||
|
||||
// Initialize FS
|
||||
vfs_initialize();
|
||||
|
||||
// Run shell
|
||||
shell();
|
||||
|
||||
// Halt at end
|
||||
debug_printf("Kernel execution ended\n");
|
||||
for(;;);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include <stdint.h>
|
||||
#include "shell.h"
|
||||
#include "lib/stdio.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/memory.h"
|
||||
#include "lib/time.h"
|
||||
#include "arch/i686/fdc.h"
|
||||
|
||||
int shell_run(char *cmd){
|
||||
int ret = 0;
|
||||
|
@ -19,6 +22,35 @@ int shell_run(char *cmd){
|
|||
else if(!strcmp(cmd, "serial")){
|
||||
serial_printf("Hello world!\n");
|
||||
}
|
||||
else if(!strcmp(cmd, "sleep")){
|
||||
printf("Sleeping...\n");
|
||||
sleep(25);
|
||||
printf("Done!\n");
|
||||
}
|
||||
else if(!strcmp(cmd, "readsect")){
|
||||
puts("Sector number: ");
|
||||
char secn_str[4];
|
||||
gets(secn_str, 3);
|
||||
int secn = atoi(secn_str);
|
||||
|
||||
uint8_t *sector = i686_fdc_read_sector(secn);
|
||||
|
||||
if(sector){
|
||||
int i = 0;
|
||||
for(int c = 0; c < 4; c++){
|
||||
for(int j = 0; j < 128; j++){
|
||||
printf("0x%x ", sector[i+j]);
|
||||
}
|
||||
i += 128;
|
||||
printf("\nPress enter to continue\n");
|
||||
gets(NULL, NULL);
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("ERROR reading sector %i from disk", secn);
|
||||
}
|
||||
printf("Done!\n");
|
||||
}
|
||||
else{
|
||||
printf("SHELL: Unknown command \"%s\"\n", cmd);
|
||||
ret = 127;
|
||||
|
@ -27,3 +59,14 @@ int shell_run(char *cmd){
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void shell(){
|
||||
puts("\x1b[33mWelcome to quark!\x1b[0m\n\n");
|
||||
|
||||
for(;;){
|
||||
static char cmd_buffer[256];
|
||||
puts("$>");
|
||||
gets(cmd_buffer, 255);
|
||||
shell_run(cmd_buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
int shell_run();
|
||||
void shell();
|
||||
|
|
Loading…
Referencia en una nova incidència