Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c new file mode 100644 index 0000000..9e3b73a --- /dev/null +++ b/drivers/ide/ide.c @@ -0,0 +1,685 @@ +/* + * This file is the driver for the PCI IDE devices, which handles access to + * ATA/ATAPI devices. It detects the drives connected to the system, and + * handles any access to them - with the ability to do DMA if possible. This + * driver will access the drives in the best available way, presenting a uniform + * interface for any other code to use. It also adds a device node to the DevFS + * mount for every device, to provide access to the rest of the OS easily. + */ + +#include <stdint.h> +#include <stddef.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include "../drivers.h" +#include "../pci.h" +#include "../../mem/frame.h" +#include "../../proc/proc.h" +#include "../../vfs/vfs.h" +#include "../../io.h" +#include "../../screen.h" + +struct partition { + uint8_t drive; + uint8_t shead, ssect, scyl; + uint8_t type; + uint8_t ehead, esect, ecyl; + uint32_t lba; + uint32_t size; +}; + +size_t ata_read(File *file, char *buf, size_t size, off_t offset); +size_t ata_write(File *file, char *buf, size_t size, off_t offset); +int ata_open(File *file); + +FileOps ideFileOps = { + .read = ata_read, + .write = ata_write, + .open = ata_open, +}; + +Driver ideDriver = { + .major = 2, + .ops = &ideFileOps, + .next = NULL, +}; + +page_t ataDmaArea; + +uint8_t ide_read(uint8_t chan, uint8_t reg); +void ide_write(uint8_t chan, uint8_t reg, uint8_t data); + +/* Status */ +#define ATA_SR_BSY 0x80 /* Busy */ +#define ATA_SR_DRDY 0x40 /* Drive ready */ +#define ATA_SR_DF 0x20 /* Drive write fault */ +#define ATA_SR_DSC 0x10 /* Drive seek complete */ +#define ATA_SR_DRQ 0x08 /* Data request ready */ +#define ATA_SR_CORR 0x04 /* Corrected data */ +#define ATA_SR_IDX 0x02 /* Index */ +#define ATA_SR_ERR 0x01 /* Error */ + +/* Error */ +#define ATA_ER_BBK 0x80 /* Bad block */ +#define ATA_ER_UNC 0x40 /* Uncorrectable data */ +#define ATA_ER_MC 0x20 /* Media changed */ +#define ATA_ER_IDNF 0x10 /* ID mark not found */ +#define ATA_ER_MCR 0x08 /* Media change request */ +#define ATA_ER_ABRT 0x04 /* Command aborted */ +#define ATA_ER_T0NF 0x02 /* Track 0 not found */ +#define ATA_ER_AMNF 0x01 /* No address mark */ + +/* Command */ +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B + +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define IDE_ATA 0 +#define IDE_ATAPI 1 +#define ATA_MASTER 0 +#define ATA_SLAVE 1 +#define ATA_PRIMARY 0 +#define ATA_SECONDARY 1 +#define ATA_READ 0 +#define ATA_WRITE 1 + +/* Registers */ +#define ATA_REG_DATA 0x0 +#define ATA_REG_ERROR 0x1 +#define ATA_REG_FEATURES 0x1 +#define ATA_REG_SECCOUNT0 0x2 +#define ATA_REG_LBA0 0x3 +#define ATA_REG_LBA1 0x4 +#define ATA_REG_LBA2 0x5 +#define ATA_REG_HDDEVSEL 0x6 +#define ATA_REG_COMMAND 0x7 +#define ATA_REG_STATUS 0x7 +#define ATA_REG_SECCOUNT1 0x8 +#define ATA_REG_LBA3 0x9 +#define ATA_REG_LBA4 0xA +#define ATA_REG_LBA5 0xB +#define ATA_REG_CONTROL 0xC +#define ATA_REG_ALTSTATUS 0xC +#define ATA_REG_DEVADDRESS 0xD + +struct IDEChanRegs { + uint16_t base; /* IO base */ + uint16_t ctrl; /* Control base */ + uint16_t bmide; /* Bus Master IDE */ + uint8_t noint; /* No interrupt */ +} channels[2]; + +uint8_t ideBuf[2048] = {0}; +volatile unsigned static char ideIrqInvoked = 0; +unsigned static char atapiPacket[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +struct IDEDevice { + uint8_t reserved; + uint8_t channel; + uint8_t drive; + uint16_t type; + uint16_t signature; + uint16_t capabilities; + uint32_t commandSets; + uint32_t size; + uint8_t model[41]; +} ideDevices[4]; + +/* Read channel */ +uint8_t +ide_read(uint8_t chan, uint8_t reg) +{ + uint8_t result; + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, 0x80 | channels[chan].noint); + if (reg < 0x08) + result = inb(channels[chan].base + reg - 0x00); + else if (reg < 0x0C) + result = inb(channels[chan].base + reg - 0x06); + else if (reg < 0x0E) + result = inb(channels[chan].ctrl + reg - 0x0A); + else if (reg < 0x16) + result = inb(channels[chan].bmide + reg - 0x0E); + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, channels[chan].noint); + return result; +} + +/* Write channel */ +void +ide_write(uint8_t chan, uint8_t reg, uint8_t data) +{ + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, 0x80 | channels[chan].noint); + if (reg < 0x08) + outb(channels[chan].base + reg - 0x00, data); + else if (reg < 0x0C) + outb(channels[chan].base + reg - 0x06, data); + else if (reg < 0x0E) + outb(channels[chan].ctrl + reg - 0x0A, data); + else if (reg < 0x16) + outb(channels[chan].bmide + reg - 0x0E, data); + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, channels[chan].noint); +} + +/* Read identification space */ +void +ide_read_buffer(uint8_t chan, uint8_t reg, void *buffer, uint32_t quads) +{ + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, 0x80 | channels[chan].noint); + asm volatile("pushw %es; movw %ds, %ax; movw %ax, %es"); + if (reg < 0x08) + insl(channels[chan].base + reg - 0x00, buffer, quads); + else if (reg < 0x0C) + insl(channels[chan].base + reg - 0x06, buffer, quads); + else if (reg < 0x0E) + insl(channels[chan].ctrl + reg - 0x0A, buffer, quads); + else if (reg < 0x16) + insl(channels[chan].bmide + reg - 0x0E, buffer, quads); + asm volatile("popw %es"); + if (reg > 0x07 && reg < 0x0C) + ide_write(chan, ATA_REG_CONTROL, channels[chan].noint); +} + +/* Poll for status after command */ +uint8_t +ide_polling(uint8_t chan, uint32_t check) +{ + uint8_t i, state; + /* Wait for BSY to set */ + for (i = 0; i < 4; i++) + ide_read(chan, ATA_REG_ALTSTATUS); + /* Wait for BSY to clear */ + while (ide_read(chan, ATA_REG_STATUS) & ATA_SR_BSY); + + if (check) { + state = ide_read(chan, ATA_REG_STATUS); + if (state & ATA_SR_ERR) + return 2; + if (state & ATA_SR_DF) + return 1; + if ((state & ATA_SR_DRQ) == 0) + return 3; + } + + return 0; +} + +/* Print an IDE error */ +uint8_t +ide_print_error(uint32_t drive, uint8_t err) +{ + if (err == 0) + return err; + + uint8_t st; + kprintf("IDE:"); + if (err == 1) { + kprintf(" - Device fault"); + err = 19; + } else if (err == 2) { + st = ide_read(ideDevices[drive].channel, ATA_REG_ERROR); + if (st & ATA_ER_AMNF) { + kprintf(" - No address mark found"); + err = 7; + } + if (st & ATA_ER_T0NF) { + kprintf(" - No media or media error"); + err = 3; + } + if (st & ATA_ER_ABRT) { + kprintf(" - Command aborted"); + err = 20; + } + if (st & ATA_ER_MCR) { + kprintf(" - No media or media error"); + err = 3; + } + if (st & ATA_ER_IDNF) { + kprintf(" - ID mark not found"); + err = 21; + } + if (st & ATA_ER_MC) { + kprintf(" - No media or media error"); + err = 3; + } + if (st & ATA_ER_UNC) { + kprintf(" - Uncorrectable data error"); + err = 22; + } + if (st & ATA_ER_BBK) { + kprintf(" - Bad sectors"); + err = 13; + } + } else if (err == 3) { + kprintf(" - Read nothing"); + err = 23; + } else if (err == 4) { + kprintf(" - Write protected"); + err = 8; + } + kprintf(" - [%s %s] %s", + (char *[]){"Primary","Secondary"}[ideDevices[drive].channel], + (char *[]){"Master","Slave"}[ideDevices[drive].drive], + ideDevices[drive].model); + return err; +} + +/* Initialise an IDE drive */ +void +ide_drive_init(uint32_t bar0, uint32_t bar1, uint32_t bar2, + uint32_t bar3, uint32_t bar4) +{ + channels[ATA_PRIMARY].base = (bar0 & ~3) + 0x1F0 * (!bar0); + channels[ATA_PRIMARY].ctrl = (bar1 & ~3) + 0x3F6 * (!bar1); + channels[ATA_SECONDARY].base = (bar2 & ~3) + 0x170 * (!bar2); + channels[ATA_SECONDARY].ctrl = (bar3 & ~3) + 0x376 * (!bar3); + channels[ATA_PRIMARY].bmide = (bar4 & ~3) + 0; + channels[ATA_SECONDARY].bmide = (bar4 & ~3) + 8; + /* Disable IRQs */ + ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2); + ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2); + + uint32_t count = 0; + uint8_t i, j, k, err, type, status; + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) { + err = 0; + type = IDE_ATA; + ideDevices[count].reserved = 0; + ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); + sleep(1); + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + sleep(1); + if (ide_read(i, ATA_REG_STATUS) == 0) + continue; + + while (1) { + status = ide_read(i, ATA_REG_STATUS); + if ((status & ATA_SR_ERR)) { + err = 1; + break; + } + if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) + break; + } + + if (err) { + uint8_t cl = ide_read(i, ATA_REG_LBA1); + uint8_t ch = ide_read(i, ATA_REG_LBA2); + + if (cl == 0x14 && ch == 0xEB) + type = IDE_ATAPI; + else if (cl == 0x69 && ch == 0x96) + type = IDE_ATAPI; + else + continue; + + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + sleep(1); + } + + ide_read_buffer(i, ATA_REG_DATA, ideBuf, 128); + + uint16_t sig, cap, set; + sig = *((uint16_t *) (ideBuf + ATA_IDENT_DEVICETYPE)); + cap = *((uint16_t *) (ideBuf + ATA_IDENT_CAPABILITIES)); + set = *((uint16_t *) (ideBuf + ATA_IDENT_COMMANDSETS)); + ideDevices[count].reserved = 1; + ideDevices[count].type = type; + ideDevices[count].channel = i; + ideDevices[count].drive = j; + ideDevices[count].signature = sig; + ideDevices[count].capabilities = cap; + ideDevices[count].commandSets = set; + + uint32_t size; + if (ideDevices[count].commandSets & (1 << 26)) + size = *((uint32_t *) (ideBuf + ATA_IDENT_MAX_LBA_EXT)); + else + size = *((uint32_t *) (ideBuf + ATA_IDENT_MAX_LBA)); + ideDevices[count].size = size; + for (k = 0; k < 40; k += 2) { + ideDevices[count].model[k] = + ideBuf[ATA_IDENT_MODEL + k + 1]; + ideDevices[count].model[k + 1] = + ideBuf[ATA_IDENT_MODEL + k]; + } + ideDevices[count].model[40] = 0; + count++; + } +} + +/* Wait for an IRQ to arrive */ +void +ide_wait_irq(void) +{ + while (!ideIrqInvoked); + ideIrqInvoked = 0; +} + +/* Access an ATA drive */ +uint8_t +ide_ata_access(uint8_t write, uint8_t drive, uint32_t lba, uint8_t sectors, + uint16_t selector, uint32_t edi) +{ + uint8_t lbaMode, dma, cmd; + uint8_t lbaIO[6]; + uint32_t chan = ideDevices[drive].channel; + uint32_t slave = ideDevices[drive].drive; + uint32_t bus = channels[chan].base; + uint32_t words = 256; + uint16_t cyl, i; + uint8_t head, sect, err; + + ide_write(chan, ATA_REG_CONTROL, + channels[chan].noint = (ideIrqInvoked = 0) + 2); + + if (lba >= 0x10000000) { + /* LBA48 */ + lbaMode = 2; + lbaIO[0] = (lba & 0x000000FF) >> 0; + lbaIO[1] = (lba & 0x0000FF00) >> 8; + lbaIO[2] = (lba & 0x00FF0000) >> 16; + lbaIO[3] = (lba & 0xFF000000) >> 24; + lbaIO[4] = 0; + lbaIO[5] = 0; + head = 0; + } else if (ideDevices[drive].capabilities & 0x200) { + /* LBA28 */ + lbaMode = 1; + lbaIO[0] = (lba & 0x000000FF) >> 0; + lbaIO[1] = (lba & 0x0000FF00) >> 8; + lbaIO[2] = (lba & 0x00FF0000) >> 16; + lbaIO[3] = 0; + lbaIO[4] = 0; + lbaIO[5] = 0; + head = (lba & 0x0F000000) >> 24; + } else { + /* CHS */ + lbaMode = 0; + sect = (lba % 63) + 1; + cyl = (lba + 1 - sect) / (16 * 63); + lbaIO[0] = sect; + lbaIO[1] = (cyl >> 0) & 0xFF; + lbaIO[2] = (cyl >> 8) & 0xFF; + lbaIO[3] = 0; + lbaIO[4] = 0; + lbaIO[5] = 0; + head = (lba + 1 - sect) % (16 * 63) / 63; + } + + dma = 0; /* XXX */ + + while (ide_read(chan, ATA_REG_STATUS) & ATA_SR_BSY); + + if (lbaMode == 0) + ide_write(chan, ATA_REG_HDDEVSEL, 0xA0 | (slave << 4) | head); + else + ide_write(chan, ATA_REG_HDDEVSEL, 0xE0 | (slave << 4) | head); + + if (lbaMode == 2) { + ide_write(chan, ATA_REG_SECCOUNT1, 0); + ide_write(chan, ATA_REG_LBA3, lbaIO[3]); + ide_write(chan, ATA_REG_LBA4, lbaIO[4]); + ide_write(chan, ATA_REG_LBA5, lbaIO[5]); + } + ide_write(chan, ATA_REG_SECCOUNT0, sectors); + ide_write(chan, ATA_REG_LBA0, lbaIO[0]); + ide_write(chan, ATA_REG_LBA1, lbaIO[1]); + ide_write(chan, ATA_REG_LBA2, lbaIO[2]); + + if (lbaMode == 0 && !dma && !write) cmd = ATA_CMD_READ_PIO; + if (lbaMode == 1 && !dma && !write) cmd = ATA_CMD_READ_PIO; + if (lbaMode == 2 && !dma && !write) cmd = ATA_CMD_READ_PIO_EXT; + if (lbaMode == 0 && dma && !write) cmd = ATA_CMD_READ_DMA; + if (lbaMode == 1 && dma && !write) cmd = ATA_CMD_READ_DMA; + if (lbaMode == 2 && dma && !write) cmd = ATA_CMD_READ_DMA_EXT; + if (lbaMode == 0 && !dma && write) cmd = ATA_CMD_WRITE_PIO; + if (lbaMode == 1 && !dma && write) cmd = ATA_CMD_WRITE_PIO; + if (lbaMode == 2 && !dma && write) cmd = ATA_CMD_WRITE_PIO_EXT; + if (lbaMode == 0 && dma && write) cmd = ATA_CMD_WRITE_DMA; + if (lbaMode == 1 && dma && write) cmd = ATA_CMD_WRITE_DMA; + if (lbaMode == 2 && dma && write) cmd = ATA_CMD_WRITE_DMA_EXT; + ide_write(chan, ATA_REG_COMMAND, cmd); + + if (dma) { + if (write) { + /* TODO */ + } else { + /* TODO */ + } + } else { + if (write) { + for (i = 0; i < sectors; i++) { + ide_polling(chan, 0); + outsw(bus, (void *) edi, words); + } + ide_write(chan, ATA_REG_COMMAND, (uint8_t []) { + ATA_CMD_CACHE_FLUSH, + ATA_CMD_CACHE_FLUSH, + ATA_CMD_CACHE_FLUSH_EXT, + }[lbaMode]); + ide_polling(chan, 0); + } else { + for (i = 0; i < sectors; i++) { + if (err = ide_polling(chan, 1)) + return err; + insw(bus, (void *) edi, words); + edi += words * 2; + } + } + } + + return 0; +} + +/* IDE IRQ handler */ +void +ide_irq(InterruptFrame *frame) +{ + ideIrqInvoked = 1; +} + +/* Initialise an IDE drive */ +void +ide_init(uint8_t bus, uint8_t slot, uint8_t func) +{ + register_driver(&ideDriver); + + uint8_t class, subclass, progif, header; + class = pci_read_byte(bus, slot, func, 11); + subclass = pci_read_byte(bus, slot, func, 10); + progif = pci_read_byte(bus, slot, func, 9); + header = pci_read_byte(bus, slot, func, 14); + + uint8_t primaryNative = 0, primaryChange = 0, + secondaryNative = 0, secondaryChange = 0, + busMaster = 0; + if (progif & (1 << 0)) + primaryNative = 1; + if (progif & (1 << 1)) + primaryChange = 1; + if (progif & (1 << 2)) + secondaryNative = 1; + if (progif & (1 << 3)) + secondaryChange = 1; + if (progif & (1 << 7)) + busMaster = 1; + + uint32_t bar0 = 0x1F0, bar1 = 0x3F6, + bar2 = 0x170, bar3 = 0x376, + bar4 = 0x00; + + if (primaryNative) { + bar0 = pci_read_dword(bus, slot, func, 0x10); + bar1 = pci_read_dword(bus, slot, func, 0x14); + } + if (secondaryNative) { + bar2 = pci_read_dword(bus, slot, func, 0x18); + bar3 = pci_read_dword(bus, slot, func, 0x1C); + } + if (busMaster) + bar4 = pci_read_dword(bus, slot, func, 0x20); + + register_interrupt(14, ide_irq); + ataDmaArea = alloc_frames(1); + + ide_drive_init(0x1F0, 0x3F6, 0x170, 0x376, 0x00); + uint8_t i, j; + char name[16]; + for (i = 0; i < 4; i++) { + if (!ideDevices[i].reserved) + continue; + sprintf(name, "/dev/%cd%c", + (char []){'h','c'}[ideDevices[i].type], + (char []){'a','b'}[ideDevices[i].channel]); + mknod(name, S_IFBLK | 0600, MKDEV(ideDriver.major, i * 16)); + kprintf(" %s drive [%s] %d MB - %s", + (char *[]){"ATA", "ATAPI"}[ideDevices[i].type], + name, ideDevices[i].size / 1024 / 2, + ideDevices[i].model); + /* Attempt to read partition table */ + if (ideDevices[i].type != 0) + continue; + ide_ata_access(0, i, 0, 0x02, 1, ataDmaArea); + struct partition *part; + for (j = 0; j < 4; j++) { + part = (void *) ataDmaArea + 446 + (j * 16); + if (!part->type) + continue; + sprintf(name, "/dev/%cd%c%d", + (char []){'h','c'}[ideDevices[i].type], + (char []){'a','b'}[ideDevices[i].channel], + j + 1); + int asdf = mknod(name, S_IFBLK | 0600, + MKDEV(ideDriver.major, (i * 16) + (j + 1))); + kprintf(" Partition %d: %#.8x - %#.8x", + j+1, part->lba*512, + (part->lba + part->size) * 512); + } + } +} + +/* Read a drive */ +size_t +ata_read(File *file, char *buf, size_t size, off_t offset) +{ + uint16_t min, bufOffset = offset % 512; + size_t count = 0; + uint16_t dev = MINOR(file->inode->dev) / 16, + parti = MINOR(file->inode->dev) % 16; + uint32_t lba; + struct partition *part; + if (parti) { + ide_ata_access(0, dev, 0, 1, 0x02, ataDmaArea); + part = (void *) ataDmaArea + 446 + ((parti - 1) * 16); + if (offset > (part->lba + part->size) * 512) + return 0; + if (offset + size > (part->lba + part->size) * 512) + size = ((part->lba + part->size) * 512) - offset; + } else { + if (offset > ideDevices[dev].size * 512) + return 0; + if (offset + size > ideDevices[dev].size * 512) + size = (ideDevices[dev].size * 512) - offset; + } + while (size + bufOffset) { + min = (size > 0x1000) ? 0x1000 : size; + lba = (parti ? part->lba : 0) + ((offset + count) / 512); + ide_ata_access(0, dev, lba, 8, 0x02, ataDmaArea); + memcpy((void *) (buf + count), + (void *) ataDmaArea + bufOffset, + min); + size -= min; + count += min; + bufOffset = 0; + } + return count; +} + +/* Write a drive */ +size_t +ata_write(File *file, char *buf, size_t size, off_t offset) +{ + uint16_t min; + size_t count = 0; + uint16_t dev = MINOR(file->inode->dev) / 16, + parti = MINOR(file->inode->dev) % 16; + uint32_t lba; + struct partition *part; + if (parti) { + ide_ata_access(0, dev, 0, 1, 0x02, ataDmaArea); + part = (void *) ataDmaArea + 446 + ((parti - 1) * 16); + if (offset > (part->lba + part->size) * 512) + return 0; + if (offset + size > (part->lba + part->size) * 512) + size = ((part->lba + part->size) * 512) - offset; + } else { + if (offset > ideDevices[dev].size * 512) + return 0; + if (offset + size > ideDevices[dev].size * 512) + size = (ideDevices[dev].size * 512) - offset; + } + while (size) { + min = (size > 0x1000) ? 0x1000 : size; + memcpy((void *) ataDmaArea, +// (void *) (((uint32_t) (buf + count) / 512) * 512), + (void *) (buf + count), + min); + lba = (parti ? part->lba : 0) + ((offset + count) / 512); + ide_ata_access(1, dev, lba, 8, 0x02, ataDmaArea); + size -= min; + count += min; + } + return count; + /* + * TODO: Currently, offset is sector-aligned, which we don't always + * want. This should be fixed by basically checking the offset + * for this and reading into the dma buffer before we write to the + * adjusted offset in the buffer, this way the surrounding data + * isn't deleted by accident with bad alignment. + */ +} + +/* Open a drive */ +int +ata_open(File *file) +{ + if (ideDevices[MINOR(file->inode->dev)/16].reserved) + return 0; + if (ideDevices[MINOR(file->inode->dev)/16].type != 0) + return -EINVAL; + return -ENODEV; +} +