Skip to content

Commit

Permalink
driver: programmable interval timer (PIT)
Browse files Browse the repository at this point in the history
Added support for the Programmable Interval Timer (PIT)

Signed-off-by: Daniele Ahmed <ahmeddan amazon   com; >
  • Loading branch information
82marbag authored and wipawel committed Oct 23, 2020
1 parent a36cbaa commit 82fb105
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 25 deletions.
14 changes: 2 additions & 12 deletions arch/x86/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,8 @@ ENTRY(handle_exception)
#endif
END_FUNC(handle_exception)

ENTRY(asm_uart_handler)
cld
SAVE_REGS
lea com_ports, %_ASM_DI
call uart_handler
RESTORE_REGS
#if defined(__x86_64__)
iretq
#else
iret
#endif
END_FUNC(asm_uart_handler)
interrupt_handler pit pit_interrupt_handler
interrupt_handler uart uart_interrupt_handler

ENTRY(usermode_call_asm)
/* FIXME: Add 32-bit support */
Expand Down
14 changes: 9 additions & 5 deletions arch/x86/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <console.h>
#include <drivers/pit.h>
#include <drivers/serial.h>
#include <ktf.h>
#include <lib.h>
Expand All @@ -38,7 +39,8 @@
#include <mm/vmm.h>

extern void ret2kern_handler(void);
extern void asm_uart_handler(void);
extern void asm_interrupt_handler_uart(void);
extern void asm_interrupt_handler_pit(void);

