mirror of
				https://github.com/tailix/drivers.git
				synced 2025-10-30 23:17:04 -04:00 
			
		
		
		
	Add existing drivers
This commit is contained in:
		
							parent
							
								
									b3dcc54312
								
							
						
					
					
						commit
						d0fc1ca09f
					
				
					 10 changed files with 339 additions and 2 deletions
				
			
		
							
								
								
									
										16
									
								
								Makefile.am
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								Makefile.am
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -8,4 +8,18 @@ SUBDIRS = include
 | 
			
		|||
lib_LTLIBRARIES = libdrivers.la
 | 
			
		||||
 | 
			
		||||
libdrivers_la_SOURCES = \
 | 
			
		||||
	src/foobar.c
 | 
			
		||||
	src/foobar.c \
 | 
			
		||||
	src/console.c \
 | 
			
		||||
	src/shutdown.c
 | 
			
		||||
 | 
			
		||||
# Intel 8253-compatible programmable interval timer
 | 
			
		||||
 | 
			
		||||
if ASM_I386
 | 
			
		||||
libdrivers_la_SOURCES += src/intel_8253_pit.c
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# Intel 8259-compatible programmable interrupt controller
 | 
			
		||||
 | 
			
		||||
if ASM_I386
 | 
			
		||||
libdrivers_la_SOURCES += src/intel_8259_pic.c
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,16 @@
 | 
			
		|||
nobase_include_HEADERS = \
 | 
			
		||||
	drivers.h
 | 
			
		||||
	drivers.h \
 | 
			
		||||
	drivers/console.h \
 | 
			
		||||
	drivers/shutdown.h
 | 
			
		||||
 | 
			
		||||
# Intel 8253-compatible programmable interval timer
 | 
			
		||||
 | 
			
		||||
if ASM_I386
 | 
			
		||||
nobase_include_HEADERS += drivers/intel_8253_pit.h
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# Intel 8259-compatible programmable interrupt controller
 | 
			
		||||
 | 
			
		||||
if ASM_I386
 | 
			
		||||
nobase_include_HEADERS += drivers/intel_8259_pic.h
 | 
			
		||||
endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								include/drivers/console.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/drivers/console.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
#ifndef INCLUDED_DRIVERS_CONSOLE
 | 
			
		||||
#define INCLUDED_DRIVERS_CONSOLE
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
void drivers_console_putc(char c);
 | 
			
		||||
 | 
			
		||||
void drivers_console_print(const char *s);
 | 
			
		||||
void drivers_console_puts(const char *s);
 | 
			
		||||
void drivers_console_write(const char *data, size_t size);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										21
									
								
								include/drivers/intel_8253_pit.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/drivers/intel_8253_pit.h
									
										
									
									
									
										Normal 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 DRIVERS_INCLUDED_INTEL_8253_PIT
 | 
			
		||||
#define DRIVERS_INCLUDED_INTEL_8253_PIT
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8253_pit_initialize(unsigned int freq);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										57
									
								
								include/drivers/intel_8259_pic.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								include/drivers/intel_8259_pic.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
/**
 | 
			
		||||
 * @brief A driver for Intel 8259-compatible programmable interrupt controller
 | 
			
		||||
 *
 | 
			
		||||
 * @details
 | 
			
		||||
 * This is not a driver for a random Intel 8259-compatible PIC, but only for a
 | 
			
		||||
 * typical configuration of it that can be found in most PCs.
 | 
			
		||||
 *
 | 
			
		||||
 * @see https://en.wikipedia.org/wiki/Intel_8259
 | 
			
		||||
 * @see https://wiki.osdev.org/8259_PIC
 | 
			
		||||
 * @see https://pdos.csail.mit.edu/6.828/2005/readings/hardware/8259A.pdf
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DRIVERS_INCLUDED_INTEL_8259_PIC
 | 
			
		||||
#define DRIVERS_INCLUDED_INTEL_8259_PIC
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enable PIC
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_enable_all();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable PIC
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_disable_all();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Enable single IRQ line
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_enable(unsigned char number);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Disable single IRQ line
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_disable(unsigned char number);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Remap PIC
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_remap(
 | 
			
		||||
    unsigned char new_master_start,
 | 
			
		||||
    unsigned char new_slave_start
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Signal end of interrupt
 | 
			
		||||
 */
 | 
			
		||||
