git-svn-id: https://profuse.googlecode.com/svn/branches/v2@196 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
9bca60e977
commit
58ffa151e3
|
@ -54,6 +54,30 @@ AbstractBlockCache *BlockDevice::createBlockCache()
|
||||||
return new BlockCache(this);
|
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 -
|
#pragma mark -
|
||||||
|
|
|
@ -6,25 +6,41 @@
|
||||||
|
|
||||||
#include <ProFUSE/Exception.h>
|
#include <ProFUSE/Exception.h>
|
||||||
|
|
||||||
|
#include <Device/TrackSector.h>
|
||||||
|
|
||||||
namespace Device {
|
namespace Device {
|
||||||
|
|
||||||
class MappedFile;
|
class MappedFile;
|
||||||
class AbstractBlockCache;
|
class AbstractBlockCache;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BlockDevice {
|
class BlockDevice {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~BlockDevice();
|
virtual ~BlockDevice();
|
||||||
|
|
||||||
virtual void read(unsigned block, void *bp) = 0;
|
virtual void read(unsigned block, void *bp) = 0;
|
||||||
virtual void write(unsigned block, const void *bp) = 0;
|
virtual void read(TrackSector ts, void *bp);
|
||||||
|
|
||||||
virtual bool readOnly() = 0;
|
|
||||||
virtual void sync() = 0;
|
|
||||||
|
|
||||||
|
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 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);
|
void zeroBlock(unsigned block);
|
||||||
|
|
||||||
AbstractBlockCache *blockCache();
|
AbstractBlockCache *blockCache();
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include <Device/DeviceReader.h>
|
||||||
|
|
||||||
|
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.");
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
#ifndef __DEVICEREADER_H__
|
||||||
|
#define __DEVICEREADER_H__
|
||||||
|
|
||||||
|
#include <Device/TrackSector.h>
|
||||||
|
|
||||||
|
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<unsigned> _map;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -146,17 +146,40 @@ void RawDevice::read(unsigned block, void *bp)
|
||||||
// sun -- use pread
|
// sun -- use pread
|
||||||
// apple - read full native block(s) ?
|
// 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?
|
// TODO -- EINTR?
|
||||||
if (ok != 512)
|
if (ok != 512)
|
||||||
throw ok < 0
|
throw ok < 0
|
||||||
? POSIXException(__METHOD__ ": Error reading block.", errno)
|
? POSIXException(__METHOD__ ": Error reading block.", errno)
|
||||||
: Exception(__METHOD__ ": Error reading block.");
|
: 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)
|
void RawDevice::write(unsigned block, const void *bp)
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
|
@ -167,8 +190,9 @@ void RawDevice::write(unsigned block, const void *bp)
|
||||||
if (_readOnly)
|
if (_readOnly)
|
||||||
throw Exception(__METHOD__ ": File is 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)
|
if (ok != 512)
|
||||||
throw ok < 0
|
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()
|
bool RawDevice::readOnly()
|
||||||
{
|
{
|
||||||
return _readOnly;
|
return _readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RawDevice::mapped()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void RawDevice::sync()
|
void RawDevice::sync()
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
|
|
|
@ -18,9 +18,13 @@ public:
|
||||||
virtual ~RawDevice();
|
virtual ~RawDevice();
|
||||||
|
|
||||||
virtual void read(unsigned block, void *bp);
|
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(unsigned block, const void *bp);
|
||||||
|
virtual void write(TrackSector ts, const void *bp);
|
||||||
|
|
||||||
virtual bool readOnly();
|
virtual bool readOnly();
|
||||||
|
virtual bool mapped();
|
||||||
virtual void sync();
|
virtual void sync();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue