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-13 23:12:11 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Add new builtin devices here
|
|
|
|
//
|
|
|
|
|
2019-06-26 21:25:59 +02:00
|
|
|
extern dev_t cpudev, memdev, clockdev, keybdev, diskdev;
|
2019-06-13 23:12:11 +02:00
|
|
|
|
|
|
|
static dev_t *arch_d[] =
|
|
|
|
{
|
2019-06-26 21:25:59 +02:00
|
|
|
&cpudev, // 0
|
|
|
|
&memdev, // 1
|
|
|
|
&clockdev, // 2
|
|
|
|
&keybdev, // 3
|
|
|
|
&diskdev, // 4
|
2019-06-13 23:12:11 +02:00
|
|
|
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
int devinitall(void)
|
2019-06-13 23:12:11 +02:00
|
|
|
{
|
|
|
|
size_t it;
|
|
|
|
|
|
|
|
for (it = 0; arch_d[it] != NULL; it++) {
|
2019-06-19 21:41:22 +02:00
|
|
|
// trace("Adding device %s\n", arch_d[it]->name);
|
2019-08-03 19:01:12 +02:00
|
|
|
if (devinit(arch_d[it]) < 0)
|
2019-06-13 23:12:11 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
int devfiniall(void)
|
2019-06-13 23:12:11 +02:00
|
|
|
{
|
|
|
|
int failed = 0;
|
|
|
|
|
|
|
|
while (ctx->dh)
|
2019-08-03 19:01:12 +02:00
|
|
|
if (devfini(ctx->dh) < 0)
|
2019-06-13 23:12:11 +02:00
|
|
|
failed = -1;
|
|
|
|
|
|
|
|
return failed;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------//
|
2019-06-05 19:31:48 +02:00
|
|
|
|
|
|
|
dev_t *devalloc(void)
|
|
|
|
{
|
|
|
|
return calloc(sizeof(dev_t)/sizeof(ulong), sizeof(ulong));
|
|
|
|
}
|
|
|
|
|
|
|
|
void devfree(dev_t *dev)
|
|
|
|
{
|
|
|
|
assert(dev != NULL);
|
|
|
|
|
|
|
|
free(dev);
|
|
|
|
}
|
|
|
|
|
2019-06-13 23:12:11 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
dev_t *devget(int idx)
|
2019-06-05 19:31:48 +02:00
|
|
|
{
|
|
|
|
if (idx < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
dev_t *dev;
|
|
|
|
|
|
|
|
for (i = 0, dev = ctx->dh; dev && i != idx; dev = dev->next, i++);
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
void devattach(dev_t *dev)
|
2019-06-05 19:31:48 +02:00
|
|
|
{
|
|
|
|
dev_t *it;
|
|
|
|
|
|
|
|
assert(dev != NULL);
|
|
|
|
|
|
|
|
if (ctx->dh) {
|
|
|
|
for (it = ctx->dh; it->next != NULL; it = it->next);
|
|
|
|
|
|
|
|
it->next = dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
else ctx->dh = dev;
|
|
|
|
}
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
int devinit(dev_t *dev)
|
2019-06-05 19:31:48 +02:00
|
|
|
{
|
|
|
|
if (!dev || dev->state != DEVPWOF)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (dev->fpwon)
|
2019-08-03 19:01:12 +02:00
|
|
|
dev->fpwon(dev);
|
2019-06-05 19:31:48 +02:00
|
|
|
|
|
|
|
else dev->state = DEVGOOD;
|
|
|
|
|
|
|
|
if (!(dev->state == DEVPLUG || dev->state == DEVGOOD))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
dev->id = random();
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
devattach(dev);
|
2019-06-05 19:31:48 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-13 23:12:11 +02:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-06-05 19:31:48 +02:00
|
|
|
// NEVER detach while some assembly code
|
|
|
|
// may still be running on the vm!
|
2019-08-03 19:01:12 +02:00
|
|
|
void devdetach(dev_t *dev)
|
2019-06-05 19:31:48 +02:00
|
|
|
{
|
|
|
|
dev_t *it;
|
|
|
|
|
|
|
|
assert(dev != NULL);
|
|
|
|
|
|
|
|
if (dev == ctx->dh) {
|
|
|
|
ctx->dh = dev->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (it = ctx->dh; it; it = it->next) {
|
|
|
|
if (!it)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (it->next == dev) {
|
|
|
|
it->next = dev->next;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
int devfini(dev_t *dev)
|
2019-06-05 19:31:48 +02:00
|
|
|
{
|
|
|
|
if (dev->state == DEVPWOF || dev->state == DEVFERR) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dev->fpwoff)
|
2019-08-03 19:01:12 +02:00
|
|
|
dev->fpwoff(dev);
|
2019-06-05 19:31:48 +02:00
|
|
|
|
|
|
|
else dev->state = DEVPWOF;
|
|
|
|
|
|
|
|
if (dev->state != DEVPWOF)
|
|
|
|
goto err;
|
|
|
|
|
2019-08-03 19:01:12 +02:00
|
|
|
devdetach(dev);
|
2019-06-05 19:31:48 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
2019-08-03 19:01:12 +02:00
|
|
|
devdetach(dev);
|
2019-06-05 19:31:48 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2019-07-04 20:33:49 +02:00
|
|
|
|