From f714df3ba8cc986ab4e49330f9746587c1a72bf6 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Fri, 24 Jun 2022 05:10:59 +0300 Subject: [PATCH] Add a driver for Intel 8253-compatible PIT (#93) --- Makefile.am | 34 ++++++++++++++++-------- README.md | 3 ++- include/Makefile.am | 34 ++++++++++++++++-------- include/kernaux/drivers/intel_8253_pit.h | 21 +++++++++++++++ src/drivers/intel_8253_pit.c | 31 +++++++++++++++++++++ src/drivers/intel_8259_pic.c | 31 +-------------------- 6 files changed, 101 insertions(+), 53 deletions(-) create mode 100644 include/kernaux/drivers/intel_8253_pit.h create mode 100644 src/drivers/intel_8253_pit.c diff --git a/Makefile.am b/Makefile.am index b598499..6e192c4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/README.md b/README.md index fb9f993..8e68956 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/include/Makefile.am b/include/Makefile.am index 24cf1e3..8781819 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -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 diff --git a/include/kernaux/drivers/intel_8253_pit.h b/include/kernaux/drivers/intel_8253_pit.h new file mode 100644 index 0000000..1f0bdce --- /dev/null +++ b/include/kernaux/drivers/intel_8253_pit.h @@ -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 diff --git a/src/drivers/intel_8253_pit.c b/src/drivers/intel_8253_pit.c new file mode 100644 index 0000000..58abccb --- /dev/null +++ b/src/drivers/intel_8253_pit.c @@ -0,0 +1,31 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef ASM_I386 +#include +#endif + +#include + +#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); +} diff --git a/src/drivers/intel_8259_pic.c b/src/drivers/intel_8259_pic.c index 37a00eb..39d0bc1 100644 --- a/src/drivers/intel_8259_pic.c +++ b/src/drivers/intel_8259_pic.c @@ -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 }