Add drivers/pit.c by 3Hren.
This commit is contained in:
parent
703ddafc34
commit
c84d214daa
2
Makefile
2
Makefile
@ -76,7 +76,7 @@ image.bin: mbr.bin fs.img
|
|||||||
|
|
||||||
kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \
|
kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \
|
||||||
drivers/ata.o cpu/vectors.o cpu/idt.o cpu/gdt.o drivers/uart.o \
|
drivers/ata.o cpu/vectors.o cpu/idt.o cpu/gdt.o drivers/uart.o \
|
||||||
fs/fs.o lib/mem.o lib/string.o proc.o cpu/swtch.o
|
fs/fs.o lib/mem.o lib/string.o proc.o cpu/swtch.o drivers/pit.o
|
||||||
$(LD) $(LDFLAGS) $(LDKERNELFLAGS) -o $@ -Ttext 0x1000 $^
|
$(LD) $(LDFLAGS) $(LDKERNELFLAGS) -o $@ -Ttext 0x1000 $^
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
|
|||||||
76
drivers/pit.c
Normal file
76
drivers/pit.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include "pit.h"
|
||||||
|
#include "port.h"
|
||||||
|
#include "../cpu/isr.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PIT_CRYSTAL_HZ = 1193182,
|
||||||
|
|
||||||
|
CLOCK_PRECISION_HZ = 100,
|
||||||
|
|
||||||
|
PIT_PROGRAM_REG = PIT_CRYSTAL_HZ / CLOCK_PRECISION_HZ,
|
||||||
|
|
||||||
|
PIT_SELECT_CHANNEL0 = 0x0,
|
||||||
|
PIT_SELECT_CHANNEL1 = 0x1,
|
||||||
|
PIT_SELECT_CHANNEL2 = 0x2,
|
||||||
|
PIT_SELECT_CHANNEL_RB = 0x3,
|
||||||
|
PIT_ACCESS_MODE_LATCH_COUNT_VALUE_COMMAND = 0x0,
|
||||||
|
PIT_ACCESS_MODE_LOBYTE_ONLY = 0x1,
|
||||||
|
PIT_ACCESS_MODE_HIBYTE_ONLY = 0x2,
|
||||||
|
PIT_ACCESS_MODE_LOHIBYTE = 0x3,
|
||||||
|
PIT_MODE_INTERRUPT_ON_TERMINAL_COUNT = 0x0,
|
||||||
|
PIT_MODE_HW_ONESHOT = 0x1,
|
||||||
|
PIT_MODE_RATE_GENERATOR = 0x2,
|
||||||
|
PIT_MODES_SQUARE_WAVE_GENERATOR = 0x3,
|
||||||
|
PIT_MODES_SW_TRIGGERRED_STROBE = 0x4,
|
||||||
|
PIT_MODES_HW_TRIGGERRED_STROBE = 0x5,
|
||||||
|
};
|
||||||
|
|
||||||
|
static timer_callback callbacks[100];
|
||||||
|
static int registered_callbacks = 0;
|
||||||
|
|
||||||
|
void add_timer_callback(timer_callback tc) {
|
||||||
|
callbacks[registered_callbacks++] = tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_interrupt_handler(registers_t *r) {
|
||||||
|
for (int i = 0; i < registered_callbacks; ++i) {
|
||||||
|
callbacks[i]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pit_command_t {
|
||||||
|
unsigned char bcd : 1;
|
||||||
|
unsigned char operating_mode : 3;
|
||||||
|
unsigned char access_mode : 2;
|
||||||
|
unsigned char select_channel : 2;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static void dec_sleep_counter(void);
|
||||||
|
|
||||||
|
void init_pit() {
|
||||||
|
struct pit_command_t cmd = {
|
||||||
|
.select_channel = PIT_SELECT_CHANNEL0,
|
||||||
|
.access_mode = PIT_ACCESS_MODE_LOHIBYTE,
|
||||||
|
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
|
||||||
|
.bcd = 0,
|
||||||
|
};
|
||||||
|
port_byte_out(0x43, *(unsigned char *)(&cmd));
|
||||||
|
port_byte_out(0x40, PIT_PROGRAM_REG & 0xff);
|
||||||
|
port_byte_out(0x40, (PIT_PROGRAM_REG & 0xff00) >> 8);
|
||||||
|
|
||||||
|
register_interrupt_handler(IRQ0, timer_interrupt_handler);
|
||||||
|
add_timer_callback(dec_sleep_counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sleep_counter = 0;
|
||||||
|
|
||||||
|
static void dec_sleep_counter(void) {
|
||||||
|
sleep_counter--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void msleep(int ms) {
|
||||||
|
sleep_counter = ms / 10;
|
||||||
|
while (sleep_counter > 0) {
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
8
drivers/pit.h
Normal file
8
drivers/pit.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef void (*timer_callback)(void);
|
||||||
|
|
||||||
|
void init_pit(void);
|
||||||
|
void add_timer_callback(timer_callback tc);
|
||||||
|
|
||||||
|
void msleep(int ms);
|
||||||
7
kernel.c
7
kernel.c
@ -7,6 +7,7 @@ asm(".asciz \"kernel start\\n\"");
|
|||||||
#include "drivers/vga.h"
|
#include "drivers/vga.h"
|
||||||
#include "drivers/ata.h"
|
#include "drivers/ata.h"
|
||||||
#include "drivers/misc.h"
|
#include "drivers/misc.h"
|
||||||
|
#include "drivers/pit.h"
|
||||||
#include "drivers/uart.h"
|
#include "drivers/uart.h"
|
||||||
#include "fs/fs.h"
|
#include "fs/fs.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
@ -16,6 +17,7 @@ asm(".asciz \"kernel start\\n\"");
|
|||||||
void _start() {
|
void _start() {
|
||||||
load_gdt();
|
load_gdt();
|
||||||
init_keyboard();
|
init_keyboard();
|
||||||
|
init_pit();
|
||||||
uartinit();
|
uartinit();
|
||||||
load_idt();
|
load_idt();
|
||||||
sti();
|
sti();
|
||||||
@ -35,6 +37,11 @@ void _start() {
|
|||||||
if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') {
|
if (kbd_buf_size > 0 && kbd_buf[kbd_buf_size-1] == '\n') {
|
||||||
if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) {
|
if (!strncmp("halt\n", kbd_buf, kbd_buf_size)) {
|
||||||
qemu_shutdown();
|
qemu_shutdown();
|
||||||
|
} else if (!strncmp("work\n", kbd_buf, kbd_buf_size)) {
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
msleep(1000);
|
||||||
|
printk(".");
|
||||||
|
}
|
||||||
} else if (!strncmp("run ", kbd_buf, 4)) {
|
} else if (!strncmp("run ", kbd_buf, 4)) {
|
||||||
kbd_buf[kbd_buf_size-1] = '\0';
|
kbd_buf[kbd_buf_size-1] = '\0';
|
||||||
const char* cmd = kbd_buf + 4;
|
const char* cmd = kbd_buf + 4;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user