PGX Loader and Interrupt Update
PGX loader is working, updated interrupt code to support keyboard interrupts (currently using Mo keyboard)
This commit is contained in:
parent
6beafc1c7e
commit
ee4d8db4fa
15
samples/HelloPGX/README.md
Normal file
15
samples/HelloPGX/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Sample: HelloPGX #
|
||||
|
||||
One of the simple executable formats that the FoenixMCP supports is the PGX format inherited from the original Foenix stock kernel. This assembly demo uses the VASM assembler to create a simple PGX file that prints "Hello, world."
|
||||
|
||||
## Building ##
|
||||
|
||||
Make sure that the VASM binaries are in your executable path and then use the `build.bat` file to create the PGX file.
|
||||
|
||||
## PGX Format ##
|
||||
|
||||
PGX is a very simple binary file format. It is designed to load a single segment of code or data to a single block of memory. A PGX file begins with a small header (eight bytes), and the remainder of the file is the data to load:
|
||||
|
||||
* The first three bytes are the format signature: the ASCII characters "PGX".
|
||||
* The fourth byte is the version and target CPU code. Currently, only format 0 is used. There are two CPU codes supported: 1 = 65816, 2 = 68000.
|
||||
* The next four bytes are the target address for loading the data (i.e. the address of the first byte of the data). The address is to be written in the 32-bit integer format native for the target processor. For the 65816, the address will be in little-endian format. For the 68000 processors, the address will be in big-endian format.
|
2
samples/HelloPGX/build.bat
Normal file
2
samples/HelloPGX/build.bat
Normal file
|
@ -0,0 +1,2 @@
|
|||
@echo off
|
||||
vasmm68k_mot -Fbin -L hello.lst -o hello.pgx hello.s
|
57
samples/HelloPGX/hello.lst
Normal file
57
samples/HelloPGX/hello.lst
Normal file
|
@ -0,0 +1,57 @@
|
|||
F00:0001 ;;;
|
||||
F00:0002 ;;; Sample PGX Program
|
||||
F00:0003 ;;;
|
||||
F00:0004
|
||||
F00:0005 org $010000
|
||||
F00:0006
|
||||
F00:0007 dc.b "PGX", $02
|
||||
S01:00010000: 50 47 58
|
||||
S01:00010003: 02
|
||||
F00:0008 dc.l _start
|
||||
S01:00010004: 00 01 00 08
|
||||
F00:0009
|
||||
F00:0010 _start: move.l #_greet_end-_greet+1,d3 ; Length of the message
|
||||
S01:00010008: 76 0E
|
||||
F00:0011 move.l #_greet,d2 ; Pointer to the message
|
||||
S01:0001000A: 24 3C 00 01 00 18
|
||||
F00:0012 clr.l d1 ; Write to channel #0 (main screen)
|
||||
S01:00010010: 72 00
|
||||
F00:0013 move.l #$14,d0 ; sys_chan_write_b
|
||||
S01:00010012: 70 14
|
||||
F00:0014 trap #15 ; Call it
|
||||
S01:00010014: 4E 4F
|
||||
F00:0015
|
||||
F00:0016 _lock: bra _lock
|
||||
S01:00010016: 60 FE
|
||||
F00:0017
|
||||
F00:0018 _greet: dc.b "Hello, world!"
|
||||
S01:00010018: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21
|
||||
F00:0019 _greet_end: dc.b 0
|
||||
S01:00010025: 00
|
||||
F00:0020
|
||||
|
||||
|
||||
Sections:
|
||||
S01 seg10000
|
||||
|
||||
|
||||
Sources:
|
||||
F00 hello.s
|
||||
|
||||
|
||||
Symbols:
|
||||
_lock EXPR(65558=0x10016) ABS
|
||||
_greet EXPR(65560=0x10018) ABS
|
||||
_greet_end EXPR(65573=0x10025) ABS
|
||||
_start EXPR(65544=0x10008) ABS
|
||||
_MOVEMBYTES EXPR(0=0x0) INTERNAL
|
||||
MOVEMSIZE EXPR(0=0x0) INTERNAL
|
||||
_MOVEMREGS EXPR(0=0x0) INTERNAL
|
||||
__LINE__ EXPR(20=0x14) INTERNAL
|
||||
__FO EXPR(0=0x0) INTERNAL
|
||||
__RS EXPR(0=0x0) INTERNAL
|
||||
REPTN EXPR(-1=0xffffffff) INTERNAL
|
||||
__VASM EXPR(1=0x1) INTERNAL
|
||||
__UNIXFS EXPR(0=0x0) INTERNAL
|
||||
|
||||
There have been no errors.
|
BIN
samples/HelloPGX/hello.pgx
Normal file
BIN
samples/HelloPGX/hello.pgx
Normal file
Binary file not shown.
19
samples/HelloPGX/hello.s
Normal file
19
samples/HelloPGX/hello.s
Normal file
|
@ -0,0 +1,19 @@
|
|||
;;;
|
||||
;;; Sample PGX Program
|
||||
;;;
|
||||
|
||||
org $010000
|
||||
|
||||
dc.b "PGX", $02
|
||||
dc.l _start
|
||||
|
||||
_start: move.l #_greet_end-_greet+1,d3 ; Length of the message
|
||||
move.l #_greet,d2 ; Pointer to the message
|
||||
clr.l d1 ; Write to channel #0 (main screen)
|
||||
move.l #$14,d0 ; sys_chan_write_b
|
||||
trap #15 ; Call it
|
||||
|
||||
_lock: bra _lock
|
||||
|
||||
_greet: dc.b "Hello, world!"
|
||||
_greet_end: dc.b 0
|
|
@ -4,22 +4,12 @@
|
|||
#include "syscalls.h"
|
||||
#include "log.h"
|
||||
#include "simpleio.h"
|
||||
#include "cli.h"
|
||||
#include "cli/dos_cmds.h"
|
||||
#include "dev/block.h"
|
||||
#include "dev/fsys.h"
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
/*
|
||||
* Fetch and display the MBR for the specified device:
|
||||
*
|
||||
* Inputs:
|
||||
* drive = "@S" for SDC, "@H" for hard drive
|
||||
*/
|
||||
short cmd_dump_mbr(short screen, char * drive) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
short cmd_dir(short screen, int argc, char * argv[]) {
|
||||
t_file_info my_file;
|
||||
char * path = "";
|
||||
|
@ -84,6 +74,7 @@ short cmd_type(short screen, int argc, char * argv[]) {
|
|||
}
|
||||
} else {
|
||||
log(LOG_ERROR, "Usage: TYPE <path>");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +85,13 @@ short cmd_type(short screen, int argc, char * argv[]) {
|
|||
short cmd_load(short screen, int argc, char * argv[]) {
|
||||
if (argc > 1) {
|
||||
long start = 0;
|
||||
short result = fsys_load(argv[1], 0x30000, &start);
|
||||
long destination = 0;
|
||||
|
||||
if (argc > 2) {
|
||||
destination = cli_eval_number(argv[2]);
|
||||
}
|
||||
|
||||
short result = fsys_load(argv[1], destination, &start);
|
||||
if (result == 0) {
|
||||
if (start != 0) {
|
||||
log(LOG_INFO, "Loaded file with a start adddress.");
|
||||
|
@ -103,10 +100,12 @@ short cmd_load(short screen, int argc, char * argv[]) {
|
|||
}
|
||||
} else {
|
||||
log_num(LOG_ERROR, "Unable to open file: ", result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
log(LOG_ERROR, "Usage: LOAD <path>");
|
||||
log(LOG_ERROR, "Usage: LOAD <path> [<destination>]");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,6 @@
|
|||
#ifndef __DOS_CMDS_H
|
||||
#define __DOS_CMDS_H
|
||||
|
||||
/*
|
||||
* Fetch and display the MBR for the specified device:
|
||||
*
|
||||
* Inputs:
|
||||
* drive = "@S" for SDC, "@H" for hard drive
|
||||
*/
|
||||
extern short cmd_dump_mbr(char * drive);
|
||||
|
||||
/*
|
||||
* List the directory at the given path
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@ short con_write_b(p_channel chan, uint8_t b) {
|
|||
short con_read_b(p_channel chan) {
|
||||
char c;
|
||||
do {
|
||||
c = kbd_getc_poll();
|
||||
c = kbdmo_getc();
|
||||
} while (c == 0);
|
||||
|
||||
// Echo the character to the screen
|
||||
|
|
118
src/dev/fsys.c
118
src/dev/fsys.c
|
@ -7,12 +7,14 @@
|
|||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "log.h"
|
||||
#include "syscalls.h"
|
||||
#include "fsys.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "dev/channel.h"
|
||||
#include "simpleio.h"
|
||||
#include "errors.h"
|
||||
|
||||
#define MAX_DRIVES 8 /* Maximum number of drives */
|
||||
|
@ -612,6 +614,87 @@ unsigned short atoi_hex(char * hex) {
|
|||
return (atoi_hex_1(hex[0]) << 4 | atoi_hex_1(hex[1]));
|
||||
}
|
||||
|
||||
/*
|
||||
* Loader for the PGX binary file format
|
||||
*
|
||||
* Inputs:
|
||||
* path = the path to the file to load
|
||||
* destination = the destination address (ignored for PGX)
|
||||
* start = pointer to the long variable to fill with the starting address
|
||||
* (0 if not an executable, any other number if file is executable
|
||||
* with a known starting address)
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative number on error
|
||||
*/
|
||||
short fsys_pgx_loader(short chan, long destination, long * start) {
|
||||
const char signature[] = "PGX\x02";
|
||||
unsigned char * chunk = 0;
|
||||
unsigned char * dest = 0;
|
||||
long file_idx = 0;
|
||||
long address = 0;
|
||||
short result = 0;
|
||||
|
||||
TRACE("fsys_pgx_loader");
|
||||
|
||||
chunk = malloc(DEFAULT_CHUNK_SIZE);
|
||||
if (chunk == 0) {
|
||||
result = ERR_OUT_OF_MEMORY;
|
||||
|
||||
} else {
|
||||
/* We have our buffer... start reading chunks into it */
|
||||
short n = 1;
|
||||
|
||||
while (result == 0) {
|
||||
/* Try to read a chunk of data */
|
||||
n = chan_read(chan, chunk, DEFAULT_CHUNK_SIZE);
|
||||
if (n > 0) {
|
||||
short i;
|
||||
|
||||
/* Loop through all the bytes of the chunk that we read */
|
||||
for (i = 0; i < n; i++, file_idx++) {
|
||||
if (file_idx < 4) {
|
||||
/* Check that the first four bytes match the signature for this CPU */
|
||||
if (chunk[i] != signature[i]) {
|
||||
/* If signature does not match, quit */
|
||||
result = ERR_BAD_BINARY;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (file_idx < 8) {
|
||||
/* Parse the next four bytes as the target address */
|
||||
address = (address << 8) + chunk[i];
|
||||
|
||||
} else {
|
||||
/* Treat the remaining bytes as data */
|
||||
if (file_idx == 8) {
|
||||
/* For the first data byte, set our destination pointer */
|
||||
dest = (unsigned char *)address;
|
||||
}
|
||||
|
||||
/* Store the data in the destination address */
|
||||
*dest++ = chunk[i];
|
||||
}
|
||||
}
|
||||
} else if (n < 0) {
|
||||
/* We got an error while reading... pass it to the caller */
|
||||
result = n;
|
||||
break;
|
||||
} else if (n == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start address is the first byte of the data */
|
||||
*start = address;
|
||||
|
||||
if (chunk != 0) {
|
||||
free(chunk);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loader for the Motorola SREC format
|
||||
*
|
||||
|
@ -786,21 +869,23 @@ short fsys_load(const char * path, long destination, long * start) {
|
|||
extension[i] = 0;
|
||||
}
|
||||
|
||||
/* Find the extension */
|
||||
char * point = strrchr(path, '.');
|
||||
if (point != 0) {
|
||||
point++;
|
||||
for (i = 0; i < MAX_EXT; i++) {
|
||||
char c = *point++;
|
||||
if (c) {
|
||||
extension[i] = toupper(c);
|
||||
} else {
|
||||
break;
|
||||
if (destination == 0) {
|
||||
/* Find the extension */
|
||||
char * point = strrchr(path, '.');
|
||||
if (point != 0) {
|
||||
point++;
|
||||
for (i = 0; i < MAX_EXT; i++) {
|
||||
char c = *point++;
|
||||
if (c) {
|
||||
extension[i] = toupper(c);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("fsys_load: ext");
|
||||
log2(LOG_VERBOSE, "fsys_load ext: ", extension);
|
||||
|
||||
if (extension[0] == 0) {
|
||||
if (destination != 0) {
|
||||
|
@ -851,9 +936,15 @@ short fsys_load(const char * path, long destination, long * start) {
|
|||
/* If it opened correctly, load the file */
|
||||
short result = loader(chan, destination, start);
|
||||
fsys_close(chan);
|
||||
|
||||
if (result != 0) {
|
||||
log_num(LOG_ERROR, "Could not load file: ", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
/* File open returned an error... pass it along */
|
||||
log_num(LOG_ERROR, "Could not open file: ", chan);
|
||||
return chan;
|
||||
}
|
||||
}
|
||||
|
@ -877,7 +968,7 @@ short fsys_register_loader(const char * extension, p_file_loader loader) {
|
|||
for (i = 0; i < MAX_LOADERS; i++) {
|
||||
if (g_file_loader[i].status == 0) {
|
||||
g_file_loader[i].status = 1; /* Claim this loader record */
|
||||
g_file_loader[j].loader = loader; /* Set the loader routine */
|
||||
g_file_loader[i].loader = loader; /* Set the loader routine */
|
||||
for (j = 0; j <= MAX_EXT; j++) { /* Clear out the extension */
|
||||
g_file_loader[i].extension[j] = 0;
|
||||
}
|
||||
|
@ -934,8 +1025,9 @@ short fsys_init() {
|
|||
}
|
||||
}
|
||||
|
||||
/* Register the SREC loader */
|
||||
/* Register the built-in binary file loaders */
|
||||
fsys_register_loader("PRS", fsys_srec_loader);
|
||||
fsys_register_loader("PGX", fsys_pgx_loader);
|
||||
|
||||
/* Register the channel driver for files. */
|
||||
|
||||
|
|
|
@ -215,13 +215,13 @@ short kbdmo_init() {
|
|||
kbdmo_flush_out();
|
||||
|
||||
/* Clear out any pending interrupt */
|
||||
// int_clear(INT_KBD_A2560K);
|
||||
//
|
||||
// /* Register a handler for the keyboard */
|
||||
// int_register(INT_KBD_A2560K, kbdmo_handle_irq);
|
||||
//
|
||||
// /* Enable the interrupt for the keyboard */
|
||||
// int_enable(INT_KBD_A2560K);
|
||||
int_clear(INT_KBD_A2560K);
|
||||
|
||||
/* Register a handler for the keyboard */
|
||||
int_register(INT_KBD_A2560K, kbdmo_handle_irq);
|
||||
|
||||
/* Enable the interrupt for the keyboard */
|
||||
int_enable(INT_KBD_A2560K);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ void kbdmo_handle_irq() {
|
|||
*/
|
||||
while ((*KBD_MO_STAT & 0x00ff) != 0) {
|
||||
/* Get a scan code from the input buffer */
|
||||
unsigned char scan_code = *KBD_MO_DATA;
|
||||
unsigned short scan_code = *KBD_MO_DATA;
|
||||
|
||||
if ((scan_code & 0x7fff) != 0) {
|
||||
/* TODO: beep if the input was full or the ring buffer is full */
|
||||
|
|
|
@ -40,4 +40,6 @@ extern char kbdmo_getc_poll();
|
|||
*/
|
||||
extern unsigned short kbdmo_get_scancode_poll();
|
||||
|
||||
extern void kbdmo_handle_irq();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -469,6 +469,9 @@ void kbd_handle_irq() {
|
|||
unsigned char scan_code = *data;
|
||||
unsigned char translated_code;
|
||||
|
||||
/* Clear the pending flag */
|
||||
int_clear(INT_KBD_PS2);
|
||||
|
||||
if (scan_code) {
|
||||
// Make sure the scan code isn't 0 or 128, which are invalid make/break codes
|
||||
if ((scan_code != 0) && (scan_code != 0x80)) {
|
||||
|
@ -763,14 +766,14 @@ short ps2_init() {
|
|||
ps2_flush_out();
|
||||
|
||||
// // Controller selftest...
|
||||
// if (ps2_controller_cmd(PS2_CTRL_SELFTEST) != PS2_RESP_OK) {
|
||||
// ; // return PS2_FAIL_SELFTEST;
|
||||
// }
|
||||
if (ps2_controller_cmd(PS2_CTRL_SELFTEST) != PS2_RESP_OK) {
|
||||
; // return PS2_FAIL_SELFTEST;
|
||||
}
|
||||
//
|
||||
// // Keyboard test
|
||||
// if (ps2_controller_cmd(PS2_CTRL_KBDTEST) != 0) {
|
||||
// ; // return PS2_FAIL_KBDTEST;
|
||||
// }
|
||||
if (ps2_controller_cmd(PS2_CTRL_KBDTEST) != 0) {
|
||||
; // return PS2_FAIL_KBDTEST;
|
||||
}
|
||||
|
||||
// Set scancode translation to set1, enable interrupts on mouse and keyboard
|
||||
ps2_controller_cmd_param(PS2_CTRL_WRITECMD, 0x43);
|
||||
|
|
|
@ -96,7 +96,7 @@ void initialize() {
|
|||
text_init(); // Initialize the text channels
|
||||
DEBUG("Foenix/MCP starting up...");
|
||||
|
||||
log_setlevel(LOG_ERROR);
|
||||
log_setlevel(LOG_VERBOSE);
|
||||
|
||||
/* Initialize the interrupt system */
|
||||
int_init();
|
||||
|
@ -146,11 +146,11 @@ void initialize() {
|
|||
|
||||
// At this point, we should be able to call into to console to print to the screens
|
||||
|
||||
if (res = ps2_init()) {
|
||||
print_error(0, "FAILED: PS/2 keyboard initialization", res);
|
||||
} else {
|
||||
DEBUG("PS/2 keyboard initialized.");
|
||||
}
|
||||
// if (res = ps2_init()) {
|
||||
// print_error(0, "FAILED: PS/2 keyboard initialization", res);
|
||||
// } else {
|
||||
// DEBUG("PS/2 keyboard initialized.");
|
||||
// }
|
||||
|
||||
if (res = kbdmo_init()) {
|
||||
print_error(0, "FAILED: A2560K built-in keyboard initialization", res);
|
||||
|
@ -171,7 +171,7 @@ void initialize() {
|
|||
}
|
||||
|
||||
/* Enable all interrupts */
|
||||
// int_enable_all();
|
||||
int_enable_all();
|
||||
}
|
||||
|
||||
// void try_mo_scancodes(short screen) {
|
||||
|
@ -259,6 +259,18 @@ void int_sof_a() {
|
|||
int_clear(SOF_A_INT00);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handler for Channel A's Start of Frame
|
||||
*/
|
||||
void change_led() {
|
||||
g_sof_counter++;
|
||||
|
||||
long counter_mod = g_sof_counter % 2;
|
||||
|
||||
*RGB_LED_L = 0x0000;
|
||||
*RGB_LED_H = 0xFF00;
|
||||
}
|
||||
|
||||
void try_format(short screen, char * path) {
|
||||
FATFS fs; /* Filesystem object */
|
||||
FIL fil; /* File object */
|
||||
|
@ -368,6 +380,14 @@ int main(int argc, char * argv[]) {
|
|||
print(CDEV_CONSOLE, "Text Channel A\n");
|
||||
print(CDEV_EVID, "Text Channel B\n");
|
||||
|
||||
print(CDEV_CONSOLE, "MASK_GRP1: ");
|
||||
print_hex_16(CDEV_CONSOLE, *MASK_GRP1);
|
||||
print(CDEV_CONSOLE, "\n");
|
||||
|
||||
print(CDEV_CONSOLE, "MASK_PEND1: ");
|
||||
print_hex_16(CDEV_CONSOLE, *PENDING_GRP1);
|
||||
print(CDEV_CONSOLE, "\n");
|
||||
|
||||
// uart_test_send(0);
|
||||
|
||||
/* Register a handler for the SOF interrupt and enable it */
|
||||
|
|
3573
src/foenixmcp.s68
3573
src/foenixmcp.s68
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@
|
|||
#ifndef __ERRORS_H
|
||||
#define __ERRORS_H
|
||||
|
||||
#define MAX_ERROR_NUMBER 12 // Largest (absolute value) of the error number
|
||||
#define MAX_ERROR_NUMBER 15 // Largest (absolute value) of the error number
|
||||
|
||||
#define ERR_GENERAL -1 // A general error condition
|
||||
#define DEV_ERR_BADDEV -2 // Device number is bad (too big or no device assigned)
|
||||
|
@ -21,5 +21,6 @@
|
|||
#define ERR_BAD_HANDLE -12 // The handle passed was not valid
|
||||
#define ERR_BAD_EXTENSION -13 // The path to load did not have an extension that matched registered loaders
|
||||
#define ERR_OUT_OF_MEMORY -14 // Unable to allocate more memory
|
||||
#define ERR_BAD_BINARY -15 // Bad binary file format... i.e. binary format does not match expectations
|
||||
|
||||
#endif
|
||||
|
|
|
@ -98,6 +98,7 @@ typedef void (*p_int_handler)();
|
|||
#define EXT_OPL3_INT25 0x0020 // External OPL3 Interrupt
|
||||
#define RESERVED5 0x0040 // No interrupt - Reserved
|
||||
#define RESERVED6 0x0080 // No interrupt - Reserved
|
||||
|
||||
#define BEATRIX_INT28 0x0100 // Beatrix Interrupt 0
|
||||
#define BEATRIX_INT29 0x0200 // Beatrix Interrupt 1
|
||||
#define BEATRIX_INT2A 0x0400 // Beatrix Interrupt 2
|
||||
|
|
|
@ -138,22 +138,27 @@ autovec1: movem.l d0-d7/a0-a6,-(a7)
|
|||
movem.l (a7)+,d0-d7/a0-a6
|
||||
rte
|
||||
|
||||
;
|
||||
; Autovector #1: Used by VICKY III Channel A interrupts
|
||||
;
|
||||
autovec2: movem.l d0-d7/a0-a6,-(a7)
|
||||
jsr _int_vicky_channel_a ; Call the dispatcher for Channel A interrupts
|
||||
movem.l (a7)+,d0-d7/a0-a6
|
||||
rte
|
||||
|
||||
;
|
||||
; Interrupt Vector 0x10 -- SuperIO Keyboard
|
||||
;
|
||||
interrupt_x10:
|
||||
movem.l d0-d7/a0-a6,-(a7) ; Save all the registers
|
||||
;lea _g_int_handler,a0 ; Look in the interrupt handler table
|
||||
;move.w #($10<<2),d0 ; Offset to interrupt #16
|
||||
;movea.l (0,a0,d0),a1 ; Get the address of the handler
|
||||
;beq done_intx10 ; If there isn't one, just return
|
||||
|
||||
; moveq #0,d2
|
||||
; moveq #'!',d3
|
||||
; moveq #$14,d1
|
||||
; trap #13
|
||||
; move.l #$00C60001,a0
|
||||
; move.l #$00C60000,a1
|
||||
; move.b (a0),d0
|
||||
; addq.b #1,d0
|
||||
; move.b d0,(a1)
|
||||
|
||||
jsr _kbd_handle_irq ; If there is, call it.
|
||||
; jsr _kbd_handle_irq ; If there is, call it.
|
||||
|
||||
done_intx10 movem.l (a7)+,d0-d7/a0-a6 ; Restore the registers
|
||||
rte
|
||||
|
@ -168,29 +173,18 @@ interrupt_x11:
|
|||
; ; movea.l (0,a0,d0),a1 ; Get the address of the handler
|
||||
; ; beq done_intx10 ; If there isn't one, just return
|
||||
;
|
||||
; moveq #0,d2
|
||||
; moveq #'@',d3
|
||||
; moveq #$14,d1
|
||||
; trap #13
|
||||
;
|
||||
; ; jsr (a1) ; If there is, call it.
|
||||
|
||||
; moveq #0,d2
|
||||
; moveq #'!',d3
|
||||
; moveq #$14,d1
|
||||
; trap #13
|
||||
move.l #$00C00102,a0 ; Clear the pending flag
|
||||
move.w (a0),d0
|
||||
andi.w #$0002,d0
|
||||
move.w d0,(a0)
|
||||
|
||||
jsr _kbdmo_handle_irq
|
||||
|
||||
done_intx11 movem.l (a7)+,d0-d7/a0-a6 ; Restore the registers
|
||||
rte
|
||||
|
||||
;
|
||||
; Autovector #1: Used by VICKY III Channel A interrupts
|
||||
;
|
||||
autovec2: movem.l d0-d7/a0-a6,-(a7)
|
||||
jsr _int_vicky_channel_a ; Call the dispatcher for Channel A interrupts
|
||||
movem.l (a7)+,d0-d7/a0-a6
|
||||
rte
|
||||
|
||||
;
|
||||
; Unimplemented Exception Handler -- just return
|
||||
;
|
||||
|
|
8572
src/mapfile
8572
src/mapfile
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,16 @@
|
|||
*** Core system calls
|
||||
***/
|
||||
|
||||
/*
|
||||
* Stop running the current user program
|
||||
*
|
||||
* Inputs:
|
||||
* result = the result code to return to the kernel
|
||||
*/
|
||||
void sys_exit(short result) {
|
||||
syscall(KFN_EXIT, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable all interrupts
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue