RASCSI/src/raspberrypi/devices/disk.h

276 lines
10 KiB
C
Raw Normal View History

//---------------------------------------------------------------------------
//
// X68000 EMULATOR "XM6"
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
//
// XM6i
// Copyright (C) 2010-2015 isaki@NetBSD.org
//
// Imported sava's Anex86/T98Next image and MO format support patch.
// Comments translated to english by akuker.
//
// [ Disk ]
//
//---------------------------------------------------------------------------
#pragma once
#include "xm6.h"
#include "log.h"
#include "scsi.h"
#include "filepath.h"
#include <string>
//---------------------------------------------------------------------------
//
// Error definition (sense code returned by REQUEST SENSE)
//
// MSB Reserved (0x00)
// Sense Key
// Additional Sense Code (ASC)
// LSB Additional Sense Code Qualifier(ASCQ)
//
//---------------------------------------------------------------------------
#define DISK_NOERROR 0x00000000 // NO ADDITIONAL SENSE INFO.
#define DISK_DEVRESET 0x00062900 // POWER ON OR RESET OCCURED
#define DISK_NOTREADY 0x00023a00 // MEDIUM NOT PRESENT
#define DISK_ATTENTION 0x00062800 // MEDIUM MAY HAVE CHANGED
#define DISK_PREVENT 0x00045302 // MEDIUM REMOVAL PREVENTED
#define DISK_READFAULT 0x00031100 // UNRECOVERED READ ERROR
#define DISK_WRITEFAULT 0x00030300 // PERIPHERAL DEVICE WRITE FAULT
#define DISK_WRITEPROTECT 0x00042700 // WRITE PROTECTED
#define DISK_MISCOMPARE 0x000e1d00 // MISCOMPARE DURING VERIFY
#define DISK_INVALIDCMD 0x00052000 // INVALID COMMAND OPERATION CODE
#define DISK_INVALIDLBA 0x00052100 // LOGICAL BLOCK ADDR. OUT OF RANGE
#define DISK_INVALIDCDB 0x00052400 // INVALID FIELD IN CDB
#define DISK_INVALIDLUN 0x00052500 // LOGICAL UNIT NOT SUPPORTED
#define DISK_INVALIDPRM 0x00052600 // INVALID FIELD IN PARAMETER LIST
#define DISK_INVALIDMSG 0x00054900 // INVALID MESSAGE ERROR
#define DISK_PARAMLEN 0x00051a00 // PARAMETERS LIST LENGTH ERROR
#define DISK_PARAMNOT 0x00052601 // PARAMETERS NOT SUPPORTED
#define DISK_PARAMVALUE 0x00052602 // PARAMETERS VALUE INVALID
#define DISK_PARAMSAVE 0x00053900 // SAVING PARAMETERS NOT SUPPORTED
#define DISK_NODEFECT 0x00010000 // DEFECT LIST NOT FOUND
#if 0
#define DISK_AUDIOPROGRESS 0x00??0011 // AUDIO PLAY IN PROGRESS
#define DISK_AUDIOPAUSED 0x00??0012 // AUDIO PLAY PAUSED
#define DISK_AUDIOSTOPPED 0x00??0014 // AUDIO PLAY STOPPED DUE TO ERROR
#define DISK_AUDIOCOMPLETE 0x00??0013 // AUDIO PLAY SUCCESSFULLY COMPLETED
#endif
#define BENDER_SIGNATURE "RaSCSI"
//===========================================================================
//
// Disk Track
//
//===========================================================================
class DiskTrack
{
public:
// Internal data definition
typedef struct {
int track; // Track Number
int size; // Sector Size(8 or 9)
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
off64_t imgoffset; // Offset to actual data
} disktrk_t;
public:
// Basic Functions
DiskTrack(); // Constructor
virtual ~DiskTrack(); // Destructor
void Init(int track, int size, int sectors, BOOL raw = FALSE, off64_t imgoff = 0);// Initialization
BOOL Load(const Filepath& path); // Load
BOOL Save(const Filepath& path); // Save
// Read / Write
BOOL Read(BYTE *buf, int sec) const; // Sector Read
BOOL Write(const BYTE *buf, int sec); // Sector Write
// Other
int GetTrack() const { return dt.track; } // Get track
BOOL IsChanged() const { return dt.changed; } // Changed flag check
private:
// Internal data
disktrk_t dt; // Internal data
};
//===========================================================================
//
// Disk Cache
//
//===========================================================================
class DiskCache
{
public:
// Internal data definition
typedef struct {
DiskTrack *disktrk; // Disk Track
DWORD serial; // Serial
} cache_t;
// Number of caches
enum {
CacheMax = 16 // Number of tracks to cache
};
public:
// Basic Functions
DiskCache(const Filepath& path, int size, int blocks,off64_t imgoff = 0);// Constructor
virtual ~DiskCache(); // Destructor
void SetRawMode(BOOL raw); // CD-ROM raw mode setting
// Access
BOOL Save(); // Save and release all
BOOL Read(BYTE *buf, int block); // Sector Read
BOOL Write(const BYTE *buf, int block); // Sector Write
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 Update(); // Update serial number
// Internal data
cache_t cache[CacheMax]; // Cache management
DWORD serial; // Last serial number
Filepath sec_path; // Path
int sec_size; // Sector size (8 or 9 or 11)
int sec_blocks; // Blocks per sector
BOOL cd_raw; // CD-ROM RAW mode
off64_t imgoffset; // Offset to actual data
};
//===========================================================================
//
// Disk
//
//===========================================================================
class Disk
{
public:
// Internal data structure
typedef struct {
std::string id; // Media ID
BOOL ready; // Valid Disk
Feature extended server information (#169) * PbDevice returns information on whether a device is removable * Fixed log message * Added additional status data (ejectable, protctable, removable) * Assume ejectable == removable * Removed obsolete fields * Added locked/lockable to interface * Code review * Logging update * The user should be allowed to also write protect hard disk drives * Updated error handling * Testing * INSERT also has to search in the default file folder * Added TODO * Manpage update * Message updates * Moved some sanity checks to the server, so that they are run for any client * Updated error handling * Moved CR/LF handling to the client, the server should not format too much * rascsi should not mention "rasctl" in its messages, there may be other clients * Improved error messages * Improved error handling by returning an error string * Added TODO * Moved check for duplicate ID to ProcessCmd() * Removed debug output * Moved include * Removed obsolete includes, updated includes * Reverted ready check * Fixed error messages * Added convenience method * Simplified error handling * Socket/error handling review * "NO MEDIA" is added by the client, not by the server * Added missing include * Only check for duplicate ID when attaching a device * Added type/string converters for PbDeviceType * PbDevice indicates whether image files are supported * Write-protecing a read-only devices is not treated as an error anymore * Updated read-only check * Made difference between read-only and protected more explicit * Added comment * Comment update * Made hard disk drives write-protectable by the user * Resolved https://github.com/akuker/RASCSI/issues/166 * Addressing compiler error - type needs to be initialized Co-authored-by: akuker <akuker@gmail.com>
2021-08-08 15:08:58 +00:00
bool readonly; // Read only
bool protectable;
bool writep; // Write protected
bool removable; // Removable
bool removed;
bool lockable;
bool locked; // Locked
// TODO Non-disk devices must not inherit from Disk class
bool supports_file;
bool attn; // Attention
bool reset; // Reset
int size; // Sector Size
DWORD blocks; // Total number of sectors
DWORD lun; // LUN
DWORD code; // Status code
DiskCache *dcache; // Disk cache
off64_t imgoffset; // Offset to actual data
} disk_t;
public:
// Basic Functions
Disk(std::string); // Constructor
virtual ~Disk(); // Destructor
virtual void Reset(); // Device Reset
// ID
const std::string& GetID() const; // Get media ID
bool IsSASI() const; // SASI Check
bool IsSCSI() const; // SASI Check
bool IsCdRom() const;
bool IsMo() const;
bool IsBridge() const;
bool IsDaynaPort() const;
bool IsNuvolink() const;
// Media Operations
virtual void Open(const Filepath& path, BOOL attn = TRUE); // Open
void GetPath(Filepath& path) const; // Get the path
Feature extended server information (#169) * PbDevice returns information on whether a device is removable * Fixed log message * Added additional status data (ejectable, protctable, removable) * Assume ejectable == removable * Removed obsolete fields * Added locked/lockable to interface * Code review * Logging update * The user should be allowed to also write protect hard disk drives * Updated error handling * Testing * INSERT also has to search in the default file folder * Added TODO * Manpage update * Message updates * Moved some sanity checks to the server, so that they are run for any client * Updated error handling * Moved CR/LF handling to the client, the server should not format too much * rascsi should not mention "rasctl" in its messages, there may be other clients * Improved error messages * Improved error handling by returning an error string * Added TODO * Moved check for duplicate ID to ProcessCmd() * Removed debug output * Moved include * Removed obsolete includes, updated includes * Reverted ready check * Fixed error messages * Added convenience method * Simplified error handling * Socket/error handling review * "NO MEDIA" is added by the client, not by the server * Added missing include * Only check for duplicate ID when attaching a device * Added type/string converters for PbDeviceType * PbDevice indicates whether image files are supported * Write-protecing a read-only devices is not treated as an error anymore * Updated read-only check * Made difference between read-only and protected more explicit * Added comment * Comment update * Made hard disk drives write-protectable by the user * Resolved https://github.com/akuker/RASCSI/issues/166 * Addressing compiler error - type needs to be initialized Co-authored-by: akuker <akuker@gmail.com>
2021-08-08 15:08:58 +00:00
bool Eject(bool); // Eject
bool IsReady() const { return disk.ready; } // Ready check
Feature extended server information (#169) * PbDevice returns information on whether a device is removable * Fixed log message * Added additional status data (ejectable, protctable, removable) * Assume ejectable == removable * Removed obsolete fields * Added locked/lockable to interface * Code review * Logging update * The user should be allowed to also write protect hard disk drives * Updated error handling * Testing * INSERT also has to search in the default file folder * Added TODO * Manpage update * Message updates * Moved some sanity checks to the server, so that they are run for any client * Updated error handling * Moved CR/LF handling to the client, the server should not format too much * rascsi should not mention "rasctl" in its messages, there may be other clients * Improved error messages * Improved error handling by returning an error string * Added TODO * Moved check for duplicate ID to ProcessCmd() * Removed debug output * Moved include * Removed obsolete includes, updated includes * Reverted ready check * Fixed error messages * Added convenience method * Simplified error handling * Socket/error handling review * "NO MEDIA" is added by the client, not by the server * Added missing include * Only check for duplicate ID when attaching a device * Added type/string converters for PbDeviceType * PbDevice indicates whether image files are supported * Write-protecing a read-only devices is not treated as an error anymore * Updated read-only check * Made difference between read-only and protected more explicit * Added comment * Comment update * Made hard disk drives write-protectable by the user * Resolved https://github.com/akuker/RASCSI/issues/166 * Addressing compiler error - type needs to be initialized Co-authored-by: akuker <akuker@gmail.com>
2021-08-08 15:08:58 +00:00
bool IsProtectable() const { return disk.protectable; }
bool WriteP(bool); // Set Write Protect flag
bool IsWriteP() const { return disk.writep; } // Get write protect flag
Feature extended server information (#169) * PbDevice returns information on whether a device is removable * Fixed log message * Added additional status data (ejectable, protctable, removable) * Assume ejectable == removable * Removed obsolete fields * Added locked/lockable to interface * Code review * Logging update * The user should be allowed to also write protect hard disk drives * Updated error handling * Testing * INSERT also has to search in the default file folder * Added TODO * Manpage update * Message updates * Moved some sanity checks to the server, so that they are run for any client * Updated error handling * Moved CR/LF handling to the client, the server should not format too much * rascsi should not mention "rasctl" in its messages, there may be other clients * Improved error messages * Improved error handling by returning an error string * Added TODO * Moved check for duplicate ID to ProcessCmd() * Removed debug output * Moved include * Removed obsolete includes, updated includes * Reverted ready check * Fixed error messages * Added convenience method * Simplified error handling * Socket/error handling review * "NO MEDIA" is added by the client, not by the server * Added missing include * Only check for duplicate ID when attaching a device * Added type/string converters for PbDeviceType * PbDevice indicates whether image files are supported * Write-protecing a read-only devices is not treated as an error anymore * Updated read-only check * Made difference between read-only and protected more explicit * Added comment * Comment update * Made hard disk drives write-protectable by the user * Resolved https://github.com/akuker/RASCSI/issues/166 * Addressing compiler error - type needs to be initialized Co-authored-by: akuker <akuker@gmail.com>
2021-08-08 15:08:58 +00:00
bool IsReadOnly() const { return disk.readonly; } // Get read only flag
bool IsRemovable() const { return disk.removable; } // Get is removable flag
Feature extended server information (#169) * PbDevice returns information on whether a device is removable * Fixed log message * Added additional status data (ejectable, protctable, removable) * Assume ejectable == removable * Removed obsolete fields * Added locked/lockable to interface * Code review * Logging update * The user should be allowed to also write protect hard disk drives * Updated error handling * Testing * INSERT also has to search in the default file folder * Added TODO * Manpage update * Message updates * Moved some sanity checks to the server, so that they are run for any client * Updated error handling * Moved CR/LF handling to the client, the server should not format too much * rascsi should not mention "rasctl" in its messages, there may be other clients * Improved error messages * Improved error handling by returning an error string * Added TODO * Moved check for duplicate ID to ProcessCmd() * Removed debug output * Moved include * Removed obsolete includes, updated includes * Reverted ready check * Fixed error messages * Added convenience method * Simplified error handling * Socket/error handling review * "NO MEDIA" is added by the client, not by the server * Added missing include * Only check for duplicate ID when attaching a device * Added type/string converters for PbDeviceType * PbDevice indicates whether image files are supported * Write-protecing a read-only devices is not treated as an error anymore * Updated read-only check * Made difference between read-only and protected more explicit * Added comment * Comment update * Made hard disk drives write-protectable by the user * Resolved https://github.com/akuker/RASCSI/issues/166 * Addressing compiler error - type needs to be initialized Co-authored-by: akuker <akuker@gmail.com>
2021-08-08 15:08:58 +00:00
bool IsRemoved() const { return disk.removed; }
bool IsLockable() const { return disk.lockable; }
bool IsLocked() const { return disk.locked; } // Get locked status
bool SupportsFile() const { return disk.supports_file; }
bool IsAttn() const { return disk.attn; } // Get attention flag
bool Flush(); // Flush the cache
// Properties
void SetLUN(DWORD lun) { disk.lun = lun; } // LUN set
DWORD GetLUN() { return disk.lun; } // LUN get
// commands
virtual int Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);// INQUIRY command
virtual int RequestSense(const DWORD *cdb, BYTE *buf); // REQUEST SENSE command
int SelectCheck(const DWORD *cdb); // SELECT check
int SelectCheck10(const DWORD *cdb); // SELECT(10) check
virtual BOOL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);// MODE SELECT command
virtual int ModeSense(const DWORD *cdb, BYTE *buf); // MODE SENSE command
virtual int ModeSense10(const DWORD *cdb, BYTE *buf); // MODE SENSE(10) command
int ReadDefectData10(const DWORD *cdb, BYTE *buf); // READ DEFECT DATA(10) command
virtual BOOL TestUnitReady(const DWORD *cdb); // TEST UNIT READY command
BOOL Rezero(const DWORD *cdb); // REZERO command
BOOL Format(const DWORD *cdb); // FORMAT UNIT command
BOOL Reassign(const DWORD *cdb); // REASSIGN UNIT command
virtual int Read(const DWORD *cdb, BYTE *buf, DWORD block); // READ command
virtual int WriteCheck(DWORD block); // WRITE check
virtual BOOL Write(const DWORD *cdb, const BYTE *buf, DWORD block); // WRITE command
BOOL Seek(const DWORD *cdb); // SEEK command
BOOL Assign(const DWORD *cdb); // ASSIGN command
BOOL Specify(const DWORD *cdb); // SPECIFY command
BOOL StartStop(const DWORD *cdb); // START STOP UNIT command
BOOL SendDiag(const DWORD *cdb); // SEND DIAGNOSTIC command
BOOL Removal(const DWORD *cdb); // PREVENT/ALLOW MEDIUM REMOVAL command
int ReadCapacity(const DWORD *cdb, BYTE *buf); // READ CAPACITY command
BOOL Verify(const DWORD *cdb); // VERIFY command
virtual int ReadToc(const DWORD *cdb, BYTE *buf); // READ TOC command
virtual BOOL PlayAudio(const DWORD *cdb); // PLAY AUDIO command
virtual BOOL PlayAudioMSF(const DWORD *cdb); // PLAY AUDIO MSF command
virtual BOOL PlayAudioTrack(const DWORD *cdb); // PLAY AUDIO TRACK command
// Other
bool IsCacheWB(); // Get cache writeback mode
void SetCacheWB(BOOL enable); // Set cache writeback mode
protected:
// Internal processing
virtual int AddError(BOOL change, BYTE *buf); // Add error
virtual int AddFormat(BOOL change, BYTE *buf); // Add format
virtual int AddDrive(BOOL change, BYTE *buf); // Add drive
int AddOpt(BOOL change, BYTE *buf); // Add optical
int AddCache(BOOL change, BYTE *buf); // Add cache
int AddCDROM(BOOL change, BYTE *buf); // Add CD-ROM
int AddCDDA(BOOL change, BYTE *buf); // Add CD_DA
virtual int AddVendor(int page, BOOL change, BYTE *buf); // Add vendor special info
BOOL CheckReady(); // Check if ready
// Internal data
disk_t disk; // Internal disk data
Filepath diskpath; // File path (for GetPath)
BOOL cache_wb; // Cache mode
};