Handle disk partitioning

This commit is contained in:
2025-10-19 22:29:19 +02:00
parent 68e0e8848d
commit 01da863b8b
21 changed files with 300 additions and 85 deletions

View File

@ -121,7 +121,7 @@ void ata_probe(void) {
.iobase = 0x1F0,
.ctrlbase = 0x3F6,
};
storedev_create(STOREDEV_ATASD, (void *)&extra);
storedev_create(STOREDEV_ATASD, "atasd-ch0-M", (void *)&extra);
}
probesize = ata_probesize_bytes(0x1F0, 0x3F6, ATA_SLAVE);
@ -135,7 +135,7 @@ void ata_probe(void) {
.iobase = 0x1F0,
.ctrlbase = 0x3F6,
};
storedev_create(STOREDEV_ATASD, (void *)&extra);
storedev_create(STOREDEV_ATASD, "atasd-ch0-S", (void *)&extra);
}
probesize = ata_probesize_bytes(0x170, 0x376, ATA_MASTER);
@ -149,7 +149,7 @@ void ata_probe(void) {
.iobase = 0x170,
.ctrlbase = 0x376,
};
storedev_create(STOREDEV_ATASD, (void *)&extra);
storedev_create(STOREDEV_ATASD, "atasd-ch1-M", (void *)&extra);
}
probesize = ata_probesize_bytes(0x170, 0x376, ATA_SLAVE);
@ -163,7 +163,7 @@ void ata_probe(void) {
.iobase = 0x170,
.ctrlbase = 0x376,
};
storedev_create(STOREDEV_ATASD, (void *)&extra);
storedev_create(STOREDEV_ATASD, "atasd-ch1-S", (void *)&extra);
}
}
@ -185,6 +185,51 @@ void ata_setup(uint16_t iobase, uint16_t ctrlbase, int devno, uint16_t sectors,
}
int32_t ata_read(uint16_t iobase, uint16_t ctrlbase, int devno,
uint64_t sectorsize, uint8_t *const buffer,
ptrdiff_t sector, ptrdiff_t off, size_t size) {
int32_t ret = E_OK;
uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sectorsize + off) / sectorsize;
size_t sectors = size / sectorsize;
if (size % sectorsize) sectors++;
ata_setup(iobase, ctrlbase, devno, sectors, lba);
io_out8(iobase + ATA_REG_COMMAND, ATA_CMD_READ_PIO_EXT);
for (size_t s = 0; s < sectors; s++) {
if (ata_wait(iobase, 100000, true, 1) < 0) { ret = E_BADIO; goto done; }
io_ins16(iobase + ATA_REG_DATA, (uint16_t *)(buffer + s * sectorsize), sectorsize / 2);
}
done:
return ret;
}
int32_t ata_write(uint16_t iobase, uint16_t ctrlbase, int devno,
uint64_t sectorsize, const uint8_t *const buffer,
ptrdiff_t sector, ptrdiff_t off, size_t size) {
int32_t ret = E_OK;
uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sectorsize + off) / sectorsize;
size_t sectors = size / sectorsize;
if (size % sectorsize) sectors++;
ata_setup(iobase, ctrlbase, devno, sectors, lba);
io_out8(iobase + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO_EXT);
for (size_t s = 0; s < sectors; s++) {
if (ata_wait(iobase, 100000, true, 1) < 0) { ret = E_BADIO; goto done; }
io_outs16(iobase + ATA_REG_DATA, (uint16_t *)(buffer + s * sectorsize), sectorsize / 2);
}
io_out8(iobase + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH_EXT);
if (ata_wait(iobase, 100000, false, 1) < 0) { ret = E_BADIO; goto done; }
done:
return ret;
}
int32_t atasd_init(struct StoreDev *sd, void *extra) {
AtaSdInitExtra *e = (AtaSdInitExtra *)extra;
sd->sd.atasd.devno = e->devno;
@ -200,21 +245,9 @@ int32_t atasd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector,
AtaSd *ata = &sd->sd.atasd;
uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sd->sectorsize + off) / (uint64_t)STOREDEV_ATASD_SECTORSIZE;
size_t sectors = size / STOREDEV_ATASD_SECTORSIZE;
if (size % STOREDEV_ATASD_SECTORSIZE) sectors++;
ret = ata_read(ata->iobase, ata->ctrlbase, ata->devno,
sd->sectorsize, buffer, sector, off, size);
ata_setup(ata->iobase, ata->ctrlbase, ata->devno, sectors, lba);
io_out8(ata->iobase + ATA_REG_COMMAND, ATA_CMD_READ_PIO_EXT);
for (size_t s = 0; s < sectors; s++) {
if (ata_wait(ata->iobase, 100000, true, 1) < 0) { ret = E_BADIO; goto done; }
io_ins16(ata->iobase + ATA_REG_DATA, (uint16_t *)(buffer + s * STOREDEV_ATASD_SECTORSIZE), STOREDEV_ATASD_SECTORSIZE/2);
}
ret = E_OK;
done:
spinlock_release(&sd->spinlock);
return ret;
}
@ -225,24 +258,9 @@ int32_t atasd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t
AtaSd *ata = &sd->sd.atasd;
uint64_t lba = (uint64_t)(sector * (ptrdiff_t)sd->sectorsize + off) / (uint64_t)STOREDEV_ATASD_SECTORSIZE;
size_t sectors = size / STOREDEV_ATASD_SECTORSIZE;
if (size % STOREDEV_ATASD_SECTORSIZE) sectors++;
ata_setup(ata->iobase, ata->ctrlbase, ata->devno, sectors, lba);
io_out8(ata->iobase + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO_EXT);
for (size_t s = 0; s < sectors; s++) {
if (ata_wait(ata->iobase, 100000, true, 1) < 0) { ret = E_BADIO; goto done; }
io_outs16(ata->iobase + ATA_REG_DATA, (uint16_t *)(buffer + s * STOREDEV_ATASD_SECTORSIZE), STOREDEV_ATASD_SECTORSIZE/2);
}
io_out8(ata->iobase + ATA_REG_COMMAND, ATA_CMD_CACHE_FLUSH_EXT);
if (ata_wait(ata->iobase, 100000, false, 1) < 0) { ret = E_BADIO; goto done; }
ret = E_OK;
ret = ata_write(ata->iobase, ata->ctrlbase, ata->devno,
sd->sectorsize, buffer, sector, off, size);
done:
spinlock_release(&sd->spinlock);
return ret;
}

