mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
235 lines
6.6 KiB
C++
235 lines
6.6 KiB
C++
#ifndef LAYOUT_H
|
|
#define LAYOUT_H
|
|
|
|
#include "lib/data/disk.h"
|
|
#include "lib/config/layout.pb.h"
|
|
#include "lib/config/config.h"
|
|
#include "lib/data/locations.h"
|
|
|
|
class ConfigProto;
|
|
|
|
struct LogicalTrackLayout
|
|
{
|
|
/* Physical cylinder of the first element of the group. */
|
|
unsigned physicalCylinder;
|
|
|
|
/* Physical head of the first element of the group. */
|
|
unsigned physicalHead;
|
|
|
|
/* Size of this group. */
|
|
unsigned groupSize;
|
|
|
|
/* Logical cylinder of this track. */
|
|
unsigned logicalCylinder = 0;
|
|
|
|
/* Logical side of this track. */
|
|
unsigned logicalHead = 0;
|
|
|
|
/* The number of sectors in this track. */
|
|
unsigned numSectors = 0;
|
|
|
|
/* Number of bytes in a sector. */
|
|
unsigned sectorSize = 0;
|
|
|
|
/* Sector IDs in sector ID order. This is the order in which the appear in
|
|
* disk images. */
|
|
std::vector<unsigned> naturalSectorOrder;
|
|
|
|
/* Sector IDs in disk order. This is the order they are written to the disk.
|
|
*/
|
|
std::vector<unsigned> diskSectorOrder;
|
|
|
|
/* Sector IDs in filesystem order. This is the order in which the filesystem
|
|
* uses them. */
|
|
std::vector<unsigned> filesystemSectorOrder;
|
|
|
|
/* Mapping of sector ID to filesystem ordering. */
|
|
std::map<unsigned, unsigned> sectorIdToFilesystemOrdering;
|
|
|
|
/* Mapping of sector ID to natural ordering. */
|
|
std::map<unsigned, unsigned> sectorIdToNaturalOrdering;
|
|
};
|
|
|
|
struct PhysicalTrackLayout
|
|
{
|
|
/* Physical location of this track. */
|
|
unsigned physicalCylinder;
|
|
|
|
/* Physical side of this track. */
|
|
unsigned physicalHead;
|
|
|
|
/* Which member of the group this is. */
|
|
unsigned groupOffset;
|
|
|
|
/* The logical track that this track is part of. */
|
|
std::shared_ptr<const LogicalTrackLayout> logicalTrackLayout;
|
|
};
|
|
|
|
class DiskLayout
|
|
{
|
|
public:
|
|
DiskLayout(const ConfigProto& config = globalConfig());
|
|
|
|
/* Makes a simplified layout for testing. */
|
|
|
|
DiskLayout(unsigned numCylinders,
|
|
unsigned numHeads,
|
|
unsigned numSectors,
|
|
unsigned sectorSize);
|
|
|
|
public:
|
|
/* Logical size. */
|
|
|
|
unsigned numLogicalCylinders;
|
|
unsigned numLogicalHeads;
|
|
|
|
/* Physical size and properties. */
|
|
|
|
unsigned minPhysicalCylinder, maxPhysicalCylinder;
|
|
unsigned minPhysicalHead, maxPhysicalHead;
|
|
unsigned groupSize; /* Number of physical cylinders per logical cylinder */
|
|
unsigned headBias; /* Physical cylinder offset */
|
|
unsigned headWidth; /* Width of the physical head */
|
|
bool swapSides; /* Whether sides need to be swapped */
|
|
unsigned totalBytes; /* Total number of bytes on the disk. */
|
|
|
|
/* Physical and logical layouts by location. */
|
|
|
|
std::map<CylinderHead, std::shared_ptr<const PhysicalTrackLayout>>
|
|
layoutByPhysicalLocation;
|
|
std::map<CylinderHead, std::shared_ptr<const LogicalTrackLayout>>
|
|
layoutByLogicalLocation;
|
|
|
|
/* Ordered lists of physical and logical locations. */
|
|
|
|
std::vector<CylinderHead> logicalLocations;
|
|
std::vector<CylinderHead> logicalLocationsInFilesystemOrder;
|
|
std::vector<CylinderHead> physicalLocations;
|
|
|
|
/* Ordered lists of sector locations, plus the reverse mapping. */
|
|
|
|
std::vector<LogicalLocation> logicalSectorLocationsInFilesystemOrder;
|
|
std::map<LogicalLocation, unsigned> blockIdByLogicalSectorLocation;
|
|
std::vector<CylinderHeadSector> physicalSectorLocationsInFilesystemOrder;
|
|
|
|
/* Mapping from logical location to sector offset and back again. */
|
|
|
|
std::map<unsigned, LogicalLocation> logicalSectorLocationBySectorOffset;
|
|
std::map<LogicalLocation, unsigned> sectorOffsetByLogicalSectorLocation;
|
|
|
|
public:
|
|
unsigned remapCylinderPhysicalToLogical(unsigned physicalCylinder) const
|
|
{
|
|
return (physicalCylinder - headBias) / groupSize;
|
|
}
|
|
|
|
unsigned remapCylinderLogicalToPhysical(unsigned logicalCylinder) const
|
|
{
|
|
return headBias + logicalCylinder * groupSize;
|
|
}
|
|
|
|
unsigned remapHeadPhysicalToLogical(unsigned physicalHead) const
|
|
{
|
|
return physicalHead ^ swapSides;
|
|
}
|
|
|
|
unsigned remapHeadLogicalToPhysical(unsigned logicalHead) const
|
|
{
|
|
return logicalHead ^ swapSides;
|
|
}
|
|
|
|
/* Given a list of CylinderHead locations, determines the minimum and
|
|
* maximum track and side settings. */
|
|
struct LayoutBounds
|
|
{
|
|
std::strong_ordering operator<=>(
|
|
const LayoutBounds& other) const = default;
|
|
|
|
int minCylinder, maxCylinder, minHead, maxHead;
|
|
};
|
|
|
|
static LayoutBounds getBounds(std::ranges::view auto keys)
|
|
{
|
|
LayoutBounds r{.minCylinder = INT_MAX,
|
|
.maxCylinder = INT_MIN,
|
|
.minHead = INT_MAX,
|
|
.maxHead = INT_MIN};
|
|
|
|
for (const auto& ch : keys)
|
|
{
|
|
r.minCylinder = std::min<int>(r.minCylinder, ch.cylinder);
|
|
r.maxCylinder = std::max<int>(r.maxCylinder, ch.cylinder);
|
|
r.minHead = std::min<int>(r.minHead, ch.head);
|
|
r.maxHead = std::max<int>(r.maxHead, ch.head);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
LayoutBounds getPhysicalBounds() const;
|
|
LayoutBounds getLogicalBounds() const;
|
|
};
|
|
|
|
static std::shared_ptr<DiskLayout> createDiskLayout(
|
|
const ConfigProto& config = globalConfig())
|
|
{
|
|
return std::make_shared<DiskLayout>(config);
|
|
}
|
|
|
|
class TrackInfo
|
|
{
|
|
public:
|
|
TrackInfo() {}
|
|
|
|
private:
|
|
/* Can't copy. */
|
|
TrackInfo(const TrackInfo&);
|
|
TrackInfo& operator=(const TrackInfo&);
|
|
|
|
public:
|
|
unsigned numCylinders = 0;
|
|
unsigned numHeads = 0;
|
|
|
|
/* The number of sectors in this track. */
|
|
unsigned numSectors = 0;
|
|
|
|
/* Physical location of this track. */
|
|
unsigned physicalCylinder = 0;
|
|
|
|
/* Physical side of this track. */
|
|
unsigned physicalHead = 0;
|
|
|
|
/* Logical location of this track. */
|
|
unsigned logicalCylinder = 0;
|
|
|
|
/* Logical side of this track. */
|
|
unsigned logicalHead = 0;
|
|
|
|
/* The number of physical tracks which need to be written for one logical
|
|
* track. */
|
|
unsigned groupSize = 0;
|
|
|
|
/* Number of bytes in a sector. */
|
|
unsigned sectorSize = 0;
|
|
|
|
/* Sector IDs in sector ID order. This is the order in which the appear in
|
|
* disk images. */
|
|
std::vector<unsigned> naturalSectorOrder;
|
|
|
|
/* Sector IDs in disk order. This is the order they are written to the disk.
|
|
*/
|
|
std::vector<unsigned> diskSectorOrder;
|
|
|
|
/* Sector IDs in filesystem order. This is the order in which the filesystem
|
|
* uses them. */
|
|
std::vector<unsigned> filesystemSectorOrder;
|
|
|
|
/* Mapping of filesystem order to natural order. */
|
|
std::map<unsigned, unsigned> filesystemToNaturalSectorMap;
|
|
|
|
/* Mapping of natural order to filesystem order. */
|
|
std::map<unsigned, unsigned> naturalToFilesystemSectorMap;
|
|
};
|
|
|
|
#endif
|