kvisc/vm/dv/cpudev.c

331 lines
6.8 KiB
C
Raw Normal View History

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-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: invalid rframe index: #%u", idx);
2019-06-15 14:20:35 +02:00
2019-06-18 22:56:41 +02:00
#define CHK_FRAME(idx) \
CHK_INDEX(idx); \
if (rfs[idx] == NULL) \
2019-08-03 19:01:12 +02:00
_except(E_UDF, \
2019-08-21 16:57:32 +02:00
"cpudev: operation on inactive rframe #%u", idx);
2019-06-18 22:56:41 +02:00
2019-06-15 14:20:35 +02:00
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long cpudev_getmaxidx(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
2019-07-24 16:52:26 +02:00
R(RAX) = MAX_RFRAME_IDX;
2019-06-15 14:20:35 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_getrfusage(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
2019-07-24 16:52:26 +02:00
R(RAX) = rfs_used;
2019-06-15 14:20:35 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_getcuridx(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
2019-07-24 16:52:26 +02:00
R(RAX) = rfs_current_idx;
2019-06-15 14:20:35 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_leastavail(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
size_t it;
for (it = 0; it <= MAX_RFRAME_IDX; it++)
{
if (rfs[it] == NULL)
{
2019-07-24 16:52:26 +02:00
R(RAX) = it;
2019-06-15 14:20:35 +02:00
return 0;
}
}
2019-07-24 16:52:26 +02:00
R(RAX) = -1;
2019-06-15 14:20:35 +02:00
return 0;
}
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long cpudev_isactive(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_INDEX(R(AX0));
2019-06-15 14:20:35 +02:00
2019-07-24 16:52:26 +02:00
R(RAX) = (rfs[R(AX0)] != NULL);
2019-06-15 14:20:35 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_activate(dev_t *dev)
2019-06-15 14:20:35 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_INDEX(R(AX0));
2019-06-15 14:20:35 +02:00
2019-07-24 16:52:26 +02:00
if (rfs[R(AX0)] != NULL)
2019-08-03 19:01:12 +02:00
_except(E_UDF,
2019-07-24 16:52:26 +02:00
"cpudev: activating already activated rframe: #%u", R(AX0));
2019-06-15 14:20:35 +02:00
2019-07-24 16:52:26 +02:00
rfs[R(AX0)] = calloc(NREGS, sizeof(ulong));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (rfs[R(AX0)] == 0)
2019-06-18 22:56:41 +02:00
return -1;
rfs_used++;
2019-06-15 14:20:35 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_deactivate(dev_t *dev)
2019-06-05 19:48:56 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
2019-06-15 14:20:35 +02:00
2019-07-24 16:52:26 +02:00
if (R(AX0) == 0)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: deactivating rframe #0");
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
free(rfs[R(AX0)]);
rfs[R(AX0)] = NULL;
2019-06-18 22:56:41 +02:00
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-08-03 19:01:12 +02:00
long cpudev_copyframe(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
CHK_FRAME(R(AX1));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (R(AX0) == R(AX1))
2019-06-18 22:56:41 +02:00
return -1;
2019-07-24 16:52:26 +02:00
memcpy(rfs[R(AX0)], rfs[R(AX1)], NREGS * sizeof(ulong));
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_moveframe(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_INDEX(R(AX0));
CHK_FRAME(R(AX1));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (R(AX1) == 0)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: trying to move frame #0");
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (rfs[R(AX0)] != NULL)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: trying to move frame #%u "
2019-07-24 16:52:26 +02:00
"active frame #%u", R(AX1), R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
rfs[R(AX0)] = rfs[R(AX1)];
rfs[R(AX1)] = NULL;
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_switchframe(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
rfs_current_idx = R(AX0);
ctx->rf = rfs[R(AX0)];
2019-06-18 22:56:41 +02:00
return 0;
}
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long cpudev_loadargs(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
R(AX5) = rfs[R(AX0)][AX5];
R(AX4) = rfs[R(AX0)][AX4];
R(AX3) = rfs[R(AX0)][AX3];
R(AX2) = rfs[R(AX0)][AX2];
R(AX1) = rfs[R(AX0)][AX1];
R(AX0) = rfs[R(AX0)][AX0];
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_loadreg(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if ((ushort)R(AX1) >= NREGS || R(AX1) == RZX)
2019-08-03 19:01:12 +02:00
_except(E_UDF,
2019-07-24 16:52:26 +02:00
"cpudev: register invalid or index out of range: #%u", R(AX1));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
R(RAX) = rfs[R(AX0)][R(AX1)];
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_storereg(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if ((ushort)R(AX1) >= NREGS)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: register index out of range: #%u", R(AX1));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
rfs[R(AX0)][R(AX1)] = R(AX2);
2019-06-18 22:56:41 +02:00
return 0;
}
//----------------------------------------------------------------------------//
#define CHK_IDT_INDEX(idx) \
if ((ulong)idx >= IDT_SLOTS) \
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: invalid IDT slot index: #%u", idx);
2019-06-18 22:56:41 +02:00
/* 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
2019-08-03 19:01:12 +02:00
long cpudev_idtadd(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_FRAME(R(AX1));
CHK_IDT_INDEX(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (idt[R(AX0)] != 0)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: IDT slot index already in use: #%u", R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
assert(idt_handling[R(AX0)] == 0);
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
idt[R(AX0)] = R(AX1);
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_idtdel(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_IDT_INDEX(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (idt[R(AX0)] == 0)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: IDT slot index not in use: #%u", R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
idt[R(AX0)] = 0;
idt_handling[R(AX0)] = 0;
2019-06-18 22:56:41 +02:00
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_idtquery(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
if (R(AX0) >= IDT_SLOTS || idt[R(AX0)] == 0)
R(RAX) = R(RDX) = 0;
2019-06-18 22:56:41 +02:00
else {
2019-07-24 16:52:26 +02:00
R(RAX) = 1;
R(RDX) = idt[R(AX0)];
2019-06-18 22:56:41 +02:00
}
return 0;
}
2019-08-03 19:01:12 +02:00
long cpudev_idtdone(dev_t *dev)
2019-06-18 22:56:41 +02:00
{
2019-07-24 16:52:26 +02:00
CHK_IDT_INDEX(R(AX0));
2019-06-18 22:56:41 +02:00
2019-07-24 16:52:26 +02:00
if (idt_handling[R(AX0)] == 0)
2019-08-03 19:01:12 +02:00
_except(E_UDF, "cpudev: idtdone, not handling E/I #%u", R(AX0));
2019-06-18 22:56:41 +02:00
2019-08-14 20:23:05 +02:00
//trace("IDT.DONE %lu\n", R(AX0));
2019-07-24 16:52:26 +02:00
idt_handling[R(AX0)]--;
2019-06-18 22:56:41 +02:00
return 0;
}
2019-06-15 14:20:35 +02:00
//----------------------------------------------------------------------------//
2019-08-03 19:01:12 +02:00
long cpudev_poweron(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;
}
2019-08-03 19:01:12 +02:00
long cpudev_poweroff(dev_t *dev)
2019-06-15 13:42:30 +02:00
{
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
};