DISK: Add support for arbitrary sector sizes in all container formats
This commit is contained in:
parent
3c081a80c1
commit
aa380517fa
1 changed files with 232 additions and 287 deletions
519
sim_disk.c
519
sim_disk.c
|
@ -334,7 +334,6 @@ static FILE *sim_vhd_disk_merge (const char *szVHDPath, char **ParentVHD);
|
||||||
static int sim_vhd_disk_close (FILE *f);
|
static int sim_vhd_disk_close (FILE *f);
|
||||||
static void sim_vhd_disk_flush (FILE *f);
|
static void sim_vhd_disk_flush (FILE *f);
|
||||||
static t_offset sim_vhd_disk_size (FILE *f);
|
static t_offset sim_vhd_disk_size (FILE *f);
|
||||||
static t_stat sim_vhd_disk_info (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom);
|
|
||||||
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||||
static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
static t_stat sim_vhd_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
||||||
static t_stat sim_vhd_disk_clearerr (UNIT *uptr);
|
static t_stat sim_vhd_disk_clearerr (UNIT *uptr);
|
||||||
|
@ -644,6 +643,7 @@ t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread,
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||||
|
uint32 f = DK_GET_FMT (uptr);
|
||||||
t_seccnt sread = 0;
|
t_seccnt sread = 0;
|
||||||
|
|
||||||
sim_debug_unit (ctx->dbit, uptr, "sim_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr - ctx->dptr->units), lba, sects);
|
sim_debug_unit (ctx->dbit, uptr, "sim_disk_rdsect(unit=%d, lba=0x%X, sects=%d)\n", (int)(uptr - ctx->dptr->units), lba, sects);
|
||||||
|
@ -658,8 +658,9 @@ if ((sects == 1) && /* Single sector reads *
|
||||||
|
|
||||||
if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */
|
if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */
|
||||||
((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) &&
|
((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) &&
|
||||||
(0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1))))) {
|
(0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1)))) ||
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
(f == DKUF_F_STD) || (f == DKUF_F_VHD)) { /* or SIMH or VHD formats */
|
||||||
|
switch (f) { /* case on format */
|
||||||
case DKUF_F_STD: /* SIMH format */
|
case DKUF_F_STD: /* SIMH format */
|
||||||
r = _sim_disk_rdsect (uptr, lba, buf, &sread, sects);
|
r = _sim_disk_rdsect (uptr, lba, buf, &sread, sects);
|
||||||
break;
|
break;
|
||||||
|
@ -677,35 +678,22 @@ if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Al
|
||||||
sim_buf_swap_data (buf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size);
|
sim_buf_swap_data (buf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
else { /* Unaligned and/or partial sector transfers */
|
else { /* Unaligned and/or partial sector transfers in RAW mode */
|
||||||
uint8 *tbuf = (uint8*) malloc (sects * ctx->sector_size + 2 * ctx->storage_sector_size);
|
size_t tbufsize = sects * ctx->sector_size + 2 * ctx->storage_sector_size;
|
||||||
t_lba sspsts = ctx->storage_sector_size / ctx->sector_size; /* sim sectors in a storage sector */
|
uint8 *tbuf = (uint8*) malloc (tbufsize);
|
||||||
t_lba tlba = lba & ~(sspsts - 1);
|
t_offset ssaddr = (lba * (t_offset)ctx->sector_size) & ~(t_offset)(ctx->storage_sector_size -1);
|
||||||
t_seccnt tsects = sects + (lba - tlba);
|
uint32 soffset = (uint32)((lba * (t_offset)ctx->sector_size) - ssaddr);
|
||||||
|
uint32 bytesread;
|
||||||
|
|
||||||
tsects = (tsects + (sspsts - 1)) & ~(sspsts - 1);
|
|
||||||
if (sectsread)
|
if (sectsread)
|
||||||
*sectsread = 0;
|
*sectsread = 0;
|
||||||
if (tbuf == NULL)
|
if (tbuf == NULL)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
r = sim_os_disk_read (uptr, ssaddr, tbuf, &bytesread, tbufsize & ~(ctx->storage_sector_size - 1));
|
||||||
case DKUF_F_STD: /* SIMH format */
|
sim_buf_swap_data (tbuf + soffset, ctx->xfer_element_size, (bytesread - soffset) / ctx->xfer_element_size);
|
||||||
r = _sim_disk_rdsect (uptr, tlba, tbuf, &sread, tsects);
|
memcpy (buf, tbuf + soffset, sects * ctx->sector_size);
|
||||||
break;
|
|
||||||
case DKUF_F_VHD: /* VHD format */
|
|
||||||
r = sim_vhd_disk_rdsect (uptr, tlba, tbuf, &sread, tsects);
|
|
||||||
break;
|
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
|
||||||
r = sim_os_disk_rdsect (uptr, tlba, tbuf, &sread, tsects);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
free (tbuf);
|
|
||||||
return SCPE_NOFNC;
|
|
||||||
}
|
|
||||||
sim_buf_swap_data (tbuf, ctx->xfer_element_size, (sread * ctx->sector_size) / ctx->xfer_element_size);
|
|
||||||
memcpy (buf, tbuf + ((lba - tlba) * ctx->sector_size), sects * ctx->sector_size);
|
|
||||||
if (sectsread) {
|
if (sectsread) {
|
||||||
*sectsread = sread - (lba - tlba);
|
*sectsread = (bytesread - soffset) / ctx->sector_size;
|
||||||
if (*sectsread > sects)
|
if (*sectsread > sects)
|
||||||
*sectsread = sects;
|
*sectsread = sects;
|
||||||
}
|
}
|
||||||
|
@ -788,96 +776,60 @@ if (uptr->dynflags & UNIT_DISK_CHK) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (f == DKUF_F_STD)
|
switch (f) { /* case on format */
|
||||||
return _sim_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
case DKUF_F_STD: /* SIMH format */
|
||||||
|
return _sim_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
||||||
|
case DKUF_F_VHD: /* VHD format */
|
||||||
|
if (!sim_end && (ctx->xfer_element_size != sizeof (char))) {
|
||||||
|
tbuf = (uint8*) malloc (sects * ctx->sector_size);
|
||||||
|
if (NULL == tbuf)
|
||||||
|
return SCPE_MEM;
|
||||||
|
sim_buf_copy_swapped (tbuf, buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size);
|
||||||
|
buf = tbuf;
|
||||||
|
}
|
||||||
|
r = sim_vhd_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
||||||
|
free (tbuf);
|
||||||
|
return r;
|
||||||
|
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
||||||
|
break; /* handle below */
|
||||||
|
default:
|
||||||
|
return SCPE_NOFNC;
|
||||||
|
}
|
||||||
if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */
|
if ((0 == (ctx->sector_size & (ctx->storage_sector_size - 1))) || /* Sector Aligned & whole sector transfers */
|
||||||
((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) &&
|
((0 == ((lba*ctx->sector_size) & (ctx->storage_sector_size - 1))) &&
|
||||||
(0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1))))) {
|
(0 == ((sects*ctx->sector_size) & (ctx->storage_sector_size - 1))))) {
|
||||||
|
|
||||||
if (sim_end || (ctx->xfer_element_size == sizeof (char)))
|
if (!sim_end && (ctx->xfer_element_size != sizeof (char))) {
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
tbuf = (uint8*) malloc (sects * ctx->sector_size);
|
||||||
case DKUF_F_VHD: /* VHD format */
|
if (NULL == tbuf)
|
||||||
return sim_vhd_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
return SCPE_MEM;
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
sim_buf_copy_swapped (tbuf, buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size);
|
||||||
return sim_os_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
buf = tbuf;
|
||||||
default:
|
|
||||||
return SCPE_NOFNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbuf = (uint8*) malloc (sects * ctx->sector_size);
|
|
||||||
if (NULL == tbuf)
|
|
||||||
return SCPE_MEM;
|
|
||||||
sim_buf_copy_swapped (tbuf, buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size);
|
|
||||||
|
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
|
||||||
case DKUF_F_VHD: /* VHD format */
|
|
||||||
r = sim_vhd_disk_wrsect (uptr, lba, tbuf, sectswritten, sects);
|
|
||||||
break;
|
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
|
||||||
r = sim_os_disk_wrsect (uptr, lba, tbuf, sectswritten, sects);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = SCPE_NOFNC;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else { /* Unaligned and/or partial sector transfers */
|
|
||||||
t_lba sspsts = ctx->storage_sector_size/ctx->sector_size; /* sim sectors in a storage sector */
|
|
||||||
t_lba tlba = lba & ~(sspsts - 1);
|
|
||||||
t_seccnt tsects = sects + (lba - tlba);
|
|
||||||
|
|
||||||
tbuf = (uint8*) malloc (sects*ctx->sector_size + 2*ctx->storage_sector_size);
|
r = sim_os_disk_wrsect (uptr, lba, buf, sectswritten, sects);
|
||||||
tsects = (tsects + (sspsts - 1)) & ~(sspsts - 1);
|
}
|
||||||
|
else { /* Unaligned and/or partial sector transfers in RAW mode */
|
||||||
|
size_t tbufsize = sects * ctx->sector_size + 2 * ctx->storage_sector_size;
|
||||||
|
t_offset ssaddr = (lba * (t_offset)ctx->sector_size) & ~(t_offset)(ctx->storage_sector_size -1);
|
||||||
|
t_offset sladdr = ((lba + sects) * (t_offset)ctx->sector_size) & ~(t_offset)(ctx->storage_sector_size -1);
|
||||||
|
uint32 soffset = (uint32)((lba * (t_offset)ctx->sector_size) - ssaddr);
|
||||||
|
uint32 byteswritten;
|
||||||
|
|
||||||
|
tbuf = (uint8*) malloc (tbufsize);
|
||||||
if (sectswritten)
|
if (sectswritten)
|
||||||
*sectswritten = 0;
|
*sectswritten = 0;
|
||||||
if (tbuf == NULL)
|
if (tbuf == NULL)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
/* Partial Sector writes require a read-modify-write sequence for the partial sectors */
|
/* Partial Sector writes require a read-modify-write sequence for the partial sectors */
|
||||||
if ((lba & (sspsts - 1)) ||
|
if (soffset)
|
||||||
(sects < sspsts))
|
sim_os_disk_read (uptr, ssaddr, tbuf, NULL, ctx->storage_sector_size);
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
sim_os_disk_read (uptr, sladdr, tbuf + (size_t)(sladdr - ssaddr), NULL, ctx->storage_sector_size);
|
||||||
case DKUF_F_VHD: /* VHD format */
|
sim_buf_copy_swapped (tbuf + soffset,
|
||||||
sim_vhd_disk_rdsect (uptr, tlba, tbuf, NULL, sspsts);
|
|
||||||
break;
|
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
|
||||||
sim_os_disk_rdsect (uptr, tlba, tbuf, NULL, sspsts);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = SCPE_NOFNC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((tsects > sspsts) &&
|
|
||||||
((sects + lba - tlba) & (sspsts - 1)))
|
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
|
||||||
case DKUF_F_VHD: /* VHD format */
|
|
||||||
sim_vhd_disk_rdsect (uptr, tlba + tsects - sspsts,
|
|
||||||
tbuf + (tsects - sspsts) * ctx->sector_size,
|
|
||||||
NULL, sspsts);
|
|
||||||
break;
|
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
|
||||||
sim_os_disk_rdsect (uptr, tlba + tsects - sspsts,
|
|
||||||
tbuf + (tsects - sspsts) * ctx->sector_size,
|
|
||||||
NULL, sspsts);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = SCPE_NOFNC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sim_buf_copy_swapped (tbuf + (lba & (sspsts - 1)) * ctx->sector_size,
|
|
||||||
buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size);
|
buf, ctx->xfer_element_size, (sects * ctx->sector_size) / ctx->xfer_element_size);
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
r = sim_os_disk_write (uptr, ssaddr, tbuf, &byteswritten, (soffset + (sects * ctx->sector_size) + ctx->storage_sector_size - 1) & ~(ctx->storage_sector_size - 1));
|
||||||
case DKUF_F_VHD: /* VHD format */
|
if (sectswritten) {
|
||||||
r = sim_vhd_disk_wrsect (uptr, tlba, tbuf, sectswritten, tsects);
|
*sectswritten = byteswritten / ctx->sector_size;
|
||||||
break;
|
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
|
||||||
r = sim_os_disk_wrsect (uptr, tlba, tbuf, sectswritten, tsects);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = SCPE_NOFNC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((r == SCPE_OK) && sectswritten) {
|
|
||||||
*sectswritten -= (lba - tlba);
|
|
||||||
if (*sectswritten > sects)
|
if (*sectswritten > sects)
|
||||||
*sectswritten = sects;
|
*sectswritten = sects;
|
||||||
}
|
}
|
||||||
|
@ -2238,7 +2190,7 @@ t_stat (*storage_function)(FILE *file, uint32 *sector_size, uint32 *removable, u
|
||||||
t_bool created = FALSE, copied = FALSE;
|
t_bool created = FALSE, copied = FALSE;
|
||||||
t_bool auto_format = FALSE;
|
t_bool auto_format = FALSE;
|
||||||
t_offset container_size, filesystem_size, current_unit_size;
|
t_offset container_size, filesystem_size, current_unit_size;
|
||||||
size_t size_tmp;
|
size_t tmp_size = 1;
|
||||||
|
|
||||||
if (uptr->flags & UNIT_DIS) /* disabled? */
|
if (uptr->flags & UNIT_DIS) /* disabled? */
|
||||||
return SCPE_UDIS;
|
return SCPE_UDIS;
|
||||||
|
@ -2252,11 +2204,8 @@ switch (xfer_element_size) {
|
||||||
case 1: case 2: case 4: case 8:
|
case 1: case 2: case 4: case 8:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size_tmp = 64;
|
if ((sector_size % xfer_element_size) != 0)
|
||||||
while ((size_tmp != sector_size) && (size_tmp < 4096))
|
return sim_messagef (SCPE_ARG, "Invalid sector size: %u - must be a multiple of the transfer element size %u\n", (uint32)sector_size, (uint32)xfer_element_size);
|
||||||
size_tmp = size_tmp << 1;
|
|
||||||
if (sector_size != size_tmp)
|
|
||||||
return sim_messagef (SCPE_ARG, "Invalid sector size: %u - must be a power of 2 between 64 and 4096\n", (uint32)sector_size);
|
|
||||||
if (sim_switches & SWMASK ('F')) { /* format spec? */
|
if (sim_switches & SWMASK ('F')) { /* format spec? */
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
|
||||||
|
@ -2464,17 +2413,20 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
uptr->fileref = NULL;
|
uptr->fileref = NULL;
|
||||||
open_function = sim_vhd_disk_open;
|
open_function = sim_vhd_disk_open;
|
||||||
size_function = sim_vhd_disk_size;
|
size_function = sim_vhd_disk_size;
|
||||||
storage_function = sim_vhd_disk_info;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (NULL != (uptr->fileref = sim_os_disk_open_raw (cptr, "rb"))) {
|
while (tmp_size < sector_size)
|
||||||
sim_disk_set_fmt (uptr, 0, "RAW", NULL); /* set file format to RAW */
|
tmp_size <<= 1;
|
||||||
sim_os_disk_close_raw (uptr->fileref); /* close raw file*/
|
if (tmp_size == sector_size) { /* Power of 2 sector size can do RAW */
|
||||||
open_function = sim_os_disk_open_raw;
|
if (NULL != (uptr->fileref = sim_os_disk_open_raw (cptr, "rb"))) {
|
||||||
size_function = sim_os_disk_size_raw;
|
sim_disk_set_fmt (uptr, 0, "RAW", NULL); /* set file format to RAW */
|
||||||
storage_function = sim_os_disk_info_raw;
|
sim_os_disk_close_raw (uptr->fileref); /* close raw file*/
|
||||||
uptr->fileref = NULL;
|
open_function = sim_os_disk_open_raw;
|
||||||
break;
|
size_function = sim_os_disk_size_raw;
|
||||||
|
storage_function = sim_os_disk_info_raw;
|
||||||
|
uptr->fileref = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sim_disk_set_fmt (uptr, 0, "SIMH", NULL); /* set file format to SIMH */
|
sim_disk_set_fmt (uptr, 0, "SIMH", NULL); /* set file format to SIMH */
|
||||||
open_function = sim_fopen;
|
open_function = sim_fopen;
|
||||||
|
@ -2487,7 +2439,6 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
uptr->fileref = NULL;
|
uptr->fileref = NULL;
|
||||||
open_function = sim_vhd_disk_open;
|
open_function = sim_vhd_disk_open;
|
||||||
size_function = sim_vhd_disk_size;
|
size_function = sim_vhd_disk_size;
|
||||||
storage_function = sim_vhd_disk_info;
|
|
||||||
auto_format = TRUE;
|
auto_format = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2507,7 +2458,6 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
uptr->fileref = NULL;
|
uptr->fileref = NULL;
|
||||||
open_function = sim_vhd_disk_open;
|
open_function = sim_vhd_disk_open;
|
||||||
size_function = sim_vhd_disk_size;
|
size_function = sim_vhd_disk_size;
|
||||||
storage_function = sim_vhd_disk_info;
|
|
||||||
auto_format = TRUE;
|
auto_format = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4111,11 +4061,6 @@ static t_offset sim_vhd_disk_size (FILE *f)
|
||||||
return (t_offset)-1;
|
return (t_offset)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_vhd_disk_info (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom)
|
|
||||||
{
|
|
||||||
return SCPE_NOFNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
|
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
|
||||||
{
|
{
|
||||||
return SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
|
@ -5074,17 +5019,6 @@ VHDHANDLE hVHD = (VHDHANDLE)f;
|
||||||
return (t_offset)(NtoHll (hVHD->Footer.CurrentSize));
|
return (t_offset)(NtoHll (hVHD->Footer.CurrentSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_vhd_disk_info (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom)
|
|
||||||
{
|
|
||||||
if (sector_size)
|
|
||||||
*sector_size = 512;
|
|
||||||
if (removable)
|
|
||||||
*removable = FALSE;
|
|
||||||
if (is_cdrom)
|
|
||||||
*is_cdrom = FALSE;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -5599,6 +5533,83 @@ static FILE *sim_vhd_disk_create_diff (const char *szVHDPath, const char *szPare
|
||||||
return (FILE *)CreateDifferencingVirtualDisk (szVHDPath, szParentVHDPath);
|
return (FILE *)CreateDifferencingVirtualDisk (szVHDPath, szParentVHDPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_stat
|
||||||
|
ReadVirtualDisk(VHDHANDLE hVHD,
|
||||||
|
uint8 *buf,
|
||||||
|
uint32 BytesToRead,
|
||||||
|
uint32 *BytesRead,
|
||||||
|
uint64 Offset)
|
||||||
|
{
|
||||||
|
uint32 TotalBytesRead = 0;
|
||||||
|
uint32 BitMapBytes;
|
||||||
|
uint32 BitMapSectors;
|
||||||
|
t_stat r = SCPE_OK;
|
||||||
|
|
||||||
|
if (BytesRead)
|
||||||
|
*BytesRead = 0;
|
||||||
|
if (!hVHD || (hVHD->File == NULL)) {
|
||||||
|
errno = EBADF;
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
||||||
|
if (BytesToRead == 0)
|
||||||
|
return SCPE_OK;
|
||||||
|
if (Offset >= (uint64)NtoHll (hVHD->Footer.CurrentSize)) {
|
||||||
|
errno = ERANGE;
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
||||||
|
if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
||||||
|
if (ReadFilePosition(hVHD->File,
|
||||||
|
buf,
|
||||||
|
BytesToRead,
|
||||||
|
BytesRead,
|
||||||
|
Offset))
|
||||||
|
r = SCPE_IOERR;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
/* We are now dealing with a Dynamically expanding or differencing disk */
|
||||||
|
BitMapBytes = (7+(NtoHl (hVHD->Dynamic.BlockSize)/VHD_Internal_SectorSize))/8;
|
||||||
|
BitMapSectors = (BitMapBytes+VHD_Internal_SectorSize-1)/VHD_Internal_SectorSize;
|
||||||
|
while (BytesToRead && (r == SCPE_OK)) {
|
||||||
|
uint32 BlockNumber = (uint32)(Offset / NtoHl (hVHD->Dynamic.BlockSize));
|
||||||
|
uint32 BytesInRead = BytesToRead;
|
||||||
|
uint32 BytesThisRead = 0;
|
||||||
|
|
||||||
|
if (BlockNumber != (Offset + BytesToRead) / NtoHl (hVHD->Dynamic.BlockSize))
|
||||||
|
BytesInRead = (uint32)(((BlockNumber + 1) * NtoHl (hVHD->Dynamic.BlockSize)) - Offset);
|
||||||
|
if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) {
|
||||||
|
if (!hVHD->Parent) {
|
||||||
|
memset (buf, 0, BytesInRead);
|
||||||
|
BytesThisRead = BytesInRead;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ReadVirtualDisk(hVHD->Parent,
|
||||||
|
buf,
|
||||||
|
BytesInRead,
|
||||||
|
&BytesThisRead,
|
||||||
|
Offset))
|
||||||
|
r = SCPE_IOERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64 BlockOffset = VHD_Internal_SectorSize * ((uint64)(NtoHl (hVHD->BAT[BlockNumber]) + BitMapSectors)) + (Offset % NtoHl (hVHD->Dynamic.BlockSize));
|
||||||
|
|
||||||
|
if (ReadFilePosition(hVHD->File,
|
||||||
|
buf,
|
||||||
|
BytesInRead,
|
||||||
|
&BytesThisRead,
|
||||||
|
BlockOffset))
|
||||||
|
r = SCPE_IOERR;
|
||||||
|
}
|
||||||
|
BytesToRead -= BytesThisRead;
|
||||||
|
buf = (uint8 *)(((char *)buf) + BytesThisRead);
|
||||||
|
Offset += BytesThisRead;
|
||||||
|
TotalBytesRead += BytesThisRead;
|
||||||
|
}
|
||||||
|
if (BytesRead)
|
||||||
|
*BytesRead = TotalBytesRead;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static t_stat
|
static t_stat
|
||||||
ReadVirtualDiskSectors(VHDHANDLE hVHD,
|
ReadVirtualDiskSectors(VHDHANDLE hVHD,
|
||||||
uint8 *buf,
|
uint8 *buf,
|
||||||
|
@ -5607,81 +5618,15 @@ ReadVirtualDiskSectors(VHDHANDLE hVHD,
|
||||||
uint32 SectorSize,
|
uint32 SectorSize,
|
||||||
t_lba lba)
|
t_lba lba)
|
||||||
{
|
{
|
||||||
uint64 BlockOffset = ((uint64)lba)*SectorSize;
|
uint32 BytesRead;
|
||||||
uint32 SectorsRead = 0;
|
t_stat r = ReadVirtualDisk(hVHD,
|
||||||
uint32 SectorsInRead;
|
buf,
|
||||||
size_t BytesRead = 0;
|
sects * SectorSize,
|
||||||
|
&BytesRead,
|
||||||
if (!hVHD || (hVHD->File == NULL)) {
|
SectorSize * (uint64)lba);
|
||||||
errno = EBADF;
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
if ((BlockOffset + sects*SectorSize) > (uint64)NtoHll (hVHD->Footer.CurrentSize)) {
|
|
||||||
errno = ERANGE;
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
if (sectsread)
|
if (sectsread)
|
||||||
*sectsread = 0;
|
*sectsread = BytesRead / SectorSize;
|
||||||
if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
return r;
|
||||||
if (ReadFilePosition(hVHD->File,
|
|
||||||
buf,
|
|
||||||
sects*SectorSize,
|
|
||||||
&BytesRead,
|
|
||||||
BlockOffset)) {
|
|
||||||
if (sectsread)
|
|
||||||
*sectsread = (t_seccnt)(BytesRead/SectorSize);
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
if (sectsread)
|
|
||||||
*sectsread = (t_seccnt)(BytesRead/SectorSize);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
/* We are now dealing with a Dynamically expanding or differencing disk */
|
|
||||||
while (sects) {
|
|
||||||
uint32 SectorsPerBlock = NtoHl (hVHD->Dynamic.BlockSize)/SectorSize;
|
|
||||||
uint64 BlockNumber = lba/SectorsPerBlock;
|
|
||||||
uint32 BitMapBytes = (7+(NtoHl (hVHD->Dynamic.BlockSize)/VHD_Internal_SectorSize))/8;
|
|
||||||
uint32 BitMapSectors = (BitMapBytes+VHD_Internal_SectorSize-1)/VHD_Internal_SectorSize;
|
|
||||||
|
|
||||||
SectorsInRead = SectorsPerBlock - lba%SectorsPerBlock;
|
|
||||||
if (SectorsInRead > sects)
|
|
||||||
SectorsInRead = sects;
|
|
||||||
if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) {
|
|
||||||
if (!hVHD->Parent)
|
|
||||||
memset (buf, 0, SectorSize*SectorsInRead);
|
|
||||||
else {
|
|
||||||
if (ReadVirtualDiskSectors(hVHD->Parent,
|
|
||||||
buf,
|
|
||||||
SectorsInRead,
|
|
||||||
NULL,
|
|
||||||
SectorSize,
|
|
||||||
lba)) {
|
|
||||||
if (sectsread)
|
|
||||||
*sectsread = SectorsRead;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
BlockOffset = VHD_Internal_SectorSize * ((uint64)(NtoHl (hVHD->BAT[BlockNumber]) + BitMapSectors))+ (SectorSize * (lba % SectorsPerBlock));
|
|
||||||
if (ReadFilePosition(hVHD->File,
|
|
||||||
buf,
|
|
||||||
SectorsInRead * SectorSize,
|
|
||||||
NULL,
|
|
||||||
BlockOffset)) {
|
|
||||||
if (sectsread)
|
|
||||||
*sectsread = SectorsRead;
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sects -= SectorsInRead;
|
|
||||||
buf = (uint8 *)(((char *)buf) + SectorSize * SectorsInRead);
|
|
||||||
lba += SectorsInRead;
|
|
||||||
SectorsRead += SectorsInRead;
|
|
||||||
}
|
|
||||||
if (sectsread)
|
|
||||||
*sectsread = SectorsRead;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
|
static t_stat sim_vhd_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects)
|
||||||
|
@ -5713,61 +5658,51 @@ return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat
|
static t_stat
|
||||||
WriteVirtualDiskSectors(VHDHANDLE hVHD,
|
WriteVirtualDisk(VHDHANDLE hVHD,
|
||||||
uint8 *buf,
|
uint8 *buf,
|
||||||
t_seccnt sects,
|
uint32 BytesToWrite,
|
||||||
t_seccnt *sectswritten,
|
uint32 *BytesWritten,
|
||||||
uint32 SectorSize,
|
uint64 Offset)
|
||||||
t_lba lba)
|
|
||||||
{
|
{
|
||||||
uint64 BlockOffset = ((uint64)lba)*SectorSize;
|
uint32 TotalBytesWritten = 0;
|
||||||
uint32 SectorsWritten = 0;
|
|
||||||
uint32 SectorsInWrite;
|
|
||||||
size_t BytesWritten = 0;
|
|
||||||
uint32 SectorsPerBlock;
|
|
||||||
uint64 BlockNumber;
|
|
||||||
uint32 BitMapBytes;
|
uint32 BitMapBytes;
|
||||||
uint32 BitMapSectors;
|
uint32 BitMapSectors;
|
||||||
t_stat r = SCPE_OK;
|
t_stat r = SCPE_OK;
|
||||||
|
|
||||||
|
if (BytesWritten)
|
||||||
|
*BytesWritten = 0;
|
||||||
if (!hVHD || !hVHD->File) {
|
if (!hVHD || !hVHD->File) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
}
|
}
|
||||||
if ((BlockOffset + sects * SectorSize) > (uint64)NtoHll(hVHD->Footer.CurrentSize)) {
|
if (BytesToWrite == 0)
|
||||||
sects = (t_seccnt)(((uint64)NtoHll(hVHD->Footer.CurrentSize) - BlockOffset) / SectorSize);
|
return SCPE_OK;
|
||||||
|
if (Offset >= (uint64)NtoHll(hVHD->Footer.CurrentSize)) {
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
r = SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
}
|
}
|
||||||
if (sectswritten)
|
|
||||||
*sectswritten = 0;
|
|
||||||
if (NtoHl(hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
if (NtoHl(hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
||||||
if (WriteFilePosition(hVHD->File,
|
if (WriteFilePosition(hVHD->File,
|
||||||
buf,
|
buf,
|
||||||
sects * SectorSize,
|
BytesToWrite,
|
||||||
&BytesWritten,
|
BytesWritten,
|
||||||
BlockOffset)) {
|
Offset))
|
||||||
if (sectswritten)
|
r = SCPE_IOERR;
|
||||||
*sectswritten = (t_seccnt)(BytesWritten / SectorSize);
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
if (sectswritten)
|
|
||||||
*sectswritten = (t_seccnt)(BytesWritten/SectorSize);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
/* We are now dealing with a Dynamically expanding or differencing disk */
|
/* We are now dealing with a Dynamically expanding or differencing disk */
|
||||||
SectorsPerBlock = NtoHl(hVHD->Dynamic.BlockSize) / SectorSize;
|
|
||||||
BitMapBytes = (7 + (NtoHl(hVHD->Dynamic.BlockSize) / VHD_Internal_SectorSize)) / 8;
|
BitMapBytes = (7 + (NtoHl(hVHD->Dynamic.BlockSize) / VHD_Internal_SectorSize)) / 8;
|
||||||
BitMapSectors = (BitMapBytes + VHD_Internal_SectorSize - 1) / VHD_Internal_SectorSize;
|
BitMapSectors = (BitMapBytes + VHD_Internal_SectorSize - 1) / VHD_Internal_SectorSize;
|
||||||
while (sects) {
|
while (BytesToWrite && (r == SCPE_OK)) {
|
||||||
BlockNumber = lba / SectorsPerBlock;
|
uint32 BlockNumber = (uint32)(Offset / NtoHl(hVHD->Dynamic.BlockSize));
|
||||||
|
uint32 BytesInWrite = BytesToWrite;
|
||||||
|
uint32 BytesThisWrite = 0;
|
||||||
|
|
||||||
if (BlockNumber >= NtoHl(hVHD->Dynamic.MaxTableEntries)) {
|
if (BlockNumber >= NtoHl(hVHD->Dynamic.MaxTableEntries)) {
|
||||||
if (sectswritten)
|
|
||||||
*sectswritten = SectorsWritten;
|
|
||||||
return SCPE_EOF;
|
return SCPE_EOF;
|
||||||
}
|
}
|
||||||
SectorsInWrite = 1;
|
if (BlockNumber != (Offset + BytesToWrite) / NtoHl (hVHD->Dynamic.BlockSize))
|
||||||
|
BytesInWrite = (uint32)(((BlockNumber + 1) * NtoHl(hVHD->Dynamic.BlockSize)) - Offset);
|
||||||
if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) {
|
if (hVHD->BAT[BlockNumber] == VHD_BAT_FREE_ENTRY) {
|
||||||
uint8 *BitMap = NULL;
|
uint8 *BitMap = NULL;
|
||||||
uint32 BitMapBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
|
uint32 BitMapBufferSize = VHD_DATA_BLOCK_ALIGNMENT;
|
||||||
|
@ -5776,16 +5711,19 @@ while (sects) {
|
||||||
uint8 *BATUpdateBufferAddress;
|
uint8 *BATUpdateBufferAddress;
|
||||||
uint32 BATUpdateBufferSize;
|
uint32 BATUpdateBufferSize;
|
||||||
uint64 BATUpdateStorageAddress;
|
uint64 BATUpdateStorageAddress;
|
||||||
|
uint64 BlockOffset;
|
||||||
|
|
||||||
if (!hVHD->Parent && BufferIsZeros(buf, SectorsInWrite * SectorSize))
|
if (!hVHD->Parent && BufferIsZeros(buf, BytesInWrite)) {
|
||||||
|
BytesThisWrite = BytesInWrite;
|
||||||
goto IO_Done;
|
goto IO_Done;
|
||||||
|
}
|
||||||
/* Need to allocate a new Data Block. */
|
/* Need to allocate a new Data Block. */
|
||||||
BlockOffset = sim_fsize_ex (hVHD->File);
|
BlockOffset = sim_fsize_ex (hVHD->File);
|
||||||
if (((int64)BlockOffset) == -1)
|
if (((int64)BlockOffset) == -1)
|
||||||
return SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
if (BitMapSectors*VHD_Internal_SectorSize > BitMapBufferSize)
|
if ((BitMapSectors * VHD_Internal_SectorSize) > BitMapBufferSize)
|
||||||
BitMapBufferSize = BitMapSectors * VHD_Internal_SectorSize;
|
BitMapBufferSize = BitMapSectors * VHD_Internal_SectorSize;
|
||||||
BitMapBuffer = (uint8 *)calloc(1, BitMapBufferSize + SectorSize * SectorsPerBlock);
|
BitMapBuffer = (uint8 *)calloc(1, BitMapBufferSize + NtoHl(hVHD->Dynamic.BlockSize));
|
||||||
if (BitMapBufferSize > BitMapSectors * VHD_Internal_SectorSize)
|
if (BitMapBufferSize > BitMapSectors * VHD_Internal_SectorSize)
|
||||||
BitMap = BitMapBuffer + BitMapBufferSize - BitMapBytes;
|
BitMap = BitMapBuffer + BitMapBufferSize - BitMapBytes;
|
||||||
else
|
else
|
||||||
|
@ -5796,7 +5734,7 @@ while (sects) {
|
||||||
{ // Already aligned, so use padded BitMapBuffer
|
{ // Already aligned, so use padded BitMapBuffer
|
||||||
if (WriteFilePosition(hVHD->File,
|
if (WriteFilePosition(hVHD->File,
|
||||||
BitMapBuffer,
|
BitMapBuffer,
|
||||||
BitMapBufferSize + SectorSize * SectorsPerBlock,
|
BitMapBufferSize + NtoHl(hVHD->Dynamic.BlockSize),
|
||||||
NULL,
|
NULL,
|
||||||
BlockOffset)) {
|
BlockOffset)) {
|
||||||
free (BitMapBuffer);
|
free (BitMapBuffer);
|
||||||
|
@ -5815,7 +5753,7 @@ while (sects) {
|
||||||
BlockOffset -= BitMapSectors * VHD_Internal_SectorSize;
|
BlockOffset -= BitMapSectors * VHD_Internal_SectorSize;
|
||||||
if (WriteFilePosition(hVHD->File,
|
if (WriteFilePosition(hVHD->File,
|
||||||
BitMap,
|
BitMap,
|
||||||
(BitMapSectors * VHD_Internal_SectorSize) + (SectorSize * SectorsPerBlock),
|
(BitMapSectors * VHD_Internal_SectorSize) + NtoHl(hVHD->Dynamic.BlockSize),
|
||||||
NULL,
|
NULL,
|
||||||
BlockOffset)) {
|
BlockOffset)) {
|
||||||
free (BitMapBuffer);
|
free (BitMapBuffer);
|
||||||
|
@ -5828,7 +5766,7 @@ while (sects) {
|
||||||
/* the BAT block address is the beginning of the block bitmap */
|
/* the BAT block address is the beginning of the block bitmap */
|
||||||
BlockOffset -= BitMapSectors * VHD_Internal_SectorSize;
|
BlockOffset -= BitMapSectors * VHD_Internal_SectorSize;
|
||||||
hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset / VHD_Internal_SectorSize));
|
hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset / VHD_Internal_SectorSize));
|
||||||
BlockOffset += (BitMapSectors * VHD_Internal_SectorSize) + (SectorSize * SectorsPerBlock);
|
BlockOffset += (BitMapSectors * VHD_Internal_SectorSize) + NtoHl(hVHD->Dynamic.BlockSize);
|
||||||
if (WriteFilePosition(hVHD->File,
|
if (WriteFilePosition(hVHD->File,
|
||||||
&hVHD->Footer,
|
&hVHD->Footer,
|
||||||
sizeof(hVHD->Footer),
|
sizeof(hVHD->Footer),
|
||||||
|
@ -5862,25 +5800,19 @@ while (sects) {
|
||||||
goto Fatal_IO_Error;
|
goto Fatal_IO_Error;
|
||||||
if (hVHD->Parent)
|
if (hVHD->Parent)
|
||||||
{ /* Need to populate data block contents from parent VHD */
|
{ /* Need to populate data block contents from parent VHD */
|
||||||
uint32 BlockSectors = SectorsPerBlock;
|
BlockData = malloc (NtoHl (hVHD->Dynamic.BlockSize));
|
||||||
|
|
||||||
BlockData = malloc(SectorsPerBlock * SectorSize);
|
if (ReadVirtualDisk(hVHD->Parent,
|
||||||
|
(uint8*) BlockData,
|
||||||
if (((lba / SectorsPerBlock) * SectorsPerBlock + BlockSectors) > ((uint64)NtoHll (hVHD->Footer.CurrentSize)) / SectorSize)
|
NtoHl (hVHD->Dynamic.BlockSize),
|
||||||
BlockSectors = (uint32)(((uint64)NtoHll (hVHD->Footer.CurrentSize)) / SectorSize - (lba / SectorsPerBlock) * SectorsPerBlock);
|
NULL,
|
||||||
if (ReadVirtualDiskSectors(hVHD->Parent,
|
(Offset / NtoHl (hVHD->Dynamic.BlockSize)) * NtoHl (hVHD->Dynamic.BlockSize)))
|
||||||
(uint8*) BlockData,
|
|
||||||
BlockSectors,
|
|
||||||
NULL,
|
|
||||||
SectorSize,
|
|
||||||
(lba / SectorsPerBlock) * SectorsPerBlock))
|
|
||||||
goto Fatal_IO_Error;
|
goto Fatal_IO_Error;
|
||||||
if (WriteVirtualDiskSectors(hVHD,
|
if (WriteVirtualDisk(hVHD,
|
||||||
(uint8*) BlockData,
|
(uint8*) BlockData,
|
||||||
BlockSectors,
|
NtoHl (hVHD->Dynamic.BlockSize),
|
||||||
NULL,
|
NULL,
|
||||||
SectorSize,
|
(Offset / NtoHl (hVHD->Dynamic.BlockSize)) * NtoHl (hVHD->Dynamic.BlockSize)))
|
||||||
(lba / SectorsPerBlock) * SectorsPerBlock))
|
|
||||||
goto Fatal_IO_Error;
|
goto Fatal_IO_Error;
|
||||||
free(BlockData);
|
free(BlockData);
|
||||||
}
|
}
|
||||||
|
@ -5888,33 +5820,46 @@ while (sects) {
|
||||||
Fatal_IO_Error:
|
Fatal_IO_Error:
|
||||||
free (BitMap);
|
free (BitMap);
|
||||||
free (BlockData);
|
free (BlockData);
|
||||||
fclose (hVHD->File);
|
r = SCPE_IOERR;
|
||||||
hVHD->File = NULL;
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BlockOffset = VHD_Internal_SectorSize * ((uint64)(NtoHl(hVHD->BAT[BlockNumber]) + BitMapSectors)) + (SectorSize * (lba % SectorsPerBlock));
|
uint64 BlockOffset = VHD_Internal_SectorSize * ((uint64)(NtoHl(hVHD->BAT[BlockNumber]) + BitMapSectors)) + (Offset % NtoHl(hVHD->Dynamic.BlockSize));
|
||||||
SectorsInWrite = SectorsPerBlock - lba % SectorsPerBlock;
|
|
||||||
if (SectorsInWrite > sects)
|
|
||||||
SectorsInWrite = sects;
|
|
||||||
if (WriteFilePosition(hVHD->File,
|
if (WriteFilePosition(hVHD->File,
|
||||||
buf,
|
buf,
|
||||||
SectorsInWrite * SectorSize,
|
BytesInWrite,
|
||||||
&BytesWritten,
|
&BytesThisWrite,
|
||||||
BlockOffset)) {
|
BlockOffset))
|
||||||
if (sectswritten)
|
r = SCPE_IOERR;
|
||||||
*sectswritten = SectorsWritten + BytesWritten / SectorSize;
|
|
||||||
return SCPE_IOERR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
IO_Done:
|
IO_Done:
|
||||||
sects -= SectorsInWrite;
|
BytesToWrite -= BytesThisWrite;
|
||||||
buf = (uint8 *)(((char *)buf) + SectorsInWrite * SectorSize);
|
buf = (uint8 *)(((char *)buf) + BytesThisWrite);
|
||||||
lba += SectorsInWrite;
|
Offset += BytesThisWrite;
|
||||||
SectorsWritten += SectorsInWrite;
|
TotalBytesWritten += BytesThisWrite;
|
||||||
}
|
}
|
||||||
|
if (BytesWritten)
|
||||||
|
*BytesWritten = TotalBytesWritten;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static t_stat
|
||||||
|
WriteVirtualDiskSectors(VHDHANDLE hVHD,
|
||||||
|
uint8 *buf,
|
||||||
|
t_seccnt sects,
|
||||||
|
t_seccnt *sectswritten,
|
||||||
|
uint32 SectorSize,
|
||||||
|
t_lba lba)
|
||||||
|
{
|
||||||
|
uint32 BytesWritten;
|
||||||
|
t_stat r = WriteVirtualDisk(hVHD,
|
||||||
|
buf,
|
||||||
|
sects * SectorSize,
|
||||||
|
&BytesWritten,
|
||||||
|
SectorSize * (uint64)lba);
|
||||||
|
|
||||||
if (sectswritten)
|
if (sectswritten)
|
||||||
*sectswritten = SectorsWritten;
|
*sectswritten = BytesWritten / SectorSize;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6052,8 +5997,8 @@ return r;
|
||||||
|
|
||||||
t_stat sim_disk_test (DEVICE *dptr)
|
t_stat sim_disk_test (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
const char *fmt[] = {"VHD", "VHD", "SIMH", "RAW", NULL};
|
const char *fmt[] = {"RAW", "VHD", "VHD", "SIMH", NULL};
|
||||||
uint32 sect_size[] = {4096, 1024, 512, 256, 128, 64, 0};
|
uint32 sect_size[] = {576, 4096, 1024, 512, 256, 128, 64, 0};
|
||||||
uint32 xfr_size[] = {1, 2, 4, 8, 0};
|
uint32 xfr_size[] = {1, 2, 4, 8, 0};
|
||||||
int x, s, f;
|
int x, s, f;
|
||||||
UNIT *uptr = &dptr->units[0];
|
UNIT *uptr = &dptr->units[0];
|
||||||
|
|
Loading…
Add table
Reference in a new issue