33
kernel/storedev/partsd.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdint.h>
#include <stddef.h>
#include "partsd.h"
#include "storedev.h"
#include "errors.h"
#include "kprintf.h"
int32_t partsd_init(struct StoreDev *sd, void *extra) {
PartSdInitExtra *e = (PartSdInitExtra *)extra;
sd->sd.partsd.sectorcount = e->sectorcount;
sd->sd.partsd.startsector = e->startsector;
sd->sd.partsd.parent = e->parent;
sd->sectorsize = e->parent->sectorsize;
return E_OK;
}
int32_t partsd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) {
PartSd *part = &sd->sd.partsd;
return part->parent->read(part->parent, buffer, part->startsector + sector, off, size);
}
int32_t partsd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size) {
PartSd *part = &sd->sd.partsd;
return part->parent->write(part->parent, buffer, part->startsector + sector, off, size);
}
int32_t partsd_cleanup(struct StoreDev *sd) {
return E_OK;
}
size_t partsd_capacity(struct StoreDev *sd) {
return sd->sd.partsd.parent->sectorsize * sd->sd.partsd.sectorcount;
}

27
kernel/storedev/partsd.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef STOREDEV_PARTSD_H_
#define STOREDEV_PARTSD_H_
#include <stdint.h>
#include <stddef.h>
struct StoreDev;
typedef struct {
struct StoreDev *parent;
size_t sectorcount;
size_t startsector;
} PartSd;
typedef struct {
struct StoreDev *parent;
size_t sectorcount;
size_t startsector;
} PartSdInitExtra;
int32_t partsd_init(struct StoreDev *sd, void *extra);
int32_t partsd_read(struct StoreDev *sd, uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size);
int32_t partsd_write(struct StoreDev *sd, const uint8_t *const buffer, ptrdiff_t sector, ptrdiff_t off, size_t size);
int32_t partsd_cleanup(struct StoreDev *sd);
size_t partsd_capacity(struct StoreDev *sd);
#endif // STOREDEV_PARTSD_H_

View File

