2019-06-05 19:31:48 +02:00
|
|
|
// The OS/K Team licenses this file to you under the MIT license.
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
2019-06-21 22:19:55 +02:00
|
|
|
#include <pc/device.h>
|
2019-06-05 19:31:48 +02:00
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-06-15 13:42:30 +02:00
|
|
|
#define MAX_RFRAME_IDX 255
|
|
|
|
|
|
|
|
//
|
2019-06-15 14:20:35 +02:00
|
|
|
// Register frames
|
2019-06-15 13:42:30 +02:00
|
|
|
//
|
2019-06-18 22:56:41 +02:00
|
|
|
ulong **rfs = NULL;
|
2019-06-15 14:20:35 +02:00
|
|
|
|
2019-06-15 13:42:30 +02:00
|
|
|
size_t rfs_used = 0;
|
2019-06-18 22:56:41 +02:00
|
|
|
size_t rfs_current_idx = 0;
|
2019-06-15 13:42:30 +02:00
|
|
|
|
2019-06-18 22:56:41 +02:00
|
|
|
#define CHK_INDEX(idx) \
|
|
|
|
if ((size_t)idx > MAX_RFRAME_IDX) \
|
2019-06-15 14:20:35 +02:00
|
|
|
_except(ctx, E_UDF, "cpudev: invalid rframe index: #%u", idx);
|
|
|
|
|
2019-06-18 22:56:41 +02:00
|
|
|
#define CHK_FRAME(idx) \
|
|
|
|
CHK_INDEX(idx); \
|
|
|
|
if (rfs[idx] == NULL) \
|
|
|
|
_except(ctx, E_UDF, \
|
|
|
|
"cpudev: operation on inactive reframe #%u", idx);
|
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
long cpudev_getmaxidx(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
rax = MAX_RFRAME_IDX;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_getrfusage(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
rax = rfs_used;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_getcuridx(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
2019-06-18 22:56:41 +02:00
|
|
|
rax = rfs_current_idx;
|
2019-06-15 14:20:35 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_leastavail(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
size_t it;
|
|
|
|
|
|
|
|
for (it = 0; it <= MAX_RFRAME_IDX; it++)
|
|
|
|
{
|
|
|
|
if (rfs[it] == NULL)
|
|
|
|
{
|
|
|
|
rax = it;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rax = -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
long cpudev_isactive(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_INDEX(ax0);
|
|
|
|
|
|
|
|
rax = (rfs[ax0] != NULL);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_activate(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_INDEX(ax0);
|
|
|
|
|
|
|
|
if (rfs[ax0] != NULL)
|
|
|
|
_except(ctx, E_UDF,
|
|
|
|
"cpudev: activating already activated rframe: #%u", ax0);
|
|
|
|
|
2019-06-18 22:56:41 +02:00
|
|
|
rfs[ax0] = calloc(NREGS, sizeof(ulong));
|
|
|
|
|
|
|
|
if (rfs[ax0] == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
rfs_used++;
|
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_deactivate(ctx_t *ctx, dev_t *dev)
|
2019-06-05 19:48:56 +02:00
|
|
|
{
|
2019-06-18 22:56:41 +02:00
|
|
|
CHK_FRAME(ax0);
|
2019-06-15 14:20:35 +02:00
|
|
|
|
|
|
|
if (ax0 == 0)
|
2019-06-18 22:56:41 +02:00
|
|
|
_except(ctx, E_UDF, "cpudev: deactivating rframe #0");
|
|
|
|
|
|
|
|
free(rfs[ax0]);
|
|
|
|
rfs[ax0] = NULL;
|
|
|
|
|
|
|
|
rfs_used--;
|
|
|
|
assert(rfs_used > 0);
|
2019-06-05 22:11:45 +02:00
|
|
|
|
|
|
|
return 0;
|
2019-06-05 19:48:56 +02:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-06-18 22:56:41 +02:00
|
|
|
long cpudev_copyframe(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax0);
|
|
|
|
CHK_FRAME(ax1);
|
|
|
|
|
|
|
|
if (ax0 == ax1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memcpy(rfs[ax0], rfs[ax1], NREGS * sizeof(ulong));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_moveframe(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_INDEX(ax0);
|
|
|
|
CHK_FRAME(ax1);
|
|
|
|
|
|
|
|
if (ax1 == 0)
|
|
|
|
_except(ctx, E_UDF, "cpudev: trying to move frame #0");
|
|
|
|
|
|
|
|
if (rfs[ax0] != NULL)
|
|
|
|
_except(ctx, E_UDF, "cpudev: trying to move frame #%u "
|
|
|
|
"active frame #%u", ax1, ax0);
|
|
|
|
|
|
|
|
rfs[ax0] = rfs[ax1];
|
|
|
|
rfs[ax1] = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_switchframe(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax0);
|
|
|
|
|
|
|
|
rfs_current_idx = ax0;
|
|
|
|
ctx->rf = rfs[ax0];
|
2019-06-23 21:12:25 +02:00
|
|
|
rx2 = 0;
|
2019-06-18 22:56:41 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
long cpudev_loadargs(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax0);
|
|
|
|
|
2019-07-01 00:45:08 +02:00
|
|
|
R(AX7) = rfs[ax0][AX7];
|
|
|
|
R(AX6) = rfs[ax0][AX6];
|
|
|
|
R(AX5) = rfs[ax0][AX5];
|
|
|
|
R(AX4) = rfs[ax0][AX4];
|
|
|
|
R(AX3) = rfs[ax0][AX3];
|
|
|
|
R(AX2) = rfs[ax0][AX2];
|
|
|
|
R(AX1) = rfs[ax0][AX1];
|
|
|
|
R(AX0) = rfs[ax0][AX0];
|
2019-06-18 22:56:41 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
long cpudev_loadreg(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax0);
|
|
|
|
|
|
|
|
if ((ushort)ax1 >= NREGS)
|
|
|
|
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
|
|
|
|
|
|
|
|
R(ax1) = rfs[ax0][ax1];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_storereg(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax0);
|
|
|
|
|
|
|
|
if ((ushort)ax1 >= NREGS)
|
|
|
|
_except(ctx, E_UDF, "cpudev: register index out of range: #%u", ax1);
|
|
|
|
|
|
|
|
rfs[ax0][ax1] = ax2;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
#define CHK_IDT_INDEX(idx) \
|
|
|
|
if ((ulong)idx >= IDT_SLOTS) \
|
|
|
|
_except(ctx, E_UDF, "cpudev: invalid IDT slot index: #%u", idx);
|
|
|
|
|
|
|
|
/* except.h */
|
|
|
|
ulong idt[IDT_SLOTS] = { 0 };
|
|
|
|
bool idt_masked[IDT_SLOTS] = { 0 }; // deliberately masked by software
|
|
|
|
bool idt_handling[IDT_SLOTS] = { 0 }; // a handler is already running
|
|
|
|
|
|
|
|
long cpudev_idtadd(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_FRAME(ax1);
|
|
|
|
CHK_IDT_INDEX(ax0);
|
|
|
|
|
|
|
|
if (idt[ax0] != 0)
|
|
|
|
_except(ctx, E_UDF, "cpudev: IDT slot index already in use: #%u", ax0);
|
|
|
|
|
|
|
|
assert(idt_handling[ax0] == 0);
|
|
|
|
|
|
|
|
idt[ax0] = ax1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_idtdel(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_IDT_INDEX(ax0);
|
|
|
|
|
|
|
|
if (idt[ax0] == 0)
|
|
|
|
_except(ctx, E_UDF, "cpudev: IDT slot index not in use: #%u", ax0);
|
|
|
|
|
|
|
|
idt[ax0] = 0;
|
|
|
|
idt_handling[ax0] = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_idtquery(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
if (ax0 >= IDT_SLOTS || idt[ax0] == 0)
|
|
|
|
rax = rdx = 0;
|
|
|
|
|
|
|
|
else {
|
|
|
|
rax = 1;
|
|
|
|
rdx = idt[ax0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_idtdone(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
|
|
|
CHK_IDT_INDEX(ax0);
|
|
|
|
|
|
|
|
if (idt_handling[ax0] == 0)
|
|
|
|
_except(ctx, E_UDF, "cpudev: idtdone, not handling E/I #%u", ax0);
|
|
|
|
|
|
|
|
idt_handling[ax0]--;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-06-05 22:11:45 +02:00
|
|
|
long cpudev_poweron(ctx_t *ctx, dev_t *dev)
|
2019-06-05 19:48:56 +02:00
|
|
|
{
|
2019-06-15 14:20:35 +02:00
|
|
|
rfs = calloc(MAX_RFRAME_IDX + 2, sizeof(reg_t *));
|
2019-06-15 13:42:30 +02:00
|
|
|
|
|
|
|
if (rfs == NULL)
|
|
|
|
return -1;
|
2019-06-05 19:48:56 +02:00
|
|
|
|
2019-06-18 22:56:41 +02:00
|
|
|
rfs[0] = ctx->rf;
|
2019-06-15 14:20:35 +02:00
|
|
|
rfs_used = 1;
|
|
|
|
|
2019-06-05 19:48:56 +02:00
|
|
|
dev->state = DEVGOOD;
|
2019-06-15 13:42:30 +02:00
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
dev->fslots[16] = cpudev_getmaxidx;
|
|
|
|
dev->fslots[17] = cpudev_getrfusage;
|
|
|
|
dev->fslots[18] = cpudev_getcuridx;
|
|
|
|
dev->fslots[19] = cpudev_leastavail;
|
|
|
|
dev->fslots[20] = cpudev_isactive;
|
|
|
|
dev->fslots[21] = cpudev_activate;
|
|
|
|
dev->fslots[22] = cpudev_deactivate;
|
2019-06-18 22:56:41 +02:00
|
|
|
dev->fslots[23] = cpudev_copyframe;
|
|
|
|
dev->fslots[24] = cpudev_moveframe;
|
|
|
|
dev->fslots[25] = cpudev_switchframe;
|
|
|
|
|
|
|
|
dev->fslots[32] = cpudev_loadargs;
|
|
|
|
dev->fslots[33] = cpudev_loadreg;
|
|
|
|
dev->fslots[48] = cpudev_storereg;
|
|
|
|
|
|
|
|
dev->fslots[64] = cpudev_idtadd;
|
|
|
|
dev->fslots[65] = cpudev_idtdel;
|
|
|
|
dev->fslots[66] = cpudev_idtquery;
|
|
|
|
dev->fslots[67] = cpudev_idtdone;
|
2019-06-15 13:42:30 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long cpudev_poweroff(ctx_t *ctx, dev_t *dev)
|
|
|
|
{
|
2019-06-18 22:56:41 +02:00
|
|
|
size_t i;
|
|
|
|
|
2019-06-15 13:42:30 +02:00
|
|
|
if (rfs)
|
2019-06-18 22:56:41 +02:00
|
|
|
{
|
|
|
|
for (i = 0; i <= MAX_RFRAME_IDX; i++)
|
|
|
|
free(rfs[i]);
|
|
|
|
|
2019-06-15 13:42:30 +02:00
|
|
|
free(rfs);
|
2019-06-18 22:56:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dev->state = DEVPWOF;
|
2019-06-05 22:11:45 +02:00
|
|
|
|
|
|
|
return 0;
|
2019-06-05 19:48:56 +02:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:20:35 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-06-05 19:31:48 +02:00
|
|
|
dev_t cpudev =
|
|
|
|
{
|
|
|
|
.type = "cpu",
|
|
|
|
.name = "K-CPU",
|
2019-06-05 22:11:45 +02:00
|
|
|
.modl = "Prisma 1",
|
2019-06-05 19:31:48 +02:00
|
|
|
.vend = "The OS/K Team",
|
|
|
|
|
2019-06-13 23:12:11 +02:00
|
|
|
.major = KARCH_MAJOR,
|
|
|
|
.minor = KARCH_MINOR,
|
|
|
|
.revis = KARCH_REVIS,
|
2019-06-05 19:48:56 +02:00
|
|
|
|
|
|
|
.fpwon = cpudev_poweron,
|
2019-06-18 22:56:41 +02:00
|
|
|
.fpwoff = cpudev_poweroff,
|
2019-06-05 19:31:48 +02:00
|
|
|
};
|
|
|
|
|