Add a driver for Intel 8253-compatible PIT (#93)

This commit is contained in:
Alex Kotov 2022-06-24 05:10:59 +03:00 committed by GitHub
parent a71618b258
commit f714df3ba8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 53 deletions

View File

@ -56,17 +56,6 @@ if ASM_X86_64
libkernaux_la_SOURCES += src/asm/x86_64.S
endif
###########
# Drivers #
###########
if WITH_DRIVERS
libkernaux_la_SOURCES += \
src/drivers/console.c \
src/drivers/framebuffer.c \
src/drivers/intel_8259_pic.c
endif
####################
# Default packages #
####################
@ -115,3 +104,26 @@ endif
if WITH_UNITS
libkernaux_la_SOURCES += src/units.c
endif
###########
# Drivers #
###########
if WITH_DRIVERS
libkernaux_la_SOURCES += \
src/drivers/console.c \
src/drivers/framebuffer.c
# Intel 8253-compatible programmable interval timer
if ASM_I386
libkernaux_la_SOURCES += src/drivers/intel_8253_pit.c
endif
# Intel 8259-compatible programmable interrupt controller
if ASM_I386
libkernaux_la_SOURCES += src/drivers/intel_8259_pic.c
endif
endif # WITH_DRIVERS

View File

@ -90,7 +90,8 @@ zero). Work-in-progress APIs can change at any time.
* Device drivers (for debugging only)
* [Serial console](/include/kernaux/drivers/console.h) (*work in progress*)
* [Framebuffer](/include/kernaux/drivers/framebuffer.h) (*planned*)
* [Intel 8259 PIC](/include/kernaux/drivers/intel_8259_pic.h) (*planned*)
* [Intel 8253-compatible PIT](/include/kernaux/drivers/intel_8253_pit.h) (*work in progress*)
* [Intel 8259-compatible PIC](/include/kernaux/drivers/intel_8259_pic.h) (*work in progress*)
* USB (*planned*)
### Definitions

View File

@ -27,17 +27,6 @@ if ASM_X86_64
nobase_include_HEADERS += kernaux/asm/x86_64.h
endif
###########
# Drivers #
###########
if WITH_DRIVERS
nobase_include_HEADERS += \
kernaux/drivers/console.h \
kernaux/drivers/framebuffer.h \
kernaux/drivers/intel_8259_pic.h
endif
####################
# Default packages #
####################
@ -78,3 +67,26 @@ endif
if WITH_UNITS
nobase_include_HEADERS += kernaux/units.h
endif
###########
# Drivers #
###########
if WITH_DRIVERS
nobase_include_HEADERS += \
kernaux/drivers/console.h \
kernaux/drivers/framebuffer.h
# Intel 8253-compatible programmable interval timer
if ASM_I386
nobase_include_HEADERS += kernaux/drivers/intel_8253_pit.h
endif
# Intel 8259-compatible programmable interrupt controller
if ASM_I386
nobase_include_HEADERS += kernaux/drivers/intel_8259_pic.h
endif
endif # WITH_DRIVERS

View File

@ -0,0 +1,21 @@
/**
* @brief A driver for Intel 8253-compatible programmable interval timer
*
* @see https://en.wikipedia.org/wiki/Intel_8253
* @see https://wiki.osdev.org/PIT
*/
#ifndef KERNAUX_INCLUDED_DRIVERS_INTEL_8253_PIT
#define KERNAUX_INCLUDED_DRIVERS_INTEL_8253_PIT
#ifdef __cplusplus
extern "C" {
#endif
void kernaux_drivers_intel_8253_pit_initialize(unsigned int freq);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,31 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <kernaux/assert.h>
#include <kernaux/drivers/intel_8253_pit.h>
#ifdef ASM_I386
#include <kernaux/asm/i386.h>
#endif
#include <stdint.h>
#if defined(ASM_I386)
# define inportb kernaux_asm_i386_inportb
# define outportb kernaux_asm_i386_outportb
#endif
void kernaux_drivers_intel_8253_pit_initialize(const unsigned int freq)
{
KERNAUX_ASSERT(freq);
const unsigned int divisor = 1193180 / freq;
const uint8_t l = divisor & 0xff;
const uint8_t h = (divisor >> 8) & 0xff;
outportb(0x43, 0x36);
outportb(0x40, l);
outportb(0x40, h);
}

View File

@ -21,10 +21,7 @@
#define IRQS_COUNT 8
#define IRQS_TOTAL 16
#undef AVAILABLE
#define NOT_AVAILABLE_MSG "Intel 8259-compatible PIC is not available"
#ifdef ASM_I386
# define AVAILABLE
#if defined(ASM_I386)
# define inportb kernaux_asm_i386_inportb
# define outportb kernaux_asm_i386_outportb
#endif
@ -34,30 +31,18 @@ static unsigned char slave_start = 8;
void kernaux_drivers_intel_8259_pic_enable_all()
{
#ifndef AVAILABLE
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
outportb(MASTER_DATA_PORT, 0);
outportb(SLAVE_DATA_PORT, 0);
#endif
}
void kernaux_drivers_intel_8259_pic_disable_all()
{
#ifndef AVAILABLE
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
outportb(MASTER_DATA_PORT, 0xFF);
outportb(SLAVE_DATA_PORT, 0xFF);
#endif
}
void kernaux_drivers_intel_8259_pic_enable(const unsigned char number)
{
#ifndef AVAILABLE
(void)number;
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
KERNAUX_ASSERT(number < IRQS_TOTAL);
if (number < IRQS_COUNT) {
@ -67,15 +52,10 @@ void kernaux_drivers_intel_8259_pic_enable(const unsigned char number)
const uint8_t mask = inportb(SLAVE_DATA_PORT);
outportb(SLAVE_DATA_PORT, mask & ~(1 << (number - IRQS_COUNT)));
}
#endif
}
void kernaux_drivers_intel_8259_pic_disable(const unsigned char number)
{
#ifndef AVAILABLE
(void)number;
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
KERNAUX_ASSERT(number < IRQS_TOTAL);
if (number < IRQS_COUNT) {
@ -85,16 +65,12 @@ void kernaux_drivers_intel_8259_pic_disable(const unsigned char number)
const uint8_t mask = inportb(SLAVE_DATA_PORT);
outportb(SLAVE_DATA_PORT, mask | (1 << (number - IRQS_COUNT)));
}
#endif
}
void kernaux_drivers_intel_8259_pic_remap(
const unsigned char new_master_start,
const unsigned char new_slave_start
) {
#ifndef AVAILABLE
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
master_start = new_master_start;
slave_start = new_slave_start;
@ -121,14 +97,10 @@ void kernaux_drivers_intel_8259_pic_remap(
// Restore masks
outportb(MASTER_DATA_PORT, master_mask);
outportb(SLAVE_DATA_PORT, slave_mask);
#endif
}
void kernaux_drivers_intel_8259_pic_eoi(const unsigned char number)
{
#ifndef AVAILABLE
KERNAUX_PANIC(NOT_AVAILABLE_MSG);
#else
KERNAUX_ASSERT(number < IRQS_TOTAL);
const bool to_slave =
@ -138,5 +110,4 @@ void kernaux_drivers_intel_8259_pic_eoi(const unsigned char number)
if (to_slave) outportb(SLAVE_COMMAND_PORT, 0x20);
if (to_master) outportb(MASTER_COMMAND_PORT, 0x20);
#endif
}