Merge pull request #92 from SamTebbs33/adding-tests-for-irq
Added unit and runtime tests
This commit is contained in:
commit
73495f1f57
7 changed files with 339 additions and 49 deletions
|
@ -239,6 +239,7 @@ test "" {
|
|||
_ = @import("idt.zig");
|
||||
_ = @import("pic.zig");
|
||||
_ = @import("isr.zig");
|
||||
_ = @import("irq.zig");
|
||||
_ = @import("syscalls.zig");
|
||||
_ = @import("paging.zig");
|
||||
}
|
||||
|
|
|
@ -1,14 +1,38 @@
|
|||
// Zig version: 0.4.0
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const expectError = std.testing.expectError;
|
||||
const build_options = @import("build_options");
|
||||
const panic = @import("../../panic.zig").panic;
|
||||
const idt = @import("idt.zig");
|
||||
const arch = @import("arch.zig");
|
||||
const pic = @import("pic.zig");
|
||||
const mock_path = build_options.arch_mock_path;
|
||||
const idt = if (is_test) @import(mock_path ++ "idt_mock.zig") else @import("idt.zig");
|
||||
const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig");
|
||||
const log = if (is_test) @import(mock_path ++ "log_mock.zig") else @import("../../log.zig");
|
||||
const pic = if (is_test) @import(mock_path ++ "pic_mock.zig") else @import("pic.zig");
|
||||
|
||||
/// The error set for the IRQ. This will be from installing a IRQ handler.
|
||||
pub const IrqError = error{
|
||||
/// The IRQ index is invalid.
|
||||
InvalidIrq,
|
||||
|
||||
/// A IRQ handler already exists.
|
||||
IrqExists,
|
||||
};
|
||||
|
||||
/// The total number of IRQ.
|
||||
const NUMBER_OF_ENTRIES: u16 = 16;
|
||||
|
||||
// The offset from the interrupt number where the IRQs are.
|
||||
const IRQ_OFFSET: u16 = 32;
|
||||
|
||||
/// The type of a IRQ handler. A function that takes a interrupt context and returns void.
|
||||
const IrqHandler = fn (*arch.InterruptContext) void;
|
||||
|
||||
/// The list of IRQ handlers initialised to unhandled.
|
||||
var irq_handlers: [NUMBER_OF_ENTRIES]?IrqHandler = [_]?IrqHandler{null} ** NUMBER_OF_ENTRIES;
|
||||
|
||||
// The external assembly that is fist called to set up the interrupt handler.
|
||||
extern fn irq0() void;
|
||||
extern fn irq1() void;
|
||||
|
@ -27,36 +51,32 @@ extern fn irq13() void;
|
|||
extern fn irq14() void;
|
||||
extern fn irq15() void;
|
||||
|
||||
/// The list of IRQ handlers initialised to unhandled.
|
||||
var irq_handlers: [NUMBER_OF_ENTRIES]fn (*arch.InterruptContext) void = [_]fn (*arch.InterruptContext) void{unhandled} ** NUMBER_OF_ENTRIES;
|
||||
|
||||
///
|
||||
/// A dummy handler that will make a call to panic as it is a unhandled interrupt.
|
||||
/// The IRQ handler that each of the IRQs will call when a interrupt happens.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN context: *arch.InterruptContext - Pointer to the interrupt context containing the
|
||||
/// contents of the register at the time of the interrupt.
|
||||
/// IN ctx: *arch.InterruptContext - Pointer to the interrupt context containing the contents
|
||||
/// of the register at the time of the interrupt.
|
||||
///
|
||||
fn unhandled(context: *arch.InterruptContext) void {
|
||||
const interrupt_num: u8 = @truncate(u8, context.int_num - IRQ_OFFSET);
|
||||
panic(null, "Unhandled IRQ number {}", interrupt_num);
|
||||
}
|
||||
|
||||
///
|
||||
/// The IRQ handler that each of the IRQ's will call when a interrupt happens.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN context: *arch.InterruptContext - Pointer to the interrupt context containing the
|
||||
/// contents of the register at the time of the interrupt.
|
||||
///
|
||||
export fn irqHandler(context: *arch.InterruptContext) void {
|
||||
const irq_num: u8 = @truncate(u8, context.int_num - IRQ_OFFSET);
|
||||
export fn irqHandler(ctx: *arch.InterruptContext) void {
|
||||
// Get the IRQ index, by getting the interrupt number and subtracting the offset.
|
||||
const irq_offset = ctx.int_num - IRQ_OFFSET;
|
||||
if (isValidIrq(irq_offset)) {
|
||||
// IRQ index is valid so can truncate
|
||||
const irq_num = @truncate(u8, irq_offset);
|
||||
if (irq_handlers[irq_num]) |handler| {
|
||||
// Make sure it isn't a spurious irq
|
||||
if (!pic.spuriousIrq(irq_num)) {
|
||||
irq_handlers[irq_num](context);
|
||||
handler(ctx);
|
||||
// Send the end of interrupt command
|
||||
pic.sendEndOfInterrupt(irq_num);
|
||||
}
|
||||
} else {
|
||||
panic(@errorReturnTrace(), "IRQ not registered: {}", irq_num);
|
||||
}
|
||||
} else {
|
||||
panic(@errorReturnTrace(), "Invalid IRQ index: {}", irq_offset);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -75,27 +95,45 @@ fn openIrq(index: u8, handler: idt.InterruptHandler) void {
|
|||
}
|
||||
|
||||
///
|
||||
/// Register a IRQ by setting its interrupt handler to the given function. This will also clear the
|
||||
/// mask bit in the PIC so interrupts can happen.
|
||||
/// Check whether the IRQ index is valid. This will have to be less than NUMBER_OF_ENTRIES.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN irq_num: u8 - The IRQ number to register.
|
||||
/// IN irq_num: u8 - The IRQ index to test.
|
||||
///
|
||||
pub fn registerIrq(irq_num: u8, handler: fn (*arch.InterruptContext) void) void {
|
||||
irq_handlers[irq_num] = handler;
|
||||
pic.clearMask(irq_num);
|
||||
/// Return: bool
|
||||
/// Whether the IRQ index if valid.
|
||||
///
|
||||
pub fn isValidIrq(irq_num: u32) bool {
|
||||
return irq_num < NUMBER_OF_ENTRIES;
|
||||
}
|
||||
|
||||
///
|
||||
/// Unregister a IRQ by setting its interrupt handler to the unhandled function call to panic. This
|
||||
/// will also set the mask bit in the PIC so no interrupts can happen anyway.
|
||||
/// Register a IRQ by setting its interrupt handler to the given function. This will also clear the
|
||||
/// mask bit in the PIC so interrupts can happen for this IRQ.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN irq_num: u16 - The IRQ number to unregister.
|
||||
/// IN irq_num: u8 - The IRQ number to register.
|
||||
/// IN handler: IrqHandler - The IRQ handler to register. This is what will be called when this
|
||||
/// interrupt happens.
|
||||
///
|
||||
pub fn unregisterIrq(irq_num: u16) void {
|
||||
irq_handlers[irq_num] = unhandled;
|
||||
pic.setMask(irq_num);
|
||||
/// Errors: IrqError
|
||||
/// IrqError.InvalidIrq - If the IRQ index is invalid (see isValidIrq).
|
||||
/// IrqError.IrqExists - If the IRQ handler has already been registered.
|
||||
///
|
||||
pub fn registerIrq(irq_num: u8, handler: IrqHandler) IrqError!void {
|
||||
// Check whether the IRQ index is valid.
|
||||
if (isValidIrq(irq_num)) {
|
||||
// Check if a handler has already been registered.
|
||||
if (irq_handlers[irq_num]) |_| {
|
||||
return IrqError.IrqExists;
|
||||
} else {
|
||||
// Register the handler and clear the PIC mask so interrupts can happen.
|
||||
irq_handlers[irq_num] = handler;
|
||||
pic.clearMask(irq_num);
|
||||
}
|
||||
} else {
|
||||
return IrqError.InvalidIrq;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -103,7 +141,9 @@ pub fn unregisterIrq(irq_num: u16) void {
|
|||
/// the IDT interrupt gates for each IRQ.
|
||||
///
|
||||
pub fn init() void {
|
||||
// Open all the IRQ's
|
||||
log.logInfo("Init irq\n");
|
||||
|
||||
// Open all the IRQs
|
||||
openIrq(32, irq0);
|
||||
openIrq(33, irq1);
|
||||
openIrq(34, irq2);
|
||||
|
@ -120,4 +160,135 @@ pub fn init() void {
|
|||
openIrq(45, irq13);
|
||||
openIrq(46, irq14);
|
||||
openIrq(47, irq15);
|
||||
|
||||
log.logInfo("Done\n");
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
extern fn testFunction0() void {}
|
||||
fn testFunction1(ctx: *arch.InterruptContext) void {}
|
||||
fn testFunction2(ctx: *arch.InterruptContext) void {}
|
||||
|
||||
test "openIrq" {
|
||||
idt.initTest();
|
||||
defer idt.freeTest();
|
||||
|
||||
const index = u8(0);
|
||||
const handler = testFunction0;
|
||||
const ret: idt.IdtError!void = {};
|
||||
|
||||
idt.addTestParams("openInterruptGate", index, handler, ret);
|
||||
|
||||
openIrq(index, handler);
|
||||
}
|
||||
|
||||
test "isValidIrq" {
|
||||
comptime var i = 0;
|
||||
inline while (i < NUMBER_OF_ENTRIES) : (i += 1) {
|
||||
expect(isValidIrq(i));
|
||||
}
|
||||
|
||||
expect(!isValidIrq(200));
|
||||
}
|
||||
|
||||
test "registerIrq re-register irq handler" {
|
||||
// Set up
|
||||
pic.initTest();
|
||||
defer pic.freeTest();
|
||||
|
||||
pic.addTestParams("clearMask", u16(0));
|
||||
|
||||
// Pre testing
|
||||
for (irq_handlers) |h| {
|
||||
expect(null == h);
|
||||
}
|
||||
|
||||
// Call function
|
||||
try registerIrq(0, testFunction1);
|
||||
expectError(IrqError.IrqExists, registerIrq(0, testFunction2));
|
||||
|
||||
// Post testing
|
||||
for (irq_handlers) |h, i| {
|
||||
if (i != 0) {
|
||||
expect(null == h);
|
||||
} else {
|
||||
expectEqual(testFunction1, h.?);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
irq_handlers[0] = null;
|
||||
}
|
||||
|
||||
test "registerIrq register irq handler" {
|
||||
// Set up
|
||||
pic.initTest();
|
||||
defer pic.freeTest();
|
||||
|
||||
pic.addTestParams("clearMask", u16(0));
|
||||
|
||||
// Pre testing
|
||||
for (irq_handlers) |h| {
|
||||
expect(null == h);
|
||||
}
|
||||
|
||||
// Call function
|
||||
try registerIrq(0, testFunction1);
|
||||
|
||||
// Post testing
|
||||
for (irq_handlers) |h, i| {
|
||||
if (i != 0) {
|
||||
expect(null == h);
|
||||
} else {
|
||||
expectEqual(testFunction1, h.?);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
irq_handlers[0] = null;
|
||||
}
|
||||
|
||||
test "registerIrq invalid irq index" {
|
||||
expectError(IrqError.InvalidIrq, registerIrq(200, testFunction1));
|
||||
}
|
||||
|
||||
///
|
||||
/// Test that all handers are null at initialisation.
|
||||
///
|
||||
fn rt_unregisteredHandlers() void {
|
||||
// Ensure all ISR are not registered yet
|
||||
for (irq_handlers) |h, i| {
|
||||
if (h) |_| {
|
||||
panic(@errorReturnTrace(), "Handler found for IRQ: {}-{}\n", i, h);
|
||||
}
|
||||
}
|
||||
|
||||
log.logInfo("IRQ: Tested registered handlers\n");
|
||||
}
|
||||
|
||||
///
|
||||
/// Test that all IDT entries for the IRQs are open.
|
||||
///
|
||||
fn rt_openedIdtEntries() void {
|
||||
const loaded_idt = arch.sidt();
|
||||
const idt_entries = @intToPtr([*]idt.IdtEntry, loaded_idt.base)[0..idt.NUMBER_OF_ENTRIES];
|
||||
|
||||
for (idt_entries) |entry, i| {
|
||||
if (i >= IRQ_OFFSET and isValidIrq(i - IRQ_OFFSET)) {
|
||||
if (!idt.isIdtOpen(entry)) {
|
||||
panic(@errorReturnTrace(), "IDT entry for {} is not open\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.logInfo("IRQ: Tested opened IDT entries\n");
|
||||
}
|
||||
|
||||
///
|
||||
/// Run all the runtime tests.
|
||||
///
|
||||
fn runtimeTests() void {
|
||||
rt_unregisteredHandlers();
|
||||
rt_openedIdtEntries();
|
||||
}
|
||||
|
|
|
@ -334,9 +334,9 @@ test "isValidIsr" {
|
|||
expectEqual(true, isValidIsr(i));
|
||||
}
|
||||
|
||||
expectEqual(true, isValidIsr(syscalls.INTERRUPT));
|
||||
expect(isValidIsr(syscalls.INTERRUPT));
|
||||
|
||||
expectEqual(false, isValidIsr(200));
|
||||
expect(!isValidIsr(200));
|
||||
}
|
||||
|
||||
test "registerIsr re-register syscall handler" {
|
||||
|
|
|
@ -275,12 +275,21 @@ pub fn getFrequency() u32 {
|
|||
pub fn init() void {
|
||||
log.logInfo("Init pit\n");
|
||||
// Set up counter 0 at 1000hz in a square wave mode counting in binary
|
||||
const f: u32 = 10000;
|
||||
setupCounter(OCW_SELECT_COUNTER_0, f, OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY);
|
||||
// TODO: https://github.com/ziglang/zig/issues/557, Need type defined
|
||||
const freq: u32 = 10000;
|
||||
setupCounter(OCW_SELECT_COUNTER_0, freq, OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY);
|
||||
|
||||
log.logInfo("Set frequency at: {}Hz, real frequency: {}Hz\n", f, getFrequency());
|
||||
log.logInfo("Set frequency at: {}Hz, real frequency: {}Hz\n", freq, getFrequency());
|
||||
|
||||
// Installs 'pitHandler' to IRQ0 (pic.IRQ_PIT)
|
||||
irq.registerIrq(pic.IRQ_PIT, pitHandler);
|
||||
irq.registerIrq(pic.IRQ_PIT, pitHandler) catch |err| switch (err) {
|
||||
error.IrqExists => {
|
||||
panic(@errorReturnTrace(), "IRQ for PIT, IRQ number: {} exists", pic.IRQ_PIT);
|
||||
},
|
||||
error.InvalidIrq => {
|
||||
panic(@errorReturnTrace(), "IRQ for PIT, IRQ number: {} is invalid", pic.IRQ_PIT);
|
||||
},
|
||||
};
|
||||
|
||||
log.logInfo("Done\n");
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ def get_test_cases(TestCase):
|
|||
TestCase("PIC tests", [r"PIC: Tested masking"]),
|
||||
TestCase("ISR init", [r"Init isr", r"Done"]),
|
||||
TestCase("ISR tests", [r"ISR: Tested registered handlers", r"ISR: Tested opened IDT entries"]),
|
||||
TestCase("IRQ init", [r"Init irq", r"Done"]),
|
||||
TestCase("IRQ tests", [r"IRQ: Tested registered handlers", r"IRQ: Tested opened IDT entries"]),
|
||||
TestCase("PIT init", [r"Init pit", r".+", r"Done"]),
|
||||
TestCase("Paging init", [r"Init paging", r"Done"]),
|
||||
TestCase("Paging tests", [r"Paging: Tested accessing unmapped memory", r"Paging: Tested accessing mapped memory"]),
|
||||
|
|
|
@ -13,6 +13,7 @@ const idt = @import("idt_mock.zig");
|
|||
/// and function types like fn () void
|
||||
///
|
||||
const DataElementType = enum {
|
||||
BOOL,
|
||||
U4,
|
||||
U8,
|
||||
U16,
|
||||
|
@ -24,6 +25,8 @@ const DataElementType = enum {
|
|||
FN_OVOID,
|
||||
FN_OUSIZE,
|
||||
FN_OU16,
|
||||
FN_IU8_OBOOL,
|
||||
FN_IU8_OVOID,
|
||||
FN_IU16_OVOID,
|
||||
FN_IU16_OU8,
|
||||
FN_IU4_IU4_OU8,
|
||||
|
@ -41,6 +44,7 @@ const DataElementType = enum {
|
|||
/// so this wraps the data into a union, (which is of one type) so can have a list of them.
|
||||
///
|
||||
const DataElement = union(DataElementType) {
|
||||
BOOL: bool,
|
||||
U4: u4,
|
||||
U8: u8,
|
||||
U16: u16,
|
||||
|
@ -52,6 +56,8 @@ const DataElement = union(DataElementType) {
|
|||
FN_OVOID: fn () void,
|
||||
FN_OUSIZE: fn () usize,
|
||||
FN_OU16: fn () u16,
|
||||
FN_IU8_OBOOL: fn (u8) bool,
|
||||
FN_IU8_OVOID: fn (u8) void,
|
||||
FN_IU16_OVOID: fn (u16) void,
|
||||
FN_IU16_OU8: fn (u16) u8,
|
||||
FN_IU4_IU4_OU8: fn (u4, u4) u8,
|
||||
|
@ -136,6 +142,7 @@ fn Mock() type {
|
|||
///
|
||||
fn createDataElement(arg: var) DataElement {
|
||||
return switch (@typeOf(arg)) {
|
||||
bool => DataElement{ .BOOL = arg },
|
||||
u4 => DataElement{ .U4 = arg },
|
||||
u8 => DataElement{ .U8 = arg },
|
||||
u16 => DataElement{ .U16 = arg },
|
||||
|
@ -147,6 +154,8 @@ fn Mock() type {
|
|||
fn () void => DataElement{ .FN_OVOID = arg },
|
||||
fn () usize => DataElement{ .FN_OUSIZE = arg },
|
||||
fn () u16 => DataElement{ .FN_OU16 = arg },
|
||||
fn (u8) bool => DataElement{ .FN_IU8_OBOOL = arg },
|
||||
fn (u8) void => DataElement{ .FN_IU8_OVOID = arg },
|
||||
fn (u16) void => DataElement{ .FN_IU16_OVOID = arg },
|
||||
fn (u16) u8 => DataElement{ .FN_IU16_OU8 = arg },
|
||||
fn (u4, u4) u8 => DataElement{ .FN_IU4_IU4_OU8 = arg },
|
||||
|
@ -171,6 +180,7 @@ fn Mock() type {
|
|||
///
|
||||
fn getDataElementType(comptime T: type) DataElementType {
|
||||
return switch (T) {
|
||||
bool => DataElementType.BOOL,
|
||||
u4 => DataElementType.U4,
|
||||
u8 => DataElementType.U8,
|
||||
u16 => DataElementType.U16,
|
||||
|
@ -181,6 +191,8 @@ fn Mock() type {
|
|||
extern fn () void => DataElementType.EFN_OVOID,
|
||||
fn () void => DataElementType.FN_OVOID,
|
||||
fn () u16 => DataElementType.FN_OU16,
|
||||
fn (u8) bool => DataElementType.FN_IU8_OBOOL,
|
||||
fn (u8) void => DataElementType.FN_IU8_OVOID,
|
||||
fn (u16) void => DataElementType.FN_IU16_OVOID,
|
||||
fn (u16) u8 => DataElementType.FN_IU16_OU8,
|
||||
fn (u4, u4) u8 => DataElementType.FN_IU4_IU4_OU8,
|
||||
|
@ -207,6 +219,7 @@ fn Mock() type {
|
|||
///
|
||||
fn getDataValue(comptime T: type, element: DataElement) T {
|
||||
return switch (T) {
|
||||
bool => element.BOOL,
|
||||
u4 => element.U4,
|
||||
u8 => element.U8,
|
||||
u16 => element.U16,
|
||||
|
@ -217,6 +230,8 @@ fn Mock() type {
|
|||
extern fn () void => element.EFN_OVOID,
|
||||
fn () void => element.FN_OVOID,
|
||||
fn () u16 => element.FN_OU16,
|
||||
fn (u8) bool => element.FN_IU8_OBOOL,
|
||||
fn (u8) void => element.FN_IU8_OVOID,
|
||||
fn (u16) void => element.FN_IU16_OVOID,
|
||||
fn (u16) u8 => element.FN_IU16_OU8,
|
||||
fn (u4, u4) u8 => element.FN_IU4_IU4_OU8,
|
||||
|
|
92
test/mock/kernel/pic_mock.zig
Normal file
92
test/mock/kernel/pic_mock.zig
Normal file
|
@ -0,0 +1,92 @@
|
|||
const mock_framework = @import("mock_framework.zig");
|
||||
pub const initTest = mock_framework.initTest;
|
||||
pub const freeTest = mock_framework.freeTest;
|
||||
pub const addTestParams = mock_framework.addTestParams;
|
||||
pub const addConsumeFunction = mock_framework.addConsumeFunction;
|
||||
pub const addRepeatFunction = mock_framework.addRepeatFunction;
|
||||
|
||||
const MASTER_COMMAND_REG: u16 = 0x20;
|
||||
const MASTER_STATUS_REG: u16 = 0x20;
|
||||
const MASTER_DATA_REG: u16 = 0x21;
|
||||
const MASTER_INTERRUPT_MASK_REG: u16 = 0x21;
|
||||
const SLAVE_COMMAND_REG: u16 = 0xA0;
|
||||
const SLAVE_STATUS_REG: u16 = 0xA0;
|
||||
const SLAVE_DATA_REG: u16 = 0xA1;
|
||||
const SLAVE_INTERRUPT_MASK_REG: u16 = 0xA1;
|
||||
|
||||
const ICW1_EXPECT_ICW4: u8 = 0x01;
|
||||
const ICW1_SINGLE_CASCADE_MODE: u8 = 0x02;
|
||||
const ICW1_CALL_ADDRESS_INTERVAL_4: u8 = 0x04;
|
||||
const ICW1_LEVEL_TRIGGER_MODE: u8 = 0x08;
|
||||
const ICW1_INITIALISATION: u8 = 0x10;
|
||||
|
||||
const ICW2_MASTER_REMAP_OFFSET: u8 = 0x20;
|
||||
const ICW2_SLAVE_REMAP_OFFSET: u8 = 0x28;
|
||||
|
||||
const ICW3_SLAVE_IRQ_MAP_TO_MASTER: u8 = 0x02;
|
||||
const ICW3_MASTER_IRQ_MAP_FROM_SLAVE: u8 = 0x04;
|
||||
|
||||
const ICW4_80x86_MODE: u8 = 0x01;
|
||||
const ICW4_AUTO_END_OF_INTERRUPT: u8 = 0x02;
|
||||
const ICW4_BUFFER_SELECT: u8 = 0x04;
|
||||
const ICW4_BUFFER_MODE: u8 = 0x08;
|
||||
const ICW4_FULLY_NESTED_MODE: u8 = 0x10;
|
||||
|
||||
const OCW1_MASK_IRQ0: u8 = 0x01;
|
||||
const OCW1_MASK_IRQ1: u8 = 0x02;
|
||||
const OCW1_MASK_IRQ2: u8 = 0x04;
|
||||
const OCW1_MASK_IRQ3: u8 = 0x08;
|
||||
const OCW1_MASK_IRQ4: u8 = 0x10;
|
||||
const OCW1_MASK_IRQ5: u8 = 0x20;
|
||||
const OCW1_MASK_IRQ6: u8 = 0x40;
|
||||
const OCW1_MASK_IRQ7: u8 = 0x80;
|
||||
|
||||
const OCW2_INTERRUPT_LEVEL_1: u8 = 0x01;
|
||||
const OCW2_INTERRUPT_LEVEL_2: u8 = 0x02;
|
||||
const OCW2_INTERRUPT_LEVEL_3: u8 = 0x04;
|
||||
const OCW2_END_OF_INTERRUPT: u8 = 0x20;
|
||||
const OCW2_SELECTION: u8 = 0x40;
|
||||
const OCW2_ROTATION: u8 = 0x80;
|
||||
|
||||
const OCW3_READ_IRR: u8 = 0x00;
|
||||
const OCW3_READ_ISR: u8 = 0x01;
|
||||
const OCW3_ACT_ON_READ: u8 = 0x02;
|
||||
const OCW3_POLL_COMMAND_ISSUED: u8 = 0x04;
|
||||
const OCW3_DEFAULT: u8 = 0x08;
|
||||
const OCW3_SPECIAL_MASK: u8 = 0x20;
|
||||
const OCW3_ACK_ON_SPECIAL_MASK: u8 = 0x40;
|
||||
|
||||
pub const IRQ_PIT: u8 = 0x00;
|
||||
pub const IRQ_KEYBOARD: u8 = 0x01;
|
||||
pub const IRQ_CASCADE_FOR_SLAVE: u8 = 0x02;
|
||||
pub const IRQ_SERIAL_PORT_2: u8 = 0x03;
|
||||
pub const IRQ_SERIAL_PORT_1: u8 = 0x04;
|
||||
pub const IRQ_PARALLEL_PORT_2: u8 = 0x05;
|
||||
pub const IRQ_DISKETTE_DRIVE: u8 = 0x06;
|
||||
pub const IRQ_PARALLEL_PORT_1: u8 = 0x07;
|
||||
pub const IRQ_REAL_TIME_CLOCK: u8 = 0x08;
|
||||
pub const IRQ_CGA_VERTICAL_RETRACE: u8 = 0x09;
|
||||
|
||||
pub const IRQ_AUXILIARY_DEVICE: u8 = 0x0C;
|
||||
pub const IRQ_FLOATING_POINT_UNIT: u8 = 0x0D;
|
||||
pub const IRQ_HARD_DISK_CONTROLLER: u8 = 0x0E;
|
||||
|
||||
pub fn sendEndOfInterrupt(irq_num: u8) void {
|
||||
return mock_framework.performAction("sendEndOfInterrupt", void, irq_num);
|
||||
}
|
||||
|
||||
pub fn spuriousIrq(irq_num: u8) bool {
|
||||
return mock_framework.performAction("spuriousIrq", bool, irq_num);
|
||||
}
|
||||
|
||||
pub fn setMask(irq_num: u16) void {
|
||||
return mock_framework.performAction("setMask", void, irq_num);
|
||||
}
|
||||
|
||||
pub fn clearMask(irq_num: u16) void {
|
||||
return mock_framework.performAction("clearMask", void, irq_num);
|
||||
}
|
||||
|
||||
pub fn remapIrq() void {
|
||||
return mock_framework.performAction("remapIrq", void);
|
||||
}
|
Loading…
Reference in a new issue