diff --git a/scp.c b/scp.c index f71ec3d..916f893 100644 --- a/scp.c +++ b/scp.c @@ -1546,7 +1546,10 @@ static const char simh_help1[] = "+SET DISABLED disable unit\n" "+SET arg{,arg...} set unit parameters (see show modifiers)\n" "+HELP SET displays the device specific set commands\n" - "++++++++ available\n"; + "++++++++ available\n" +#define HLP_NOAUTOSIZE "*Commands SET NoAutosize" + "3NoAutosize\n" + "+SET NOAUTOSIZE disables disk autosizing for all disks\n"; static const char simh_help2[] = /***************** 80 character line width template *************************/ #define HLP_SHOW "*Commands SHOW" @@ -2597,6 +2600,7 @@ static CTAB set_glob_tab[] = { { "PROMPT", &set_prompt, 0, HLP_SET_PROMPT }, { "RUNLIMIT", &set_runlimit, 1, HLP_RUNLIMIT }, { "NORUNLIMIT", &set_runlimit, 0, HLP_RUNLIMIT }, + { "NOAUTOSIZE", &sim_disk_set_noautosize, 1, HLP_NOAUTOSIZE }, { NULL, NULL, 0 } }; @@ -5821,37 +5825,43 @@ if ((dptr = find_dev (gbuf))) { /* device match? */ lvl = MTAB_VDV; /* device match */ GET_SWITCHES (cptr); /* get more switches */ } -else if ((dptr = find_unit (gbuf, &uptr))) { /* unit match? */ - if (uptr == NULL) /* invalid unit */ - return SCPE_NXUN; - ctbr = set_unit_tab; /* global table */ - lvl = MTAB_VUN; /* unit match */ - GET_SWITCHES (cptr); /* get more switches */ - } -else if ((gcmdp = find_ctab (set_glob_tab, gbuf))) { /* global? */ - GET_SWITCHES (cptr); /* get more switches */ - return gcmdp->action (gcmdp->arg, cptr); /* do the rest */ - } else { - if (sim_dflt_dev->modifiers) { - if ((cvptr = strchr (gbuf, '='))) /* = value? */ - *cvptr++ = 0; - for (mptr = sim_dflt_dev->modifiers; mptr->mask != 0; mptr++) { - if (mptr->mstring && (MATCH_CMD (gbuf, mptr->mstring) == 0)) { - dptr = sim_dflt_dev; - cptr = svptr; - while (sim_isspace(*cptr)) - ++cptr; - break; + if ((dptr = find_unit (gbuf, &uptr))) { /* unit match? */ + if (uptr == NULL) /* invalid unit */ + return SCPE_NXUN; + ctbr = set_unit_tab; /* global table */ + lvl = MTAB_VUN; /* unit match */ + GET_SWITCHES (cptr); /* get more switches */ + } + else { + if ((gcmdp = find_ctab (set_glob_tab, gbuf))) { /* global? */ + GET_SWITCHES (cptr); /* get more switches */ + return gcmdp->action (gcmdp->arg, cptr); /* do the rest */ + } + else { + if (sim_dflt_dev->modifiers) { + if ((cvptr = strchr (gbuf, '='))) /* = value? */ + *cvptr++ = 0; + for (mptr = sim_dflt_dev->modifiers; mptr->mask != 0; mptr++) { + if (mptr->mstring && (MATCH_CMD (gbuf, mptr->mstring) == 0)) { + dptr = sim_dflt_dev; + cptr = svptr; + while (sim_isspace(*cptr)) + ++cptr; + break; + } + } } + if (!dptr) + return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */ + lvl = MTAB_VDV; /* device match */ + uptr = dptr->units; /* first unit */ } } - if (!dptr) - return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */ - lvl = MTAB_VDV; /* device match */ - uptr = dptr->units; /* first unit */ } -if ((*cptr == 0) || (*cptr == ';') || (*cptr == '#')) /* must be more */ +if ((*cptr == 0) || /* must be more */ + (*cptr == ';') || + (*cptr == '#')) return SCPE_2FARG; GET_SWITCHES (cptr); /* get more switches */ @@ -6121,42 +6131,46 @@ if ((dptr = find_dev (gbuf))) { /* device match? */ lvl = MTAB_VDV; /* device match */ GET_SWITCHES (cptr); /* get more switches */ } -else if ((dptr = find_unit (gbuf, &uptr))) { /* unit match? */ - if (uptr == NULL) /* invalid unit */ - return sim_messagef (SCPE_NXUN, "Non-existent unit: %s\n", gbuf); - if (uptr->flags & UNIT_DIS) /* disabled? */ - return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", gbuf); - shtb = show_unit_tab; /* global table */ - lvl = MTAB_VUN; /* unit match */ - GET_SWITCHES (cptr); /* get more switches */ - } -else if ((shptr = find_shtab (show_glob_tab, gbuf))) { /* global? */ - GET_SWITCHES (cptr); /* get more switches */ - return shptr->action (ofile, NULL, NULL, shptr->arg, cptr); - } else { - if (sim_dflt_dev->modifiers) { - if ((cvptr = strchr (gbuf, '='))) /* = value? */ - *cvptr++ = 0; - for (mptr = sim_dflt_dev->modifiers; mptr && (mptr->mask != 0); mptr++) { - if ((((mptr->mask & MTAB_VDV) == MTAB_VDV) && - (mptr->pstring && (MATCH_CMD (gbuf, mptr->pstring) == 0))) || - (!(mptr->mask & MTAB_VDV) && (mptr->mstring && (MATCH_CMD (gbuf, mptr->mstring) == 0)))) { - dptr = sim_dflt_dev; - lvl = MTAB_VDV; /* device match */ - cptr = svptr; - while (sim_isspace(*cptr)) - ++cptr; - break; + if ((dptr = find_unit (gbuf, &uptr))) { /* unit match? */ + if (uptr == NULL) /* invalid unit */ + return sim_messagef (SCPE_NXUN, "Non-existent unit: %s\n", gbuf); + if (uptr->flags & UNIT_DIS) /* disabled? */ + return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", gbuf); + shtb = show_unit_tab; /* global table */ + lvl = MTAB_VUN; /* unit match */ + GET_SWITCHES (cptr); /* get more switches */ + } + else { + if ((shptr = find_shtab (show_glob_tab, gbuf))) {/* global? */ + GET_SWITCHES (cptr); /* get more switches */ + return shptr->action (ofile, NULL, NULL, shptr->arg, cptr); + } + else { + if (sim_dflt_dev->modifiers) { + if ((cvptr = strchr (gbuf, '='))) /* = value? */ + *cvptr++ = 0; + for (mptr = sim_dflt_dev->modifiers; mptr && (mptr->mask != 0); mptr++) { + if ((((mptr->mask & MTAB_VDV) == MTAB_VDV) && + (mptr->pstring && (MATCH_CMD (gbuf, mptr->pstring) == 0))) || + (!(mptr->mask & MTAB_VDV) && (mptr->mstring && (MATCH_CMD (gbuf, mptr->mstring) == 0)))) { + dptr = sim_dflt_dev; + lvl = MTAB_VDV; /* device match */ + cptr = svptr; + while (sim_isspace(*cptr)) + ++cptr; + break; + } + } + } + if (!dptr) { + if ((shptr = find_shtab (show_dev_tab, gbuf))) /* global match? */ + return shptr->action (ofile, sim_dflt_dev, uptr, shptr->arg, cptr); + else + return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */ } } } - if (!dptr) { - if ((shptr = find_shtab (show_dev_tab, gbuf))) /* global match? */ - return shptr->action (ofile, sim_dflt_dev, uptr, shptr->arg, cptr); - else - return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */ - } } if ((*cptr == 0) || (*cptr == ';') || (*cptr == '#')) { /* now eol? */ @@ -6215,8 +6229,9 @@ return NULL; /* Show device and unit */ static size_t dev_name_len; +static size_t unit_name_len; -const char *_sim_name_prefix (const char *name, const char *prefix) +const char *_sim_name_prefix (const char *name, const char *prefix, size_t max_name_len) { static char nambuf[CBUFSIZE]; size_t prefix_len = prefix ? strlen (prefix) : 0; @@ -6224,20 +6239,20 @@ size_t name_len = name ? strlen (name) : 0; size_t string_len = prefix_len + name_len; snprintf (nambuf, sizeof (nambuf), "%s%*s", prefix ? prefix : "", - ((string_len <= 6) && (dev_name_len <= 6)) ? -((int)(8 - prefix_len)) : - -((int)(dev_name_len + 2)), - name ? name : ""); + ((string_len <= 6) && (max_name_len <= 6)) ? -((int)(8 - prefix_len)) : + -((int)(max_name_len + 2)), + name ? name : ""); return nambuf; } const char *_sim_dname_prefix (DEVICE *dptr, const char *prefix) { -return _sim_name_prefix (sim_dname (dptr), prefix); +return _sim_name_prefix (sim_dname (dptr), prefix, dev_name_len); } const char *_sim_uname_prefix (UNIT *uptr, const char *prefix) { -return _sim_name_prefix (sim_uname (uptr), prefix); +return _sim_name_prefix (sim_uname (uptr), prefix, unit_name_len); } const char *_sim_dname (DEVICE *dptr) @@ -6255,12 +6270,32 @@ const char *_sim_dname_space (void) return _sim_dname_prefix (NULL, ""); } +void _set_dname_len (DEVICE *dptr) +{ +uint32 i; + +if (dev_name_len < strlen (dptr->name)) + dev_name_len = strlen (dptr->name); +for (i = 0; i < dptr->numunits; i++) { + UNIT *uptr = &dptr->units[i]; + + if (((uptr->flags & UNIT_DIS) == 0) && + (unit_name_len < strlen (sim_uname (uptr)))) + unit_name_len = strlen (sim_uname (uptr)); + } +} + t_stat show_device (FILE *st, DEVICE *dptr, int32 flag) { uint32 j, udbl, ucnt; UNIT *uptr; int32 toks = -1; +t_bool did_set_dname_len = FALSE; +if (dev_name_len == 0) { + _set_dname_len (dptr); + did_set_dname_len = TRUE; + } fprintf (st, "%s", _sim_dname (dptr)); /* print dev name */ if ((flag == 2) && dptr->description) { fprintf (st, "%s\n", dptr->description(dptr)); @@ -6309,6 +6344,8 @@ for (j = 0; j < dptr->numunits; j++) { /* loop thru units */ if ((uptr->flags & UNIT_DIS) == 0) show_unit (st, dptr, uptr, ucnt + udbl); } +if (did_set_dname_len) + dev_name_len = unit_name_len = 0; return SCPE_OK; } @@ -6791,24 +6828,22 @@ t_bool only_enabled = (sim_switches & SWMASK ('E')); if (cptr && (*cptr != 0)) return SCPE_2MARG; fprintf (st, "%s simulator configuration%s\n\n", sim_name, only_enabled ? " (enabled devices)" : ""); -for (i = dev_name_len = 0; (dptr = sim_devices[i]) != NULL; i++) +for (i = dev_name_len = unit_name_len = 0; (dptr = sim_devices[i]) != NULL; i++) if (!only_enabled || !qdisable (dptr)) - if (dev_name_len < strlen (dptr->name)) - dev_name_len = strlen (dptr->name); + _set_dname_len (dptr); for (i = 0; (dptr = sim_devices[i]) != NULL; i++) if (!only_enabled || !qdisable (dptr)) show_device (st, dptr, flag); if (sim_switches & SWMASK ('I')) { for (i = dev_name_len = 0; sim_internal_device_count && (dptr = sim_internal_devices[i]); ++i) if (!only_enabled || !qdisable (dptr)) - if (dev_name_len < strlen (dptr->name)) - dev_name_len = strlen (dptr->name); + _set_dname_len (dptr); fprintf (st, "\nInternal Devices%s\n\n", only_enabled ? " (enabled devices)" : ""); for (i = 0; sim_internal_device_count && (dptr = sim_internal_devices[i]); ++i) if (!only_enabled || !qdisable (dptr)) show_device (st, dptr, flag); } -dev_name_len = 0; +dev_name_len = unit_name_len = 0; return SCPE_OK; } @@ -8066,10 +8101,12 @@ if ((sim_switches & SWMASK ('R')) || /* read only? */ ((uptr->flags & UNIT_RO) != 0)) { if (((uptr->flags & UNIT_ROABLE) == 0) && /* allowed? */ ((uptr->flags & UNIT_RO) == 0)) - return attach_err (uptr, SCPE_NORO); /* no, error */ + return sim_messagef (attach_err (uptr, SCPE_NORO), "%s: Read Only operation not allowed\n", /* no, error */ + sim_uname (uptr)); uptr->fileref = sim_fopen (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (attach_err (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); if (!(uptr->flags & UNIT_RO)) sim_messagef (SCPE_OK, "%s: unit is read only\n", sim_uname (uptr)); uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ @@ -8078,7 +8115,8 @@ else { if (sim_switches & SWMASK ('N')) { /* new file only? */ uptr->fileref = sim_fopen (cptr, "wb+"); /* open new file */ if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (attach_err (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); sim_messagef (SCPE_OK, "%s: creating new file: %s\n", sim_uname (uptr), cptr); } else { /* normal */ @@ -8090,19 +8128,23 @@ else { if ((errno == EROFS) || (errno == EACCES)) {/* read only? */ #endif if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return attach_err (uptr, SCPE_NORO);/* no error */ + return sim_messagef (attach_err (uptr, SCPE_NORO), "%s: Read Only operation not allowed\n", /* no, error */ + sim_uname (uptr)); uptr->fileref = sim_fopen (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (attach_err (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ sim_messagef (SCPE_OK, "%s: unit is read only\n", sim_uname (uptr)); } else { /* doesn't exist */ if (sim_switches & SWMASK ('E')) /* must exist? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (attach_err (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); uptr->fileref = sim_fopen (cptr, "wb+");/* open new file */ if (uptr->fileref == NULL) /* open fail? */ - return attach_err (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (attach_err (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); sim_messagef (SCPE_OK, "%s: creating new file\n", sim_uname (uptr)); } } /* end if null */ @@ -8112,13 +8154,24 @@ else { } if (uptr->flags & UNIT_BUFABLE) { /* buffer? */ uint32 cap = ((uint32) uptr->capac) / dptr->aincr; /* effective size */ - if (uptr->flags & UNIT_MUSTBUF) /* dyn alloc? */ - uptr->filebuf = calloc (cap, SZ_D (dptr)); /* allocate */ - if (uptr->filebuf == NULL) /* no buffer? */ + + uptr->filebuf2 = calloc (cap, SZ_D (dptr)); /* allocate copy */ + if (uptr->filebuf2 == NULL) return attach_err (uptr, SCPE_MEM); /* error */ + if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ + uptr->filebuf = calloc (cap, SZ_D (dptr)); /* allocate */ + if (uptr->filebuf == NULL) { + free (uptr->filebuf); + uptr->filebuf = NULL; + free (uptr->filebuf2); + uptr->filebuf2 = NULL; + return attach_err (uptr, SCPE_MEM); /* error */ + } + } sim_messagef (SCPE_OK, "%s: buffering file in memory\n", sim_uname (uptr)); uptr->hwmark = (uint32)sim_fread (uptr->filebuf, /* read file */ SZ_D (dptr), cap, uptr->fileref); + memcpy (uptr->filebuf2, uptr->filebuf, cap * SZ_D (dptr));/* save initial contents */ uptr->flags = uptr->flags | UNIT_BUF; /* set buffered */ } uptr->flags = uptr->flags | UNIT_ATT; @@ -8237,7 +8290,8 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK; if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr; - if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { + if (((uptr->flags & UNIT_RO) == 0) && + (memcmp (uptr->filebuf, uptr->filebuf2, (size_t)(SZ_D (dptr) * (uptr->capac / dptr->aincr))) != 0)) { sim_messagef (SCPE_OK, "%s: writing buffer to file: %s\n", sim_uname (uptr), uptr->filename); rewind (uptr->fileref); sim_fwrite (uptr->filebuf, SZ_D (dptr), cap, uptr->fileref); @@ -8245,8 +8299,10 @@ if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { sim_printf ("%s: I/O error - %s", sim_uname (uptr), strerror (errno)); } if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ - free (uptr->filebuf); /* free buf */ + free (uptr->filebuf); /* free buffers */ uptr->filebuf = NULL; + free (uptr->filebuf2); + uptr->filebuf2 = NULL; } uptr->flags = uptr->flags & ~UNIT_BUF; } diff --git a/sim_defs.h b/sim_defs.h index 4b5ceb1..256e7d9 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -579,6 +579,7 @@ struct UNIT { char *filename; /* open file name */ FILE *fileref; /* file reference */ void *filebuf; /* memory buffer */ + void *filebuf2; /* copy of initial memory buffer */ uint32 hwmark; /* high water mark */ int32 time; /* time out */ uint32 flags; /* flags */ @@ -899,7 +900,7 @@ struct MEMFILE { */ -#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 +#define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0 /* Internal use ONLY (see below) Generic Register declaration for all fields */ #define _REGDATANF(nm,loc,rdx,wd,off,dep,desc,flds,qptr,siz,elesiz,macro) \ diff --git a/sim_disk.c b/sim_disk.c index 8f1b889..91f08fc 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -516,6 +516,37 @@ AIO_CALL(DOP_IAVL, 0, NULL, NULL, 0, callback); return r; } +static t_bool sim_disk_no_autosize = FALSE; + +t_stat sim_disk_set_noautosize (int32 flag, CONST char *cptr) +{ +DEVICE *dptr; +uint32 dev, unit, count = 0; + +if (flag == sim_disk_no_autosize) + return sim_messagef (SCPE_ARG, "Autosizing is already %sabled!\n", + sim_disk_no_autosize ? "dis" : "en"); +for (dev = 0; (dptr = sim_devices[dev]) != NULL; dev++) { + if ((DEV_TYPE (dptr) != DEV_DISK) || + (dptr->flags & DEV_DIS)) + continue; + ++count; + for (unit = 0; unit < dptr->numunits; unit++) { + char cmd[CBUFSIZE]; + int32 saved_sim_show_message = sim_show_message; + + sim_show_message = FALSE; + sprintf (cmd, "%s %sAUTOSIZE", sim_uname (&dptr->units[unit]), (flag != 0) ? "NO" : ""); + set_cmd (0, cmd); + sim_show_message = saved_sim_show_message; + } + if (count == 0) + return sim_messagef (SCPE_ARG, "No disk devices support autosizing\n"); + } +sim_disk_no_autosize = flag; +return SCPE_OK; +} + /* Test for write protect */ t_bool sim_disk_wrp (UNIT *uptr) @@ -2421,6 +2452,10 @@ t_bool auto_format = FALSE; t_offset container_size, filesystem_size, current_unit_size; size_t tmp_size = 1; +if (sim_disk_no_autosize) { + dontchangecapac = TRUE; + drivetypes = NULL; + } if (uptr->flags & UNIT_DIS) /* disabled? */ return SCPE_UDIS; if (!(uptr->flags & UNIT_ATTABLE)) /* not attachable? */ @@ -2719,10 +2754,12 @@ if ((sim_switches & SWMASK ('R')) || /* read only? */ ((uptr->flags & UNIT_RO) != 0)) { if (((uptr->flags & UNIT_ROABLE) == 0) && /* allowed? */ ((uptr->flags & UNIT_RO) == 0)) - return _err_return (uptr, SCPE_NORO); /* no, error */ + return sim_messagef (_err_return (uptr, SCPE_NORO), "%s: Read Only operation not allowed\n", /* no, error */ + sim_uname (uptr)); uptr->fileref = open_function (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ - return _err_return (uptr, SCPE_OPENERR); /* yes, error */ + return sim_messagef (_err_return (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ sim_messagef (SCPE_OK, "%s: Unit is read only\n", sim_uname (uptr)); } @@ -2731,10 +2768,12 @@ else { /* normal */ if (uptr->fileref == NULL) { /* open fail? */ if ((errno == EROFS) || (errno == EACCES)) { /* read only? */ if ((uptr->flags & UNIT_ROABLE) == 0) /* allowed? */ - return _err_return (uptr, SCPE_NORO); /* no error */ + return sim_messagef (_err_return (uptr, SCPE_NORO), "%s: Read Only operation not allowed\n", /* no, error */ + sim_uname (uptr)); uptr->fileref = open_function (cptr, "rb"); /* open rd only */ if (uptr->fileref == NULL) /* open fail? */ - return _err_return (uptr, SCPE_OPENERR);/* yes, error */ + return sim_messagef (_err_return (uptr, SCPE_OPENERR), "%s: Can't open '%s': %s\n", /* yes, error */ + sim_uname (uptr), cptr, strerror (errno)); uptr->flags = uptr->flags | UNIT_RO; /* set rd only */ sim_messagef (SCPE_OK, "%s: Unit is read only\n", sim_uname (uptr)); } @@ -2796,7 +2835,7 @@ if ((DK_GET_FMT (uptr) == DKUF_F_VHD) || (ctx->footer)) { } else { /* Type already matches, Need to confirm compatibility */ t_addr saved_capac = uptr->capac; - t_lba current_unit_sectors = (t_lba)((uptr->capac*ctx->capac_factor)/(ctx->sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))); + t_lba current_unit_sectors = (t_lba)((dptr->flags & DEV_SECTORS) ? uptr->capac : (uptr->capac*ctx->capac_factor)/ctx->sector_size); if ((container_sector_size != 0) && (sector_size != container_sector_size)) r = sim_messagef (SCPE_OPENERR, "%s: Incompatible Container Sector Size %d\n", sim_uname (uptr), container_sector_size); @@ -2804,10 +2843,17 @@ if ((DK_GET_FMT (uptr) == DKUF_F_VHD) || (ctx->footer)) { if (dontchangecapac && ((((t_lba)(ctx->container_size/sector_size) > current_unit_sectors)) || ((container_sectors != 0) && (container_sectors != current_unit_sectors)))) { + r = sim_messagef (SCPE_OK, "%s: Container has %u sectors, drive has: %u sectors\n", sim_uname (uptr), container_sectors, current_unit_sectors); if (container_sectors != 0) r = sim_messagef (SCPE_INCOMPDSK, "%s: %s container created by the %s simulator is incompatible with the %s device on the %s simulator\n", sim_uname (uptr), container_dtype, created_name, uptr->dptr->name, sim_name); else r = sim_messagef (SCPE_INCOMPDSK, "%s: disk container %s is incompatible with the %s device\n", sim_uname (uptr), uptr->filename, uptr->dptr->name); + if ((uptr->flags & UNIT_RO) != 0) + r = sim_messagef (SCPE_OK, "%s: Read Only access to incompatible %s container '%s' allowed\n", sim_uname (uptr), container_dtype, uptr->filename); + if (container_sectors < current_unit_sectors) { + r = sim_messagef (SCPE_BARE_STATUS (r), "%s: Since the container is smaller than the drive, this might be useful:\n", sim_uname (uptr)); + r = sim_messagef (SCPE_BARE_STATUS (r), "%s: sim> ATTACH %s -C New-%s %s\n", sim_uname (uptr), sim_uname (uptr), uptr->filename, uptr->filename); + } } } if (r == SCPE_OK) { @@ -2976,6 +3022,9 @@ filesystem_size = get_filesystem_size (uptr); if (filesystem_size != (t_offset)-1) filesystem_size += reserved_sectors * sector_size; container_size = sim_disk_size (uptr); +if ((filesystem_size == (t_offset)-1) && + (ctx->footer != NULL)) /* The presence of metadata means we already */ + filesystem_size = ctx->container_size; /* know the interesting disk size */ current_unit_size = ((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? ctx->sector_size : 1); if (container_size && (container_size != (t_offset)-1)) { if (dontchangecapac) { /* autosize by changing drive type */ @@ -3015,7 +3064,7 @@ if (container_size && (container_size != (t_offset)-1)) { autosized = TRUE; } else { - if (!created) { + if (!created && (ctx->footer == NULL)) { sim_messagef (SCPE_OK, "%s: Amount of data in use in disk container '%s' cannot be determined, skipping autosizing\n", sim_uname (uptr), cptr); if (container_size > current_unit_size) { t_stat r = SCPE_FSSIZE; @@ -3120,6 +3169,30 @@ sim_disk_set_async (uptr, completion_delay); #endif uptr->io_flush = _sim_disk_io_flush; +if (uptr->flags & UNIT_BUFABLE) { /* buffer in memory? */ + t_seccnt sectsread; + t_stat r = SCPE_OK; + + if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ + uptr->filebuf = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size), + ctx->xfer_element_size); /* allocate */ + uptr->filebuf2 = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size), + ctx->xfer_element_size); /* allocate copy */ + if ((uptr->filebuf == NULL) || /* either failed? */ + (uptr->filebuf2 == NULL)) { + sim_disk_detach (uptr); + return SCPE_MEM; /* memory allocation error */ + } + } + sim_messagef (SCPE_OK, "%s: buffering file in memory\n", sim_uname (uptr)); + r = sim_disk_rdsect (uptr, 0, uptr->filebuf, §sread, (t_seccnt)(ctx->container_size / ctx->sector_size)); + if (r != SCPE_OK) + return sim_disk_detach (uptr); + uptr->hwmark = (sectsread * ctx->sector_size) / ctx->xfer_element_size; + memcpy (uptr->filebuf2, uptr->filebuf, (size_t)ctx->container_size);/* save initial contents */ + uptr->flags |= UNIT_BUF; /* mark as buffered */ + } + return SCPE_OK; } @@ -3160,6 +3233,21 @@ if (!(uptr->flags & UNIT_ATT)) /* attached? */ if (NULL == find_dev_from_unit (uptr)) return SCPE_OK; +if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { + uint32 cap = (uptr->hwmark + uptr->dptr->aincr - 1) / uptr->dptr->aincr; + + if (((uptr->flags & UNIT_RO) == 0) && + (memcmp (uptr->filebuf, uptr->filebuf2, (size_t)ctx->container_size) != 0)) { + sim_messagef (SCPE_OK, "%s: writing buffer to file: %s\n", sim_uname (uptr), uptr->filename); + sim_disk_wrsect (uptr, 0, uptr->filebuf, NULL, (cap + ctx->sector_size - 1) / ctx->sector_size); + } + uptr->flags = uptr->flags & ~UNIT_BUF; + } +free (uptr->filebuf); /* free buffers */ +uptr->filebuf = NULL; +free (uptr->filebuf2); +uptr->filebuf2 = NULL; + update_disk_footer (uptr); /* Update meta data if highwater has changed */ auto_format = ctx->auto_format; @@ -3180,6 +3268,7 @@ uptr->disk_ctx = NULL; uptr->io_flush = NULL; if (auto_format) sim_disk_set_fmt (uptr, 0, "AUTO", NULL); /* restore file format */ + if (close_function (fileref) == EOF) return SCPE_IOERR; return SCPE_OK; @@ -3990,8 +4079,6 @@ while (bytestoread) { if (sectsread) *sectsread += sectorbytes / ctx->sector_size; bytestoread -= sectorbytes; - if (bytestoread == 0) - break; buf += sectorbytes; addr += sectorbytes; } @@ -4192,8 +4279,6 @@ while (bytestoread) { if (sectsread) *sectsread += sectorbytes / ctx->sector_size; bytestoread -= sectorbytes; - if ((bytestoread == 0) || (bytesread == 0)) - break; buf += sectorbytes; addr += sectorbytes; } @@ -6236,6 +6321,12 @@ return WriteVirtualDiskSectors(hVHD, buf, sects, sectswritten, ctx->sector_size, t_stat sim_disk_init (void) { +int32 saved_sim_show_message = sim_show_message; + +sim_show_message = FALSE; +sim_disk_no_autosize = TRUE; +sim_disk_set_noautosize (FALSE, NULL); +sim_show_message = saved_sim_show_message; return SCPE_OK; } diff --git a/sim_disk.h b/sim_disk.h index 5b265dd..25ed588 100644 --- a/sim_disk.h +++ b/sim_disk.h @@ -48,10 +48,12 @@ typedef uint32 t_lba; /* disk logical block ad #define DKUF_F_STD 1 /* SIMH format */ #define DKUF_F_RAW 2 /* Raw Physical Disk Access */ #define DKUF_F_VHD 3 /* VHD format */ -#define DKUF_V_UF (DKUF_V_FMT + DKUF_W_FMT) +#define DKUF_V_NOAUTOSIZE (DKUF_V_FMT + DKUF_W_FMT) /* Don't Autosize disk option */ +#define DKUF_V_UF (DKUF_V_NOAUTOSIZE + 1) #define DKUF_WLK UNIT_WLK #define DKUF_FMT (DKUF_M_FMT << DKUF_V_FMT) #define DKUF_WRP (DKUF_WLK | UNIT_RO) +#define DKUF_NOAUTOSIZE (1 << DKUF_V_NOAUTOSIZE) #define DK_F_STD (DKUF_F_STD << DKUF_V_FMT) #define DK_F_RAW (DKUF_F_RAW << DKUF_V_FMT) @@ -126,6 +128,7 @@ t_bool sim_disk_vhd_support (void); t_bool sim_disk_raw_support (void); void sim_disk_data_trace (UNIT *uptr, const uint8 *data, size_t lba, size_t len, const char* txt, int detail, uint32 reason); t_stat sim_disk_info_cmd (int32 flag, CONST char *ptr); +t_stat sim_disk_set_noautosize (int32 flag, CONST char *cptr); t_stat sim_disk_test (DEVICE *dptr, const char *cptr); #ifdef __cplusplus diff --git a/sim_scsi.h b/sim_scsi.h index 8dff757..21eb021 100644 --- a/sim_scsi.h +++ b/sim_scsi.h @@ -70,7 +70,7 @@ #define SCSI_V_NOAUTO ((DKUF_V_UF > MTUF_V_UF) ? DKUF_V_UF : MTUF_V_UF)/* noautosize */ #define SCSI_V_UF (SCSI_V_NOAUTO + 1) #define SCSI_WLK (UNIT_WLK|UNIT_RO) /* hwre write lock */ -#define SCSI_NOAUTO (1 << SCSI_V_NOAUTO) +#define SCSI_NOAUTO DKUF_NOAUTOSIZE struct scsi_dev_t { diff --git a/sim_tape.c b/sim_tape.c index 6f38a99..57cc71f 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -1051,6 +1051,8 @@ fprintf (st, "Attach command switches\n"); fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified, the default behavior is to\n"); fprintf (st, " attempt to create the indicated virtual tape file).\n"); +fprintf (st, " -N Create a new empty tape container file.\n"); +fprintf (st, " -Q Suppress informative messages during attach activities.\n"); fprintf (st, " -F Open the indicated tape container in a specific format\n"); fprintf (st, " (default is SIMH, alternatives are E11, TPC, P7B, AWS, TAR,\n"); fprintf (st, " ANSI-VMS, ANSI-RT11, ANSI-RSX11, ANSI-RSTS, ANSI-VAR, FIXED,\n");