2020-08-28 14:18:02 +00:00
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// X68000 EMULATOR "XM6"
|
|
|
|
|
//
|
|
|
|
|
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
|
|
|
|
// Copyright (C) 2014-2020 GIMONS
|
|
|
|
|
//
|
|
|
|
|
// XM6i
|
|
|
|
|
// Copyright (C) 2010-2015 isaki@NetBSD.org
|
|
|
|
|
// Copyright (C) 2010 Y.Sugahara
|
|
|
|
|
//
|
|
|
|
|
// Imported sava's Anex86/T98Next image and MO format support patch.
|
|
|
|
|
// Imported NetBSD support and some optimisation patch by Rin Okuyama.
|
2021-03-08 01:29:30 +00:00
|
|
|
|
// Comments translated to english by akuker.
|
2020-08-28 14:18:02 +00:00
|
|
|
|
//
|
|
|
|
|
// [ Disk ]
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#include "os.h"
|
|
|
|
|
#include "xm6.h"
|
|
|
|
|
#include "filepath.h"
|
|
|
|
|
#include "fileio.h"
|
|
|
|
|
#include "gpiobus.h"
|
|
|
|
|
#include "ctapdriver.h"
|
|
|
|
|
#include "cfilesystem.h"
|
|
|
|
|
#include "disk.h"
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
//
|
|
|
|
|
// Disk
|
|
|
|
|
//
|
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
//
|
|
|
|
|
// Disk Track
|
|
|
|
|
//
|
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Constructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Destructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Initialization
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void DiskTrack::Init(
|
2020-08-28 14:18:02 +00:00
|
|
|
|
int track, int size, int sectors, BOOL raw, off64_t imgoff)
|
|
|
|
|
{
|
|
|
|
|
ASSERT(track >= 0);
|
|
|
|
|
ASSERT((size >= 8) && (size <= 11));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Load
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskTrack::Load(const Filepath& path)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
Fileio fio;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
// 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)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
off64_t offset = ((off64_t)dt.track << 8);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
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)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int length = dt.sectors << dt.size;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Allocate buffer memory
|
|
|
|
|
ASSERT((dt.size >= 8) && (dt.size <= 11));
|
|
|
|
|
ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100));
|
|
|
|
|
|
|
|
|
|
if (dt.buffer == NULL) {
|
2021-06-23 00:03:53 +00:00
|
|
|
|
if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) {
|
|
|
|
|
LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__);
|
|
|
|
|
}
|
2020-08-28 14:18:02 +00:00
|
|
|
|
dt.length = length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dt.buffer) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reallocate if the buffer length is different
|
|
|
|
|
if (dt.length != (DWORD)length) {
|
|
|
|
|
free(dt.buffer);
|
2021-06-23 00:03:53 +00:00
|
|
|
|
if (posix_memalign((void **)&dt.buffer, 512, ((length + 511) / 512) * 512)) {
|
|
|
|
|
LOGWARN("%s posix_memalign failed", __PRETTY_FUNCTION__);
|
|
|
|
|
}
|
2020-08-28 14:18:02 +00:00
|
|
|
|
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
|
|
|
|
|
if (!fio.OpenDIO(path, Fileio::ReadOnly)) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (dt.raw) {
|
|
|
|
|
// Split Reading
|
|
|
|
|
for (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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Save
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskTrack::Save(const Filepath& path)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int j;
|
|
|
|
|
int total;
|
|
|
|
|
|
|
|
|
|
// 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.size >= 8) && (dt.size <= 11));
|
|
|
|
|
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
|
2021-07-07 21:46:45 +00:00
|
|
|
|
off64_t offset = ((off64_t)dt.track << 8);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
offset <<= dt.size;
|
|
|
|
|
|
|
|
|
|
// Add offset to real image
|
|
|
|
|
offset += dt.imgoffset;
|
|
|
|
|
|
|
|
|
|
// Calculate length per sector
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int length = 1 << dt.size;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Open file
|
2021-07-07 21:46:45 +00:00
|
|
|
|
Fileio fio;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (!fio.Open(path, Fileio::ReadWrite)) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Partial write loop
|
|
|
|
|
for (i = 0; i < dt.sectors;) {
|
|
|
|
|
// If changed
|
|
|
|
|
if (dt.changemap[i]) {
|
|
|
|
|
// Initialize write size
|
|
|
|
|
total = 0;
|
|
|
|
|
|
|
|
|
|
// Seek
|
|
|
|
|
if (!fio.Seek(offset + ((off64_t)i << dt.size))) {
|
|
|
|
|
fio.Close();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Consectutive sector length
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Read Sector
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskTrack::Read(BYTE *buf, int sec) const
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
ASSERT((sec >= 0) & (sec < 0x100));
|
|
|
|
|
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s reading sector: %d", __PRETTY_FUNCTION__,sec);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// 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.size >= 8) && (dt.size <= 11));
|
|
|
|
|
ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100));
|
|
|
|
|
memcpy(buf, &dt.buffer[(off64_t)sec << dt.size], (off64_t)1 << dt.size);
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Write Sector
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskTrack::Write(const BYTE *buf, int sec)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
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
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int offset = sec << dt.size;
|
|
|
|
|
int length = 1 << dt.size;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Compare
|
|
|
|
|
ASSERT(dt.buffer);
|
|
|
|
|
ASSERT((dt.size >= 8) && (dt.size <= 11));
|
|
|
|
|
ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100));
|
|
|
|
|
if (memcmp(buf, &dt.buffer[offset], length) == 0) {
|
|
|
|
|
// 同じものを書き込もうとしているので、正常終了
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy, change
|
|
|
|
|
memcpy(&dt.buffer[offset], buf, length);
|
|
|
|
|
dt.changemap[sec] = TRUE;
|
|
|
|
|
dt.changed = TRUE;
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
//
|
|
|
|
|
// Disk Cache
|
|
|
|
|
//
|
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Constructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
DiskCache::DiskCache(
|
|
|
|
|
const Filepath& path, int size, int blocks, off64_t imgoff)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
ASSERT((size >= 8) && (size <= 11));
|
|
|
|
|
ASSERT(blocks > 0);
|
|
|
|
|
ASSERT(imgoff >= 0);
|
|
|
|
|
|
|
|
|
|
// Cache work
|
|
|
|
|
for (i = 0; i < CacheMax; i++) {
|
|
|
|
|
cache[i].disktrk = NULL;
|
|
|
|
|
cache[i].serial = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Other
|
|
|
|
|
serial = 0;
|
|
|
|
|
sec_path = path;
|
|
|
|
|
sec_size = size;
|
|
|
|
|
sec_blocks = blocks;
|
|
|
|
|
cd_raw = FALSE;
|
|
|
|
|
imgoffset = imgoff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Destructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
DiskCache::~DiskCache()
|
|
|
|
|
{
|
|
|
|
|
// Clear the track
|
|
|
|
|
Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// RAW Mode Setting
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void DiskCache::SetRawMode(BOOL raw)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(sec_size == 11);
|
|
|
|
|
|
|
|
|
|
// Configuration
|
|
|
|
|
cd_raw = raw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Save
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskCache::Save()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Save track
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// 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
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskCache::GetCache(int index, int& track, DWORD& aserial) const
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Clear
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void DiskCache::Clear()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Free the cache
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (cache[i].disktrk) {
|
|
|
|
|
delete cache[i].disktrk;
|
|
|
|
|
cache[i].disktrk = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Sector Read
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskCache::Read(BYTE *buf, int block)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(sec_size != 0);
|
|
|
|
|
|
|
|
|
|
// Update first
|
|
|
|
|
Update();
|
|
|
|
|
|
|
|
|
|
// Calculate track (fixed to 256 sectors/track)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int track = block >> 8;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Get the track data
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DiskTrack *disktrk = Assign(track);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (!disktrk) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read the track data to the cache
|
|
|
|
|
return disktrk->Read(buf, (BYTE)block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Sector write
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskCache::Write(const BYTE *buf, int block)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(sec_size != 0);
|
|
|
|
|
|
|
|
|
|
// Update first
|
|
|
|
|
Update();
|
|
|
|
|
|
|
|
|
|
// Calculate track (fixed to 256 sectors/track)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int track = block >> 8;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Get that track data
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DiskTrack *disktrk = Assign(track);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (!disktrk) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write the data to the cache
|
|
|
|
|
return disktrk->Write(buf, (BYTE)block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Track Assignment
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
DiskTrack* DiskCache::Assign(int track)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(sec_size != 0);
|
|
|
|
|
ASSERT(track >= 0);
|
|
|
|
|
|
|
|
|
|
// First, check if it is already assigned
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (cache[i].disktrk) {
|
|
|
|
|
if (cache[i].disktrk->GetTrack() == track) {
|
|
|
|
|
// Track match
|
|
|
|
|
cache[i].serial = serial;
|
|
|
|
|
return cache[i].disktrk;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Next, check for empty
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (!cache[i].disktrk) {
|
|
|
|
|
// Try loading
|
|
|
|
|
if (Load(i, track)) {
|
|
|
|
|
// Success loading
|
|
|
|
|
cache[i].serial = serial;
|
|
|
|
|
return cache[i].disktrk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load failed
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Finally, find the youngest serial number and delete it
|
|
|
|
|
|
|
|
|
|
// Set index 0 as candidate c
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD s = cache[0].serial;
|
|
|
|
|
int c = 0;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Compare candidate with serial and update to smaller one
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
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
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DiskTrack *disktrk = cache[c].disktrk;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
cache[c].disktrk = NULL;
|
|
|
|
|
|
|
|
|
|
// Load
|
|
|
|
|
if (Load(c, track, disktrk)) {
|
|
|
|
|
// Successful loading
|
|
|
|
|
cache[c].serial = serial;
|
|
|
|
|
return cache[c].disktrk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load failed
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Load cache
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL DiskCache::Load(int index, int track, DiskTrack *disktrk)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT((index >= 0) && (index < CacheMax));
|
|
|
|
|
ASSERT(track >= 0);
|
|
|
|
|
ASSERT(!cache[index].disktrk);
|
|
|
|
|
|
|
|
|
|
// Get the number of sectors on this track
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int sectors = sec_blocks - (track << 8);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
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)) {
|
|
|
|
|
// 失敗
|
|
|
|
|
delete disktrk;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocation successful, work set
|
|
|
|
|
cache[index].disktrk = disktrk;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Update serial number
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void DiskCache::Update()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Update and do nothing except 0
|
|
|
|
|
serial++;
|
|
|
|
|
if (serial != 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear serial of all caches (loop in 32bit)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
for (int i = 0; i < CacheMax; i++) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
cache[i].serial = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
//
|
|
|
|
|
// Disk
|
|
|
|
|
//
|
|
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Constructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
Disk::Disk(std::string id)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
2021-07-26 18:33:36 +00:00
|
|
|
|
assert(id.length() == 4);
|
|
|
|
|
|
|
|
|
|
disk.id = id;
|
|
|
|
|
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// Work initialization
|
|
|
|
|
disk.ready = FALSE;
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.protectable = false;
|
|
|
|
|
disk.writep = false;
|
|
|
|
|
disk.readonly = false;
|
|
|
|
|
disk.removable = false;
|
|
|
|
|
disk.removed = false;
|
|
|
|
|
disk.lockable = false;
|
|
|
|
|
disk.locked = false;
|
|
|
|
|
disk.supports_file = true;
|
|
|
|
|
disk.attn = false;
|
|
|
|
|
disk.reset = false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
disk.size = 0;
|
|
|
|
|
disk.blocks = 0;
|
|
|
|
|
disk.lun = 0;
|
|
|
|
|
disk.code = 0;
|
|
|
|
|
disk.dcache = NULL;
|
|
|
|
|
disk.imgoffset = 0;
|
|
|
|
|
|
|
|
|
|
// Other
|
|
|
|
|
cache_wb = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Destructor
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
Disk::~Disk()
|
|
|
|
|
{
|
|
|
|
|
// Save disk cache
|
|
|
|
|
if (disk.ready) {
|
|
|
|
|
// Only if ready...
|
|
|
|
|
if (disk.dcache) {
|
|
|
|
|
disk.dcache->Save();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear disk cache
|
|
|
|
|
if (disk.dcache) {
|
|
|
|
|
delete disk.dcache;
|
|
|
|
|
disk.dcache = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Reset
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void Disk::Reset()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// no lock, no attention, reset
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.locked = false;
|
|
|
|
|
disk.attn = false;
|
|
|
|
|
disk.reset = false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-07 19:00:48 +00:00
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Retrieve the disk's ID
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
const std::string& Disk::GetID() const
|
2021-02-07 19:00:48 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Get cache writeback mode
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsCacheWB()
|
2021-02-07 19:00:48 +00:00
|
|
|
|
{
|
|
|
|
|
return cache_wb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Set cache writeback mode
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void Disk::SetCacheWB(BOOL enable)
|
2021-02-07 19:00:48 +00:00
|
|
|
|
{
|
|
|
|
|
cache_wb = enable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
2021-07-24 00:41:55 +00:00
|
|
|
|
// Device type checks
|
2021-02-07 19:00:48 +00:00
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-24 00:41:55 +00:00
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsSASI() const
|
2021-07-24 00:41:55 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id == "SAHD";
|
2021-02-07 19:00:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsSCSI() const
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
2021-07-24 00:41:55 +00:00
|
|
|
|
return disk.id == "SCHD";
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsCdRom() const
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
2021-07-24 00:41:55 +00:00
|
|
|
|
return disk.id == "SCCD";
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsMo() const
|
2021-07-24 00:41:55 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id == "SCMO";
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsBridge() const
|
2021-07-24 00:41:55 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id == "SCBR";
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsDaynaPort() const
|
2021-07-24 00:41:55 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id == "SCDP";
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-26 18:33:36 +00:00
|
|
|
|
bool Disk::IsNuvolink() const
|
2021-07-24 00:41:55 +00:00
|
|
|
|
{
|
|
|
|
|
return disk.id == "SCNL";
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Open
|
|
|
|
|
// * Call as a post-process after successful opening in a derived class
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-08-09 23:56:13 +00:00
|
|
|
|
void Disk::Open(const Filepath& path, BOOL /*attn*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT((disk.size >= 8) && (disk.size <= 11));
|
|
|
|
|
ASSERT(disk.blocks > 0);
|
|
|
|
|
|
|
|
|
|
// Ready
|
|
|
|
|
disk.ready = TRUE;
|
|
|
|
|
|
|
|
|
|
// Cache initialization
|
|
|
|
|
ASSERT(!disk.dcache);
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.dcache = new DiskCache(path, disk.size, disk.blocks, disk.imgoffset);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Can read/write open
|
2021-07-07 21:46:45 +00:00
|
|
|
|
Fileio fio;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (fio.Open(path, Fileio::ReadWrite)) {
|
|
|
|
|
// Write permission, not read only
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.writep = false;
|
|
|
|
|
disk.readonly = false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
fio.Close();
|
|
|
|
|
} else {
|
|
|
|
|
// Write protected, read only
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.writep = true;
|
|
|
|
|
disk.readonly = true;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-08 15:08:58 +00:00
|
|
|
|
// Not locked, not removed
|
|
|
|
|
disk.locked = false;
|
|
|
|
|
disk.removed = false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// Save path
|
|
|
|
|
diskpath = path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Eject
|
2021-08-08 15:08:58 +00:00
|
|
|
|
// TODO This implemenation appears to be wrong: If a device is locked there
|
|
|
|
|
// is no way to eject the medium without unlocking. In other words, there is
|
|
|
|
|
// no "force" mode.
|
2020-08-28 14:18:02 +00:00
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-08-08 15:08:58 +00:00
|
|
|
|
bool Disk::Eject(bool force)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Can only be ejected if it is removable
|
|
|
|
|
if (!disk.removable) {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
return false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If you're not ready, you don't need to eject
|
|
|
|
|
if (!disk.ready) {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
return false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Must be unlocked if there is no force flag
|
2021-08-08 15:08:58 +00:00
|
|
|
|
if (!force && disk.locked) {
|
|
|
|
|
return false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove disk cache
|
|
|
|
|
disk.dcache->Save();
|
|
|
|
|
delete disk.dcache;
|
|
|
|
|
disk.dcache = NULL;
|
|
|
|
|
|
|
|
|
|
// Not ready, no attention
|
|
|
|
|
disk.ready = FALSE;
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.writep = false;
|
|
|
|
|
disk.readonly = false;
|
|
|
|
|
disk.removed = true;
|
|
|
|
|
disk.attn = false;
|
|
|
|
|
|
|
|
|
|
return true;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Write Protected
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-08-08 15:08:58 +00:00
|
|
|
|
bool Disk::WriteP(bool writep)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// be ready
|
|
|
|
|
if (!disk.ready) {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
return false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read Only, protect only
|
2021-08-08 15:08:58 +00:00
|
|
|
|
if (disk.readonly && !writep) {
|
|
|
|
|
return false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write protect flag setting
|
|
|
|
|
disk.writep = writep;
|
2021-08-08 15:08:58 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Get Path
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
void Disk::GetPath(Filepath& path) const
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
path = diskpath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Flush
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-08-07 00:50:20 +00:00
|
|
|
|
bool Disk::Flush()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Do nothing if there's nothing cached
|
|
|
|
|
if (!disk.dcache) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save cache
|
|
|
|
|
return disk.dcache->Save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Check Ready
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::CheckReady()
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Not ready if reset
|
|
|
|
|
if (disk.reset) {
|
|
|
|
|
disk.code = DISK_DEVRESET;
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.reset = false;
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s Disk in reset", __PRETTY_FUNCTION__);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Not ready if it needs attention
|
|
|
|
|
if (disk.attn) {
|
|
|
|
|
disk.code = DISK_ATTENTION;
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.attn = false;
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s Disk in needs attention", __PRETTY_FUNCTION__);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return status if not ready
|
|
|
|
|
if (!disk.ready) {
|
|
|
|
|
disk.code = DISK_NOTREADY;
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s Disk not ready", __PRETTY_FUNCTION__);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialization with no error
|
|
|
|
|
disk.code = DISK_NOERROR;
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s Disk is ready!", __PRETTY_FUNCTION__);
|
|
|
|
|
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// INQUIRY
|
|
|
|
|
// *You need to be successful at all times
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::Inquiry(
|
2020-08-28 14:18:02 +00:00
|
|
|
|
const DWORD* /*cdb*/, BYTE* /*buf*/, DWORD /*major*/, DWORD /*minor*/)
|
|
|
|
|
{
|
|
|
|
|
// default is INQUIRY failure
|
|
|
|
|
disk.code = DISK_INVALIDCMD;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// REQUEST SENSE
|
|
|
|
|
// *SASI is a separate process
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::RequestSense(const DWORD *cdb, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Return not ready only if there are no errors
|
|
|
|
|
if (disk.code == DISK_NOERROR) {
|
|
|
|
|
if (!disk.ready) {
|
|
|
|
|
disk.code = DISK_NOTREADY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Size determination (according to allocation length)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int size = (int)cdb[4];
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s size of data = %d", __PRETTY_FUNCTION__, size);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
ASSERT((size >= 0) && (size < 0x100));
|
|
|
|
|
|
|
|
|
|
// For SCSI-1, transfer 4 bytes when the size is 0
|
|
|
|
|
// (Deleted this specification for SCSI-2)
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
size = 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear the buffer
|
|
|
|
|
memset(buf, 0, size);
|
|
|
|
|
|
|
|
|
|
// Set 18 bytes including extended sense data
|
2021-07-16 00:49:54 +00:00
|
|
|
|
|
|
|
|
|
// Current error
|
2020-08-28 14:18:02 +00:00
|
|
|
|
buf[0] = 0x70;
|
2021-07-16 00:49:54 +00:00
|
|
|
|
|
2020-08-28 14:18:02 +00:00
|
|
|
|
buf[2] = (BYTE)(disk.code >> 16);
|
|
|
|
|
buf[7] = 10;
|
|
|
|
|
buf[12] = (BYTE)(disk.code >> 8);
|
|
|
|
|
buf[13] = (BYTE)disk.code;
|
|
|
|
|
|
|
|
|
|
// Clear the code
|
|
|
|
|
disk.code = 0x00;
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// MODE SELECT check
|
|
|
|
|
// *Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::SelectCheck(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
|
|
|
|
|
// Error if save parameters are set instead of SCSIHD
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (!IsSCSI()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// Error if save parameters are set
|
|
|
|
|
if (cdb[1] & 0x01) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Receive the data specified by the parameter length
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int length = (int)cdb[4];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// MODE SELECT(10) check
|
|
|
|
|
// * Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::SelectCheck10(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
|
|
|
|
|
// Error if save parameters are set instead of SCSIHD
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (!IsSCSI()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (cdb[1] & 0x01) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Receive the data specified by the parameter length
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD length = cdb[7];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
length <<= 8;
|
|
|
|
|
length |= cdb[8];
|
|
|
|
|
if (length > 0x800) {
|
|
|
|
|
length = 0x800;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (int)length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// MODE SELECT
|
|
|
|
|
// * Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::ModeSelect(
|
2020-08-28 14:18:02 +00:00
|
|
|
|
const DWORD* /*cdb*/, const BYTE *buf, int length)
|
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
ASSERT(length >= 0);
|
|
|
|
|
|
|
|
|
|
// cannot be set
|
|
|
|
|
disk.code = DISK_INVALIDPRM;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// MODE SENSE
|
|
|
|
|
// *Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::ModeSense(const DWORD *cdb, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
BOOL valid;
|
|
|
|
|
BOOL change;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
ASSERT(cdb[0] == 0x1a);
|
|
|
|
|
|
|
|
|
|
// Get length, clear buffer
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int length = (int)cdb[4];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
ASSERT((length >= 0) && (length < 0x100));
|
|
|
|
|
memset(buf, 0, length);
|
|
|
|
|
|
|
|
|
|
// Get changeable flag
|
|
|
|
|
if ((cdb[2] & 0xc0) == 0x40) {
|
|
|
|
|
change = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
change = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get page code (0x00 is valid from the beginning)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int page = cdb[2] & 0x3f;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (page == 0x00) {
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
valid = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Basic information
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int size = 4;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
|
|
|
|
|
// MEDIUM TYPE
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsMo()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
buf[1] = 0x03; // optical reversible or erasable
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DEVICE SPECIFIC PARAMETER
|
|
|
|
|
if (disk.writep) {
|
|
|
|
|
buf[2] = 0x80;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add block descriptor if DBD is 0
|
|
|
|
|
if ((cdb[1] & 0x08) == 0) {
|
|
|
|
|
// Mode parameter header
|
|
|
|
|
buf[3] = 0x08;
|
|
|
|
|
|
|
|
|
|
// Only if ready
|
|
|
|
|
if (disk.ready) {
|
|
|
|
|
// Block descriptor (number of blocks)
|
|
|
|
|
buf[5] = (BYTE)(disk.blocks >> 16);
|
|
|
|
|
buf[6] = (BYTE)(disk.blocks >> 8);
|
|
|
|
|
buf[7] = (BYTE)disk.blocks;
|
|
|
|
|
|
|
|
|
|
// Block descriptor (block length)
|
|
|
|
|
size = 1 << disk.size;
|
|
|
|
|
buf[9] = (BYTE)(size >> 16);
|
|
|
|
|
buf[10] = (BYTE)(size >> 8);
|
|
|
|
|
buf[11] = (BYTE)size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// size
|
|
|
|
|
size = 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 1(read-write error recovery)
|
|
|
|
|
if ((page == 0x01) || (page == 0x3f)) {
|
|
|
|
|
size += AddError(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 3(format device)
|
|
|
|
|
if ((page == 0x03) || (page == 0x3f)) {
|
|
|
|
|
size += AddFormat(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 4(drive parameter)
|
|
|
|
|
if ((page == 0x04) || (page == 0x3f)) {
|
|
|
|
|
size += AddDrive(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 6(optical)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsMo()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x06) || (page == 0x3f)) {
|
|
|
|
|
size += AddOpt(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 8(caching)
|
|
|
|
|
if ((page == 0x08) || (page == 0x3f)) {
|
|
|
|
|
size += AddCache(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 13(CD-ROM)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsCdRom()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x0d) || (page == 0x3f)) {
|
|
|
|
|
size += AddCDROM(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 14(CD-DA)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsCdRom()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x0e) || (page == 0x3f)) {
|
|
|
|
|
size += AddCDDA(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page (vendor special)
|
|
|
|
|
ret = AddVendor(page, change, &buf[size]);
|
|
|
|
|
if (ret > 0) {
|
|
|
|
|
size += ret;
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// final setting of mode data length
|
|
|
|
|
buf[0] = (BYTE)(size - 1);
|
|
|
|
|
|
|
|
|
|
// Unsupported page
|
|
|
|
|
if (!valid) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MODE SENSE success
|
|
|
|
|
disk.code = DISK_NOERROR;
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// MODE SENSE(10)
|
|
|
|
|
// *Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::ModeSense10(const DWORD *cdb, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
BOOL valid;
|
|
|
|
|
BOOL change;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
ASSERT(cdb[0] == 0x5a);
|
|
|
|
|
|
|
|
|
|
// Get length, clear buffer
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int length = cdb[7];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
length <<= 8;
|
|
|
|
|
length |= cdb[8];
|
|
|
|
|
if (length > 0x800) {
|
|
|
|
|
length = 0x800;
|
|
|
|
|
}
|
|
|
|
|
ASSERT((length >= 0) && (length < 0x800));
|
|
|
|
|
memset(buf, 0, length);
|
|
|
|
|
|
|
|
|
|
// Get changeable flag
|
|
|
|
|
if ((cdb[2] & 0xc0) == 0x40) {
|
|
|
|
|
change = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
change = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get page code (0x00 is valid from the beginning)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int page = cdb[2] & 0x3f;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (page == 0x00) {
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
valid = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Basic Information
|
2021-07-07 21:46:45 +00:00
|
|
|
|
int size = 4;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (disk.writep) {
|
|
|
|
|
buf[2] = 0x80;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add block descriptor if DBD is 0
|
|
|
|
|
if ((cdb[1] & 0x08) == 0) {
|
|
|
|
|
// Mode parameter header
|
|
|
|
|
buf[3] = 0x08;
|
|
|
|
|
|
|
|
|
|
// Only if ready
|
|
|
|
|
if (disk.ready) {
|
|
|
|
|
// Block descriptor (number of blocks)
|
|
|
|
|
buf[5] = (BYTE)(disk.blocks >> 16);
|
|
|
|
|
buf[6] = (BYTE)(disk.blocks >> 8);
|
|
|
|
|
buf[7] = (BYTE)disk.blocks;
|
|
|
|
|
|
|
|
|
|
// Block descriptor (block length)
|
|
|
|
|
size = 1 << disk.size;
|
|
|
|
|
buf[9] = (BYTE)(size >> 16);
|
|
|
|
|
buf[10] = (BYTE)(size >> 8);
|
|
|
|
|
buf[11] = (BYTE)size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Size
|
|
|
|
|
size = 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 1(read-write error recovery)
|
|
|
|
|
if ((page == 0x01) || (page == 0x3f)) {
|
|
|
|
|
size += AddError(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 3(format device)
|
|
|
|
|
if ((page == 0x03) || (page == 0x3f)) {
|
|
|
|
|
size += AddFormat(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 4(drive parameter)
|
|
|
|
|
if ((page == 0x04) || (page == 0x3f)) {
|
|
|
|
|
size += AddDrive(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ペPage code 6(optical)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsMo()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x06) || (page == 0x3f)) {
|
|
|
|
|
size += AddOpt(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 8(caching)
|
|
|
|
|
if ((page == 0x08) || (page == 0x3f)) {
|
|
|
|
|
size += AddCache(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 13(CD-ROM)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsCdRom()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x0d) || (page == 0x3f)) {
|
|
|
|
|
size += AddCDROM(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page code 14(CD-DA)
|
2021-07-24 00:41:55 +00:00
|
|
|
|
if (IsCdRom()) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if ((page == 0x0e) || (page == 0x3f)) {
|
|
|
|
|
size += AddCDDA(change, &buf[size]);
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Page (vendor special)
|
|
|
|
|
ret = AddVendor(page, change, &buf[size]);
|
|
|
|
|
if (ret > 0) {
|
|
|
|
|
size += ret;
|
|
|
|
|
valid = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// final setting of mode data length
|
|
|
|
|
buf[0] = (BYTE)(size - 1);
|
|
|
|
|
|
|
|
|
|
// Unsupported page
|
|
|
|
|
if (!valid) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MODE SENSE success
|
|
|
|
|
disk.code = DISK_NOERROR;
|
|
|
|
|
return length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add error page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddError(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x01;
|
|
|
|
|
buf[1] = 0x0a;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retry count is 0, limit time uses internal default value
|
|
|
|
|
return 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add format page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddFormat(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
int size;
|
|
|
|
|
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x80 | 0x03;
|
|
|
|
|
buf[1] = 0x16;
|
|
|
|
|
|
|
|
|
|
// Show the number of bytes in the physical sector as changeable
|
2021-03-08 01:29:30 +00:00
|
|
|
|
// (though it cannot be changed in practice)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
if (change) {
|
|
|
|
|
buf[0xc] = 0xff;
|
|
|
|
|
buf[0xd] = 0xff;
|
|
|
|
|
return 24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (disk.ready) {
|
|
|
|
|
// Set the number of tracks in one zone to 8 (TODO)
|
|
|
|
|
buf[0x3] = 0x08;
|
|
|
|
|
|
|
|
|
|
// Set sector/track to 25 (TODO)
|
|
|
|
|
buf[0xa] = 0x00;
|
|
|
|
|
buf[0xb] = 0x19;
|
|
|
|
|
|
|
|
|
|
// Set the number of bytes in the physical sector
|
|
|
|
|
size = 1 << disk.size;
|
|
|
|
|
buf[0xc] = (BYTE)(size >> 8);
|
|
|
|
|
buf[0xd] = (BYTE)size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set removable attribute
|
|
|
|
|
if (disk.removable) {
|
|
|
|
|
buf[20] = 0x20;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add drive page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddDrive(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x04;
|
|
|
|
|
buf[1] = 0x16;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (disk.ready) {
|
|
|
|
|
// Set the number of cylinders (total number of blocks
|
|
|
|
|
// divided by 25 sectors/track and 8 heads)
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD cylinder = disk.blocks;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
cylinder >>= 3;
|
|
|
|
|
cylinder /= 25;
|
|
|
|
|
buf[0x2] = (BYTE)(cylinder >> 16);
|
|
|
|
|
buf[0x3] = (BYTE)(cylinder >> 8);
|
|
|
|
|
buf[0x4] = (BYTE)cylinder;
|
|
|
|
|
|
|
|
|
|
// Fix the head at 8
|
|
|
|
|
buf[0x5] = 0x8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 24;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add option
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddOpt(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x06;
|
|
|
|
|
buf[1] = 0x02;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do not report update blocks
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add Cache Page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddCache(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x08;
|
|
|
|
|
buf[1] = 0x0a;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only read cache is valid, no prefetch
|
|
|
|
|
return 12;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add CDROM Page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddCDROM(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x0d;
|
|
|
|
|
buf[1] = 0x06;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2 seconds for inactive timer
|
|
|
|
|
buf[3] = 0x05;
|
|
|
|
|
|
|
|
|
|
// MSF multiples are 60 and 75 respectively
|
|
|
|
|
buf[5] = 60;
|
|
|
|
|
buf[7] = 75;
|
|
|
|
|
|
|
|
|
|
return 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// CD-DAページ追加
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddCDDA(BOOL change, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Set the message length
|
|
|
|
|
buf[0] = 0x0e;
|
|
|
|
|
buf[1] = 0x0e;
|
|
|
|
|
|
|
|
|
|
// No changeable area
|
|
|
|
|
if (change) {
|
|
|
|
|
return 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Audio waits for operation completion and allows
|
2021-03-08 01:29:30 +00:00
|
|
|
|
// PLAY across multiple tracks
|
2020-08-28 14:18:02 +00:00
|
|
|
|
return 16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Add special vendor page
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::AddVendor(int /*page*/, BOOL /*change*/, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// READ DEFECT DATA(10)
|
|
|
|
|
// *Not affected by disk.code
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
ASSERT(cdb[0] == 0x37);
|
|
|
|
|
|
|
|
|
|
// Get length, clear buffer
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD length = cdb[7];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
length <<= 8;
|
|
|
|
|
length |= cdb[8];
|
|
|
|
|
if (length > 0x800) {
|
|
|
|
|
length = 0x800;
|
|
|
|
|
}
|
|
|
|
|
ASSERT((length >= 0) && (length < 0x800));
|
|
|
|
|
memset(buf, 0, length);
|
|
|
|
|
|
|
|
|
|
// P/G/FORMAT
|
|
|
|
|
buf[1] = (cdb[1] & 0x18) | 5;
|
|
|
|
|
buf[3] = 8;
|
|
|
|
|
|
|
|
|
|
buf[4] = 0xff;
|
|
|
|
|
buf[5] = 0xff;
|
|
|
|
|
buf[6] = 0xff;
|
|
|
|
|
buf[7] = 0xff;
|
|
|
|
|
|
|
|
|
|
buf[8] = 0xff;
|
|
|
|
|
buf[9] = 0xff;
|
|
|
|
|
buf[10] = 0xff;
|
|
|
|
|
buf[11] = 0xff;
|
|
|
|
|
|
|
|
|
|
// no list
|
|
|
|
|
disk.code = DISK_NODEFECT;
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Command
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// TEST UNIT READY
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::TestUnitReady(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TEST UNIT READY Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// REZERO UNIT
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Rezero(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// REZERO Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// FORMAT UNIT
|
|
|
|
|
// *Opcode $06 for SASI, Opcode $04 for SCSI
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Format(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FMTDATA=1 is not supported (but OK if there is no DEFECT LIST)
|
|
|
|
|
if ((cdb[1] & 0x10) != 0 && cdb[4] != 0) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FORMAT Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// REASSIGN BLOCKS
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Reassign(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// REASSIGN BLOCKS Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// READ
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::Read(const DWORD *cdb, BYTE *buf, DWORD block)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error if the total number of blocks is exceeded
|
|
|
|
|
if (block >= disk.blocks) {
|
|
|
|
|
disk.code = DISK_INVALIDLBA;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// leave it to the cache
|
|
|
|
|
if (!disk.dcache->Read(buf, block)) {
|
|
|
|
|
disk.code = DISK_READFAULT;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return (1 << disk.size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// WRITE check
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::WriteCheck(DWORD block)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error if the total number of blocks is exceeded
|
|
|
|
|
if (block >= disk.blocks) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error if write protected
|
|
|
|
|
if (disk.writep) {
|
|
|
|
|
disk.code = DISK_WRITEPROTECT;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return (1 << disk.size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// WRITE
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Write(const DWORD *cdb, const BYTE *buf, DWORD block)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
2021-02-07 19:00:48 +00:00
|
|
|
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// Error if not ready
|
|
|
|
|
if (!disk.ready) {
|
|
|
|
|
disk.code = DISK_NOTREADY;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error if the total number of blocks is exceeded
|
|
|
|
|
if (block >= disk.blocks) {
|
|
|
|
|
disk.code = DISK_INVALIDLBA;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Error if write protected
|
|
|
|
|
if (disk.writep) {
|
|
|
|
|
disk.code = DISK_WRITEPROTECT;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Leave it to the cache
|
|
|
|
|
if (!disk.dcache->Write(buf, block)) {
|
|
|
|
|
disk.code = DISK_WRITEFAULT;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
disk.code = DISK_NOERROR;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// SEEK
|
|
|
|
|
// *Does not check LBA (SASI IOCS)
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Seek(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SEEK Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// ASSIGN
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Assign(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// SPECIFY
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Specify(const DWORD* /*cdb*/)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// START STOP UNIT
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::StartStop(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x1b);
|
|
|
|
|
|
|
|
|
|
// Look at the eject bit and eject if necessary
|
|
|
|
|
if (cdb[4] & 0x02) {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
if (disk.locked) {
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// Cannot be ejected because it is locked
|
|
|
|
|
disk.code = DISK_PREVENT;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Eject
|
2021-08-08 15:08:58 +00:00
|
|
|
|
Eject(false);
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OK
|
|
|
|
|
disk.code = DISK_NOERROR;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// SEND DIAGNOSTIC
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::SendDiag(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x1d);
|
|
|
|
|
|
|
|
|
|
// Do not support PF bit
|
|
|
|
|
if (cdb[1] & 0x10) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Do not support parameter list
|
|
|
|
|
if ((cdb[3] != 0) || (cdb[4] != 0)) {
|
|
|
|
|
disk.code = DISK_INVALIDCDB;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Always successful
|
|
|
|
|
disk.code = DISK_NOERROR;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// PREVENT/ALLOW MEDIUM REMOVAL
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Removal(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x1e);
|
|
|
|
|
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Lock flag
|
|
|
|
|
if (cdb[4] & 0x01) {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.locked = true;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
} else {
|
2021-08-08 15:08:58 +00:00
|
|
|
|
disk.locked = false;
|
2020-08-28 14:18:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// REMOVAL Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// READ CAPACITY
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::ReadCapacity(const DWORD* /*cdb*/, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD blocks;
|
|
|
|
|
DWORD length;
|
|
|
|
|
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// Buffer clear
|
|
|
|
|
memset(buf, 0, 8);
|
|
|
|
|
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 00:49:54 +00:00
|
|
|
|
if (disk.blocks <= 0) {
|
|
|
|
|
LOGWARN("%s Capacity not available, medium may not be present", __PRETTY_FUNCTION__);
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 14:18:02 +00:00
|
|
|
|
// Create end of logical block address (disk.blocks-1)
|
|
|
|
|
blocks = disk.blocks - 1;
|
|
|
|
|
buf[0] = (BYTE)(blocks >> 24);
|
|
|
|
|
buf[1] = (BYTE)(blocks >> 16);
|
|
|
|
|
buf[2] = (BYTE)(blocks >> 8);
|
|
|
|
|
buf[3] = (BYTE)blocks;
|
|
|
|
|
|
|
|
|
|
// Create block length (1 << disk.size)
|
|
|
|
|
length = 1 << disk.size;
|
|
|
|
|
buf[4] = (BYTE)(length >> 24);
|
|
|
|
|
buf[5] = (BYTE)(length >> 16);
|
|
|
|
|
buf[6] = (BYTE)(length >> 8);
|
|
|
|
|
buf[7] = (BYTE)length;
|
|
|
|
|
|
|
|
|
|
// return the size
|
|
|
|
|
return 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VERIFY
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::Verify(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x2f);
|
|
|
|
|
|
|
|
|
|
// Get parameters
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD record = cdb[2];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
record <<= 8;
|
|
|
|
|
record |= cdb[3];
|
|
|
|
|
record <<= 8;
|
|
|
|
|
record |= cdb[4];
|
|
|
|
|
record <<= 8;
|
|
|
|
|
record |= cdb[5];
|
2021-07-07 21:46:45 +00:00
|
|
|
|
DWORD blocks = cdb[7];
|
2020-08-28 14:18:02 +00:00
|
|
|
|
blocks <<= 8;
|
|
|
|
|
blocks |= cdb[8];
|
|
|
|
|
|
|
|
|
|
// Status check
|
|
|
|
|
if (!CheckReady()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parameter check
|
|
|
|
|
if (disk.blocks < (record + blocks)) {
|
|
|
|
|
disk.code = DISK_INVALIDLBA;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Success
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// READ TOC
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
int Disk::ReadToc(const DWORD *cdb, BYTE *buf)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x43);
|
|
|
|
|
ASSERT(buf);
|
|
|
|
|
|
|
|
|
|
// This command is not supported
|
|
|
|
|
disk.code = DISK_INVALIDCMD;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// PLAY AUDIO
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::PlayAudio(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x45);
|
|
|
|
|
|
|
|
|
|
// This command is not supported
|
|
|
|
|
disk.code = DISK_INVALIDCMD;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// PLAY AUDIO MSF
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::PlayAudioMSF(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x47);
|
|
|
|
|
|
|
|
|
|
// This command is not supported
|
|
|
|
|
disk.code = DISK_INVALIDCMD;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// PLAY AUDIO TRACK
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
2021-07-26 18:33:36 +00:00
|
|
|
|
BOOL Disk::PlayAudioTrack(const DWORD *cdb)
|
2020-08-28 14:18:02 +00:00
|
|
|
|
{
|
|
|
|
|
ASSERT(cdb);
|
|
|
|
|
ASSERT(cdb[0] == 0x48);
|
|
|
|
|
|
|
|
|
|
// This command is not supported
|
|
|
|
|
disk.code = DISK_INVALIDCMD;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|