diff --git a/sortix/ata.cpp b/sortix/ata.cpp index 769a37b1..a1cb8d38 100644 --- a/sortix/ata.cpp +++ b/sortix/ata.cpp @@ -26,6 +26,7 @@ #include #include #include "ata.h" +#include "fs/devfs.h" // TODO: Use the PCI to detect ATA devices instead of relying on them being on // standard locations. @@ -66,7 +67,7 @@ namespace Sortix unsigned ataid = busid*2 + driveid; ATADrive* drive = bus->Instatiate(driveid); if ( !drive ) { return; } - // TODO: Actually use the drive somewhere. + RegisterATADrive(ataid, drive); } void DetectBus(unsigned busid, uint16_t ioport, uint16_t altio) @@ -78,6 +79,7 @@ namespace Sortix void Init() { + InitATADriveList(); DetectBus(0, 0x1F0, 0x3F6); DetectBus(1, 0x170, 0x366); } diff --git a/sortix/fs/devfs.cpp b/sortix/fs/devfs.cpp index 07f92f82..634fa9fa 100644 --- a/sortix/fs/devfs.cpp +++ b/sortix/fs/devfs.cpp @@ -30,12 +30,125 @@ #include "../directory.h" #include "../stream.h" #include "../vga.h" +#include "../ata.h" #include "devfs.h" using namespace Maxsi; namespace Sortix { + class DevATA : public DevBuffer + { + public: + typedef DevBuffer BaseClass; + + public: + DevATA(ATADrive* drive); + virtual ~DevATA(); + + private: + ATADrive* drive; + off_t offset; + + public: + virtual ssize_t Read(byte* dest, size_t count); + virtual ssize_t Write(const byte* src, size_t count); + virtual bool IsReadable(); + virtual bool IsWritable(); + virtual size_t BlockSize(); + virtual uintmax_t Size(); + virtual uintmax_t Position(); + virtual bool Seek(uintmax_t position); + virtual bool Resize(uintmax_t size); + + }; + + DevATA::DevATA(ATADrive* drive) + { + this->drive = drive; + offset = 0; + } + + DevATA::~DevATA() + { + } + + ssize_t DevATA::Read(byte* dest, size_t count) + { + if ( SIZE_MAX < count ) { count = SIZE_MAX; } + if ( drive->GetSize() - offset < count ) { count = drive->GetSize() - offset; } + size_t amount = drive->Read(offset, dest, count); + if ( count && !amount ) { return -1; } + offset += amount; + return amount; + } + + ssize_t DevATA::Write(const byte* src, size_t count) + { + if ( SIZE_MAX < count ) { count = SIZE_MAX; } + if ( drive->GetSize() <= offset && count ) { Error::Set(ENOSPC); return -1; } + if ( drive->GetSize() - offset < count ) { count = drive->GetSize() - offset; } + size_t amount = drive->Write(offset, src, count); + if ( count && !amount ) { return -1; } + offset += amount; + return amount; + } + + bool DevATA::IsReadable() + { + return true; + } + + bool DevATA::IsWritable() + { + return true; + } + + size_t DevATA::BlockSize() + { + return drive->GetSectorSize(); + } + + uintmax_t DevATA::Size() + { + return drive->GetSize(); + } + + uintmax_t DevATA::Position() + { + return offset; + } + + bool DevATA::Seek(uintmax_t position) + { + if ( drive->GetSize() <= position ) { Error::Set(ENOSPC); return false; } + offset = position; + return true; + } + + bool DevATA::Resize(uintmax_t size) + { + Error::Set(EPERM); + return false; + } + + const size_t NUM_ATAS = 4; + DevATA* atalist[NUM_ATAS]; + + void InitATADriveList() + { + for ( size_t i = 0; i < NUM_ATAS; i++ ) + { + atalist[i] = NULL; + } + } + + void RegisterATADrive(unsigned ataid, ATADrive* drive) + { + atalist[ataid] = new DevATA(drive); + atalist[ataid]->Refer(); + } + class DevLogTTY : public DevStream { public: @@ -177,8 +290,8 @@ namespace Sortix int DevDevFSDir::Read(sortix_dirent* dirent, size_t available) { - const char* names[] = { "null", "tty", "vga" }; - const size_t nameslength = 3; + const char* names[] = { "null", "tty", "vga", "ata0", "ata1", "ata2", "ata3" }; + const size_t nameslength = 7; if ( available <= sizeof(sortix_dirent) ) { return -1; } if ( nameslength <= position ) @@ -192,6 +305,15 @@ namespace Sortix size_t namelen = String::Length(name); size_t needed = sizeof(sortix_dirent) + namelen + 1; + if ( name[0] == 'a' && name[1] == 't' && name[2] == 'a' ) + { + if ( !atalist[name[3]-'0'] ) + { + position++; + return Read(dirent, available); + } + } + if ( available < needed ) { dirent->d_namelen = needed; @@ -225,6 +347,23 @@ namespace Sortix if ( String::Compare(path, "/null") == 0 ) { return new DevNull; } if ( String::Compare(path, "/tty") == 0 ) { return new DevLogTTY; } if ( String::Compare(path, "/vga") == 0 ) { return new DevVGA; } + if ( path[0] == '/' && path[1] == 'a' && path[2] == 't' && path[3] == 'a' && path[4] && !path[5] ) + { + if ( '0' <= path[4] && path[4] <= '9' ) + { + size_t index = path[4] - '0'; + if ( index <= NUM_ATAS && atalist[index] ) + { + bool write = flags & O_WRONLY; // TODO: HACK: O_RDWD != O_WRONLY | O_RDONLY + if ( write && !ENABLE_DISKWRITE ) + { + Error::Set(EPERM); + return false; + } + return new DevFileWrapper(atalist[index], flags); + } + } + } Error::Set(flags & O_CREAT ? EPERM : ENOENT); return NULL; diff --git a/sortix/fs/devfs.h b/sortix/fs/devfs.h index 7a1e899a..ec123981 100644 --- a/sortix/fs/devfs.h +++ b/sortix/fs/devfs.h @@ -30,6 +30,8 @@ namespace Sortix { + class ATADrive; + class DevDevFS : public DevFileSystem { public: @@ -41,6 +43,9 @@ namespace Sortix virtual bool Unlink(const char* path); }; + + void InitATADriveList(); + void RegisterATADrive(unsigned ataid, ATADrive* drive); } #endif