Handle disk partitioning
This commit is contained in:
@ -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
33
kernel/storedev/partsd.c
Normal 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
27
kernel/storedev/partsd.h
Normal 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_
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
Reference in New Issue
Block a user