Add a skeleton for the interrupt controller
This commit is contained in:
103
source/peripherals/interrupt_controller.c
Normal file
103
source/peripherals/interrupt_controller.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*******************************************************************************
|
||||
* NewOswan
|
||||
* interrupt_controller.c:
|
||||
*
|
||||
* Created by mlt on 14/03/2022.
|
||||
* Copyright (c) 2022 986-Studio. All rights reserved.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <device.h>
|
||||
#include <io.h>
|
||||
#include <interrupt_controller.h>
|
||||
|
||||
/* device internal parameters */
|
||||
typedef struct ic_params_t
|
||||
{
|
||||
uint8_t address_base;
|
||||
uint8_t int_enable_mask;
|
||||
uint8_t int_status;
|
||||
} ic_params_t;
|
||||
|
||||
static ic_params_t interrupt_controller;
|
||||
|
||||
static uint8_t IC_IO_read(void *pdata, uint8_t port)
|
||||
{
|
||||
ic_params_t *params = (ic_params_t *)pdata;
|
||||
|
||||
switch(port)
|
||||
{
|
||||
case 0xB0: return params->address_base;
|
||||
case 0xB2: return params->int_enable_mask;
|
||||
case 0xB4: return params->int_status;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void IC_IO_write(void *pdata, uint8_t port, uint8_t value)
|
||||
{
|
||||
ic_params_t *params = (ic_params_t *)pdata;
|
||||
|
||||
switch(port)
|
||||
{
|
||||
case 0xB0: params->address_base = value; break;
|
||||
case 0xB2: params->int_enable_mask = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void IC_IO_write_ack(void *pdata, uint8_t port, uint8_t value)
|
||||
{
|
||||
ic_params_t *params = (ic_params_t *)pdata;
|
||||
|
||||
// De-assert CPU interrupt accordingly to the mask in value
|
||||
}
|
||||
|
||||
|
||||
static void IC_init(void *params)
|
||||
{
|
||||
UNUSED_PARAMETER(params);
|
||||
|
||||
register_io_hook(0xB0, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(0xB2, IC_IO_read, IC_IO_write, &interrupt_controller);
|
||||
register_io_hook(0xB4, IC_IO_read, NULL, &interrupt_controller);
|
||||
register_io_hook(0xB6, NULL, IC_IO_write_ack, &interrupt_controller);
|
||||
}
|
||||
|
||||
static void IC_reset()
|
||||
{
|
||||
interrupt_controller.int_enable_mask = 0;
|
||||
interrupt_controller.address_base = 0;
|
||||
}
|
||||
|
||||
static void IC_free()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
device_t InterruptController =
|
||||
{
|
||||
.init = IC_init,
|
||||
.reset = IC_reset,
|
||||
.free = IC_free,
|
||||
.deviceType = DT_INTERRUPT_CONTROLLER,
|
||||
};
|
||||
|
||||
/* Exported functions */
|
||||
void trigger_interrupt(hw_interrupt_type_t type)
|
||||
{
|
||||
uint16_t int_vector = interrupt_controller.address_base & 0xF8 + (uint8_t)type;
|
||||
|
||||
/* Check that the INT is enabled */
|
||||
if ((interrupt_controller.int_enable_mask >> type) & 0x1)
|
||||
{
|
||||
/* TODO: Do we have to enable that even if the int is not enabled? */
|
||||
interrupt_controller.int_status |= (1 << type);
|
||||
|
||||
// Fire the NEC interrupt
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user