summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/arch')
-rw-r--r--src/kernel/arch/amd64/ata.c10
-rw-r--r--src/kernel/arch/amd64/ata.h4
-rw-r--r--src/kernel/arch/amd64/driver/pata.c21
3 files changed, 23 insertions, 12 deletions
diff --git a/src/kernel/arch/amd64/ata.c b/src/kernel/arch/amd64/ata.c
index 5c5fc57..d88f890 100644
--- a/src/kernel/arch/amd64/ata.c
+++ b/src/kernel/arch/amd64/ata.c
@@ -23,8 +23,6 @@ enum {
CMD = 7,
STATUS = 7,
- /* note: the OSDev wiki uses a different base port for the control port
- * however i can just use this offset and stuff will just work tm */
CTRL = 0x206,
}; // offsets
@@ -40,11 +38,11 @@ static void ata_400ns(void) {
port_in8(base + STATUS);
}
-static void ata_driveselect(int drive, int block) {
+static void ata_driveselect(int drive, int lba) {
uint8_t v = 0xE0;
if (drive&1) // slave?
v |= 0x10; // set drive number bit
- // TODO account for block
+ v |= (lba >> 24) & 0xf;
port_out8(ata_iobase(drive) + DRV, v);
}
@@ -124,6 +122,10 @@ bool ata_available(int drive) {
return ata_drives[drive].type != DEV_UNKNOWN;
}
+size_t ata_size(int drive) {
+ return ata_drives[drive].sectors * ATA_SECTOR;
+}
+
int ata_read(int drive, uint32_t lba, void *buf) {
if (ata_drives[drive].type != DEV_PATA)
panic_unimplemented();
diff --git a/src/kernel/arch/amd64/ata.h b/src/kernel/arch/amd64/ata.h
index 82f4f81..0c20281 100644
--- a/src/kernel/arch/amd64/ata.h
+++ b/src/kernel/arch/amd64/ata.h
@@ -1,7 +1,11 @@
#pragma once
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
+#define ATA_SECTOR 512
+
void ata_init(void);
bool ata_available(int drive);
+size_t ata_size(int drive);
int ata_read(int drive, uint32_t lba, void *buf);
diff --git a/src/kernel/arch/amd64/driver/pata.c b/src/kernel/arch/amd64/driver/pata.c
index b4ec46c..1193add 100644
--- a/src/kernel/arch/amd64/driver/pata.c
+++ b/src/kernel/arch/amd64/driver/pata.c
@@ -1,4 +1,5 @@
#include <camellia/errno.h>
+#include <camellia/fsutil.h>
#include <kernel/arch/amd64/ata.h>
#include <kernel/arch/amd64/driver/pata.h>
#include <kernel/arch/amd64/driver/util.h>
@@ -53,22 +54,26 @@ static void accept(struct vfs_request *req) {
vfsreq_finish_short(req, req_readcopy(req, list, len));
break;
}
- // TODO ata size get
- if (req->offset < 0) {
- vfsreq_finish_short(req, -ENOSYS);
- break;
- }
+ fs_normslice(&req->offset, &req->output.len, ata_size(id), false);
+
char buf[512]; /* stupid */
- uint32_t sector = req->offset / 512;
- size_t len = min(req->output.len, 512 - ((size_t)req->offset & 511));
+ uint32_t sector = req->offset / ATA_SECTOR;
+ size_t skip = (size_t)req->offset & (ATA_SECTOR - 1);
+ size_t len = min(req->output.len, ATA_SECTOR - skip);
ata_read(id, sector, buf);
- virt_cpy_to(req->caller->pages, req->output.buf, buf, len);
+ virt_cpy_to(req->caller->pages, req->output.buf, buf + skip, len);
vfsreq_finish_short(req, len);
break;
case VFSOP_WRITE:
panic_unimplemented();
+ case VFSOP_GETSIZE:
+ if (id == root_id)
+ panic_unimplemented();
+ vfsreq_finish_short(req, ata_size(id));
+ break;
+
default:
vfsreq_finish_short(req, -ENOSYS);
break;