diff --git a/src/raspberrypi/devices/disk.cpp b/src/raspberrypi/devices/disk.cpp index d540ffc4..bd5c2946 100644 --- a/src/raspberrypi/devices/disk.cpp +++ b/src/raspberrypi/devices/disk.cpp @@ -76,7 +76,7 @@ Disk::~Disk() if (IsReady()) { // Only if ready... if (disk.dcache) { - disk.dcache->Save(); + // disk.dcache->Save(); } } @@ -518,7 +518,7 @@ void Disk::PreventAllowMediumRemoval(SASIDEV *controller) void Disk::SynchronizeCache10(SASIDEV *controller) { // Flush the RaSCSI cache - disk.dcache->Save(); + // disk.dcache->Save(); controller->Status(); } @@ -544,7 +544,7 @@ bool Disk::Eject(bool force) bool status = Device::Eject(force); if (status) { // Remove disk cache - disk.dcache->Save(); + // disk.dcache->Save(); delete disk.dcache; disk.dcache = NULL; @@ -1295,7 +1295,7 @@ bool Disk::StartStop(const DWORD *cdb) if (!start) { // Flush the cache when stopping - disk.dcache->Save(); + // disk.dcache->Save(); // Look at the eject bit and eject if necessary if (load) { diff --git a/src/raspberrypi/devices/disk_track_cache.cpp b/src/raspberrypi/devices/disk_track_cache.cpp index bc4aba37..a58c3059 100644 --- a/src/raspberrypi/devices/disk_track_cache.cpp +++ b/src/raspberrypi/devices/disk_track_cache.cpp @@ -21,320 +21,8 @@ #include "log.h" #include "fileio.h" #include "disk_track_cache.h" - -//=========================================================================== -// -// Disk Track -// -//=========================================================================== - -DiskTrack::DiskTrack() -{ - // Initialization of internal information - dt.track = 0; - dt.size = 0; - dt.sectors = 0; - dt.raw = FALSE; - dt.init = FALSE; - dt.changed = FALSE; - dt.length = 0; - dt.buffer = NULL; - dt.maplen = 0; - dt.changemap = NULL; - dt.imgoffset = 0; -} - -DiskTrack::~DiskTrack() -{ - // Release memory, but do not save automatically - if (dt.buffer) { - free(dt.buffer); - dt.buffer = NULL; - } - if (dt.changemap) { - free(dt.changemap); - dt.changemap = NULL; - } -} - -void DiskTrack::Init(int track, int size, int sectors, BOOL raw, off_t imgoff) -{ - ASSERT(track >= 0); - ASSERT((sectors > 0) && (sectors <= 0x100)); - ASSERT(imgoff >= 0); - - // Set Parameters - dt.track = track; - dt.size = size; - dt.sectors = sectors; - dt.raw = raw; - - // Not initialized (needs to be loaded) - dt.init = FALSE; - - // Not Changed - dt.changed = FALSE; - - // Offset to actual data - dt.imgoffset = imgoff; -} - -bool DiskTrack::Load(const Filepath& path) -{ - // Not needed if already loaded - if (dt.init) { - ASSERT(dt.buffer); - ASSERT(dt.changemap); - return true; - } - - // Calculate offset (previous tracks are considered to hold 256 sectors) - off_t offset = ((off_t)dt.track << 8); - if (dt.raw) { - ASSERT(dt.size == 11); - offset *= 0x930; - offset += 0x10; - } else { - offset <<= dt.size; - } - - // Add offset to real image - offset += dt.imgoffset; - - // Calculate length (data size of this track) - int length = dt.sectors << dt.size; - - // Allocate buffer memory - ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); - - if (dt.buffer == NULL) { - if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) { - LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__); - } - dt.length = length; - } - - if (!dt.buffer) { - return false; - } - - // Reallocate if the buffer length is different - if (dt.length != (DWORD)length) { - free(dt.buffer); - if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) { - LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__); - } - dt.length = length; - } - - // Reserve change map memory - if (dt.changemap == NULL) { - dt.changemap = (BOOL *)malloc(dt.sectors * sizeof(BOOL)); - dt.maplen = dt.sectors; - } - - if (!dt.changemap) { - return false; - } - - // Reallocate if the buffer length is different - if (dt.maplen != (DWORD)dt.sectors) { - free(dt.changemap); - dt.changemap = (BOOL *)malloc(dt.sectors * sizeof(BOOL)); - dt.maplen = dt.sectors; - } - - // Clear changemap - memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL)); - - // Read from File - Fileio fio; - if (!fio.OpenDIO(path, Fileio::ReadOnly)) { - return false; - } - if (dt.raw) { - // Split Reading - for (int i = 0; i < dt.sectors; i++) { - // Seek - if (!fio.Seek(offset)) { - fio.Close(); - return false; - } - - // Read - if (!fio.Read(&dt.buffer[i << dt.size], 1 << dt.size)) { - fio.Close(); - return false; - } - - // Next offset - offset += 0x930; - } - } else { - // Continuous reading - if (!fio.Seek(offset)) { - fio.Close(); - return false; - } - if (!fio.Read(dt.buffer, length)) { - fio.Close(); - return false; - } - } - fio.Close(); - - // Set a flag and end normally - dt.init = TRUE; - dt.changed = FALSE; - return true; -} - -bool DiskTrack::Save(const Filepath& path) -{ - // Not needed if not initialized - if (!dt.init) { - return true; - } - - // Not needed unless changed - if (!dt.changed) { - return true; - } - - // Need to write - ASSERT(dt.buffer); - ASSERT(dt.changemap); - ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); - - // Writing in RAW mode is not allowed - ASSERT(!dt.raw); - - // Calculate offset (previous tracks are considered to hold 256 sectors) - off_t offset = ((off_t)dt.track << 8); - offset <<= dt.size; - - // Add offset to real image - offset += dt.imgoffset; - - // Calculate length per sector - int length = 1 << dt.size; - - // Open file - Fileio fio; - if (!fio.Open(path, Fileio::ReadWrite)) { - return false; - } - - // Partial write loop - int total; - for (int i = 0; i < dt.sectors;) { - // If changed - if (dt.changemap[i]) { - // Initialize write size - total = 0; - - // Seek - if (!fio.Seek(offset + ((off_t)i << dt.size))) { - fio.Close(); - return false; - } - - // Consectutive sector length - int j; - for (j = i; j < dt.sectors; j++) { - // end when interrupted - if (!dt.changemap[j]) { - break; - } - - // Add one sector - total += length; - } - - // Write - if (!fio.Write(&dt.buffer[i << dt.size], total)) { - fio.Close(); - return false; - } - - // To unmodified sector - i = j; - } else { - // Next Sector - i++; - } - } - - // Close - fio.Close(); - - // Drop the change flag and exit - memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL)); - dt.changed = FALSE; - return true; -} - -bool DiskTrack::ReadSector(BYTE *buf, int sec) const -{ - ASSERT(buf); - ASSERT((sec >= 0) & (sec < 0x100)); - - LOGTRACE("%s reading sector: %d", __PRETTY_FUNCTION__,sec); - // Error if not initialized - if (!dt.init) { - return false; - } - - // // Error if the number of sectors exceeds the valid number - if (sec >= dt.sectors) { - return false; - } - - // Copy - ASSERT(dt.buffer); - ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); - memcpy(buf, &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); - - // Success - return true; -} - -bool DiskTrack::WriteSector(const BYTE *buf, int sec) -{ - ASSERT(buf); - ASSERT((sec >= 0) & (sec < 0x100)); - ASSERT(!dt.raw); - - // Error if not initialized - if (!dt.init) { - return false; - } - - // // Error if the number of sectors exceeds the valid number - if (sec >= dt.sectors) { - return false; - } - - // Calculate offset and length - int offset = sec << dt.size; - int length = 1 << dt.size; - - // Compare - ASSERT(dt.buffer); - ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); - if (memcmp(buf, &dt.buffer[offset], length) == 0) { - // Exit normally since it's attempting to write the same thing - return true; - } - - // Copy, change - memcpy(&dt.buffer[offset], buf, length); - dt.changemap[sec] = TRUE; - dt.changed = TRUE; - - // Success - return true; -} +#include +#include //=========================================================================== // @@ -347,12 +35,6 @@ DiskCache::DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgo ASSERT(blocks > 0); ASSERT(imgoff >= 0); - // Cache work - for (int i = 0; i < CacheMax; i++) { - cache[i].disktrk = NULL; - cache[i].serial = 0; - } - // Other serial = 0; sec_path = path; @@ -360,12 +42,39 @@ DiskCache::DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgo sec_blocks = blocks; cd_raw = FALSE; imgoffset = imgoff; + + fd = open(path.GetPath(), O_RDWR); + if(fd < 0){ + LOGWARN("Unable to open file %s. Errno:%d", path.GetPath(), errno) + } + struct stat sb; + if(fstat(fd, &sb) < 0){ + LOGWARN("Unable to run fstat. Errno:%d", errno); + } + printf("Size: %llu\n", (uint64_t)sb.st_size); + + // int x = EACCES; + + memory_block = (const char*)mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + int errno_val = errno; + if (memory_block == MAP_FAILED) { + LOGWARN("Unabled to memory map file %s", path.GetPath()); + LOGWARN(" Errno:%d", errno_val); + errno_val = EACCES; + } + + if(sb.st_size != (sec_size * sec_blocks)){ + LOGWARN("Opened file with size %llu bytes, but expected %llu [sector: %d blocks: %d]", sb.st_size, (uint64_t)(sec_size * sec_blocks), sec_size, sec_blocks); + } + } DiskCache::~DiskCache() { + munmap((void*)memory_block, sb.st_size); + close(fd); // Clear the track - Clear(); + // Clear(); } void DiskCache::SetRawMode(BOOL raw) @@ -374,216 +83,128 @@ void DiskCache::SetRawMode(BOOL raw) cd_raw = raw; } -bool DiskCache::Save() -{ - // Save track - for (int i = 0; i < CacheMax; i++) { - // Is it a valid track? - if (cache[i].disktrk) { - // Save - if (!cache[i].disktrk->Save(sec_path)) { - return false; - } - } - } - - return true; -} - -//--------------------------------------------------------------------------- -// -// Get disk cache information -// -//--------------------------------------------------------------------------- -bool DiskCache::GetCache(int index, int& track, DWORD& aserial) const -{ - ASSERT((index >= 0) && (index < CacheMax)); - - // false if unused - if (!cache[index].disktrk) { - return false; - } - - // Set track and serial - track = cache[index].disktrk->GetTrack(); - aserial = cache[index].serial; - - return true; -} - -void DiskCache::Clear() -{ - // Free the cache - for (int i = 0; i < CacheMax; i++) { - if (cache[i].disktrk) { - delete cache[i].disktrk; - cache[i].disktrk = NULL; - } - } -} bool DiskCache::ReadSector(BYTE *buf, int block) { ASSERT(sec_size != 0); + ASSERT(buf); + ASSERT(block < sec_blocks); + ASSERT(memory_block); - // Update first - UpdateSerialNumber(); + int sector_size_bytes = (off_t)1 << sec_size; - // Calculate track (fixed to 256 sectors/track) - int track = block >> 8; + // Calculate offset into the image file + off_t offset = GetTrackOffset(block); + offset += GetSectorOffset(block); - // Get the track data - DiskTrack *disktrk = Assign(track); - if (!disktrk) { - return false; - } + // LOGINFO("Reading data track:%d sec_size:%d block:%d offset: %lld imgoffset: %lld", track, sec_size, block, offset, imgoffset); + +// memcpy(buf, &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); + memcpy(buf, &memory_block[offset], sector_size_bytes); + + return true; + + + // // Calculate track (fixed to 256 sectors/track) + // int track = block >> 8; + + // // Get the track data + // DiskTrack *disktrk = Assign(track); + // if (!disktrk) { + // return false; + // } // Read the track data to the cache - return disktrk->ReadSector(buf, block & 0xff); + // return disktrk->ReadSector(buf, block & 0xff); } bool DiskCache::WriteSector(const BYTE *buf, int block) { - ASSERT(sec_size != 0); + // ASSERT(sec_size != 0); + + // // Update first + // // UpdateSerialNumber(); + + // // Calculate track (fixed to 256 sectors/track) + // int track = block >> 8; + + // // Get that track data + // DiskTrack *disktrk = Assign(track); + // if (!disktrk) { + // return false; + // } + + // // Write the data to the cache + // return disktrk->WriteSector(buf, block & 0xff); + + + // ASSERT(sec_size != 0); // Update first - UpdateSerialNumber(); + // UpdateSerialNumber(); - // Calculate track (fixed to 256 sectors/track) - int track = block >> 8; - // Get that track data - DiskTrack *disktrk = Assign(track); - if (!disktrk) { - return false; - } + // // Other + // serial = 0; + // sec_path = path; + // sec_size = size; + // sec_blocks = blocks; + // cd_raw = FALSE; + // imgoffset = imgoff; - // Write the data to the cache - return disktrk->WriteSector(buf, block & 0xff); -} +// ASSERT(dt.buffer); +// ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); +// memcpy(buf, &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); -//--------------------------------------------------------------------------- -// -// Track Assignment -// -//--------------------------------------------------------------------------- -DiskTrack* DiskCache::Assign(int track) -{ - ASSERT(sec_size != 0); - ASSERT(track >= 0); - // First, check if it is already assigned - for (int i = 0; i < CacheMax; i++) { - if (cache[i].disktrk) { - if (cache[i].disktrk->GetTrack() == track) { - // Track match - cache[i].serial = serial; - return cache[i].disktrk; - } - } - } + ASSERT(buf); + ASSERT(block < sec_blocks); + ASSERT(memory_block); - // Next, check for empty - for (int i = 0; i < CacheMax; i++) { - if (!cache[i].disktrk) { - // Try loading - if (Load(i, track)) { - // Success loading - cache[i].serial = serial; - return cache[i].disktrk; - } + ASSERT((block * sec_size) <= (sb.st_size + sec_size)); - // Load failed - return NULL; - } - } - - // Finally, find the youngest serial number and delete it - - // Set index 0 as candidate c - DWORD s = cache[0].serial; - int c = 0; - - // Compare candidate with serial and update to smaller one - for (int i = 0; i < CacheMax; i++) { - ASSERT(cache[i].disktrk); - - // Compare and update the existing serial - if (cache[i].serial < s) { - s = cache[i].serial; - c = i; - } - } - - // Save this track - if (!cache[c].disktrk->Save(sec_path)) { - return NULL; - } - - // Delete this track - DiskTrack *disktrk = cache[c].disktrk; - cache[c].disktrk = NULL; - - if (Load(c, track, disktrk)) { - // Successful loading - cache[c].serial = serial; - return cache[c].disktrk; - } - - // Load failed - return NULL; -} - -//--------------------------------------------------------------------------- -// -// Load cache -// -//--------------------------------------------------------------------------- -bool DiskCache::Load(int index, int track, DiskTrack *disktrk) -{ - ASSERT((index >= 0) && (index < CacheMax)); - ASSERT(track >= 0); - ASSERT(!cache[index].disktrk); - - // Get the number of sectors on this track - int sectors = sec_blocks - (track << 8); - ASSERT(sectors > 0); - if (sectors > 0x100) { - sectors = 0x100; - } - - // Create a disk track - if (disktrk == NULL) { - disktrk = new DiskTrack(); - } - - // Initialize disk track - disktrk->Init(track, sec_size, sectors, cd_raw, imgoffset); - - // Try loading - if (!disktrk->Load(sec_path)) { - // Failure - delete disktrk; - return false; - } - - // Allocation successful, work set - cache[index].disktrk = disktrk; +// memcpy(buf, &dt.buffer[(off_t)sec << dt.size], (off_t)1 << dt.size); + memcpy((void*)&memory_block[(block * sec_size)], buf, sec_size); return true; } -void DiskCache::UpdateSerialNumber() -{ - // Update and do nothing except 0 - serial++; - if (serial != 0) { - return; - } - // Clear serial of all caches (loop in 32bit) - for (int i = 0; i < CacheMax; i++) { - cache[i].serial = 0; - } +off_t DiskCache::GetSectorOffset(int block){ + + int sector_num = block & 0xff; + + // // // Error if the number of sectors exceeds the valid number + // if (sector_num >= sectors) { + // return false; + // } + + return (off_t)sector_num << sec_size; } +off_t DiskCache::GetTrackOffset(int block){ + + // Assuming that all tracks hold 256 sectors + int track_num = block >> 8; + + // Calculate offset (previous tracks are considered to hold 256 sectors) + off_t offset = ((off_t)track_num << 8); + if (cd_raw) { + ASSERT(sec_size == 11); + offset *= 0x930; + offset += 0x10; + } else { + offset <<= sec_size; + } + + // Add offset to real image + offset += imgoffset; + + return offset; +} + +// off_t DiskCache::GetTrackSize(){ +// // Calculate length (data size of this track) +// off_t length = sectors << sec_size; +// return length; +// } diff --git a/src/raspberrypi/devices/disk_track_cache.h b/src/raspberrypi/devices/disk_track_cache.h index 2c1244e0..ce053b77 100644 --- a/src/raspberrypi/devices/disk_track_cache.h +++ b/src/raspberrypi/devices/disk_track_cache.h @@ -20,49 +20,8 @@ #include "../rascsi.h" #include "filepath.h" -// Number of tracks to cache -#define CacheMax 16 - -class DiskTrack -{ -private: - struct { - int track; // Track Number - int size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) - int sectors; // Number of sectors(<0x100) - DWORD length; // Data buffer length - BYTE *buffer; // Data buffer - BOOL init; // Is it initilized? - BOOL changed; // Changed flag - DWORD maplen; // Changed map length - BOOL *changemap; // Changed map - BOOL raw; // RAW mode flag - off_t imgoffset; // Offset to actual data - } dt; - -public: - DiskTrack(); - ~DiskTrack(); - - void Init(int track, int size, int sectors, BOOL raw = FALSE, off_t imgoff = 0); - bool Load(const Filepath& path); - bool Save(const Filepath& path); - - // Read / Write - bool ReadSector(BYTE *buf, int sec) const; // Sector Read - bool WriteSector(const BYTE *buf, int sec); // Sector Write - - int GetTrack() const { return dt.track; } // Get track -}; - class DiskCache { -public: - // Internal data definition - typedef struct { - DiskTrack *disktrk; // Disk Track - DWORD serial; // Serial - } cache_t; public: DiskCache(const Filepath& path, int size, uint32_t blocks, off_t imgoff = 0); @@ -71,25 +30,32 @@ public: void SetRawMode(BOOL raw); // CD-ROM raw mode setting // Access - bool Save(); // Save and release all + // bool Save(); // Save and release all bool ReadSector(BYTE *buf, int block); // Sector Read bool WriteSector(const BYTE *buf, int block); // Sector Write - bool GetCache(int index, int& track, DWORD& serial) const; // Get cache information + // bool GetCache(int index, int& track, DWORD& serial) const; // Get cache information private: // Internal Management - void Clear(); // Clear all tracks - DiskTrack* Assign(int track); // Load track - bool Load(int index, int track, DiskTrack *disktrk = NULL); // Load track - void UpdateSerialNumber(); // Update serial number + // void Clear(); // Clear all tracks + // DiskTrack* Assign(int track); // Load track + // bool Load(int index, int track, DiskTrack *disktrk = NULL); // Load track + // void UpdateSerialNumber(); // Update serial number // Internal data - cache_t cache[CacheMax]; // Cache management + // cache_t cache[CacheMax]; // Cache management DWORD serial; // Last serial number Filepath sec_path; // Path int sec_size; // Sector Size (8=256, 9=512, 10=1024, 11=2048, 12=4096) int sec_blocks; // Blocks per sector BOOL cd_raw; // CD-ROM RAW mode off_t imgoffset; // Offset to actual data + + const char *memory_block; + struct stat sb; + int fd; + + off_t GetTrackOffset(int block); + off_t GetSectorOffset(int block); };