From 4d0939e2853ffd9d49b83524923351f9776866d7 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sat, 28 Nov 2009 12:36:01 +0100 Subject: Caching mechanism added and floppy driver fixed on qemu/vbox --- .../Devices/Floppy/FloppyController.class.cpp | 3 +- Source/Kernel/Devices/Floppy/FloppyDrive.class.cpp | 27 ++++--- Source/Kernel/Devices/Floppy/FloppyDrive.class.h | 2 +- Source/Kernel/FileSystems/FAT/FATFS.class.cpp | 10 +-- Source/Kernel/FileSystems/FAT/FATFS.class.h | 8 +- Source/Kernel/VFS/BlockCache.class.cpp | 89 ++++++++++++++++++++++ Source/Kernel/VFS/BlockCache.class.h | 32 ++++++++ Source/Kernel/VFS/Part.ns.cpp | 2 +- Source/Kernel/VFS/Partition.class.cpp | 8 +- Source/Kernel/VFS/Partition.class.h | 2 + Source/Kernel/VFS/VFS.ns.cpp | 1 - 11 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 Source/Kernel/VFS/BlockCache.class.cpp create mode 100644 Source/Kernel/VFS/BlockCache.class.h diff --git a/Source/Kernel/Devices/Floppy/FloppyController.class.cpp b/Source/Kernel/Devices/Floppy/FloppyController.class.cpp index db148d0..7201c5c 100644 --- a/Source/Kernel/Devices/Floppy/FloppyController.class.cpp +++ b/Source/Kernel/Devices/Floppy/FloppyController.class.cpp @@ -153,7 +153,6 @@ void FloppyController::setDOR() { checkInterrupt(&st0, &cyl); m_first = false; } - //PANIC("test"); } void FloppyController::setActiveDrive(u8int drive) { @@ -190,10 +189,10 @@ u8int FloppyController::readData() { bool FloppyController::reset() { outb(m_base + FR_DOR, 0x00); //Disable controller m_first = true; - setNoActiveDrive(); if (m_drives[0] != NULL) m_drives[0]->m_motorState = 0; if (m_drives[1] != NULL) m_drives[1]->m_motorState = 0; + setNoActiveDrive(); for (int i = 0; i < 2; i++) { if (m_drives[i] != NULL) { diff --git a/Source/Kernel/Devices/Floppy/FloppyDrive.class.cpp b/Source/Kernel/Devices/Floppy/FloppyDrive.class.cpp index 4036927..b7fd69b 100644 --- a/Source/Kernel/Devices/Floppy/FloppyDrive.class.cpp +++ b/Source/Kernel/Devices/Floppy/FloppyDrive.class.cpp @@ -92,7 +92,10 @@ bool FloppyDrive::calibrate() { int st0, cyl = -1; - if (!setMotorState(true)) return false; + if (!setMotorState(true)) { + *kvt << getName() << ": calibrate fail\n"; + return false; + } for (int i = 0; i < 10; i++) { m_fdc->resetIrq(); @@ -138,18 +141,17 @@ bool FloppyDrive::killMotor() { return true; } -bool FloppyDrive::seek(u32int cyli, s32int head) { +bool FloppyDrive::seek(u32int cyli, s32int head, bool recursive) { if (cyli >= m_cylinders) return false; - m_fdc->setActiveDrive(m_driveNumber); setMotorState(true); //Turn on motor int st0, cyl = -1; - for (u32int i = 0; i < 10; i++) { + for (u32int i = 0; i < (recursive ? 10 : 5); i++) { m_fdc->resetIrq(); m_fdc->writeCmd(FC_SEEK); - m_fdc->writeCmd(head << 2); + m_fdc->writeCmd(head << 2 | m_driveNumber); m_fdc->writeCmd(cyl); m_fdc->waitIrq(); @@ -160,20 +162,23 @@ bool FloppyDrive::seek(u32int cyli, s32int head) { } if (cyl == 0xFF or cyl == 0x00 or cyl == (int)cyli) { //0xFF for bochs, 0x00 for qemu :D setMotorState(false); - m_fdc->setNoActiveDrive(); return true; } } - setMotorState(false); - m_fdc->setNoActiveDrive(); - *kvt << getName() << ": seek fail\n"; - return false; + if (recursive) { + setMotorState(false); + *kvt << getName() << ": seek fail\n"; + return false; + } else { + calibrate(); + return seek(cyli, head, true); + } } bool FloppyDrive::doTrack(u32int cyl, u8int dir) { + m_fdc->setActiveDrive(m_driveNumber); if (!seek(cyl, 0)) return false; if (!seek(cyl, 1)) return false; - m_fdc->setActiveDrive(m_driveNumber); u8int cmd, flags = 0xC0; switch (dir) { diff --git a/Source/Kernel/Devices/Floppy/FloppyDrive.class.h b/Source/Kernel/Devices/Floppy/FloppyDrive.class.h index 75926ea..73229b1 100644 --- a/Source/Kernel/Devices/Floppy/FloppyDrive.class.h +++ b/Source/Kernel/Devices/Floppy/FloppyDrive.class.h @@ -22,7 +22,7 @@ class FloppyDrive : public BlockDevice { bool calibrate(); bool setMotorState(bool on); bool killMotor(); - bool seek(u32int cyli, s32int head); + bool seek(u32int cyli, s32int head, bool recursive = false); bool doTrack(u32int cyl, u8int dir); public: diff --git a/Source/Kernel/FileSystems/FAT/FATFS.class.cpp b/Source/Kernel/FileSystems/FAT/FATFS.class.cpp index e4cb40c..35c18eb 100644 --- a/Source/Kernel/FileSystems/FAT/FATFS.class.cpp +++ b/Source/Kernel/FileSystems/FAT/FATFS.class.cpp @@ -25,7 +25,7 @@ FileSystem* FATFS::mount(Partition* p, DirectoryNode* mountpoint, bool readwrite if (bs.s.extBS_16.boot_signature != 0x28 and bs.s.extBS_16.boot_signature != 0x29 and bs.s.extBS_32.boot_signature != 0x28 and bs.s.extBS_32.boot_signature != 0x29) return 0; // *** DO SOME CALCULATIONS *** - FATFS* fs = new FATFS(); + FATFS* fs = new FATFS(p); fs->m_fatSize = (bs.s.table_size_16 == 0 ? bs.s.extBS_32.table_size_32 : bs.s.table_size_16); fs->m_totalSectors = (bs.s.total_sectors_16 == 0 ? bs.s.total_sectors_32 : bs.s.total_sectors_16); fs->m_rootDirSectors = ((bs.s.root_entry_count * 32) + (bs.s.bytes_per_sector - 1)) / bs.s.bytes_per_sector; @@ -42,7 +42,6 @@ FileSystem* FATFS::mount(Partition* p, DirectoryNode* mountpoint, bool readwrite } fs->m_readOnly = true; fs->m_bs = bs.s; - fs->m_part = p; // *** CREATE ROOT DIRECTORY NODE *** fs->m_rootNode = new FATDirectoryNode("/", fs, mountpoint); FIRSTCLUS(fs->m_rootNode) = 2; @@ -52,6 +51,7 @@ FileSystem* FATFS::mount(Partition* p, DirectoryNode* mountpoint, bool readwrite delete fs; return 0; } + fs->m_fatCache.init(fs->m_fatType == 12 ? 8 : (fs->m_fatType == 16 ? 20 : 40)); if (mountpoint != 0) mountpoint->mount(fs->m_rootNode); VFS::registerFilesystem(fs); *kvt << "Detected a FAT" << (s64int)fs->m_fatType << " filesystem.\n" << @@ -69,7 +69,7 @@ u32int FATFS::nextCluster(u32int cluster) { u32int fat_offset = cluster + (cluster / 2); u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize()); u32int ent_offset = fat_offset % m_part->getBlockSize(); - m_part->readBlocks(fat_sector, 1, fat_table); + m_fatCache.readBlocks(fat_sector, 1, fat_table); u16int tblval = *(u16int*)&fat_table[ent_offset]; if (cluster & 1) val = tblval >> 4; else val = tblval & 0x0FFF; @@ -78,7 +78,7 @@ u32int FATFS::nextCluster(u32int cluster) { u32int fat_offset = cluster * 2; u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize()); u32int ent_offset = fat_offset % m_part->getBlockSize(); - m_part->readBlocks(fat_sector, 1, fat_table); + m_fatCache.readBlocks(fat_sector, 1, fat_table); u16int tblval = *(u16int*)&fat_table[ent_offset]; val = tblval; if (tblval >= 0xFFF7) val = 0; @@ -86,7 +86,7 @@ u32int FATFS::nextCluster(u32int cluster) { u32int fat_offset = cluster * 4; u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize()); u32int ent_offset = fat_offset % m_part->getBlockSize(); - m_part->readBlocks(fat_sector, 1, fat_table); + m_fatCache.readBlocks(fat_sector, 1, fat_table); val = *(u32int*)&fat_table[ent_offset] & 0x0FFFFFFF; if (val >= 0x0FFFFFF7) val = 0; } diff --git a/Source/Kernel/FileSystems/FAT/FATFS.class.h b/Source/Kernel/FileSystems/FAT/FATFS.class.h index 251b2a8..fbefc02 100644 --- a/Source/Kernel/FileSystems/FAT/FATFS.class.h +++ b/Source/Kernel/FileSystems/FAT/FATFS.class.h @@ -3,6 +3,7 @@ #include #include +#include struct fat_extBS_32_t { //Extended boot sector for FAT32 unsigned int table_size_32; @@ -88,9 +89,6 @@ struct fat_dir_entry_t { class FATFS : public FileSystem { private: - FATFS() {} - ~FATFS() {} - fat_BS_t m_bs; bool m_readOnly; u32int m_fatSize; //Size of one FAT, in sectors @@ -101,10 +99,14 @@ class FATFS : public FileSystem { u32int m_clusterSize; //size of a cluster in bytes u32int m_fatType; //12, 16 or 32 Partition* m_part; + BlockCache m_fatCache; u32int nextCluster(u32int cluster); //Get the next cluster number in the chain (0 = EOF) bool readCluster(u32int cluster, u8int* data); //Read the content of a cluster to a buffer + ~FATFS() {} + FATFS(Partition* p) : m_part(p), m_fatCache(p) {} + public: static FileSystem* mount(Partition* p, DirectoryNode* mountpoint, bool readwrite = false); diff --git a/Source/Kernel/VFS/BlockCache.class.cpp b/Source/Kernel/VFS/BlockCache.class.cpp new file mode 100644 index 0000000..458faf6 --- /dev/null +++ b/Source/Kernel/VFS/BlockCache.class.cpp @@ -0,0 +1,89 @@ +#include + +template +BlockCache::BlockCache(T* dev) { + m_dev = dev; + m_count = 0; +} + +template +BlockCache::~BlockCache() { + sync(); + m_count = 0; + delete m_cache; + delete m_cacheInfo; +} + +template +void BlockCache::sync() { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].dirty) m_dev->writeBlocks(m_cacheInfo[i].id, 1, m_cache + (i * m_dev->getBlockSize())); + } +} + +template +void BlockCache::init(u32int count) { + m_count = count; + m_cacheInfo = new cached_block_t[count]; + for (u32int i = 0; i < m_count; i++) { + m_cacheInfo[i].id = 0; + m_cacheInfo[i].lastuse = 0; + m_cacheInfo[i].dirty = false; + } + m_cache = (u8int*)Mem::alloc(m_count * m_dev->getBlockSize()); +} + +template +bool BlockCache::setCache(u64int block, u8int* data, bool dirty) { + u32int best = 0; + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block) { + best = i; + break; + } + if (m_cacheInfo[i].lastuse < m_cacheInfo[best].lastuse) best = i; + } + if (best >= m_count) return false; + if (m_cacheInfo[best].dirty && (m_cacheInfo[best].id != block or !dirty)) + m_dev->writeBlocks(m_cacheInfo[best].id, 1, m_cache + (best * m_dev->getBlockSize())); + m_cacheInfo[best].id = block; + m_cacheInfo[best].lastuse = Time::uptime(); + m_cacheInfo[best].dirty = dirty; + memcpy(m_cache + (best * m_dev->getBlockSize()), data, m_dev->getBlockSize()); + return true; +} + +template +bool BlockCache::getCache(u64int block, u8int* data) { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block && m_cacheInfo[i].lastuse != 0) { + m_cacheInfo[i].lastuse = Time::uptime(); + memcpy(data, m_cache + (i * m_dev->getBlockSize()), m_dev->getBlockSize()); + return true; + } + } + return false; +} + +template +bool BlockCache::readBlocks(u64int startblock, u32int count, u8int* data) { + if (count == 1) { + if (getCache(startblock, data)) return true; + if (!m_dev->readBlocks(startblock, count, data)) return false; + setCache(startblock, data); + return true; + } else { + return m_dev->readBlocks(startblock, count, data); + } +} + +template +bool BlockCache::writeBlocks(u64int startblock, u32int count, u8int* data) { + if (m_dev->readOnly()) return false; + if (count == 1) { + if (!setCache(startblock, data, true)) return m_dev->writeBlocks(startblock, count, data); + return true; + } else { + return m_dev->writeBlocks(startblock, count, data); + } +} diff --git a/Source/Kernel/VFS/BlockCache.class.h b/Source/Kernel/VFS/BlockCache.class.h new file mode 100644 index 0000000..0b26180 --- /dev/null +++ b/Source/Kernel/VFS/BlockCache.class.h @@ -0,0 +1,32 @@ +#ifndef DEF_BLOCKCACHE_CLASS_H +#define DEF_BLOCKCACHE_CLASS_H + +template +class BlockCache { + private: + T* m_dev; + u32int m_count; + struct cached_block_t { + u64int id; + u32int lastuse; + bool dirty; + } *m_cacheInfo; + u8int* m_cache; + + void sync(); + bool setCache(u64int block, u8int* data, bool dirty = false); + bool getCache(u64int block, u8int* data); + + public: + BlockCache(T* dev); + ~BlockCache(); + void init(u32int count); + + bool readBlocks(u64int startblock, u32int count, u8int* data); + bool writeBlocks(u64int startblock, u32int count, u8int* data); + +}; + +#include "BlockCache.class.cpp" + +#endif diff --git a/Source/Kernel/VFS/Part.ns.cpp b/Source/Kernel/VFS/Part.ns.cpp index 1bd6a8e..9ead6b5 100644 --- a/Source/Kernel/VFS/Part.ns.cpp +++ b/Source/Kernel/VFS/Part.ns.cpp @@ -57,7 +57,7 @@ u32int getDeviceID(BlockDevice* dev) { } BlockDevice* dev(String _class, u32int idx) { - if (_class.empty()) _class = "block"; + if (_class.empty()) return devices[idx]; for (u32int i = 0; i < devices.size(); i++) { String devclass = devices[i]->getClass(); if (devclass == _class or (devclass.size() > _class.size() and devclass.substr(0, _class.size()) == _class)) { diff --git a/Source/Kernel/VFS/Partition.class.cpp b/Source/Kernel/VFS/Partition.class.cpp index b62f33c..1476b14 100644 --- a/Source/Kernel/VFS/Partition.class.cpp +++ b/Source/Kernel/VFS/Partition.class.cpp @@ -2,21 +2,23 @@ using namespace CMem; //For memcpy -Partition::Partition(BlockDevice* dev, u8int partnumber, u64int startblock, u64int blockcount) { +Partition::Partition(BlockDevice* dev, u8int partnumber, u64int startblock, u64int blockcount) +: m_cache(dev) { m_device = dev; m_partnumber = partnumber; m_startblock = startblock; m_blockcount = blockcount; + m_cache.init(10 + (m_device->blocks() / 1000 > 100 ? 100 : m_device->blocks() / 1000)); } bool Partition::readBlocks(u64int startblock, u32int count, u8int *data) { if (startblock + count > m_startblock + m_blockcount) return false; - return m_device->readBlocks(startblock - m_startblock, count, data); + return m_cache.readBlocks(startblock - m_startblock, count, data); } bool Partition::writeBlocks(u64int startblock, u32int count, u8int *data) { if (startblock + count > m_startblock + m_blockcount) return false; - return m_device->writeBlocks(startblock - m_startblock, count, data); + return m_cache.writeBlocks(startblock - m_startblock, count, data); } bool Partition::read(u64int start, u32int length, u8int *data) { diff --git a/Source/Kernel/VFS/Partition.class.h b/Source/Kernel/VFS/Partition.class.h index 8df1c4f..f511074 100644 --- a/Source/Kernel/VFS/Partition.class.h +++ b/Source/Kernel/VFS/Partition.class.h @@ -2,10 +2,12 @@ #define DEF_PARTITION_CLASS_H #include +#include class Partition { private: BlockDevice* m_device; + BlockCache m_cache; u64int m_startblock, m_blockcount; u8int m_partnumber; //Partition number in partition table of device diff --git a/Source/Kernel/VFS/VFS.ns.cpp b/Source/Kernel/VFS/VFS.ns.cpp index 6a5fe4e..3b59c5a 100644 --- a/Source/Kernel/VFS/VFS.ns.cpp +++ b/Source/Kernel/VFS/VFS.ns.cpp @@ -90,7 +90,6 @@ bool mount(String str, VirtualTerminal* vt, multiboot_info_t *mbd) { *vt << "Syntax: :[]::[:[:[ro|rw]]]\n"; return false; } - if (fs[1] == "") fs[1] = "block"; if (fs.size() < 5) fs.push(""); if (fs.size() < 6) fs.push("ro"); //By default, mount file systems read-only BlockDevice* d = Part::dev(fs[1], fs[2].toInt()); -- cgit v1.2.3