Update project organisation (part 1)

This commit is contained in:
Yann MAGNIN 2020-02-24 23:30:49 +01:00
parent 6576cf1e5d
commit 4be64372bb
31 changed files with 283 additions and 521 deletions

View File

@ -1,40 +0,0 @@
#ifndef __KERNEL_DEVICES_DISPLAY_H__
# define __KERNEL_DEVICES_DISPLAY_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/util/types.h>
#include <kernel/util/draw.h>
// Define screen informations.
#define DISPLAY_SCREEN_WIDTH (128)
#define DISPLAY_SCREEN_HEIGHT (64)
// Define Number of vertical lines
// and horizontal lines.
#define DISPLAY_VCHAR_MAX (DISPLAY_SCREEN_HEIGHT / (KERNEL_FONT_REAL_HEIGHT + 1))
#define DISPLAY_HCHAR_MAX (DISPLAY_SCREEN_WIDTH / (KERNEL_FONT_REAL_WIDTH + 1))
// Device primitives.
extern int display_open(void);
extern ssize_t display_write(const void *buffer, size_t count);
extern int display_close(void);
// IOCTL code.
#define DISPLAY_IOCTL_GETX (0x00)
#define DISPLAY_IOCTL_GETY (0x01)
#define DISPLAY_IOCTL_SETX (0x02)
#define DISPLAY_IOCTL_SETY (0x03)
#define DISPLAY_IOCTL_CLEAR (0x04)
#define DISPLAY_IOCTL_DISPLAY (0x05)
extern void display_ioctl(uint32_t cmd, ...);
// Sheared Video RAM
// @note:
// The user *SHOULD* not use the
// VRAM without atomic operation (because
// of reentrance).
extern uint32_t vram[256];
#endif /*__KERNEL_DEVICES_DISPLAY_H__*/

View File

