summaryrefslogtreecommitdiffstats
path: root/sw/z80/kernel/programs.c
blob: 705ea968e6fb551573be9611dbc89b5e981c0d2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "progman.h"
#include "string.h"

#define EMPTY_PROG_INFO 0x0

struct program_info *prog_0 = PROG_0_INFO,
                    *prog_1 = PROG_1_INFO;

void progman_init() {

    *prog_0 = EMPTY_PROG_INFO;
    *prog_1 = EMPTY_PROG_INFO;

    // TODO other stuff
}

int8_t prog_req(struct program_info *info) {

    uint8_t prog;

    if (!prog_0->enabled) {

        prog = PROG_0;
        *info = *prog_0;

    } else if (!prog_1->enabled) {

        prog = PROG_1;
        *info = *prog_1;

    } else {

        return PROG_REQ_FULL;
    }

    return prog;
}

void prog_alloc(int8_t id, struct program_info *info, const struct program_base *base) {

    void *addr = (id ? PROG_1_PREFIX : PROG_0_PREFIX) + PROG_VSTART;

    if (info->enabled) {

        if (id)
            prog_1_fquit(); // force quit operation
        else
            prog_0_fquit();
    }
        

    memcpy(addr, base->inst_set, base->inst_size);

    addr += base->inst_size;

    memcpy(addr, base->bss_data, base->data_size);

    addr += base->data_size;

    // TODO, empty heap and stack
}

/*
*   TODO Called from the assembly, system calls
*/

extern void exec_0(void);
extern void exec_1(void);

void prog_exec(int8_t id, struct program_info *info) {

    // TODO, perform a program counter jump
}

void prog_0_qcb(void (*callback)(void)) {

    prog_0->quit_cb = callback;
}

void prog_1_qcb(void (*callback)(void)) {

    prog_1->quit_cb = callback;
}

void prog_0_quit() {
    
    if (!prog_0->enabled || prog_0->exiting)
        return;

    if (prog_0->quit_cb)
        prog_0->quit_cb();

    // TODO free space in RAM

    *prog_0 = EMPTY_PROG_INFO;

    // TODO jump program counter
}

void prog_1_quit() {
    
    if (!prog_1->enabled || prog_1->exiting)
        return;

    if (prog_1->quit_cb)
        prog_1->quit_cb();

    // TODO free space in RAM

    *prog_1 = EMPTY_PROG_INFO;

    // TODO jump program counter
}

void prog_0_fquit() {

    if (!prog_0->enabled)
        return;

    // TODO free space in RAM

    *prog_0 = EMPTY_PROG_INFO;

    // TODO jump program counter
}

void prog_1_fquit() {

    if (!prog_1->enabled)
        return;

    // TODO free space in RAM

    *prog_1 = EMPTY_PROG_INFO;

    // TODO jump program counter
}