Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void bus_io_out(ceda_ioaddr_t _address, uint8_t value) {
ubus_io_out(address, value);
}

void bus_init(CEDAModule *mod) {
static void bus_prepareFirstAccess(void) {
// when starting, BIOS ROM is mounted at 0x0,
// until the first I/O access is performed,
// but we'll just emulate this behaviour with an equivalent
Expand All @@ -150,8 +150,19 @@ void bus_init(CEDAModule *mod) {
for (uint8_t address = 0; address < (uint8_t)ARRAY_SIZE(jmp); ++address) {
dyn_ram_write(address, jmp[address]);
}
}

static bool bus_restart(void) {
is_mem_switched = false;
bus_prepareFirstAccess();
return true;
}

void bus_init(CEDAModule *mod) {
memset(mod, 0, sizeof(*mod));
mod->restart = bus_restart;

bus_prepareFirstAccess();
}

void bus_memSwitch(bool switched) {
Expand Down
41 changes: 33 additions & 8 deletions src/ceda.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "serial.h"
#include "sio2.h"
#include "speaker.h"
#include "timer.h"
#include "ubus.h"
#include "upd8255.h"
#include "video.h"
Expand All @@ -30,28 +31,32 @@
static CEDAModule mod_bios;
static CEDAModule mod_bus;
static CEDAModule mod_cpu;
static CEDAModule mod_charmon;
static CEDAModule mod_cli;
static CEDAModule mod_fdc;
static CEDAModule mod_gui;
static CEDAModule mod_video;
static CEDAModule mod_speaker;
static CEDAModule mod_sio2;
static CEDAModule mod_int;
static CEDAModule mod_serial;
static CEDAModule mod_speaker;
static CEDAModule mod_sio2;
static CEDAModule mod_timer;
static CEDAModule mod_ubus;
static CEDAModule mod_charmon;
static CEDAModule mod_upd8255;
static CEDAModule mod_video;

static CEDAModule *modules[] = {
&mod_bios, &mod_cli, &mod_gui, &mod_bus, &mod_cpu, &mod_video,
&mod_speaker, &mod_int, &mod_serial, &mod_sio2, &mod_ubus, &mod_charmon,
&mod_bios, &mod_cli, &mod_gui, &mod_bus, &mod_cpu,
&mod_video, &mod_speaker, &mod_int, &mod_timer, &mod_serial,
&mod_sio2, &mod_upd8255, &mod_fdc, &mod_ubus, &mod_charmon,
};

void ceda_init(void) {
conf_init();
cli_init(&mod_cli);
gui_init(&mod_gui);

fdc_init();
upd8255_init();
fdc_init(&mod_fdc);
upd8255_init(&mod_upd8255);
rom_bios_init(&mod_bios);
video_init(&mod_video);
speaker_init(&mod_speaker);
Expand All @@ -60,6 +65,7 @@ void ceda_init(void) {
bus_init(&mod_bus);
cpu_init(&mod_cpu);
int_init(&mod_int);
timer_init(&mod_timer);
serial_init(&mod_serial);
sio2_init(&mod_sio2);
}
Expand Down Expand Up @@ -112,6 +118,21 @@ static void ceda_performance(void) {
}
}

static bool ceda_restart(void) {
bool ret = false;
for (unsigned int i = 0; i < ARRAY_SIZE(modules); ++i) {
bool (*restart)(void) = modules[i]->restart;
if (!restart)
continue;
ret = restart();
if (!ret) {
LOG_ERR("module %u: restart error\n", i);
break;
}
}
return ret;
}

static void ceda_cleanup(void) {
for (int i = ARRAY_SIZE(modules) - 1; i >= 0; --i) {
void (*cleanup)(void) = modules[i]->cleanup;
Expand Down Expand Up @@ -140,6 +161,10 @@ int ceda_run(void) {
if (gui_isQuit() || cli_isQuit()) {
break;
}
if (cli_checkRestart()) {
if (!ceda_restart())
break;
}

// check for how long each module can sleep, and yield host cpu
ceda_remaining();
Expand Down
14 changes: 14 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ enum { BLOCK_BUFFER_SIZE = 4096 }; // big page-like stuff

static bool initialized = false;
static bool quit = false;
static bool restart = false;
static const us_interval_t UPDATE_INTERVAL = 20000; // [us] 20 ms => 50 Hz
static us_time_t last_update = 0; // last poll() call

Expand All @@ -50,6 +51,12 @@ bool cli_isQuit(void) {
return quit;
}

bool cli_checkRestart(void) {
bool prev = restart;
restart = false;
return prev;
}

/**
* @brief Send a string to the connected client.
*
Expand Down Expand Up @@ -696,6 +703,12 @@ static ceda_string_t *cli_int(const char *arg) {
return NULL;
}

static ceda_string_t *cli_reset(const char *arg) {
(void)arg;
restart = true;
return NULL;
}

static ceda_string_t *cli_in(const char *arg) {
char word[LINE_BUFFER_SIZE];
ceda_string_t *msg = ceda_string_new(0);
Expand Down Expand Up @@ -815,6 +828,7 @@ static const cli_command cli_commands[] = {
{"step", "step one instruction", cli_step},
{"goto", "override cpu program counter", cli_goto},
{"int", "trigger interrupt request", cli_int},
{"reset", "perform an hard reset", cli_reset},
{"read", "read from memory", cli_read},
{"write", "write to memory", cli_write},
{"in", "read from io", cli_in},
Expand Down
9 changes: 9 additions & 0 deletions src/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ void cli_init(CEDAModule *mod);

bool cli_isQuit(void);

/**
* @brief Check if the computer must be restarted (cold hard reset).
*
* The restart value is automatically reset upon read.
*
* @return true if must be restarted, false otherwise.
*/
bool cli_checkRestart(void);

#endif // CEDA_CLI_H
13 changes: 12 additions & 1 deletion src/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,25 @@ static uint8_t cpu_int_read(void *context, zuint16 address) {
return int_pop();
}

static void cpu_cleanup(void) {
z80_power(&cpu, false);
}

static bool cpu_restart(void) {
cpu_cleanup();
z80_power(&cpu, true);
return true;
}

void cpu_init(CEDAModule *mod) {
// init mod struct
memset(mod, 0, sizeof(*mod));
mod->init = cpu_init;
mod->start = NULL;
mod->poll = cpu_poll;
mod->remaining = cpu_remaining;
mod->cleanup = NULL;
mod->cleanup = cpu_cleanup;
mod->restart = cpu_restart;
mod->performance = cpu_performance;

// init cpu
Expand Down
19 changes: 14 additions & 5 deletions src/crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <assert.h>
#include <stdint.h>
#include <string.h>

#include "video.h"

Expand All @@ -27,14 +28,10 @@ static uint8_t regs[CRTC_REGISTER_COUNT];
#define REG_CURSOR_L 15
#define REG_LIGHT_PEN_H 16
#define REG_LIGHT_PEN_L 17
unsigned int rselect = 0; // current register selected
static unsigned int rselect = 0; // current register selected

#define CRTC_NOT_IMPLEMENTED_STR "not implemented\n"

void crtc_init(void) {
// TODO(giomba): missing initialization
}

uint8_t crtc_in(ceda_ioaddr_t address) {
(void)address;

Expand Down Expand Up @@ -139,3 +136,15 @@ uint16_t crtc_startAddress(void) {

return start_address;
}

static bool crtc_restart(void) {
memset(&regs, 0, sizeof(regs));
rselect = 0;
return true;
}

void crtc_init(CEDAModule *mod) {
memset(mod, 0, sizeof(*mod));
mod->init = crtc_init;
mod->restart = crtc_restart;
}
3 changes: 2 additions & 1 deletion src/crtc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CEDA_CRTC_H
#define CEDA_CRTC_H

#include "module.h"
#include "type.h"

#include <Z80.h>
Expand All @@ -12,7 +13,7 @@ typedef enum CRTCCursorBlink {
CRTC_CURSOR_BLINK_FAST,
} CRTCCursorBlink;

void crtc_init(void);
void crtc_init(CEDAModule *mod);

uint8_t crtc_in(ceda_ioaddr_t address);
void crtc_out(ceda_ioaddr_t address, uint8_t value);
Expand Down
18 changes: 12 additions & 6 deletions src/fdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,9 +911,7 @@ static bool fdc_commit_write(void) {
return false;
}

/* * * * * * * * * * * * * * * Public routines * * * * * * * * * * * * * * */

void fdc_init(void) {
static bool fdc_restart(void) {
// Reset current command status
fdc_status = CMD;
fdc_currop = NULL;
Expand All @@ -931,9 +929,17 @@ void fdc_init(void) {
// Reset track positions
memset(track, 0, sizeof(track));

// Detach any read/write callback
read_buffer_cb = NULL;
write_buffer_cb = NULL;
return true;
}

/* * * * * * * * * * * * * * * Public routines * * * * * * * * * * * * * * */

void fdc_init(CEDAModule *mod) {
memset(mod, 0, sizeof(*mod));
mod->init = fdc_init;
mod->restart = fdc_restart;

fdc_restart();
}

uint8_t fdc_in(ceda_ioaddr_t address) {
Expand Down
3 changes: 2 additions & 1 deletion src/fdc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CEDA_FDC_H
#define CEDA_FDC_H

#include "module.h"
#include "type.h"

#include <Z80.h>
Expand Down Expand Up @@ -30,7 +31,7 @@ typedef int (*fdc_read_write_t)(uint8_t *buffer, uint8_t unit_number,
* @brief Initialize the Floppy Disk Controller system
*
*/
void fdc_init(void);
void fdc_init(CEDAModule *mod);

/**
* @brief Read data from the Floppy Disk Controller using its bus
Expand Down
14 changes: 14 additions & 0 deletions src/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ typedef struct CEDAModule {
*/
bool (*start)(void);

/**
* @brief Restart a module.
*
* This routine is used to implement the "reset" functionality of a module.
*
* This routine should perform a suitable module cleanup (eg. release
* dynamically acquired resources), and then the subsequent proper restart
* (eg. reinitialize variables, reacquire dynamic resources, etc...).
*
* Return true in case of success, false otherwise.
*
*/
bool (*restart)(void);

/**
* @brief Advance the internal status of the module.
*
Expand Down
17 changes: 12 additions & 5 deletions src/sio2.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,16 +426,23 @@ void sio2_detachPeripheral(sio_channel_idx_t channel) {
channels[channel].putc = NULL;
}

static bool sio2_restart(void) {
for (size_t i = 0; i < ARRAY_SIZE(channels); ++i)
sio_channel_init(&channels[i]);

// attach keyboard to channel B
channels[SIO_CHANNEL_B].getc = keyboard_getChar;

return true;
}

void sio2_init(CEDAModule *mod) {
mod->init = sio2_init;
mod->start = sio2_start;
mod->restart = sio2_restart;
mod->poll = sio2_poll;
mod->remaining = sio2_remaining;
mod->cleanup = sio2_cleanup;

for (size_t i = 0; i < ARRAY_SIZE(channels); ++i)
sio_channel_init(&channels[i]);

// attach keyboard to channel B
channels[SIO_CHANNEL_B].getc = keyboard_getChar;
sio2_restart();
}
Loading
Loading