@ -24,23 +24,10 @@ void storedev_init(void) {
ata_probe();
}
size_t ramsd_counter = 0;
void storedev_register_dev_entry(StoreDev *sd, int32_t sdtype) {
char key[20];
if (sdtype == STOREDEV_RAMSD) {
ksprintf(key, "ramsd-%zu", ramsd_counter++);
} else if (sdtype == STOREDEV_ATASD) {
ksprintf(key, "atasd-ch%d-%c",
sd->sd.atasd.iobase == 0x1F0 ? 0 : 1,
sd->sd.atasd.devno == 0x00 ? 'M' : 'S'
);
}
void storedev_register_dev_entry(StoreDev *sd, char *name, int32_t sdtype) {
spinlock_acquire(&DEVTABLE.spinlock);
Dev *dev = NULL;
HSHTB_ALLOC(DEVTABLE.devs, ident, key, dev);
HSHTB_ALLOC(DEVTABLE.devs, ident, name, dev);
spinlock_release(&DEVTABLE.spinlock);
if (dev == NULL) {
@ -58,7 +45,7 @@ void storedev_unregister_dev_entry(Dev *dev) {
spinlock_release(&DEVTABLE.spinlock);
}
StoreDev *storedev_create(int32_t sdtype, void *extra) {
StoreDev *storedev_create(int32_t sdtype, char *name, void *extra) {
StoreDev *sd = dlmalloc(sizeof(*sd));
if (sd == NULL) {
return NULL;
@ -67,28 +54,36 @@ StoreDev *storedev_create(int32_t sdtype, void *extra) {
spinlock_acquire(&STOREDEV_LIST.spinlock);
sd->_magic = STOREDEV_MAGIC;
spinlock_init(&sd->spinlock);
switch (sdtype) {
case STOREDEV_RAMSD: {
spinlock_init(&sd->spinlock);
sd->sdtype = STOREDEV_RAMSD;
sd->init = &ramsd_init;
sd->cleanup = &ramsd_cleanup;
sd->read = &ramsd_read;
sd->write = &ramsd_write;
sd->capacity = &ramsd_capacity;
sd->sdtype = STOREDEV_RAMSD;
sd->init = &ramsd_init;
sd->cleanup = &ramsd_cleanup;
sd->read = &ramsd_read;
sd->write = &ramsd_write;
sd->capacity = &ramsd_capacity;
sd->sectorsize = STOREDEV_RAMSD_SECTORSIZE;
} break;
case STOREDEV_ATASD: {
spinlock_init(&sd->spinlock);
sd->sdtype = STOREDEV_ATASD;
sd->init = &atasd_init;
sd->cleanup = &atasd_cleanup;
sd->read = &atasd_read;
sd->write = &atasd_write;
sd->capacity = &atasd_capacity;
sd->sdtype = STOREDEV_ATASD;
sd->init = &atasd_init;
sd->cleanup = &atasd_cleanup;
sd->read = &atasd_read;
sd->write = &atasd_write;
sd->capacity = &atasd_capacity;
sd->sectorsize = STOREDEV_ATASD_SECTORSIZE;
} break;
case STOREDEV_PARTSD: {
sd->sdtype = STOREDEV_PARTSD;
sd->init = &partsd_init;
sd->cleanup = &partsd_cleanup;
sd->read = &partsd_read;
sd->write = &partsd_write;
sd->capacity = &partsd_capacity;
sd->sectorsize = 0; // lazy
} break;
default:
spinlock_release(&STOREDEV_LIST.spinlock);
return NULL;
@ -102,7 +97,7 @@ StoreDev *storedev_create(int32_t sdtype, void *extra) {
LL_APPEND(STOREDEV_LIST.head, sd);
spinlock_release(&STOREDEV_LIST.spinlock);
storedev_register_dev_entry(sd, sdtype);
storedev_register_dev_entry(sd, name, sdtype);
return sd;
}

View File

@ -6,6 +6,7 @@
#include "spinlock/spinlock.h"
#include "ramsd.h"
#include "atasd.h"
#include "partsd.h"
#include "compiler/attr.h"
#include "dev/dev.h"
@ -14,10 +15,11 @@
enum {
STOREDEV_RAMSD,
STOREDEV_ATASD,
STOREDEV_PARTSD,
};
UNUSED static const char *storedev_strings[] = {
"RAMSD", "ATASD"
"RAMSD", "ATASD", "PARTSD",
};
typedef struct StoreDev {
@ -35,6 +37,7 @@ typedef struct StoreDev {
union {
RamSd ramsd;
AtaSd atasd;
PartSd partsd;
} sd;
SpinLock spinlock;
} StoreDev;
@ -48,10 +51,10 @@ extern StoreDevList STOREDEV_LIST;
void storedev_init(void);
StoreDev *storedev_create(int32_t sdtype, void *extra);
StoreDev *storedev_create(int32_t sdtype, char *name, void *extra);
int32_t storedev_delete(StoreDev *sd);
void storedev_register_dev_entry(StoreDev *sd, int32_t sdtype);
void storedev_register_dev_entry(StoreDev *sd, char *name, int32_t sdtype);
void storedev_unregister_dev_entry(Dev *dev);
#endif // STOREDEV_STOREDEV_H_