Large changes to configuration files again (the old ones might break, be careful);

Applied the mainline PCem slight CPU emulation speedup commit;
Added emulation of removable SCSI hard disks;
CD-ROM image handler now uses C FILE's (with the 64-bit size calls) instead of C++ iostreams, ISO images bigger than 2 GB should work properly again;
Split RLL/ESDI and XT IDE disks to their own bus types;
Turned status bar pane meaning and hard disks and CD-ROM BUS numbers to #define's;
Other miscellaneous cleanups.
This commit is contained in:
OBattler
2017-05-27 03:53:32 +02:00
parent 94680da416
commit a36720f174
56 changed files with 4736 additions and 2682 deletions

View File

@@ -20,7 +20,9 @@
#include "ide.h"
#include "piix.h"
#include "scsi.h"
#include "scsi_disk.h"
#include "timer.h"
#include "WIN/plat_iodev.h"
/* Bits of 'status' */
#define ERR_STAT 0x01
@@ -41,6 +43,8 @@
#define scsi_hd_asc shdc[id].sense[12]
#define scsi_hd_ascq shdc[id].sense[13]
scsi_hard_disk_t shdc[HDC_NUM];
uint8_t scsi_hard_disks[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
@@ -177,7 +181,15 @@ int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
for (i = 0; i < HDC_NUM; i++)
{
if ((hdc[i].bus == 4) && (hdc[i].scsi_id == scsi_id) && (hdc[i].scsi_lun == scsi_lun))
if ((wcslen(hdc[i].fn) == 0) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE))
{
continue;
}
if (((hdc[i].spt == 0) || (hdc[i].hpc == 0) || (hdc[i].tracks == 0)) && (hdc[i].bus != HDD_BUS_SCSI_REMOVABLE))
{
continue;
}
if (((hdc[i].bus == HDD_BUS_SCSI) || (hdc[i].bus == HDD_BUS_SCSI_REMOVABLE)) && (hdc[i].scsi_id == scsi_id) && (hdc[i].scsi_lun == scsi_lun))
{
return i;
}
@@ -185,27 +197,47 @@ int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
return 0xff;
}
static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
void scsi_disk_insert(uint8_t id)
{
shdc[id].unit_attention = (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0;
}
char empty_sector[512];
void scsi_loadhd(int scsi_id, int scsi_lun, int id)
{
uint32_t sector_size = 512;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
wchar_t *fn = hdd_fn[id];
uint64_t i = 0, s = 0;;
wchar_t *fn = hdc[id].fn;
memset(empty_sector, 0, sizeof(empty_sector));
shdc[id].base = 0;
if (shdf[id] != NULL)
{
fclose(shdf[id]);
shdf[id] == NULL;
shdf[id] = NULL;
}
/* Try to open existing hard disk image */
if (fn[0] == '.')
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
scsi_hd_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
shdc[id].cdb_len = 12;
}
return;
}
shdf[id] = _wfopen(fn, L"rb+");
@@ -216,10 +248,26 @@ static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
{
scsi_hd_log("A write-protected image must exist\n");
goto scsi_hd_load_error;
}
shdf[id] = _wfopen(fn, L"wb+");
if (shdf[id] == NULL)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
scsi_hd_load_error:
scsi_hd_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
shdc[id].cdb_len = 12;
}
return;
}
else
@@ -227,6 +275,7 @@ static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x1000;
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
@@ -243,6 +292,7 @@ static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x28;
fwrite(&signature, 1, 8, shdf[id]);
fwrite(&full_size, 1, 8, shdf[id]);
@@ -253,15 +303,29 @@ static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
}
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
shdc[id].last_sector = 0;
shdc[id].cdb_len = 12;
}
scsi_disk_insert(id);
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
goto prepare_new_hard_disk;
}
else
{
/* Failed for another reason */
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
scsi_hd_log("Failed for another reason\n");
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
}
@@ -272,41 +336,334 @@ static void scsi_loadhd(int scsi_id, int scsi_lun, int id)
{
fseeko64(shdf[id], 0x8, SEEK_SET);
fread(&(shdc[id].base), 1, 4, shdf[id]);
fseeko64(shdf[id], 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDI: Sector size is not 512\n");
fclose(shdf[id]);
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
fread(&(hdc[id].spt), 1, 4, shdf[id]);
fread(&(hdc[id].hpc), 1, 4, shdf[id]);
fread(&(hdc[id].tracks), 1, 4, shdf[id]);
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_load_error;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
}
else if (image_is_hdx(fn, 1))
{
shdc[id].base = 0x28;
fseeko64(shdf[id], 8, SEEK_SET);
fread(&full_size, 1, 8, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDX: Sector size is not 512\n");
fclose(shdf[id]);
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hard_disks[scsi_id][scsi_lun] = 0xff;
}
else
{
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
}
return;
}
fread(&(hdc[id].spt), 1, 4, shdf[id]);
fread(&(hdc[id].hpc), 1, 4, shdf[id]);
fread(&(hdc[id].tracks), 1, 4, shdf[id]);
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_load_error;
}
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, shdf[id]);
fread(&(hdc[id].at_hpc), 1, 4, shdf[id]);
}
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
}
shdc[id].cdb_len = 12;
scsi_disk_insert(id);
}
fseeko64(shdf[id], 0, SEEK_END);
if (ftello64(shdf[id]) != (full_size + shdc[id].base))
{
s = (full_size + shdc[id].base) - ftello64(shdf[id]);
prepare_new_hard_disk:
s >>= 9;
for (i = 0; i < s; i++)
{
fwrite(empty_sector, 1, 512, shdf[id]);
}
}
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
fclose(shdf[id]);
}
void scsi_reloadhd(int id)
{
uint32_t sector_size = 512;
uint32_t zero = 0;
uint64_t signature = 0xD778A82044445459ll;
uint64_t full_size = 0;
uint64_t spt = 0, hpc = 0, tracks = 0;
int c;
uint64_t i = 0, s = 0;;
wchar_t *fn = hdc[id].fn;
memset(empty_sector, 0, sizeof(empty_sector));
if(hdc[id].prev_fn == NULL)
{
return;
}
else
{
wcscpy(hdc[id].fn, hdc[id].prev_fn);
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
}
shdc[id].base = 0;
if (shdf[id] != NULL)
{
fclose(shdf[id]);
shdf[id] = NULL;
}
/* Try to open existing hard disk image */
if (fn[0] == '.')
{
scsi_hd_log("File name starts with .\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
shdf[id] = _wfopen(fn, L"rb+");
if (shdf[id] == NULL)
{
/* Failed to open existing hard disk image */
if (errno == ENOENT)
{
/* Failed because it does not exist,
so try to create new file */
if (hdc[id].wp)
{
scsi_hd_log("A write-protected image must exist\n");
goto scsi_hd_reload_error;
}
shdf[id] = _wfopen(fn, L"wb+");
if (shdf[id] == NULL)
{
scsi_hd_reload_error:
scsi_hd_log("Unable to open image\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
else
{
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x1000;
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&(shdc[id].base), 1, 4, shdf[id]);
fwrite(&full_size, 1, 4, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
for (c = 0; c < 0x3f8; c++)
{
fwrite(&zero, 1, 4, shdf[id]);
}
}
else if (image_is_hdx(fn, 0))
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
shdc[id].base = 0x28;
fwrite(&signature, 1, 8, shdf[id]);
fwrite(&full_size, 1, 8, shdf[id]);
fwrite(&sector_size, 1, 4, shdf[id]);
fwrite(&(hdc[id].spt), 1, 4, shdf[id]);
fwrite(&(hdc[id].hpc), 1, 4, shdf[id]);
fwrite(&(hdc[id].tracks), 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
fwrite(&zero, 1, 4, shdf[id]);
}
shdc[id].last_sector = 0;
shdc[id].cdb_len = 12;
}
scsi_disk_insert(id);
s = full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
goto reload_prepare_new_hard_disk;
}
else
{
/* Failed for another reason */
scsi_hd_log("Failed for another reason\n");
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
}
else
{
memset(&(shdc[id]), 0, sizeof(scsi_hard_disk_t));
if (image_is_hdi(fn))
{
fseeko64(shdf[id], 0x8, SEEK_SET);
fread(&(shdc[id].base), 1, 4, shdf[id]);
fseeko64(shdf[id], 0xC, SEEK_SET);
full_size = 0;
fread(&full_size, 1, 4, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDI: Sector size is not 512\n");
fclose(shdf[id]);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_reload_error;
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
}
else if (image_is_hdx(fn, 1))
{
shdc[id].base = 0x28;
fseeko64(shdf[id], 8, SEEK_SET);
fread(&full_size, 1, 8, shdf[id]);
fseeko64(shdf[id], 0x10, SEEK_SET);
fread(&sector_size, 1, 4, shdf[id]);
if (sector_size != 512)
{
/* Sector size is not 512 */
scsi_hd_log("HDX: Sector size is not 512\n");
fclose(shdf[id]);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
return;
}
fread(&spt, 1, 4, shdf[id]);
fread(&hpc, 1, 4, shdf[id]);
fread(&tracks, 1, 4, shdf[id]);
if ((spt != hdc[id].spt) || (hpc != hdc[id].hpc) || (tracks != hdc[id].tracks))
{
fclose(shdf[id]);
shdf[id] = NULL;
goto scsi_hd_reload_error;
}
hdc[id].spt = spt;
hdc[id].hpc = hpc;
hdc[id].tracks = tracks;
fread(&(hdc[id].at_spt), 1, 4, shdf[id]);
fread(&(hdc[id].at_hpc), 1, 4, shdf[id]);
}
else
{
full_size = hdc[id].spt * hdc[id].hpc * hdc[id].tracks * 512;
}
shdc[id].cdb_len = 12;
scsi_disk_insert(id);
}
fseeko64(shdf[id], 0, SEEK_END);
if (ftello64(shdf[id]) != (full_size + shdc[id].base))
{
s = (full_size + shdc[id].base) - ftello64(shdf[id]);
reload_prepare_new_hard_disk:
s >>= 9;
for (i = 0; i < s; i++)
{
fwrite(empty_sector, 1, 512, shdf[id]);
}
}
shdc[id].last_sector = (uint32_t) (full_size >> 9) - 1;
}
void scsi_unloadhd(int scsi_id, int scsi_lun, int id)
{
if (wcslen(hdc[id].fn) == 0)
{
return;
}
if (shdf[id] != NULL)
{
fclose(shdf[id]);
shdf[id] = NULL;
}
shdc[id].last_sector = -1;
memset(hdc[id].prev_fn, 0, sizeof(hdc[id].prev_fn));
wcscpy(hdc[id].prev_fn, hdc[id].fn);
memset(hdc[id].fn, 0, sizeof(hdc[id].fn));
shdc[id].cdb_len = 12;
fclose(shdf[id]);
}
void build_scsi_hd_map()
@@ -326,7 +683,15 @@ void build_scsi_hd_map()
scsi_hard_disks[i][j] = find_hdc_for_scsi_id(i, j);
if (scsi_hard_disks[i][j] != 0xff)
{
scsi_loadhd(i, j, scsi_hard_disks[i][j]);
memset(&(shdc[scsi_hard_disks[i][j]]), 0, sizeof(shdc[scsi_hard_disks[i][j]]));
if (wcslen(hdc[scsi_hard_disks[i][j]].fn) > 0)
{
scsi_loadhd(i, j, scsi_hard_disks[i][j]);
}
else
{
shdc[scsi_hard_disks[i][j]].cdb_len = 12;
}
}
}
}
@@ -334,7 +699,6 @@ void build_scsi_hd_map()
int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len)
{
int ret = 0;
int size = 0;
size = shdc[id].last_sector;
@@ -477,7 +841,7 @@ static void scsi_hd_sense_clear(int id, int command)
static void scsi_hd_cmd_error(uint8_t id)
{
shdc[id].error = ((scsi_hd_sense_key & 0xf) << 4) | ABRT_ERR;
if (shdc[id].unit_attention)
if (shdc[id].unit_attention & 3)
{
shdc[id].error |= MCR_ERR;
}
@@ -490,8 +854,8 @@ static void scsi_hd_cmd_error(uint8_t id)
static void scsi_hd_unit_attention(uint8_t id)
{
shdc[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR;
if (cdrom[id].unit_attention)
shdc[id].error = (SENSE_NOT_READY << 4) | ABRT_ERR;
if (shdc[id].unit_attention & 3)
{
shdc[id].error |= MCR_ERR;
}
@@ -510,6 +874,32 @@ static void scsi_hd_not_ready(uint8_t id)
scsi_hd_cmd_error(id);
}
#if 0
static void scsi_hd_icmd_required(uint8_t id)
{
scsi_hd_sense_key = SENSE_NOT_READY;
scsi_hd_asc = ASC_NOT_READY;
scsi_hd_ascq = ASCQ_INITIALIZING_COMMAND_REQUIRED;
scsi_hd_cmd_error(id);
}
static void scsi_hd_capacity_data_changed(uint8_t id)
{
scsi_hd_sense_key = SENSE_UNIT_ATTENTION;
scsi_hd_asc = ASC_CAPACITY_DATA_CHANGED;
scsi_hd_ascq = ASCQ_CAPACITY_DATA_CHANGED;
scsi_hd_cmd_error(id);
}
#endif
static void scsi_hd_write_protected(uint8_t id)
{
scsi_hd_sense_key = SENSE_UNIT_ATTENTION;
scsi_hd_asc = ASC_WRITE_PROTECTED;
scsi_hd_ascq = 0;
scsi_hd_cmd_error(id);
}
static void scsi_hd_invalid_lun(uint8_t id)
{
scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST;
@@ -586,78 +976,6 @@ void scsi_hd_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks)
}
}
int scsi_hd_read_data(uint8_t id, uint32_t *len)
{
uint8_t *hdbufferb = (uint8_t *) shdc[id].buffer;
int temp_len = 0;
int last_valid_data_pos = 0;
uint64_t pos64 = (uint64_t) shdc[id].sector_pos;
if (shdc[id].sector_pos > shdc[id].last_sector)
{
/* scsi_hd_log("SCSI HD %i: Trying to read beyond the end of disk\n", id); */
scsi_hd_lba_out_of_range(id);
return 0;
}
shdc[id].old_len = 0;
*len = 0;
fseeko64(shdf[id], pos64 << 9, SEEK_SET);
fread(hdbufferb + shdc[id].data_pos, (shdc[id].sector_len << 9), 1, shdf[id]);
temp_len = (shdc[id].sector_len << 9);
last_valid_data_pos = shdc[id].data_pos;
shdc[id].data_pos += temp_len;
shdc[id].old_len += temp_len;
*len += temp_len;
scsi_hd_log("SCSI HD %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, hdbufferb[last_valid_data_pos + 0], hdbufferb[last_valid_data_pos + 1], hdbufferb[last_valid_data_pos + 2], hdbufferb[last_valid_data_pos + 3], hdbufferb[last_valid_data_pos + 4], hdbufferb[last_valid_data_pos + 5], hdbufferb[last_valid_data_pos + 6], hdbufferb[last_valid_data_pos + 7]);
return 1;
}
int scsi_hd_read_blocks(uint8_t id, uint32_t *len, int first_batch)
{
int ret = 0;
shdc[id].data_pos = 0;
if (!shdc[id].sector_len)
{
scsi_hd_command_complete(id);
return -1;
}
scsi_hd_log("Reading %i blocks starting from %i...\n", shdc[id].requested_blocks, shdc[id].sector_pos);
scsi_hd_update_cdb(shdc[id].current_cdb, shdc[id].sector_pos, shdc[id].requested_blocks);
ret = scsi_hd_read_data(id, len);
scsi_hd_log("Read %i bytes of blocks...\n", *len);
if (!ret)
{
return 0;
}
shdc[id].sector_pos += shdc[id].requested_blocks;
shdc[id].sector_len -= shdc[id].requested_blocks;
return 1;
}
void scsi_disk_insert(uint8_t id)
{
shdc[id].unit_attention = (hdc[id].bus == 5) ? 1 : 0;
}
/*SCSI Sense Initialization*/
void scsi_hd_sense_code_ok(uint8_t id)
{
@@ -680,14 +998,15 @@ int scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb)
if (!(scsi_hd_command_flags[cdb[0]] & IMPLEMENTED))
{
scsi_hd_log("SCSI HD %i: Attempting to execute unknown command %02X\n", id, cdb[0]);
/* pclog("SCSI HD %i: Attempting to execute unknown command %02X (%02X %02X)\n", id, cdb[0], ((cdb[1] >> 3) & 1) ? 0 : 1, cdb[2] & 0x3F); */
scsi_hd_illegal_opcode(id);
return 0;
}
if (hdc[id].bus == 5)
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
/* Removable disk, set ready state. */
if (wcslen(hdd_fn[id]) > 0)
if (wcslen(hdc[id].fn) > 0)
{
ready = 1;
}
@@ -761,6 +1080,11 @@ static void scsi_hd_seek(uint8_t id, uint32_t pos)
static void scsi_hd_rezero(uint8_t id)
{
if (id == 255)
{
return;
}
shdc[id].sector_pos = shdc[id].sector_len = 0;
scsi_hd_seek(id, 0);
}
@@ -775,6 +1099,8 @@ void scsi_hd_reset(uint8_t id)
void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
{
int is_ua = 0;
/*Will return 18 bytes of 0*/
if (alloc_length != 0)
{
@@ -788,7 +1114,8 @@ void scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length)
{
buffer[2]=SENSE_UNIT_ATTENTION;
buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
buffer[13]=0;
buffer[13]=0x00;
is_ua = 1;
}
/* scsi_hd_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", id, hdbufferb[2], hdbufferb[12], hdbufferb[13]); */
@@ -808,10 +1135,10 @@ void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_l
{
int ready = 1;
if (hdc[id].bus == 5)
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
/* Removable disk, set ready state. */
if (wcslen(hdd_fn[id]) > 0)
if (wcslen(hdc[id].fn) > 0)
{
ready = 1;
}
@@ -851,10 +1178,10 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
unsigned size_idx;
unsigned preamble_len;
uint32_t alloc_length;
int ret;
uint64_t pos64;
char device_identify[8] = { '8', '6', 'B', '_', 'H', 'D', '0', 0 };
char device_identify_ex[14] = { '8', '6', 'B', '_', 'H', 'D', '0', ' ', 'v', '1', '.', '0', '0', 0 };
uint64_t full_size = 0;
char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 };
char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
#if 0
int CdbLength;
@@ -864,13 +1191,22 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].packet_len = 0;
shdc[id].request_pos = 0;
device_identify[6] = id + 0x30;
device_identify[6] = (id / 10) + 0x30;
device_identify[7] = (id % 10) + 0x30;
device_identify_ex[6] = (id / 10) + 0x30;
device_identify_ex[7] = (id % 10) + 0x30;
device_identify_ex[10] = emulator_version[0];
device_identify_ex[12] = emulator_version[2];
device_identify_ex[13] = emulator_version[3];
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
device_identify[4] = 'R';
device_identify_ex[4] = 'R';
}
device_identify_ex[6] = id + 0x30;
device_identify_ex[9] = emulator_version[0];
device_identify_ex[11] = emulator_version[2];
device_identify_ex[12] = emulator_version[3];
shdc[id].data_pos = 0;
memcpy(shdc[id].current_cdb, cdb, shdc[id].cdb_len);
@@ -958,20 +1294,15 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
max_len = shdc[id].sector_len;
shdc[id].requested_blocks = max_len;
#if 0
ret = scsi_hd_read_blocks(id, &alloc_length, 1);
if (ret <= 0)
{
return;
}
#endif
pos64 = (uint64_t) shdc[id].sector_pos;
if (shdc[id].requested_blocks > 0)
{
fseeko64(shdf[id], pos64 << 9, SEEK_SET);
fread(hdbufferb, (shdc[id].sector_len << 9), 1, shdf[id]);
shdf[id] = _wfopen(hdc[id].fn, L"rb+");
fseeko64(shdf[id], shdc[id].base + (pos64 << 9), SEEK_SET);
memset(hdbufferb, 0, shdc[id].sector_len << 9);
fread(hdbufferb, 1, (shdc[id].sector_len << 9), shdf[id]);
fclose(shdf[id]);
}
alloc_length = shdc[id].packet_len = max_len << 9;
@@ -986,17 +1317,23 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].all_blocks_total = shdc[id].block_total;
if (shdc[id].packet_status != CDROM_PHASE_COMPLETE)
{
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 1);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
}
else
{
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 0);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}
return;
case GPCMD_WRITE_6:
case GPCMD_WRITE_10:
case GPCMD_WRITE_12:
if ((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdc[id].wp)
{
scsi_hd_write_protected(id);
return;
}
switch(cdb[0])
{
case GPCMD_WRITE_6:
@@ -1031,8 +1368,10 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
if (shdc[id].requested_blocks > 0)
{
fseeko64(shdf[id], pos64 << 9, SEEK_SET);
shdf[id] = _wfopen(hdc[id].fn, L"rb+");
fseeko64(shdf[id], shdc[id].base + (pos64 << 9), SEEK_SET);
fwrite(hdbufferb, 1, (shdc[id].sector_len << 9), shdf[id]);
fclose(shdf[id]);
}
alloc_length = shdc[id].packet_len = max_len << 9;
@@ -1047,16 +1386,16 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].all_blocks_total = shdc[id].block_total;
if (shdc[id].packet_status != CDROM_PHASE_COMPLETE)
{
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 1);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1);
}
else
{
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 0);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}
return;
case GPCMD_START_STOP_UNIT:
if (hdc[id].bus != 5)
if (hdc[id].bus != HDD_BUS_SCSI_REMOVABLE)
{
scsi_hd_illegal_opcode(id);
break;
@@ -1068,18 +1407,10 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case 1: /* Start the disc and read the TOC. */
break;
case 2: /* Eject the disc if possible. */
#ifndef __unix
#if 0
win_removable_disk_eject(id);
#endif
#endif
removable_disk_eject(id);
break;
case 3: /* Load the disc (close tray). */
#ifndef __unix
#if 0
win_removable_disk_reload(id);
#endif
#endif
removable_disk_reload(id);
break;
}
@@ -1150,7 +1481,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
memset(hdbufferb, 0, 8);
hdbufferb[0] = 0; /*SCSI HD*/
if (hdc[id].bus == 5)
if (hdc[id].bus == HDD_BUS_SCSI_REMOVABLE)
{
hdbufferb[1] = 0x80; /*Removable*/
}
@@ -1204,6 +1535,7 @@ atapi_out:
break;
default:
/* pclog("SCSI HD %i: Attempting to execute pseudo-implemented command %02X\n", id, cdb[0]); */
scsi_hd_illegal_opcode(id);
break;
}
@@ -1301,7 +1633,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
shdc[id].packet_status = 0xFF;
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 0);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_DATA_OUT:
scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT\n", id);
@@ -1314,7 +1646,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 0);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_DATA_IN:
scsi_hd_log("SCSI HD %i: PHASE_DATA_IN\n", id);
@@ -1327,7 +1659,7 @@ void scsi_hd_callback(uint8_t id)
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
shdc[id].status = READY_STAT;
shdc[id].phase = 3;
update_status_bar_icon((hdc[id].bus == 5) ? (0x20 | id) : 0x23, 0);
update_status_bar_icon((hdc[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
case CDROM_PHASE_ERROR:
scsi_hd_log("SCSI HD %i: PHASE_ERROR\n", id);