static void init_tss(percpu_t *percpu) {
#if defined(__i386__)
Expand Down Expand Up @@ -145,10 +147,12 @@ void init_traps(unsigned int cpu) {
set_intr_gate(&percpu->idt[X86_RET2KERN_INT], __KERN_CS, _ul(ret2kern_handler), GATE_DPL3, GATE_PRESENT, 0);
/* clang-format on */

set_intr_gate(&percpu->idt[COM1_IRQ0_OFFSET], __KERN_CS, _ul(asm_uart_handler),
GATE_DPL0, GATE_PRESENT, 0);
set_intr_gate(&percpu->idt[COM2_IRQ0_OFFSET], __KERN_CS, _ul(asm_uart_handler),
GATE_DPL0, GATE_PRESENT, 0);
set_intr_gate(&percpu->idt[COM1_IRQ0_OFFSET], __KERN_CS,
_ul(asm_interrupt_handler_uart), GATE_DPL0, GATE_PRESENT, 0);
set_intr_gate(&percpu->idt[COM2_IRQ0_OFFSET], __KERN_CS,
_ul(asm_interrupt_handler_uart), GATE_DPL0, GATE_PRESENT, 0);
set_intr_gate(&percpu->idt[PIT_IRQ0_OFFSET], __KERN_CS,
_ul(asm_interrupt_handler_pit), GATE_DPL0, GATE_PRESENT, 0);

barrier();
lidt(&percpu->idt_ptr);
Expand Down
2 changes: 1 addition & 1 deletion common/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ void kernel_main(void) {
printk("All tasks done.\n");

while (1)
io_delay();
cpu_relax();
}
4 changes: 4 additions & 0 deletions common/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <smp/smp.h>

#include <drivers/pic.h>
#include <drivers/pit.h>
#include <drivers/serial.h>
#include <slab.h>

Expand Down Expand Up @@ -222,6 +223,9 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic,
/* Initialize console input */
uart_input_init(0);

/* Initialize Programmable Interrupt Timer */
init_pit();

/* Jump from .text.init section to .text */
asm volatile("push %0; ret" ::"r"(&kernel_main));

Expand Down
48 changes: 48 additions & 0 deletions drivers/pit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright © 2020 Amazon.com, Inc. or its affiliates.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <atomic.h>
#include <drivers/pic.h>
#include <drivers/pit.h>
#include <lib.h>
#include <time.h>

static volatile uint64_t ticks = 0;

void init_pit(void) {
outb(PIT_COMMAND_PORT,
PIT_CHANNEL_0 & PIT_ACCESS_MODE_LH & PIT_OP_MODE_RATE & PIT_BCD_MODE);
outb(PIT_DATA_PORT_CH0, PIT_FREQUENCY & 0xFF); /* send low byte */
outb(PIT_DATA_PORT_CH0, (PIT_FREQUENCY & 0xFF00) >> 8); /* send high byte */
pic_enable_irq(PIC1_DEVICE_SEL, PIT_IRQ);
}

void pit_interrupt_handler(void) { ++ticks; }

void pit_sleep(uint64_t ms) {
uint64_t end = ticks + ms;
while (ticks < end) {
cpu_relax();
}
}
10 changes: 6 additions & 4 deletions drivers/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ static struct {
unsigned init;
} input_state;

extern io_port_t com_ports[2];

static inline void set_port_mode(io_port_t port, bool stop_bit, uint8_t width) {
lcr_t lcr = {0};

Expand Down Expand Up @@ -158,12 +160,12 @@ int serial_write(io_port_t port, const char *buf, size_t len) {
return rc;
}

void uart_handler(io_port_t ports[2]) {
void uart_interrupt_handler(void) {
unsigned int i;
for (i = 0; i < sizeof(*ports); ++i) {
uint8_t status = inb(ports[i] + UART_IIR_REG_OFFSET);
for (i = 0; i < ARRAY_SIZE(com_ports); ++i) {
uint8_t status = inb(com_ports[i] + UART_IIR_REG_OFFSET);
if ((status & UART_IIR_STATUS_MASK) == UART_IIR_RBR_READY) {
uint8_t input = inb(ports[i] + UART_RBR_REG_OFFSET);
uint8_t input = inb(com_ports[i] + UART_RBR_REG_OFFSET);

input_state.buf[input_state.curr] = input;
input_state.curr = (input_state.curr + 1) % sizeof(input_state.buf);
Expand Down
4 changes: 2 additions & 2 deletions include/drivers/pic.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
#define PIC_CASCADE_PIC2_IRQ 0x02
#define PIC_CASCADE_PIC1_IRQ 0x04

#define PIC_IRQ0_OFFSET 0x20
#define PIC_IRQ8_OFFSET 0x28
#define PIC_IRQ0_OFFSET 0x28
#define PIC_IRQ8_OFFSET (PIC_IRQ0_OFFSET + 8)

#define PIC_IRQ_END_OFFSET 0x08 /* One beyond the max IRQ number */

Expand Down
63 changes: 63 additions & 0 deletions include/drivers/pit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright © 2020 Amazon.com, Inc. or its affiliates.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KTF_PIT_H
#define KTF_PIT_H

#include <drivers/pic.h>
#include <ktf.h>

#define PIT_IRQ 0x00 /* IRQ line */
#define PIT_IRQ0_OFFSET (PIC_IRQ0_OFFSET + PIT_IRQ) /* IRQ relative to PIC master */

#define PIT_OUT_FREQUENCY 1193182 /* oscillator output frequency */
#define PIT_RELOAD 1000 /* 1ms */
#define PIT_FREQUENCY (PIT_OUT_FREQUENCY / PIT_RELOAD)
#define PIT_DATA_PORT_CH0 0x40
#define PIT_COMMAND_PORT 0x43

#define PIT_CHANNEL_0 (~((1 << 7) | (1 << 6)))
#define PIT_ACCESS_MODE_LOW (1 << 4)
#define PIT_ACCESS_MODE_HIGH (1 << 5)
#define PIT_ACCESS_MODE_LH (PIT_ACCESS_MODE_LOW | PIT_ACCESS_MODE_HIGH)

enum pit_operational_mode {
PIT_OP_MODE_COUNT = 0x00, /* interrupt on terminal count */
PIT_OP_MODE_ONE_SHOT = 0x01, /* hardware re-triggerable one-shot */
PIT_OP_MODE_RATE = 0x02, /* rate generator */
PIT_OP_MODE_WAVE = 0x03, /* square wave generator */
PIT_OP_MODE_SW_STROBE = 0x04, /* software triggered strobe */
PIT_OP_MODE_HW_STROBE = 0x05, /* hardware triggered strobe */
PIT_OP_MODE_RATE_6 = 0x06, /* rate generator */
PIT_OP_MODE_WAVE_7 = 0x07 /* square wave generator */
};
typedef enum pit_operational_mode pit_operational_mode_t;

#define PIT_BCD_MODE (~(1 << 0))

extern void init_pit(void);
extern void pit_interrupt_handler(void);
extern void pit_sleep(uint64_t ms);

#endif
2 changes: 1 addition & 1 deletion include/drivers/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ typedef union interrupt_enable_register ier_t;
/* External declarations */

extern void uart_init(io_port_t port, unsigned baud);
extern void uart_handler(io_port_t ports[2]);
extern void uart_input_init(uint8_t dst_cpus);
extern void uart_interrupt_handler(void);
extern int serial_putchar(io_port_t port, char c);
extern int serial_write(io_port_t port, const char *buf, size_t len);

Expand Down
35 changes: 35 additions & 0 deletions include/time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright © 2020 Amazon.com, Inc. or its affiliates.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KTF_TIME_H
#define KTF_TIME_H

#include <drivers/pit.h>
#include <ktf.h>

typedef uint64_t time_t;

static inline void sleep(time_t ms) { pit_sleep(ms); }

#endif

0 comments on commit 82fb105

Please sign in to comment.