idedrv Full asynchronous reading/writing, process suspension
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 2m15s
Build documentation / build-and-deploy (push) Successful in 42s

This commit is contained in:
2026-04-29 11:32:19 +02:00
parent 77fa271cca
commit 4be928e80c
2 changed files with 70 additions and 33 deletions

View File

@@ -106,6 +106,19 @@ static void ide_delay(uint16_t ctrl) {
}
#pragma clang optimize on
static int ide_flush(struct idedrv* idedrv) {
uint8_t ctrl = inb(idedrv->ctrl);
ctrl |= 0x02;
outb(idedrv->ctrl, ctrl);
if (idedrv->lba48)
outb(idedrv->io + IDE_REG_CMD, IDE_CMD_FLUSH48);
else
outb(idedrv->io + IDE_REG_CMD, IDE_CMD_FLUSH28);
return ST_OK;
}
static void ide_irq(void* arg, void* regs, bool user, struct reschedule_ctx* rctx) {
(void)user, (void)regs, (void)rctx;
@@ -123,6 +136,18 @@ static void ide_irq(void* arg, void* regs, bool user, struct reschedule_ctx* rct
if ((status & (IDE_ERR | IDE_DF))) {
atomic_store(&req->done, 1);
idedrv->current_req = NULL;
struct list_node_link* node = idedrv->sq.proc_list;
if (node != NULL) {
struct proc_sq_entry* sq_entry = list_entry(node, struct proc_sq_entry, sq_link);
struct proc* proc = sq_entry->proc;
free(req);
int status = req->type == IDE_READ ? -ST_XDRV_READ_ERROR : -ST_XDRV_WRITE_ERROR;
proc_sq_resume(proc, sq_entry, rctx, (uintptr_t)status);
}
return;
}
@@ -140,6 +165,20 @@ static void ide_irq(void* arg, void* regs, bool user, struct reschedule_ctx* rct
if ((req->sector_done_count >= req->sector_count)) {
atomic_store(&req->done, 1);
idedrv->current_req = NULL;
if (req->type == IDE_WRITE)
ide_flush(idedrv);
struct list_node_link* node = idedrv->sq.proc_list;
if (node != NULL) {
struct proc_sq_entry* sq_entry = list_entry(node, struct proc_sq_entry, sq_link);
struct proc* proc = sq_entry->proc;
free(req);
proc_sq_resume(proc, sq_entry, rctx, (uintptr_t)ST_OK);
}
}
}
@@ -319,7 +358,8 @@ DEFINE_DEVICE_FINI(idedrv_fini) {
free(idedrv);
}
static int idedrv_do_read_irqs(struct idedrv* idedrv, size_t sector, size_t sector_count,
static int idedrv_do_read_irqs(struct idedrv* idedrv, struct proc* proc,
struct reschedule_ctx* rctx, size_t sector, size_t sector_count,
void* buffer) {
struct idedrv_request* req = malloc(sizeof(*req));
@@ -339,14 +379,18 @@ static int idedrv_do_read_irqs(struct idedrv* idedrv, size_t sector, size_t sect
uint8_t cmd = idedrv->lba48 ? IDE_CMD_READ48 : IDE_CMD_READ28;
outb(idedrv->io + IDE_REG_CMD, cmd);
biglock_unlock();
if ((proc->flags & PROC_KPROC)) {
biglock_unlock();
while (!atomic_load(&req->done))
spin_lock_relax();
while (!atomic_load(&req->done))
spin_lock_relax();
biglock_lock();
biglock_lock();
free(req);
free(req);
} else {
proc_sq_suspend(proc, &idedrv->sq, rctx, NULL, NULL);
}
return ST_OK;
}
@@ -448,12 +492,13 @@ DEFINE_DEVICE_OP(idedrv_read) {
return -ST_XDRV_READ_ERROR;
if (idedrv->irqs_support)
return idedrv_do_read_irqs(idedrv, sector, sector_count, buffer);
return idedrv_do_read_irqs(idedrv, proc, rctx, sector, sector_count, buffer);
else
return idedrv_do_read_no_irqs(idedrv, sector, sector_count, buffer);
}
static int idedrv_do_write_irqs(struct idedrv* idedrv, size_t sector, size_t sector_count,
static int idedrv_do_write_irqs(struct idedrv* idedrv, struct proc* proc,
struct reschedule_ctx* rctx, size_t sector, size_t sector_count,
void* buffer) {
struct idedrv_request* req = malloc(sizeof(*req));
@@ -479,18 +524,24 @@ static int idedrv_do_write_irqs(struct idedrv* idedrv, size_t sector, size_t sec
return -ST_XDRV_WRITE_ERROR;
}
outsw(idedrv->io + IDE_REG_DATA, buffer, idedrv->sector_size / 2);
req->sector_done_count = 1;
biglock_unlock();
if (!(proc->flags & PROC_KPROC)) {
proc_sq_suspend(proc, &idedrv->sq, rctx, NULL, NULL);
}
while (!atomic_load(&req->done))
spin_lock_relax();
outsw(idedrv->io + IDE_REG_DATA, buffer, idedrv->sector_size / 2);
biglock_lock();
if ((proc->flags & PROC_KPROC)) {
biglock_unlock();
free(req);
while (!atomic_load(&req->done))
spin_lock_relax();
biglock_lock();
free(req);
}
return ST_OK;
}
@@ -561,6 +612,8 @@ static int idedrv_do_write_no_irqs(struct idedrv* idedrv, size_t sector, size_t
}
}
ide_flush(idedrv);
return ST_OK;
}
@@ -589,30 +642,13 @@ DEFINE_DEVICE_OP(idedrv_write) {
return -ST_XDRV_WRITE_ERROR;
if (idedrv->irqs_support)
ret = idedrv_do_write_irqs(idedrv, sector, sector_count, buffer);
ret = idedrv_do_write_irqs(idedrv, proc, rctx, sector, sector_count, buffer);
else
ret = idedrv_do_write_no_irqs(idedrv, sector, sector_count, buffer);
if (ret < 0)
return ret;
uint8_t ctrl = inb(idedrv->ctrl);
ctrl |= 0x02;
outb(idedrv->ctrl, ctrl);
if (idedrv->lba48)
outb(idedrv->io + IDE_REG_CMD, IDE_CMD_FLUSH48);
else
outb(idedrv->io + IDE_REG_CMD, IDE_CMD_FLUSH28);
uint8_t status;
do {
status = inb(idedrv->io + IDE_REG_STATUS);
} while (status & IDE_BSY);
if (status & (IDE_ERR | IDE_DF))
return -ST_XDRV_WRITE_ERROR;
return ST_OK;
}

View File

@@ -56,6 +56,7 @@ struct idedrv {
size_t prdt_entry_count;
uintptr_t bounce_buffer_phys;
void* bounce_buffer;
struct proc_suspension_q sq;
};
struct ide_probe {