// The OS/K Team licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include static_assert(sizeof(dev_t) % 8 == 0, ""); dev_t *devalloc(void) { return calloc(sizeof(dev_t)/sizeof(ulong), sizeof(ulong)); } void devfree(dev_t *dev) { assert(dev != NULL); free(dev); } dev_t *devget(ctx_t *ctx, int idx) { 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; } void devattach(ctx_t *ctx, dev_t *dev) { 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; } int devinit(ctx_t *ctx, dev_t *dev) { if (!dev || dev->state != DEVPWOF) return -1; if (dev->fpwon) dev->fpwon(ctx, dev); else dev->state = DEVGOOD; if (!(dev->state == DEVPLUG || dev->state == DEVGOOD)) return -1; dev->id = random(); devattach(ctx, dev); return 0; } // NEVER detach while some assembly code // may still be running on the vm! void devdetach(ctx_t *ctx, dev_t *dev) { 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; } } } int devfini(ctx_t *ctx, dev_t *dev) { if (dev->state == DEVPWOF || dev->state == DEVFERR) { goto err; } if (dev->fpwoff) dev->fpwoff(ctx, dev); else dev->state = DEVPWOF; if (dev->state != DEVPWOF) goto err; devdetach(ctx, dev); return 0; err: devdetach(ctx, dev); return -1; } int devinitall(ctx_t *ctx) { return devinit(ctx, &cpudev); } int devfiniall(ctx_t *ctx) { int failed = 0; while (ctx->dh) if (devfini(ctx, ctx->dh) < 0) failed = -1; return failed; }