Nucleus
Barry ATA driver read function 639da90 (3 years, 2 months ago)
diff --git a/drivers/storage/ata.c b/drivers/storage/ata.c
index d0ff1e8..bf56afc 100644
--- a/drivers/storage/ata.c
+++ b/drivers/storage/ata.c
@@ -4,11 +4,13 @@
* actual hardware.
*/
+#include <stdio.h>
#include <stdint.h>
+#include <string.h>
#include <sys/stat.h>
+#include <errno.h>
#include <io.h>
#include <nucleus/driver.h>
-#include <nucleus/panic.h>
#include <nucleus/vfs.h>
#include "ide.h"
@@ -25,11 +27,14 @@ struct Partition {
size_t ata_dev_read(File *file, char *buf, size_t size, off_t offset);
size_t ata_dev_write(File *file, char *buf, size_t size, off_t offset);
+/* File Operations for the ATA device nodes */
FileOps ataFileOps = {
.read = ata_dev_read,
.write = ata_dev_write,
};
+static void *ataDmaArea = NULL;
+
/* Access an ATA drive */
static uint8_t
ata_access(int write, struct IDEDevice *dev, uint32_t lba, uint8_t sectors,
@@ -168,21 +173,18 @@ void
ata_init(struct IDEDevice *dev)
{
static int drive = 0;
- static void *ataDmaArea = NULL;
- if (!ataDmaArea)
- ataDmaArea = (void *) alloc_frame();
static int ataMajor = 0;
if (!ataMajor)
ataMajor = register_driver(1, &ataFileOps);
+ if (!ataDmaArea)
+ ataDmaArea = (void *) alloc_frame();
/* Create device node */
char name[16];
int minor = drive * 16;
sprintf(name, "/dev/hd%d", drive);
mknod(name, S_IFBLK | 0600, MKDEV(ataMajor, minor));
- kprintf(" ATA drive [%s] (%d MB) %s", name,
- dev->size / 1024 / 2, dev->model);
/* Attempt to read partition table */
int i;
@@ -194,8 +196,6 @@ ata_init(struct IDEDevice *dev)
continue;
sprintf(name, "/dev/hd%dp%d", drive, i);
mknod(name, S_IFBLK | 0600, MKDEV(ataMajor, minor + i + 1));
- kprintf(" Partition [%s] %#.8x - %#.8x", name,
- part[i].lba*512, (part[i].lba + part[i].size) * 512);
}
drive++;
@@ -205,7 +205,42 @@ ata_init(struct IDEDevice *dev)
size_t
ata_dev_read(File *file, char *buf, size_t size, off_t offset)
{
-
+ uint16_t min, bufOffset = offset % 512;
+ size_t count = 0;
+ uint16_t parti = MINOR(file->inode->dev) % 16;
+ uint32_t lba;
+ struct Partition *part;
+
+ struct IDEDevice *dev = &ideDevices[MINOR(file->inode->dev) / 16];
+
+ if (parti) {
+ ata_read(dev, 0, 1, ataDmaArea);
+ part = (void *) ataDmaArea + 446
+ + ((parti - 1) * sizeof(struct Partition));
+ if (offset > part->size * 512)
+ return 0;
+ if (offset + size > part->size * 512)
+ size = (part->size * 512) - offset;
+ } else {
+ if (offset > dev->size * 512)
+ return 0;
+ if (offset + size > dev->size * 512)
+ size = (dev->size * 512) - offset;
+ }
+
+ while (size + bufOffset) {
+ min = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+ lba = (parti ? part->lba : 0) + ((offset + count) / 512);
+ ata_read(dev, lba, PAGE_SIZE / 512, ataDmaArea);
+ memcpy((void *) (buf + count),
+ (void *) ataDmaArea + bufOffset,
+ min);
+ size -= min;
+ count += min;
+ bufOffset = 0;
+ }
+
+ return count;
}
/* Write to an ATA drive */
@@ -214,3 +249,15 @@ ata_dev_write(File *file, char *buf, size_t size, off_t offset)
{
}
+
+/* Open an ATA drive */
+int
+ata_dev_open(File *file)
+{
+ struct IDEDevice *dev = &ideDevices[MINOR(file->inode->dev) / 16];
+ if (!dev->reserved)
+ return -ENODEV;
+ if (dev->type != 0)
+ return -EINVAL;
+ return 0;
+}