summaryrefslogtreecommitdiff
path: root/src/sys/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/io')
-rw-r--r--src/sys/io/ic/ahci.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/src/sys/io/ic/ahci.c b/src/sys/io/ic/ahci.c
index e6137e8..b363418 100644
--- a/src/sys/io/ic/ahci.c
+++ b/src/sys/io/ic/ahci.c
@@ -43,6 +43,7 @@
#include <io/ic/ahcivar.h>
#include <io/dma/alloc.h>
#include <vm/physseg.h>
+#include <dms/dms.h>
#include <os/kalloc.h>
#include <os/module.h>
#include <os/clkdev.h>
@@ -75,6 +76,9 @@ static struct clkdev *clkdev;
static struct ahci_hba root_hba;
static TAILQ_HEAD(, ahci_port) portlist;
+/* Disk management operations */
+static struct dms_ops dms_ops;
+
/*
* Poll register to have 'bits' set/unset.
*
@@ -177,12 +181,19 @@ ahci_submit_cmd(struct ahci_hba *hba, struct ahci_port *port, uint8_t slot)
return 0;
}
+
+/*
+ * Log information and register the disk
+ * to the DMS subsystem
+ */
static int
-ahci_log_info(struct ata_identity *identity)
+ahci_register(struct ata_identity *identity, struct ahci_port *port)
{
+ struct dms_disk *dp;
char tmp;
char serial[SERIAL_LEN];
char model[MODEL_LEN];
+ int error;
if (identity == NULL) {
return -EINVAL;
@@ -218,6 +229,14 @@ ahci_log_info(struct ata_identity *identity)
pr_trace("detected %s\n", model);
pr_trace("serial number: %s\n", serial);
+
+ error = dms_register(model, &dms_ops, &dp);
+ if (error < 0) {
+ pr_trace("could not register drive!\n");
+ return error;
+ }
+
+ dp->data = (void *)port;
return 0;
}
@@ -266,7 +285,7 @@ ahci_identify(struct ahci_hba *hba, struct ahci_port *port)
return status;
}
- ahci_log_info(PHYS_TO_VIRT(buf));
+ ahci_register(PHYS_TO_VIRT(buf), port);
vm_free_frame(buf, 1);
return 0;
}
@@ -365,6 +384,45 @@ ahci_rw(struct ahci_hba *hba, struct ahci_port *port, struct bufargs *bufd)
}
/*
+ * DMS write interface
+ */
+static ssize_t
+sata_write(struct dms_disk *dp, void *p, off_t off, size_t len)
+{
+ struct bufargs bd;
+ struct ahci_port *port;
+ size_t real_off, real_len;
+ int error;
+
+ if (dp == NULL || p == NULL) {
+ return -EINVAL;
+ }
+
+ if (len == 0) {
+ return -EINVAL;
+ }
+
+ real_off = ALIGN_DOWN(off, 512);
+ real_len = ALIGN_UP(len, 512);
+
+ bd.buf = p;
+ bd.nblocks = real_len / 512;
+ bd.lba = real_off / 512;
+ bd.write = 1;
+
+ if ((port = dp->data) == NULL) {
+ return -EIO;
+ }
+
+ error = ahci_rw((void *)port->parent, port, &bd);
+ if (error < 0) {
+ return error;
+ }
+
+ return real_len;
+}
+
+/*
* Stop a running port, turn off the command list engine,
* as well as its FIS receive engine
*
@@ -809,6 +867,11 @@ ahci_attach(struct pci_adv *adv)
return ahci_hba_init(&root_hba);
}
+static struct dms_ops dms_ops = {
+ .write = sata_write,
+ .read = NULL
+};
+
static struct pci_adv driver = {
.lookup = PCI_CS_ID(0x1, 0x06),
.attach = ahci_attach,