void drivers_intel_8259_pic_eoi(unsigned char number);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										15
									
								
								include/drivers/shutdown.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/drivers/shutdown.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
#ifndef DRIVERS_INCLUDED_SHUTDOWN
 | 
			
		||||
#define DRIVERS_INCLUDED_SHUTDOWN
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__attribute__((noreturn)) void drivers_shutdown_halt();
 | 
			
		||||
__attribute__((noreturn)) void drivers_shutdown_poweroff();
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										36
									
								
								src/console.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/console.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <drivers/console.h>
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
void drivers_console_putc(const char c)
 | 
			
		||||
{
 | 
			
		||||
#if defined(ASM_X86)
 | 
			
		||||
    __asm__ __volatile__("outb %1, %0" : : "dN" (0x3f8), "a" (c));
 | 
			
		||||
#else
 | 
			
		||||
    (void)c;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_console_print(const char *const s)
 | 
			
		||||
{
 | 
			
		||||
    for (const char *c = s; *c; ++c) {
 | 
			
		||||
        drivers_console_putc(*c);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_console_puts(const char *const s)
 | 
			
		||||
{
 | 
			
		||||
    drivers_console_print(s);
 | 
			
		||||
    drivers_console_putc('\n');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_console_write(const char *const data, const size_t size)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < size; i++) {
 | 
			
		||||
        drivers_console_putc(data[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								src/intel_8253_pit.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/intel_8253_pit.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <drivers/intel_8253_pit.h>
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8253_pit_initialize(const unsigned int freq)
 | 
			
		||||
{
 | 
			
		||||
    const unsigned int divisor = 1193180 / freq;
 | 
			
		||||
 | 
			
		||||
    const uint8_t l = divisor & 0xff;
 | 
			
		||||
    const uint8_t h = (divisor >> 8) & 0xff;
 | 
			
		||||
 | 
			
		||||
    __asm__ __volatile__("outb %1, %0" : : "dN" (0x43), "a" (0x36));
 | 
			
		||||
    __asm__ __volatile__("outb %1, %0" : : "dN" (0x40), "a" (l));
 | 
			
		||||
    __asm__ __volatile__("outb %1, %0" : : "dN" (0x40), "a" (h));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										112
									
								
								src/intel_8259_pic.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/intel_8259_pic.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,112 @@
 | 
			
		|||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <drivers/intel_8259_pic.h>
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define BITS8(n)  ((uint8_t )(((uint8_t )1) << (n)))
 | 
			
		||||
 | 
			
		||||
#define MASTER_COMMAND_PORT 0x20
 | 
			
		||||
#define SLAVE_COMMAND_PORT  0xA0
 | 
			
		||||
 | 
			
		||||
#define MASTER_DATA_PORT 0x21
 | 
			
		||||
#define SLAVE_DATA_PORT  0xA1
 | 
			
		||||
 | 
			
		||||
#define IRQS_COUNT 8
 | 
			
		||||
#define IRQS_TOTAL 16
 | 
			
		||||
 | 
			
		||||
static unsigned char master_start = 0;
 | 
			
		||||
static unsigned char slave_start  = 8;
 | 
			
		||||
 | 
			
		||||
static uint8_t inportb(const uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    register uint8_t result;
 | 
			
		||||
    __asm__ __volatile__("inb %1, %0" : "=a" (result) : "dN" (port));
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void outportb(const uint16_t port, const uint8_t value)
 | 
			
		||||
{
 | 
			
		||||
    __asm__ __volatile__("outb %1, %0" : : "dN" (port), "a" (value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_enable_all()
 | 
			
		||||
{
 | 
			
		||||
    outportb(MASTER_DATA_PORT, 0);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_disable_all()
 | 
			
		||||
{
 | 
			
		||||
    outportb(MASTER_DATA_PORT, 0xFF);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  0xFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_enable(const unsigned char number)
 | 
			
		||||
{
 | 
			
		||||
    if (number < IRQS_COUNT) {
 | 
			
		||||
        const uint8_t mask = inportb(MASTER_DATA_PORT);
 | 
			
		||||
        outportb(MASTER_DATA_PORT, mask & ~BITS8(number));
 | 
			
		||||
    } else {
 | 
			
		||||
        const uint8_t mask = inportb(SLAVE_DATA_PORT);
 | 
			
		||||
        outportb(SLAVE_DATA_PORT, mask & ~BITS8((number - IRQS_COUNT)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_disable(const unsigned char number)
 | 
			
		||||
{
 | 
			
		||||
    if (number < IRQS_COUNT) {
 | 
			
		||||
        const uint8_t mask = inportb(MASTER_DATA_PORT);
 | 
			
		||||
        outportb(MASTER_DATA_PORT, mask | BITS8(number));
 | 
			
		||||
    } else {
 | 
			
		||||
        const uint8_t mask = inportb(SLAVE_DATA_PORT);
 | 
			
		||||
        outportb(SLAVE_DATA_PORT, mask | BITS8((number - IRQS_COUNT)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_remap(
 | 
			
		||||
    const unsigned char new_master_start,
 | 
			
		||||
    const unsigned char new_slave_start
 | 
			
		||||
) {
 | 
			
		||||
    master_start = new_master_start;
 | 
			
		||||
    slave_start  = new_slave_start;
 | 
			
		||||
 | 
			
		||||
    // Save masks
 | 
			
		||||
    const uint8_t master_mask = inportb(MASTER_DATA_PORT);
 | 
			
		||||
    const uint8_t slave_mask  = inportb(SLAVE_DATA_PORT);
 | 
			
		||||
 | 
			
		||||
    // Start the initialization sequence
 | 
			
		||||
    outportb(MASTER_COMMAND_PORT, 0x11);
 | 
			
		||||
    outportb(SLAVE_COMMAND_PORT,  0x11);
 | 
			
		||||
 | 
			
		||||
    // Set IRQ vectors
 | 
			
		||||
    outportb(MASTER_DATA_PORT, new_master_start);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  new_slave_start);
 | 
			
		||||
 | 
			
		||||
    // Connect master and slave with each other
 | 
			
		||||
    outportb(MASTER_DATA_PORT, 0x04);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  0x02);
 | 
			
		||||
 | 
			
		||||
    // 8086/88 (MCS-80/85) mode
 | 
			
		||||
    outportb(MASTER_DATA_PORT, 0x01);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  0x01);
 | 
			
		||||
 | 
			
		||||
    // Restore masks
 | 
			
		||||
    outportb(MASTER_DATA_PORT, master_mask);
 | 
			
		||||
    outportb(SLAVE_DATA_PORT,  slave_mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_intel_8259_pic_eoi(const unsigned char number)
 | 
			
		||||
{
 | 
			
		||||
    const bool to_slave =
 | 
			
		||||
        number >= slave_start && number < slave_start + IRQS_COUNT;
 | 
			
		||||
    const bool to_master = to_slave ||
 | 
			
		||||
        (number >= master_start && number < master_start + IRQS_COUNT);
 | 
			
		||||
 | 
			
		||||
    if (to_slave)  outportb(SLAVE_COMMAND_PORT,  0x20);
 | 
			
		||||
    if (to_master) outportb(MASTER_COMMAND_PORT, 0x20);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/shutdown.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/shutdown.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <drivers/shutdown.h>
 | 
			
		||||
 | 
			
		||||
void drivers_shutdown_halt()
 | 
			
		||||
{
 | 
			
		||||
#ifdef ASM_X86
 | 
			
		||||
    // Disable interrupts
 | 
			
		||||
    __asm__ __volatile__("cli");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    volatile int x = 0;
 | 
			
		||||
    for (;;) ++x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void drivers_shutdown_poweroff()
 | 
			
		||||
{
 | 
			
		||||
#ifdef ASM_X86
 | 
			
		||||
    // QEMU >= 2.0
 | 
			
		||||
    __asm__ __volatile__("outw %1, %0" : : "dN" (0x604), "a" (0x2000));
 | 
			
		||||
    // QEMU < 2.0
 | 
			
		||||
    __asm__ __volatile__("outw %1, %0" : : "dN" (0xB004), "a" (0x2000));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // If we can't poweroff then we halt
 | 
			
		||||
    drivers_shutdown_halt();
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue