From 58ffa151e3cadafe96bfa39bd9b42f92541fc7d4 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 21 Dec 2009 13:57:48 +0000 Subject: [PATCH] git-svn-id: https://profuse.googlecode.com/svn/branches/v2@196 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/BlockDevice.cpp | 24 +++++ Device/BlockDevice.h | 24 ++++- Device/DeviceReader.cpp | 204 ++++++++++++++++++++++++++++++++++++++++ Device/DeviceReader.h | 109 +++++++++++++++++++++ Device/RawDevice.cpp | 63 +++++++++++-- Device/RawDevice.h | 6 +- Device/TrackSector.h | 19 ++++ 7 files changed, 438 insertions(+), 11 deletions(-) create mode 100644 Device/DeviceReader.cpp create mode 100644 Device/DeviceReader.h create mode 100644 Device/TrackSector.h diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 1c556d6..2c76f0d 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -54,6 +54,30 @@ AbstractBlockCache *BlockDevice::createBlockCache() return new BlockCache(this); } +bool BlockDevice::mapped() +{ + return false; +} + +void BlockDevice::sync(unsigned block) +{ + sync(); +} + +void BlockDevice::sync(TrackSector ts) +{ + sync(); +} + +void *BlockDevice::read(unsigned block) +{ + return NULL; +} + +void *BlockDevice::read(TrackSector ts) +{ + return NULL; +} #pragma mark - diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 41d899e..7d8b262 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -6,25 +6,41 @@ #include +#include + namespace Device { class MappedFile; class AbstractBlockCache; + class BlockDevice { public: virtual ~BlockDevice(); virtual void read(unsigned block, void *bp) = 0; - virtual void write(unsigned block, const void *bp) = 0; - - virtual bool readOnly() = 0; - virtual void sync() = 0; + virtual void read(TrackSector ts, void *bp); + virtual void write(unsigned block, const void *bp) = 0; + virtual void write(TrackSector ts, const void *bp); + + // direct access to mapped memory (not always possible). + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + virtual unsigned blocks() = 0; + virtual bool mapped(); + + virtual bool readOnly() = 0; + + virtual void sync() = 0; + virtual void sync(unsigned block); + virtual void sync(TrackSector ts); + + void zeroBlock(unsigned block); AbstractBlockCache *blockCache(); diff --git a/Device/DeviceReader.cpp b/Device/DeviceReader.cpp new file mode 100644 index 0000000..fceb664 --- /dev/null +++ b/Device/DeviceReader.cpp @@ -0,0 +1,204 @@ + + +#include + +using namespace Device; + +DeviceReader::~DeviceReader() +{ +} + +void *DeviceReader::read(unsigned block) +{ + return NULL; +} + +void DeviceReader::read(TrackSector ts) +{ + return NULL; +} + +void DeviceReader::mapped() +{ + return false; +} + +#pragma mark - +#pragma mark ProDOS Order + +void ProDOSOrderDeviceReader::read(unsigned block, void *bp) +{ + std::memcpy(bp, read(block), 512); +} + +void ProDOSOrderDeviceReader::read(TrackSector ts, void *bp) +{ + std::memcpy(bp, read(ts), 256); +} + +void *ProDOSOrderDeviceReader::read(unsigned block) +{ + if (block > _blocks) + { + throw ProFUSE::Exception("Invalid block."); + } + return block * 512 + (uint8_t *)_data; +} + + +void *ProDOSOrderDeviceReader::read(TrackSector ts) +{ + unsigned block = (ts.track * 16 + ts.sector) / 2; + + if (block > _blocks) + { + throw ProFUSE::Exception("Invalid track/sector."); + } + + return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; +} + + +void ProDOSOrderDeviceReader::write(unsigned block, const void *bp) +{ + std::memcpy(read(block), bp, 512); +} + +void ProDOSOrderDeviceReader::write(TrackSector ts, const void *bp) +{ + std::memcpy(read(ts), bp, 256); +} + + +#pragma mark - +#pragma mark DOS Order + +const unsigned DOSMap[] = { + 0x00, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x0f +}; + +void *DOSOrderDeviceReader::read(TrackSector ts) +{ + if (ts.track > _tracks || ts.sector > 16) + { + throw ProFUSE::Exception("Invalid track/sector."); + } + + return (ts.track * 16 + ts.sector) * 256 + (uint8_t *)_data; +} + + +void DOSOrderDeviceReader::read(unsigned block, void *bp) +{ + TrackSector ts(block >> 3, 0); + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + ts.sector = DOSMap[sector]; + std::memcpy(bp, read(ts), 256); + bp = 256 + (uint8_t *)bp; + ++sector; + } +} + + +void DOSOrderDeviceReader::read(TrackSector ts, void *bp) +{ + std::memcpy(bp, read(ts), 256); +} + + +void DOSOrderDeviceReader::write(unsigned block, const void *bp) +{ + TrackSector ts(block >> 3, 0); + unsigned sector = (block & 0x07) << 1; + + for (unsigned i = 0; i < 2; ++i) + { + ts.sector = DOSMap[sector]; + std::memcpy(read(ts), bp, 256); + bp = 256 + (const uint8_t *)bp; + ++sector; + } +} + +void DOSOrderDeviceReader::write(TrackSector ts, const void *bp) +{ + std::memcpy(read(ts), bp, 256); +} + + +#pragma mark - +#pragma mark FileDeviceReader + +FileDeviceReader::FileDeviceReader(int fd, unsigned blocks, bool readOnly) +{ + _fd = fd; + _readOnly = readOnly; + _blocks = blocks; +} + +bool FileDeviceReader::readOnly() +{ + return _readOnly; +} + +void FileDeviceReader::write(unsigned block, const void *bp) +{ + + off_t offset = block * 512; + + size_t ok = ::pwrite(_fd, bp, 512, offset); + + if (ok != 512) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + +void FileDeviceReader::write(TrackSector ts, const void *bp) +{ + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pwrite(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + + + + + + + +void FileDeviceReader::read(unsigned block, void *bp) +{ + + off_t offset = block * 512; + + size_t ok = ::pread(_fd, bp, 512, offset); + + if (ok != 512) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} + +void FileDeviceReader::read(TrackSector ts, void *bp) +{ + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pread(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} diff --git a/Device/DeviceReader.h b/Device/DeviceReader.h new file mode 100644 index 0000000..e2e8c71 --- /dev/null +++ b/Device/DeviceReader.h @@ -0,0 +1,109 @@ +#ifndef __DEVICEREADER_H__ +#define __DEVICEREADER_H__ + +#include + +namespace Device { + + +class DeviceReader { + public: + + virtual ~DeviceReader(); + + virtual void read(unsigned block, void *bp) = 0; + virtual void read(TrackSector ts, void *bp) = 0; + + virtual void write(unsigned block, const void *bp) = 0; + virtual void write(TrackSector ts, const void *bp) = 0; + + // direct access -- not always available. + + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + + virtual bool readOnly() = 0; + virtual bool mapped(); + +}; + +class FileDeviceReader : public DeviceReader { + + // does not assume ownership of fd. + FileDeviceReader(int fd, unsigned blocks, bool readOnly); + //virtual ~FileDeviceReader(); + +public: + + virtual bool readOnly(); + + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + private: + + int _fd; + unsigned _blocks; + bool _readOnly; +} + +class MappedFileDeviceReader : public DeviceReader { + + protected: + + MappedFileDeviceReader(MappedFile *f, unsigned offset); + + void *_data; + + private: + MappedFile *_file +}; + +class ProDOSOrderDeviceReader : public MappedFileDeviceReader { + public: + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + virtual void *read(unsigned block); + virtual void *read(TrackSector ts); + + private: + unsigned blocks; +}; + +// 16 sectors only. +class DOSOrderDeviceReader : public MappedFileDeviceReader { + public: + + virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + + virtual void write(unsigned block, const void *bp); + virtual void write(TrackSector ts, const void *bp); + + virtual void *read(TrackSector ts); + + private: + unsigned _tracks; +}; + + + +class NibbleDeviceReader : public MappedFileDeviceReader { + + private: + + std::vector _map; +}; + +} + +#endif \ No newline at end of file diff --git a/Device/RawDevice.cpp b/Device/RawDevice.cpp index 9047f17..1e9c6ca 100644 --- a/Device/RawDevice.cpp +++ b/Device/RawDevice.cpp @@ -146,17 +146,40 @@ void RawDevice::read(unsigned block, void *bp) // sun -- use pread // apple - read full native block(s) ? - size_t ok = ::pread(_fd, bp, 512, block * 512); + off_t offset = block * 512; + size_t ok = ::pread(_fd, bp, 512, offset); // TODO -- EINTR? if (ok != 512) throw ok < 0 ? POSIXException(__METHOD__ ": Error reading block.", errno) : Exception(__METHOD__ ": Error reading block."); - - - } + + +void RawDevice::read(TrackSector ts, void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::read" + + unsigned block = ts.track * 8 + ts.sector / 2; + if (block >= _blocks) throw Exception(__METHOD__ ": Invalid block number."); + if (bp == 0) throw Exception(__METHOD__ ": Invalid address."); + + // sun -- use pread + // apple - read full native block(s) ? + + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pread(_fd, bp, 256, offset); + + // TODO -- EINTR? + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error reading block.", errno) + : Exception(__METHOD__ ": Error reading block."); +} + + void RawDevice::write(unsigned block, const void *bp) { #undef __METHOD__ @@ -167,8 +190,9 @@ void RawDevice::write(unsigned block, const void *bp) if (_readOnly) throw Exception(__METHOD__ ": File is readonly."); - - size_t ok = ::pwrite(_fd, bp, 512, block * 512); + + off_t offset = block * 512; + size_t ok = ::pwrite(_fd, bp, 512, offset); if (ok != 512) throw ok < 0 @@ -177,11 +201,38 @@ void RawDevice::write(unsigned block, const void *bp) } +void RawDevice::write(TrackSector ts, const void *bp) +{ +#undef __METHOD__ +#define __METHOD__ "RawDevice::write" + + unsigned block = ts.track * 8 + ts.sector / 2; + if (block > _blocks) throw Exception(__METHOD__ ": Invalid block number."); + + if (_readOnly) + throw Exception(__METHOD__ ": File is readonly."); + + + off_t offset = (ts.track * 16 + ts.sector) * 256; + size_t ok = ::pwrite(_fd, bp, 256, offset); + + if (ok != 256) + throw ok < 0 + ? POSIXException(__METHOD__ ": Error writing block.", errno) + : Exception(__METHOD__ ": Error writing block."); +} + + bool RawDevice::readOnly() { return _readOnly; } +bool RawDevice::mapped() +{ + return false; +} + void RawDevice::sync() { #undef __METHOD__ diff --git a/Device/RawDevice.h b/Device/RawDevice.h index dfbeb8f..f39fa70 100644 --- a/Device/RawDevice.h +++ b/Device/RawDevice.h @@ -18,9 +18,13 @@ public: virtual ~RawDevice(); virtual void read(unsigned block, void *bp); + virtual void read(TrackSector ts, void *bp); + virtual void write(unsigned block, const void *bp); - + virtual void write(TrackSector ts, const void *bp); + virtual bool readOnly(); + virtual bool mapped(); virtual void sync(); private: diff --git a/Device/TrackSector.h b/Device/TrackSector.h new file mode 100644 index 0000000..dd96d7e --- /dev/null +++ b/Device/TrackSector.h @@ -0,0 +1,19 @@ +#ifndef __TRACKSECTOR_H__ +#define __TRACKSECTOR_H__ + +namespace Device { + + struct TrackSector { + TrackSector(unsigned, unsigned); + unsigned track; + unsigned sector; + }; + + inline TrackSector::TrackSector(unsigned t, unsigned s) + { + track = t; + sector = s; + } +} + +#endif \ No newline at end of file