Channel Redirection

Added basic support for redirecting channel IDs to other channels (sys_chan_swap and sys_chan_dev).

Current flash version is not quite working... panics on running an external file.
This commit is contained in:
Peter Weingartner 2022-04-16 21:32:07 -04:00
parent 660d8c5b3f
commit b315be98b7
16 changed files with 10233 additions and 15220 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -4,7 +4,7 @@
# and where the MCP will run (ram or flash)
#
UNIT := a2560k
MEMORY := ram
MEMORY := flash
# CPU_WDC65816 0x16 /* CPU code for the Western Design Center 65816 */
# CPU_M68000 0x20 /* CPU code for the Motorola 68000 */

View file

@ -88,6 +88,8 @@ extern short cmd_credits(short channel, int argc, const char * argv[]);
/** The channel to use for interactions */
short g_current_channel = 0;
short g_channels_swapped = 1;
/** Flag to indicate that the current working directory has changed */
short g_cwd_changed = 0;
@ -136,21 +138,24 @@ const t_cli_command g_cli_commands[] = {
};
/**
* Set the number of the channel to use for interactions
* Set the number of the screen to use for interactions
*
* @param channel the number of the text device to use
* @param screen the number of the text device to use
*/
void cli_channel_set(short channel) {
g_current_channel = channel;
void cli_txt_screen_set(short screen) {
if (sys_chan_device(0) != screen) {
sys_chan_swap(0, 1);
g_channels_swapped = 1;
}
}
/**
* Get the number of the channel to use for interactions
* Get the number of the screen used for interactions
*
* @return channel the number of the text device to use
* @return the number of the text device to use
*/
short cli_channel_get() {
return g_current_channel;
short cli_txt_screen_get() {
return sys_chan_device(0);
}
//
@ -730,24 +735,26 @@ void cli_draw_window(short channel, const char * status, short is_active) {
t_rect region, old_region, full_region;
short i = 0, j;
short dev = sys_chan_device(channel);
// Save the current region and cursor location
sys_txt_get_xy(channel, &cursor);
sys_txt_get_region(channel, &old_region);
sys_txt_get_color(channel, &foreground, &background);
sys_txt_get_xy(dev, &cursor);
sys_txt_get_region(dev, &old_region);
sys_txt_get_color(dev, &foreground, &background);
// Return to the full region and get its dimensions
region.origin.x = 0;
region.origin.y = 0;
region.size.width = 0;
region.size.height = 0;
sys_txt_set_region(channel, &region);
sys_txt_get_region(channel, &full_region);
sys_txt_set_region(dev, &region);
sys_txt_get_region(dev, &full_region);
// Display the titlebar
i = 0;
sys_txt_set_xy(channel, 0, 0);
if (is_active) {
sys_txt_set_color(channel, background, foreground);
sys_txt_set_xy(dev, 0, 0);
if (channel == 0) {
sys_txt_set_color(dev, background, foreground);
}
for (j = 0; j < strlen(title_header); j++) {
buffer[i++] = title_header[j];
@ -766,16 +773,13 @@ void cli_draw_window(short channel, const char * status, short is_active) {
print(channel, buffer);
// Restore the region and cursor location
sys_txt_set_color(channel, foreground, background);
sys_txt_set_region(channel, &old_region);
sys_txt_set_xy(channel, cursor.x, cursor.y);
sys_txt_set_color(dev, foreground, background);
sys_txt_set_region(dev, &old_region);
sys_txt_set_xy(dev, cursor.x, cursor.y);
// Set cursor visibility based on if the screen is active
if (is_active) {
sys_chan_ioctrl(channel, 0x06, 0, 0);
} else {
sys_chan_ioctrl(channel, 0x07, 0, 0);
}
sys_chan_ioctrl(0, 0x06, 0, 0);
sys_chan_ioctrl(1, 0x07, 0, 0);
}
/**
@ -785,13 +789,15 @@ void cli_setup_screen(short channel, const char * path, short is_active) {
t_rect full_region, command_region;
char message[80];
short dev = sys_chan_device(channel);
// Get the size of the screen
full_region.origin.x = 0;
full_region.origin.y = 0;
full_region.size.width = 0;
full_region.size.height = 0;
sys_txt_set_region(channel, &full_region);
sys_txt_get_region(channel, &full_region);
sys_txt_set_region(dev, &full_region);
sys_txt_get_region(dev, &full_region);
// Clear the screen
print(channel, "\x1b[2J\x1b[H");
@ -803,7 +809,7 @@ void cli_setup_screen(short channel, const char * path, short is_active) {
command_region.size.height = full_region.size.height - 1;
// Restrict the region to the command panel
sys_txt_set_region(channel, &command_region);
sys_txt_set_region(dev, &command_region);
// Draw the window
cli_draw_window(channel, path, is_active);
@ -829,6 +835,7 @@ short cli_repl(short channel) {
short old_channel;
old_channel = channel;
g_channels_swapped = 1;
g_cwd_changed = 1;
cursor.x = 0;
@ -836,7 +843,7 @@ short cli_repl(short channel) {
while (1) {
// Refresh window if the current working directory has changed
if (g_cwd_changed || (old_channel != g_current_channel)) {
if (g_cwd_changed || g_channels_swapped) {
g_cwd_changed = 0;
// Get and display the new working directory
@ -844,13 +851,13 @@ short cli_repl(short channel) {
// char message[80];
// sprintf(message, "%d", strlen(cwd_buffer));
print(0, "");
if (old_channel != g_current_channel) {
if (g_channels_swapped) {
// If channel has changed, deactivate old channel
cli_draw_window(old_channel, cwd_buffer, 0);
cli_draw_window(1, cwd_buffer, 0);
old_channel = g_current_channel;
g_channels_swapped = 0;
}
cli_draw_window(g_current_channel, cwd_buffer, 1);
cli_draw_window(0, cwd_buffer, 1);
}
}
@ -858,7 +865,9 @@ short cli_repl(short channel) {
result = cli_readline(g_current_channel, command_line);
switch (result) {
case -1:
g_current_channel = (g_current_channel == 0) ? 1 : 0;
// g_current_channel = (g_current_channel == 0) ? 1 : 0;
sys_chan_swap(0, 1);
g_channels_swapped = 1;
break;
case -2:
@ -886,7 +895,7 @@ short cli_repl(short channel) {
cli_process_line(g_current_channel, command_line);
print(g_current_channel, "\n");
sys_txt_get_xy(channel, &cursor);
sys_txt_get_xy(sys_chan_device(g_current_channel), &cursor);
}
return 0;

View file

@ -66,18 +66,18 @@ extern short cmd_help(short channel, int argc, const char * argv[]);
extern short cli_exec_batch(short channel, const char * path);
/**
* Set the number of the channel to use for interactions
* Set the number of the screen to use for interactions
*
* @param channel the number of the text device to use
* @param screen the number of the text device to use
*/
extern void cli_channel_set(short channel);
extern void cli_txt_screen_set(short screen);
/**
* Get the number of the channel to use for interactions
* Get the number of the screen used for interactions
*
* @return channel the number of the text device to use
* @return the number of the text device to use
*/
extern short cli_channel_get();
extern short cli_txt_screen_get();
/**
* Indicate that the current working directory has changed

View file

@ -575,7 +575,7 @@ short cli_screen_set(short channel, const char * value) {
sys_get_info(&info);
if (screen < info.screens) {
cli_channel_set(screen);
cli_txt_screen_set(screen);
} else {
sprintf(message, "Screen #%d not present.\n", screen);
print(channel, message);
@ -587,7 +587,7 @@ short cli_screen_set(short channel, const char * value) {
* Get the number of the text screen to use for interactions
*/
short cli_screen_get(short channel, const char * value) {
sprintf(value, "%d", cli_channel_get());
sprintf(value, "%d", cli_txt_screen_get());
return 0;
}
@ -617,7 +617,7 @@ void cli_set_init() {
cli_set_register("KEYCOLOR", "KEYCOLOR 0x0RGB -- set the keyboard color", cli_keycolor_set, cli_keycolor_get);
}
if (info.screens == 1) {
if (info.screens > 1) {
cli_set_register("SCREEN", "SCREEN <0 - 1> -- set the channel number to use for interactions", cli_screen_set, cli_screen_get);
}

View file

@ -6,6 +6,8 @@
* Examples include: console, serial port, an open file, etc.
*/
#include <string.h>
#include "dev/channel.h"
#include "errors.h"
#include "simpleio.h"
@ -475,3 +477,62 @@ short chan_ioctrl(short channel, short command, uint8_t * buffer, short size) {
return res;
}
}
/**
* Return the device associated with the channel
*
* @param channel the ID of the channel to query
* @return the ID of the device associated with the channel, negative number for error
*/
short chan_device(short channel) {
if (channel >= CHAN_MAX) {
// If either channel ID is bad...
return ERR_BADCHANNEL;
} else {
if (g_channels[channel].number != channel) {
// Channel is closed
return ERR_BADCHANNEL;
} else {
return g_channels[channel].dev;
}
}
}
/**
* Swap the channel ID assignments for two channels
*
* Before call: channel1 = "Channel A", channel2 = "Channel B"
* After call: channel1 = "Channel B", channel2 = "Channel A"
*
* @param channel1 the ID of one of the channels
* @param channel2 the ID of the other channel
* @return 0 on success, any other number is an error
*/
short chan_swap(short channel1, short channel2) {
if ((channel1 >= CHAN_MAX) || (channel2 >= CHAN_MAX)) {
// If either channel ID is bad...
return ERR_BADCHANNEL;
} else {
uint8_t tmp_data[CHAN_DATA_SIZE];
p_channel chan1 = 0, chan2 = 0;
short i = 0, tmp_dev = 0;
chan1 = &g_channels[channel1];
chan2 = &g_channels[channel2];
// Swap the devices
tmp_dev = chan1->dev;
chan1->dev = chan2->dev;
chan2->dev = tmp_dev;
// Swap the data blocks
memcpy(tmp_data, chan1->data, CHAN_DATA_SIZE);
memcpy(chan1->data, chan2->data, CHAN_DATA_SIZE);
memcpy(chan2->data, tmp_data, CHAN_DATA_SIZE);
return 0;
}
}

View file

@ -265,4 +265,16 @@ extern short chan_seek(short channel, long position, short base);
*/
extern short chan_ioctrl(short channel, short command, uint8_t * buffer, short size);
/**
* Swap the channel ID assignments for two channels
*
* Before call: channel1 = "Channel A", channel2 = "Channel B"
* After call: channel1 = "Channel B", channel2 = "Channel A"
*
* @param channel1 the ID of one of the channels
* @param channel2 the ID of the other channel
* @return 0 on success, any other number is an error
*/
extern short chan_swap(short channel1, short channel2);
#endif

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,8 @@
#define KFN_CHAN_REGISTER 0x19 /* Register a channel device driver */
#define KFN_CHAN_OPEN 0x1A /* Open a channel device */
#define KFN_CHAN_CLOSE 0x1B /* Close an open channel (not for files) */
#define KFN_CHAN_SWAP 0x1C /* Swap the channel ID assignment of two channels */
#define KFN_CHAN_DEVICE 0x1D /* Get the number of the device associated with the channel */
/* Block device system calls */
@ -344,6 +346,26 @@ extern short sys_chan_open(short dev, const uint8_t * path, short mode);
*/
extern short sys_chan_close(short chan);
/**
* Swap the channel ID assignments for two channels
*
* Before call: channel1 = "Channel A", channel2 = "Channel B"
* After call: channel1 = "Channel B", channel2 = "Channel A"
*
* @param channel1 the ID of one of the channels
* @param channel2 the ID of the other channel
* @return 0 on success, any other number is an error
*/
extern short sys_chan_swap(short channel1, short channel2);
/**
* Return the device associated with the channel
*
* @param channel the ID of the channel to query
* @return the ID of the device associated with the channel, negative number for error
*/
extern short sys_chan_device(short channel);
/*
* Compute the size information for the text screen based on the current settings in VICKY
* These settings are needed to correctly position text on the screen.

View file

@ -123,81 +123,69 @@ void panic(void) {
txt_clear(0, 2);
txt_set_xy(0, column, row++);
sprintf(buffer, "\xDA\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xBF");
print(0, buffer);
txt_print(0, "\xDA\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xBF");
txt_set_xy(0, column, row++);
sprintf(buffer, "\xB3 \xB3");
print(0, buffer);
txt_print(0, "\xB3 \xB3");
txt_set_xy(0, column, row++);
sprintf(buffer, "\xB3 Oh dear, something has gone wrong... \xB3");
print(0, buffer);
txt_print(0, "\xB3 Oh dear, something has gone wrong... \xB3");
txt_set_xy(0, column, row++);
sprintf(buffer, "\xB3 \xB3");
print(0, buffer);
txt_print(0, "\xB3 \xB3");
txt_set_xy(0, column, row++);
switch (panic_number) {
case 2:
sprintf(buffer, "\xB3 Bus Error \xB3");
txt_print(0, "\xB3 Bus Error \xB3");
address_expected = 1;
break;
case 3:
sprintf(buffer, "\xB3 Address Error \xB3");
txt_print(0, "\xB3 Address Error \xB3");
address_expected = 1;
break;
case 4:
sprintf(buffer, "\xB3 Illegal Instruction Error \xB3");
txt_print(0, "\xB3 Illegal Instruction Error \xB3");
break;
case 5:
sprintf(buffer, "\xB3 Division by Zero Error \xB3");
txt_print(0, "\xB3 Division by Zero Error \xB3");
break;
case 6:
sprintf(buffer, "\xB3 Range Check Exception \xB3");
txt_print(0, "\xB3 Range Check Exception \xB3");
break;
case 7:
sprintf(buffer, "\xB3 Overflow Exception \xB3");
txt_print(0, "\xB3 Overflow Exception \xB3");
break;
case 8:
sprintf(buffer, "\xB3 Privilege Exception \xB3");
txt_print(0, "\xB3 Privilege Exception \xB3");
break;
case 24:
sprintf(buffer, "\xB3 Spurious Interrupt \xB3");
txt_print(0, "\xB3 Spurious Interrupt \xB3");
break;
default:
sprintf(buffer, "\xB3 Unknown Exception \xB3");
txt_print(0, "\xB3 Unknown Exception \xB3");
break;
}
print(0, buffer);
txt_set_xy(0, column, row++);
sprintf(buffer, "\xB3 \xB3");
print(0, buffer);
txt_print(0, "\xB3 \xB3");
if (address_expected) {
txt_set_xy(0, column, row++);
print(0, "\xB3 PC: ");
print_hex_32(0, panic_pc);
print(0, " Address: ");
print_hex_32(0, panic_address);
print(0, " \xB3");
sprintf(buffer, "\xB3 PC: %08X Address: %08X \xB3", panic_pc, panic_address);
txt_print(0, buffer);
} else {
txt_set_xy(0, column, row++);
print(0, "\xB3 PC: ");
print_hex_32(0, panic_pc);
print(0, " \xB3");
sprintf(buffer, "\xB3 PC: %08X \xB3", panic_pc);
txt_print(0, buffer);
}
txt_set_xy(0, column, row++);
sprintf(buffer, "\xB3 \xB3");
print(0, buffer);
txt_print(0, "\xB3 \xB3");
txt_set_xy(0, column, row++);
sprintf(buffer, "\xC0\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xD9");
print(0, buffer);
txt_print(0, "\xC0\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xC4\xD9");
/* Wait forever */
while (1) ;

View file

@ -110,6 +110,12 @@ unsigned long syscall_dispatch(int32_t function, int32_t param0, int32_t param1,
case KFN_CHAN_REGISTER:
return cdev_register((p_dev_chan)param0);
case KFN_CHAN_SWAP:
return chan_swap((short)param0, (short)param1);
case KFN_CHAN_DEVICE:
return chan_device((short)param0);
default:
return ERR_GENERAL;
}

20051
src/mapfile

File diff suppressed because it is too large Load diff

View file

@ -264,6 +264,26 @@ short sys_chan_close(short chan) {
return syscall(KFN_CHAN_CLOSE, chan);
}
/**
* Swap the channel ID assignments for two channels
*
* Before call: channel1 = "Channel A", channel2 = "Channel B"
* After call: channel1 = "Channel B", channel2 = "Channel A"
*/
short sys_chan_swap(short channel1, short channel2) {
return syscall(KFN_CHAN_SWAP, channel1, channel2);
}
/**
* Return the device associated with the channel
*
* @param channel the ID of the channel to query
* @return the ID of the device associated with the channel, negative number for error
*/
short sys_chan_device(short channel) {
return syscall(KFN_CHAN_DEVICE, channel);
}
/*
* Compute the size information for the text screen based on the current settings in VICKY
* These settings are needed to correctly position text on the screen.

View file

@ -6,7 +6,7 @@
#define __VERSION_H
#define VER_MAJOR 0
#define VER_MINOR 5
#define VER_BUILD 4
#define VER_MINOR 51
#define VER_BUILD 6
#endif