@ -26,14 +26,16 @@ struct tty_s
int16_t y;
} max;
} cursor;
struct {
/*struct {
ssize_t (*write)(const void *buffer, size_t count);
ssize_t (*read)(void *buffer, size_t count);
} primitives;
} primitives;*/
};
// internal strct used by the TTY read primitives
// TODO: Move me ?
// TODO: Add internal keyboard buffer !!!
struct keyboard_obj_s
{
struct {

View File

@ -1,37 +0,0 @@
#ifndef __KERNEL_DEVICES_UBC_H__
# define __KERNEL_DEVICES_UBC_H__
#include <stddef.h>
#include <stdint.h>
struct ubc_context_s
{
uint32_t reg[16];
uint32_t gbr;
uint32_t macl;
uint32_t mach;
uint32_t ssr;
uint32_t spc;
};
typedef struct ubc_session_s
{
struct {
struct {
uint32_t cursor;
} context;
struct {
int32_t vcursor;
int32_t hcursor;
} disassembly;
} menu;
struct ubc_context_s *context;
unsigned int key;
int channel;
} ubc_session_t;
// Primitives.
extern int ubc_open(void);
extern int ubc_close(void);
#endif /*__KERNEL_DEVICES_UBC_H__*/

View File

@ -14,6 +14,17 @@
#define KERNEL_FONT_NB_CHAR_X ((KERNEL_FONT_BITMAP_WIDTH / KERNEL_FONT_BITMAP_CWIDTH) + 1)
#define KERNEL_FONT_NB_CHAR_Y ((KERNEL_FONT_BITMAP_HEIGHT / KERNEL_FONT_BITMAP_CHEIGHT) + 1)
// Define screen informations.
#define DISPLAY_SCREEN_WIDTH (128)
#define DISPLAY_SCREEN_HEIGHT (64)
// Define Number of vertical lines
// and horizontal lines.
#define DISPLAY_VCHAR_MAX (DISPLAY_SCREEN_HEIGHT / (KERNEL_FONT_REAL_HEIGHT + 1))
#define DISPLAY_HCHAR_MAX (DISPLAY_SCREEN_WIDTH / (KERNEL_FONT_REAL_WIDTH + 1))
// Internal struct used to draw
// the ASCII character.
struct font_block_s
@ -36,6 +47,7 @@ extern void kvram_display(void);
extern void kvram_scroll(int lines);
extern void kvram_reverse(int x, int y, int width, int height);
extern void kvram_clr_str_area(int x, int y, int width, int height);
extern void kvram_print(int x, int y, const char *string, size_t len);
extern void kvram_ascii(int x, int y, char const c);
#endif /*__KERNEL_UTIL_DRAW_H__*/

View File

@ -1,10 +0,0 @@
#include <kernel/devices/keyboard.h>
// Internal constructor.
extern void keycache_init(void);
int keyboard_open(void)
{
keycache_init();
return (0);
}

View File

@ -1,14 +0,0 @@
#include <kernel/devices/keyboard.h>
ssize_t keyboard_read(void *buffer, size_t count)
{
extern struct keycache_s *keylist;
extern volatile uint8_t keylist_isUpdate;
// Wait key list update.
while (keylist_isUpdate == 0)
{
__asm__ volatile ("sleep");
}
return (0);
}

View File

@ -1,189 +0,0 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/display.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
// Internal TTY object.
extern struct tty_s tty;
static void tty_vertical_update(void)
{
// Get next line.
tty.cursor.y =
(tty.cursor.y + 1 <= tty.cursor.max.y)
? tty.cursor.y + 1
: 0;
// Wipe new line.
memset(tty.buffer[tty.cursor.y], '\0', tty.cursor.max.x);
}
static int tty_horizontal_update(void)
{
tty.cursor.x = tty.cursor.x + 1;
if (tty.cursor.x >= tty.cursor.max.x)
{
tty_vertical_update();
tty.cursor.x = 0;
return (1);
}
return (0);
}
// Line discipline :D
static ssize_t tty_buffer_update(const uint8_t *buffer, size_t count)
{
int16_t offset;
ssize_t i;
i = -1;
while (++i < (ssize_t)count)
{
// Check bell char.
if (buffer[i] == '\a')
{
// TODO
continue;
}
// Check backspace.
if (buffer[i] == '\b')
{
if (tty.cursor.x > 0)
tty.cursor.x = tty.cursor.x - 1;
tty.buffer[tty.cursor.y][tty.cursor.x] = '\0';
continue;
}
// Check horizotal tab.
if (buffer[i] == '\t')
{
// Check if we need a new line or not.
offset = 5 - (tty.cursor.x - ((tty.cursor.x / 5) * 5));
if (tty.cursor.x + offset < tty.cursor.max.x)
{
memset(&tty.buffer[tty.cursor.y][tty.cursor.x], ' ', offset);
tty.cursor.x = tty.cursor.x + offset;
continue;
}
// If a new line is required char.
// Generate a new line.
tty.cursor.x = 0;
tty_vertical_update();
continue;
}
// Check new line char.
if (buffer[i] == '\n')
{
tty.cursor.x = 0;
tty_vertical_update();
continue;
}
// Check 'form feed' and 'vertical tab' char.
// @note: for now this character is interpreted like '\v'
if (buffer[i] == '\f' || buffer[i] == '\v')
{
tty_vertical_update();
memset(tty.buffer[tty.cursor.y], ' ', tty.cursor.x);
continue;
}
// Check carriage return.
if (buffer[i] == '\r') { tty.cursor.x = 0; continue;}
// Update TTY buffer char.
tty.buffer[tty.cursor.y][tty.cursor.x] = buffer[i];
tty_horizontal_update();
}
return (i);
}
// FIXME: this function is device-specific !
// TODO: Update me ?
static void tty_display(void)
{
int saved_start;
int line_len;
int scolumn;
int srow;
int line;
int start;
int i;
// Start atomic operation.
atomic_start();
// Save display "context".
display_ioctl(DISPLAY_IOCTL_GETY, &srow);
display_ioctl(DISPLAY_IOCTL_GETX, &scolumn);
// Clear Display
// TODO: IOCTL to disable auto put on screen.
display_ioctl(DISPLAY_IOCTL_CLEAR);
// Get the "first" line and number of line.
// @note: circular buffer.
line = 0;
start = tty.cursor.y;
while (++line < DISPLAY_VCHAR_MAX)
{
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty.cursor.max.y : start - 1;
// Check if the line existe.
if (tty.buffer[start][0] == '\0')
{
start = saved_start;
break;
}
}
// Display "on-screen" string lines.
i = -1;
while (++i < line)
{
// Set display cursor.
display_ioctl(DISPLAY_IOCTL_SETX, 0);
display_ioctl(DISPLAY_IOCTL_SETY, i);
// Get / check line lenght.
line_len = strnlen(tty.buffer[start], tty.cursor.max.x);
if (line_len == 0)
continue;
// Display line.
tty.primitives.write(tty.buffer[start], line_len);
// Get "next" line.
start = (start + 1 > tty.cursor.max.y) ? 0 : start + 1;
}
// Display on screen.
display_ioctl(DISPLAY_IOCTL_DISPLAY);
// Restore display "context"
display_ioctl(DISPLAY_IOCTL_SETX, scolumn);
display_ioctl(DISPLAY_IOCTL_SETY, srow);
// End atomic operation
atomic_stop();
}
ssize_t tty_write(void *inode, const void *buffer, size_t count)
{
ssize_t written;
// Uopdate internal buffer and display
// TTY on the screen.
written = tty_buffer_update(buffer, count);
tty_display();
// Return the number of char written into
// TTY's internal buffer.
return (written);
}

View File

@ -1,15 +1,20 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/display.h>
#include <kernel/devices/keyboard.h>
#include <kernel/util/string.h>
// Internal TTY object.
struct tty_s tty;
//TODO: MULTIPLE OPEN !!!!
//TODO: SHARED TTY DEVICE !!!!
void *tty_open(dev_t major, dev_t minor)
{
int lines;
// TODO: handle major / minor ?
(void)major;
(void)minor;
// Initialize TTY cursor.
tty.cursor.x = 0;
tty.cursor.y = 0;
@ -21,15 +26,5 @@ void *tty_open(dev_t major, dev_t minor)
lines = TTY_BUFFER_LINES;
while (--lines >= 0)
memset(tty.buffer[lines], '\0', TTY_BUFFER_COLUMNS);
// Set TTY primitives
// TODO: Add USB primitives
// TODO: update this part.
tty.primitives.write = &display_write;
tty.primitives.read = &keyboard_read;
// Call TTY primitives constructor
keyboard_open();
display_open();
return (&tty);
}

View File

@ -1,12 +1,12 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/keyboard.h>
#include <kernel/context.h>
#include <kernel/syscall.h>
#include <kernel/drivers/keyboard.h>
#include <kernel/drivers/timer.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/util/timer.h>
#include <kernel/util/casio.h>
#include <kernel/context.h>
#include <kernel/syscall.h>
// Intenral functions
static void wait_keyboard_event(void);
@ -21,15 +21,18 @@ static void cursor_callback(struct keyboard_obj_s *keyboard);
ssize_t tty_read(void *inode, void *buffer, size_t count)
{
extern struct keycache_s *keylist;
extern struct tty_s tty;
struct keycache_s *keynode;
struct keyboard_obj_s keyboard;
struct tty_s *tty;
int first_key;
int timer_fd;
// Check potential error.
if (count < 2)
return (0);
// get tty device
tty = inode;
// Initialize internal struc.
memset(buffer, '\0', count);
@ -41,8 +44,8 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
keyboard.cvisible = 0;
// save TTY informations.
keyboard.saved.tty.cursor.x = tty.cursor.x;
keyboard.saved.tty.cursor.y = tty.cursor.y;
keyboard.saved.tty.cursor.x = tty->cursor.x;
keyboard.saved.tty.cursor.y = tty->cursor.y;
// Initialize timer for cursor.
// FIXME: find real ticks value !!
@ -227,7 +230,6 @@ static int check_special(struct keyboard_obj_s *keyboard, key_t key)
static void tty_buffer_display(struct keyboard_obj_s *keyboard)
{
extern struct tty_s tty;
size_t size;
// Restore TTY X/Y axis positions.
@ -315,7 +317,6 @@ static int buffer_insert(struct keyboard_obj_s *keyboard, char n)
static void cursor_callback(struct keyboard_obj_s *keyboard)
{
extern struct tty_s tty;
int x;
int y;

View File

@ -0,0 +1,171 @@
#include <kernel/devices/tty.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
/* tty_vertical_update() - Check / update TTY vertical cursor */
static void tty_vertical_update(struct tty_s *tty)
{
// Get next line.
tty->cursor.y = 0;
if (tty->cursor.y + 1 <= tty->cursor.max.y)
tty->cursor.y = tty->cursor.y + 1;
// Wipe new line.
memset(tty->buffer[tty->cursor.y], '\0', tty->cursor.max.x);
}
/* tty_horizontal_update() - Check / update TTY horizotal cursor */
static int tty_horizontal_update(struct tty_s *tty)
{
tty->cursor.x = tty->cursor.x + 1;
if (tty->cursor.x >= tty->cursor.max.x)
{
tty_vertical_update(tty);
tty->cursor.x = 0;
return (1);
}
return (0);
}
/* tty_buffer_update() - Line discipline */
static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_t count)
{
int16_t offset;
ssize_t i;
i = -1;
while (++i < (ssize_t)count)
{
// Check bell char.
if (buffer[i] == '\a')
{
// TODO
continue;
}
// Check backspace.
if (buffer[i] == '\b')
{
if (tty->cursor.x > 0)
tty->cursor.x = tty->cursor.x - 1;
tty->buffer[tty->cursor.y][tty->cursor.x] = '\0';
continue;
}
// Check horizotal tab.
if (buffer[i] == '\t')
{
// Check if we need a new line or not.
offset = 5 - (tty->cursor.x - ((tty->cursor.x / 5) * 5));
if (tty->cursor.x + offset < tty->cursor.max.x)
{
memset(&tty->buffer[tty->cursor.y][tty->cursor.x], ' ', offset);
tty->cursor.x = tty->cursor.x + offset;
continue;
}
// If a new line is required char.
// Generate a new line.
tty->cursor.x = 0;
tty_vertical_update(tty);
continue;
}
// Check new line char.
if (buffer[i] == '\n')
{
tty->cursor.x = 0;
tty_vertical_update(tty);
continue;
}
// Check 'form feed' and 'vertical tab' char.
// @note: for now this character is interpreted like '\v'
if (buffer[i] == '\f' || buffer[i] == '\v')
{
tty_vertical_update(tty);
memset(tty->buffer[tty->cursor.y], ' ', tty->cursor.x);
continue;
}
// Check carriage return.
if (buffer[i] == '\r') { tty->cursor.x = 0; continue;}
// Update TTY buffer char.
tty->buffer[tty->cursor.y][tty->cursor.x] = buffer[i];
tty_horizontal_update(tty);
}
return (i);
}
// FIXME: this function is device-specific !
// TODO: Update me ?
static void tty_display(struct tty_s *tty)
{
int saved_start;
int line_len;
int line;
int start;
int y;
// Start atomic operation.
atomic_start();
// Get the "first" line and number of line.
// @note: circular buffer.
line = 0;
start = tty->cursor.y;
while (++line < DISPLAY_VCHAR_MAX)
{
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty->cursor.max.y : start - 1;
// Check if the line existe.
if (tty->buffer[start][0] == '\0')
{
start = saved_start;
break;
}
}
// Display "on-screen" string lines.
y = -1;
while (++y < line)
{
// Get / check line lenght.
line_len = strnlen(tty->buffer[start], tty->cursor.max.x);
if (line_len == 0)
continue;
// Display line.
kvram_print(0, y, tty->buffer[start], line_len);
// Get "next" line.
start = (start + 1 > tty->cursor.max.y) ? 0 : start + 1;
}
// Display on screen.
kvram_display();
// Stop atomic operation
atomic_stop();
}
/* tty_write() - TTY write primitive ! */
ssize_t tty_write(void *inode, const void *buffer, size_t count)
{
ssize_t written;
// Update internal buffer and display
// TTY on the screen.
written = tty_buffer_update(inode, buffer, count);
// TODO: Monotonic display ?
tty_display(inode);
// Return the number of char written into
// TTY's internal buffer.
return (written);
}

View File

@ -0,0 +1,34 @@
#include <kernel/drivers/keyboard.h>
/*
** Internal cache, used like chained list.
**
** @note:
** The KEYSC have 6 key data 16-bits registers
** this is why we used 6 * 16 = 96 cache slot.
*/
struct keycache_s keycache[96];
struct keycache_s *keylist;
/*
** keycache_init()
**
** @info
** Constructor used by the kernel during the
** bootstrap part. It will initialize keycache
** and the chained list.
** This function sould not be called anymore.
*/
__attribute__((constructor))
static void keycache_init(void)
{
int i;
i = 96;
while (--i >= 0)
{
keycache[i].keycode = KEY_UNUSED;
keycache[i].next = NULL;
}
keylist = NULL;
}

View File

@ -1,30 +1,37 @@
#include <kernel/devices/keyboard.h>
// Internal cache, used like chained list.
// @note:
// The KEYSC have 6 key data 16-bits registers
// this is why we used 6 * 16 = 96 cache slot.
static struct keycache_s keycache[96];
// chained list.
// FIXME: avoid reentrace
struct keycache_s *keylist;
#include <kernel/drivers/keyboard.h>
#include <kernel/util/atomic.h>
/* keycache_alloc() - Try to alloc a new keycache node */
static struct keycache_s *keycache_alloc(void)
{
extern struct keycache_s keycache[96];
void *node;
int i;
// Start atomic operations
atomic_start();
// Try to find free slot
i = 96;
node = NULL;
while (--i >= 0)
{
if (keycache[i].keycode == KEY_UNUSED)
return (&keycache[i]);
{
node = &keycache[i];
break;
}
}
return (NULL);
// Stop atomic operations
atomic_stop();
return (node);
}
/* keycache_update() - Add / update key code node */
void keycache_update(int row, int column, uint8_t key_frame)
{
extern struct keycache_s *keylist;
struct keycache_s *current_node;
struct keycache_s *new_node;
uint8_t keycode;
@ -32,6 +39,9 @@ void keycache_update(int row, int column, uint8_t key_frame)
// Generate keycode.
keycode = KEYCODE_GEN(row, column);
// Start atomic operations
atomic_start();
// Try to fint the key node.
current_node = keylist;
while (current_node != NULL)
@ -40,6 +50,7 @@ void keycache_update(int row, int column, uint8_t key_frame)
if (current_node->keycode == keycode)
{
current_node->key_frame = key_frame;
atomic_stop();
return;
}
@ -49,25 +60,33 @@ void keycache_update(int row, int column, uint8_t key_frame)
// If no node is found, create new node.
new_node = keycache_alloc();
if (new_node == NULL)
return;
if (new_node != NULL)
{
// Fill new node
new_node->keycode = keycode;
new_node->key_frame = key_frame;
new_node->counter = 0;
// Fill new node
new_node->keycode = keycode;
new_node->key_frame = key_frame;
new_node->counter = 0;
// And place it on the first node because
// the first node designates the last key
// pressed.
new_node->next = keylist;
keylist = new_node;
}
// And place it on the first node because
// the first node designates the last key
// pressed.
new_node->next = keylist;
keylist = new_node;
// Stop atomic operations
atomic_stop();
}
/* keycache_clean() - Remove dirty node */
void keycache_clean(int key_frame)
{
extern struct keycache_s *keylist;
struct keycache_s **current_node;
// Start atomic operations
atomic_start();
current_node = &keylist;
while (*current_node != NULL)
{
@ -85,18 +104,7 @@ void keycache_clean(int key_frame)
(*current_node)->counter = (*current_node)->counter + 1;
current_node = &(*current_node)->next;
}
}
// Contructor.
void keycache_init(void)
{
int i;
i = 96;
while (--i >= 0)
{
keycache[i].keycode = KEY_UNUSED;
keycache[i].next = NULL;
}
keylist = NULL;
// Stop atomic operations
atomic_stop();
}

View File

@ -1,5 +1,5 @@
#include <kernel/hardware/tmu.h>
#include <kernel/util/timer.h>
#include <kernel/drivers/timer.h>
void timer_handler(void)
{

View File

@ -1,56 +0,0 @@
#include <kernel/devices/ubc.h>
#include <kernel/devices/display.h>
#include <kernel/hardware/ubc.h>
#include <kernel/syscall.h>
#include <kernel/util/extra.h>
// Internal function.
extern void menu_context(ubc_session_t *session);
extern void menu_disassembly(ubc_session_t *session);
void ubc_module_handler(int action)
{
/* dclear();
dprint(0, 0, "spc = %p", action);
dupdate();
for (int i = 0 ; i < 4000000 ; i = i + 1);
*/ //TODO stop all clock / timer.
}
void ubc_handler(struct ubc_context_s *context, int channel)
{
/* void (*menu)(ubc_session_t *session);
ubc_session_t session;
// Initialize new session.
session.key = 0;
session.channel = channel;
session.context = context;
session.menu.context.cursor = 0;
session.menu.disassembly.vcursor = -(DISPLAY_VCHAR_MAX >> 1);
session.menu.disassembly.hcursor = 0;
// Initialize menu function.
menu = &menu_disassembly;
// Main loop.
while (session.key != KEY_CTRL_EXIT)
{
menu(&session);
casio_GetKey(&session.key);
switch (session.key)
{
case KEY_CTRL_F1: menu = &menu_disassembly; break;
case KEY_CTRL_F2: menu = &menu_context; break;
}
}*/
// Update UBC
SH7305_UBC.CBR0.CE = 0; // Disable channel.
// SH7305_UBC.CAR0 = context->spc; // Update break address.
// SH7305_UBC.CAMR0 = 0x00000000; // Update break address.
// SH7305_UBC.CBR0.CE = 1; // Enable channel.
icbi((void*)0xa0000000);
}

View File

@ -1,115 +0,0 @@
.section ".ubc.handler", "awx", @progbits
.global _ubc_handler_pre
.type _ubc_handler_pre, @function
.extern _ubc_handler
.extern _ubc_module_handler
.align 2
_ubc_handler_pre:
! Stack management.
mov.l r9, @-r15 ! Save r9 register.
mov.l r8, @-r15 ! Save r8 register.
sts.l pr, @-r15 ! Save pr regsiter.
! Generate "programe" context (used by the UBC handler)
stc.l spc, @-r15 ! Get SPC register.
stc.l ssr, @-r15 ! Get SSR register.
sts.l mach, @-r15 ! Get MACH register.
sts.l macl, @-r15 ! Get MACL register.
stc.l gbr, @-r15 ! Get GBR register.
.word 0b0100111100110010 ! Get SGR register (save r15 address befor break) "stc.l sgr, @-r15"
mov.l r14, @-r15 ! Get "program" r14 register.
mov.l r13, @-r15 ! Get "program" r13 register.
mov.l r12, @-r15 ! Get "program" r12 register.
mov.l r11, @-r15 ! Get "program" r11 register.
mov.l r10, @-r15 ! Get "program" r10 register.
mov.l r9, @-r15 ! Get "program" r9 register.
mov.l r8, @-r15 ! Get "program" r8 register.
stc.l R7_BANK, @-r15 ! Get "program" r7 regsiter.
stc.l R6_BANK, @-r15 ! Get "program" r6 regsiter.
stc.l R5_BANK, @-r15 ! Get "program" r5 regsiter.
stc.l R4_BANK, @-r15 ! Get "program" r4 regsiter.
stc.l R3_BANK, @-r15 ! Get "program" r3 regsiter.
stc.l R2_BANK, @-r15 ! Get "program" r2 regsiter.
stc.l R1_BANK, @-r15 ! Get "program" r1 regsiter.
stc.l R0_BANK, @-r15 ! Get "program" r0 regsiter.
! We need to stop (and save) all clocks / timers
! before do any job.
mov.l .ubc_module_handler, r0 ! Get high level abstraction for handle hardware module.
jsr @r0 ! call ubc_module(MODULE_STOP)
mov #0, r4 ! (db) r4 = MODULE_STOP
! Get which channel is trigger and clear interrupt Flags.
mov.l .ubc_ccmfr, r0 ! Get UBC.CCMFR register
mov.l @r0, r9 ! r5 = UBC.CCMFR. (save register)
mov #0, r1 ! r2 = 0x00000000 (clear flags)
mov.l r1, @r0 ! Clear UBC.CCMFR.MF1 = 0 and UBC.CCMFR.MF1 = 0
mov.l .icbi_addr, r2 ! Get P2 area for ICBI instruction.
.word 0b0000001011100011 ! SH4 instruction "icbi @r2"
! Allow / unblock interrupt and switch register bank !
stc sr, r8 ! Save SR register.
mov r8, r1 ! Get SR register.
mov.l .sr_mask, r0 ! Get SR mask for SR.BL, SR.IMASK and SR.RB
and r0, r1 ! SR.BL = 0, SR.IMASK = 0b0000 and SR.RB = 0
ldc r1, sr ! Update SR register.
! Call high-level abstraction
mov r15, r4 ! Send UBC context object to the abstraction.
mov r9, r5 ! Send which channel is trigger.
mov.l .ubc_handler, r0 ! Get high-level abstraction address
jsr @r0 ! Jump into it.
nop ! (db) nop.
! Block interrupt and switch
! register bank
ldc r8, sr ! Restore SR register (with SR.BL = 1, SR.IMASK = 0b1111, SR.RB = 1)
! Restore "program" context.
ldc.l @r15+, R0_BANK ! Restore "program" r0 regsiter.
ldc.l @r15+, R1_BANK ! Restore "program" r1 regsiter.
ldc.l @r15+, R2_BANK ! Restore "program" r2 regsiter.
ldc.l @r15+, R3_BANK ! Restore "program" r3 regsiter.
ldc.l @r15+, R4_BANK ! Restore "program" r4 regsiter.
ldc.l @r15+, R5_BANK ! Restore "program" r5 regsiter.
ldc.l @r15+, R6_BANK ! Restore "program" r6 regsiter.
ldc.l @r15+, R7_BANK ! Restore "program" r7 regsiter.
mov.l @r15+, r8 ! Restore "program" r8 regsiter.
mov.l @r15+, r9 ! Restore "program" r9 regsiter.
mov.l @r15+, r10 ! Restore "program" r10 regsiter.
mov.l @r15+, r11 ! Restore "program" r11 regsiter.
mov.l @r15+, r12 ! Restore "program" r12 regsiter.
mov.l @r15+, r13 ! Restore "program" r13 regsiter.
mov.l @r15+, r14 ! Restore "program" r14 regsiter.
.word 0b0100111100110110 ! Restore SGR regsiter. "ldc.l @r15+, sgr"
ldc.l @r15+, gbr ! Get GBR register.
lds.l @r15+, macl ! Get MACL register.
lds.l @r15+, mach ! Get MACH register.
ldc.l @r15+, ssr ! Restore SSR regsiter.
ldc.l @r15+, spc ! Restore SPC regsiter.
! Retore and restart clock / timers
stc spc, r4 ! (db) r4 = MODULE_START
mov.l .ubc_module_handler, r0 ! Get high level abstraction for handle hardware module.
jsr @r0 ! call ubc_module(MODULE_START)
nop
! Clean exit.
lds.l @r15+, pr ! Restor PR register.
mov.l @r15+, r8 ! Restore r8 register.
mov.l @r15+, r9 ! Restore r8 register.
rte ! Interrupt Exit.
nop ! (db) Safety first.
.align 4
.ubc_handler: .long _ubc_handler
.ubc_module_handler: .long _ubc_module_handler
.ubc_ccmfr: .long 0xff200600
.icbi_addr: .long 0xa0000000
.sr_mask: .long ~(0x300000f0)
.end