From 6c56968f15f0e6ccf527917f7783cddc4e9ea1e5 Mon Sep 17 00:00:00 2001 From: Leo Broukhis Date: Mon, 7 Mar 2022 21:06:57 -0800 Subject: [PATCH] BESM6: 29 Mb disks (EC-5061, clones of IBM 2314) are now functional. The OS seems to support them only on device MD4, though. Native formatting works. --- BESM6/besm6_disk.c | 361 ++++++++++++++++++++++++++++----------------- 1 file changed, 222 insertions(+), 139 deletions(-) diff --git a/BESM6/besm6_disk.c b/BESM6/besm6_disk.c index cbb812d3..dd0c73c1 100644 --- a/BESM6/besm6_disk.c +++ b/BESM6/besm6_disk.c @@ -45,17 +45,33 @@ #define DISK_HALFZONE 000000001 /* выбор половины зоны */ /* - * "Хороший" статус чтения/записи. - * Вычислено по текстам ОС Дубна. - * Диспак доволен. + * Status register bits (most are unused: error conditions are not simulated) */ -#define STATUS_GOOD 014000400 - +#define STATUS_SEEK 000000377 /* "Seek done" mask, per unit */ +#define STATUS_READY 000000400 /* Selected unit is ready */ +#define STATUS_SEEK_FAIL 000001000 /* Head location unknown, unit not ready */ +#define STATUS_CHECKSUM 000002000 /* Bad checksum on read */ +#define STATUS_FAILURE 000004000 /* Failure, OR of some upper bits */ +#define STATUS_MAYDAY 000010000 /* Unspecified failure */ +#define STATUS_NO_AMRK 000020000 /* Address marker not found after a revolution */ +#define STATUS_WRONG_CYL 000040000 /* Wrong address marker */ +#define STATUS_WRONG_ID 000100000 /* Bad track ID */ +#define STATUS_BAD_ACSUM 000200000 /* Bad checksum of the address marker */ +#define STATUS_UNFINISHED 000400000 /* IO not finished after a revolution */ +#define STATUS_TRK_PARITY 001000000 /* Track parity in two-track IO */ +#define STATUS_READONLY 002000000 /* The selected unit is read-only */ +#define STATUS_POWERUP 004000000 /* The unit is powered up */ +#define STATUS_ABSENT 010000000 /* The unit is not connected */ +#define STATUS_BUF_ERR 020000000 /* Transfer buffer not ready */ + /* - * Total size of a disk in blocks, including hidden blocks + * Total size of a "7.25 Mb" disk is 1000 (decimal) blocks; + * of a "29 Mb" disk - 4000 blocks, out of which 4 are so called + * pre-blocks. Logical blocks are mapped to physical by adding 4. + * Physical blocks 0 to 2 are accesible only by standalone programs, + * block 3 has the logical number "minus one". */ -#define DISK_TOTBLK 01767 - +#define SYSTEM_VOLUME_ID 2053 /* * Параметры обмена с внешним устройством. */ @@ -81,75 +97,75 @@ t_stat disk_event (UNIT *u); /* * DISK data structures * - * mg_dev DISK device descriptor - * mg_unit DISK unit descriptor - * mg_reg DISK register list + * md_dev DISK device descriptor + * md_unit DISK unit descriptor + * md_reg DISK register list */ UNIT md_unit [64] = { - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, - { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, + { UDATA (disk_event, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }, }; REG disk_reg[] = { @@ -186,12 +202,36 @@ t_stat disk_setsyslog (UNIT *up, int32 v, CONST char *cp, void *dp) { return SCPE_OK; } +#define DISK_TYPE_MASK (1 << UNIT_V_UF) +#define DISK_TYPE_7_25M 0 +#define DISK_TYPE_29M (1 << UNIT_V_UF) +#define IS_29MB(u) (((u)->flags & DISK_TYPE_MASK) == DISK_TYPE_29M) + +t_stat disk_set_type (UNIT *up, int32 v, CONST char *cp, void *dp) { + int first_unit = (up->dptr - md_dev) * 8; + int unit; + for (unit = first_unit; unit < first_unit + 8; ++unit) { + if (md_unit[unit].flags & UNIT_ATT) + return sim_messagef(SCPE_ALATT, "Drive type cannot be set if any unit is attached"); + } + for (unit = first_unit; unit < first_unit + 8; ++unit) { + md_unit[unit].flags &= ~DISK_TYPE_MASK; + md_unit[unit].flags |= v; + md_unit[unit].capac = 7250000 * (v ? 4 : 1); + } + return SCPE_OK; +} + + MTAB disk_mod[] = { + { MTAB_VDV, DISK_TYPE_7_25M, NULL, "EC-5052", &disk_set_type, NULL, NULL, "EC-5052 drive (7.25 Mb)"}, + { MTAB_VDV, DISK_TYPE_29M, NULL, "EC-5061", &disk_set_type, NULL, NULL, "EC-5061 drive (29 Mb)"}, { MTAB_XTD | MTAB_VDV | MTAB_VALR, 1, NULL, "SYSLOG", &disk_setsyslog, NULL, NULL, "file name (always appending) or OFF" }, { 0 } }; + t_stat disk_reset (DEVICE *dptr); t_stat disk_attach (UNIT *uptr, CONST char *cptr); t_stat disk_detach (UNIT *uptr); @@ -218,49 +258,49 @@ DEBTAB disk_deb[] = { DEVICE md_dev[8] = { { "MD0", md_unit, disk_reg, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD1", md_unit + 8, disk_reg, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD2", md_unit + 16, disk_reg, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD3", md_unit + 24, disk_reg, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD4", md_unit + 32, disk_reg + 8, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD5", md_unit + 40, disk_reg + 8, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD6", md_unit + 48, disk_reg + 8, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, { "MD7", md_unit + 56, disk_reg + 8, disk_mod, - 8, 8, 21, 1, 8, 50, + 8, 8, 21, 50, 8, 50, NULL, NULL, &disk_reset, NULL, &disk_attach, &disk_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, disk_deb }, @@ -289,6 +329,7 @@ t_stat disk_reset (DEVICE *dptr) c->mask_fail = 020 >> ctlr; for (i = first_unit; i < first_unit + 8; ++i) { md_unit[i].dptr = dptr; + md_unit[i].capac = 7250000 * (IS_29MB(&md_unit[i]) ? 4 : 1); sim_cancel (&md_unit[i]); } return SCPE_OK; @@ -342,10 +383,12 @@ t_stat disk_attach (UNIT *u, CONST char *cptr) control[1] |= 01370707LL << 24; /* Magic mark */ control[1] |= diskno << 12; - for (blkno = 0; blkno < DISK_TOTBLK; ++blkno) { - control[0] = SET_PARITY((t_value)(2*blkno) << 36, PARITY_NUMBER); + /* Unlike the O/S routine, does not format the (useless) reserve tracks */ + for (blkno = 0; blkno < (IS_29MB(u) ? 4000 : 1000); ++blkno) { + uint val = IS_29MB(u) ? blkno : 2 * blkno; + control[0] = SET_PARITY((t_value)val << 36, PARITY_NUMBER); sim_fwrite(control, sizeof(t_value), 4, u->fileref); - control[0] = SET_PARITY((t_value)(2*blkno+1) << 36, PARITY_NUMBER); + control[0] = SET_PARITY((t_value)(val+1) << 36, PARITY_NUMBER); sim_fwrite(control, sizeof(t_value), 4, u->fileref); for (word = 0; word < 02000; ++word) { sim_fwrite(control+2, sizeof(t_value), 1, u->fileref); @@ -358,11 +401,6 @@ t_stat disk_attach (UNIT *u, CONST char *cptr) break; sim_switches |= SWMASK ('N'); } - { - struct stat buf; - fstat(fileno(u->fileref), &buf); - u->capac = buf.st_size / 8; - } return SCPE_OK; } @@ -435,9 +473,10 @@ void disk_write (UNIT *u) sim_fwrite (c->sysdata, 8, 8, u->fileref); sim_fwrite (&memory [c->memory], 8, 1024, u->fileref); } - - if (syslog && ((c->sysdata[1] >> 12) & 0xFFF) == 2053) { - fprintf(syslog, "W %04o\n", (c->zone-4)&07777); + + /* Logging system disk accesses */ + if (syslog && ((c->sysdata[1] >> 12) & 0xFFF) == SYSTEM_VOLUME_ID) { + fprintf(syslog, "W %04o @%05o\n", (c->zone-4)&07777, c->memory); fflush(syslog); } @@ -470,7 +509,8 @@ void disk_write_track (UNIT *u) void disk_format (UNIT *u) { KMD *c = unit_to_ctlr (u); - t_value fmtbuf[5], *ptr; + t_value fmtbuf[5]; + t_value *ptr; int i; int cnum = c - controller; /* По сути, эмулятору ничего делать не надо. */ @@ -488,16 +528,24 @@ void disk_format (UNIT *u) /* При первой попытке разметки адресный маркер начинается в старшем 5-разрядном слоге, * пропускаем первый слог. */ - for (i=0; i<4; i++) + for (i=0; i<5; i++) fmtbuf[i] = ((fmtbuf[i] & BITS48) << 5) | - ((fmtbuf[i+1] >> 40) & BITS(5)); + (i == 4 ? 0 : (fmtbuf[i+1] >> 40) & BITS(5)); + + log_data(fmtbuf, 5); /* Печатаем идентификатор, адрес и контрольную сумму адреса. */ - besm6_debug ("::: формат МД %02o полузона %04o.%d память %05o и-а-кса %010o %010o", - c->dev, c->zone, c->track, c->memory, - (int) (fmtbuf[0] >> 8 & BITS(30)), - (int) (fmtbuf[2] >> 14 & BITS(30))); - /* log_data (fmtbuf, 4); */ + if (u->dptr->dctrl & DEB_TRC) + if (IS_29MB(u)) + besm6_debug ("::: формат МД %02o зона %04o память %05o skip %02o и-а-кса %010o %010o", + c->dev, c->zone, c->memory, ptr - memory -c ->memory, + (int) (fmtbuf[0] >> 8 & BITS(30)), + (int) (fmtbuf[2] >> 14 & BITS(30))); + else + besm6_debug ("::: формат МД %02o полузона %04o.%d память %05o skip %02o и-а-кса %010o %010o", + c->dev, c->zone, c->track, c->memory, ptr - memory -c ->memory, + (int) (fmtbuf[0] >> 8 & BITS(30)), + (int) (fmtbuf[2] >> 14 & BITS(30))); } /* @@ -525,8 +573,9 @@ void disk_read (UNIT *u) return; } - if (syslog && ((c->sysdata[1] >> 12) & 0xFFF) == 2053) { - fprintf(syslog, "R %04o\n", (c->zone-4)&07777); + /* Logging system disk accesses */ + if (syslog && ((c->sysdata[1] >> 12) & 0xFFF) == SYSTEM_VOLUME_ID) { + fprintf(syslog, "R %04o @%05o\n", (c->zone-4)&07777, c->memory); fflush(syslog); } @@ -580,17 +629,26 @@ void disk_read_track (UNIT *u) void disk_read_header (UNIT *u) { KMD *c = unit_to_ctlr (u); - t_value *sysdata = c->sysdata + 4*c->track; + t_value *sysdata = IS_29MB(u) ? c->sysdata : c->sysdata + 4*c->track; int iaksa, i, cyl, head; + int reserve_start = IS_29MB(u) ? 07640 : 01750; /* Адрес: номер цилиндра и головки. */ - head = (c->zone << 1) + c->track; - cyl = head / 10; - head %= 10; - iaksa = (cyl << 20) | (head << 16); + if (IS_29MB(u)) { + head = c->zone; + cyl = head / 20; + head %= 20; + iaksa = (head << 3) + (cyl << 8); + iaksa <<= 12; + } else { + head = (c->zone << 1) + c->track; + cyl = head / 10; + head %= 10; + iaksa = (cyl << 20) | (head << 16); + } /* Идентификатор дорожки замены. */ - if (c->zone >= 01750) + if (c->zone >= reserve_start) iaksa |= BBIT(30); /* Контрольная сумма адреса с переносом вправо. */ @@ -601,12 +659,17 @@ void disk_read_header (UNIT *u) sysdata[1] = 03740LL; sysdata[2] = 00400000000037777LL | (t_value) iaksa << 14; sysdata[3] = BITS48; - if (u->dptr->dctrl & DEB_TRC) - log_data (sysdata, 4); + + if (IS_29MB(u)) { + for (i=0; i<4; i++) { + memory[c->memory + i + 014] = SET_PARITY(sysdata[i] & 0777777777777777LL, PARITY_NUMBER); + } + } /* Кодируем гребенку. */ for (i=0; i<4; i++) sysdata[i] = SET_PARITY (collect (sysdata[i]), PARITY_NUMBER); + } /* @@ -631,8 +694,8 @@ void disk_io (int ctlr, uint32 cmd) c->memory = (cmd & (DISK_PAGE | DISK_HALFPAGE)) >> 2 | (cmd & DISK_BLOCK) >> 8; } if (md_dev[ctlr * 4].dctrl & DEB_RWR) - besm6_debug ("::: КМД %c: задание на %s %08o", ctlr + '3', - (c->op & DISK_READ) ? "чтение" : "запись", cmd); + besm6_debug ("::: КМД %c: задание на %s %016llo RAM @%05o", ctlr + '3', + (c->op & DISK_READ) ? "чтение" : "запись", cmd, c->memory); disk_fail &= ~c->mask_fail; /* Гасим главный регистр прерываний. */ @@ -647,7 +710,15 @@ void disk_ctl (int ctlr, uint32 cmd) KMD *c = &controller [ctlr]; UNIT *u = &md_unit [c->dev]; + if ((md_dev[ctlr].dctrl & DEB_OPS || c->dev != -1 && u->dptr->dctrl & DEB_OPS) && cmd & BBIT(13)) { + besm6_debug ("::: КМД %c: bit 13 + %04o", + ctlr + '3', cmd & 07777); + } + if (cmd & BBIT(12)) { + if (c->dev == -1) + besm6_debug("Setting block address for unknown device"); + /* Выдача в КМД адреса дорожки. * Здесь же выполняем обмен с диском. * Номер дисковода к этому моменту уже известен. */ @@ -656,21 +727,24 @@ void disk_ctl (int ctlr, uint32 cmd) disk_fail |= c->mask_fail; return; } - if (u->capac <= (2<<20)) { + if (IS_29MB(u)) { + c->zone = ((cmd & BITS(11)) << 1) | (c->zone & 1); + } else { c->zone = (cmd >> 1) & BITS(10); c->track = cmd & 1; - } else { - c->zone = ((cmd & BITS(11)) << 1) | c->track; - c->track = 0; } - if (u->dptr->dctrl & DEB_OPS) - besm6_debug ("::: КМД %c: выдача адреса дорожки %04o.%d", - ctlr + '3', c->zone, c->track); - + if (u->dptr->dctrl & DEB_OPS) { + if (IS_29MB(u)) + besm6_debug ("::: КМД %c: cmd %08o = выдача адреса дорожки %04o", + ctlr + '3', cmd, c->zone); + else + besm6_debug ("::: КМД %c: cmd %08o = выдача адреса дорожки %04o.%d", + ctlr + '3', cmd, c->zone, c->track); + } disk_fail &= ~c->mask_fail; if (c->op & DISK_READ) { - if (u->capac >= 2<<20 || c->op & DISK_PAGE_MODE) + if (IS_29MB(u) || c->op & DISK_PAGE_MODE) disk_read (u); else disk_read_track (u); @@ -683,7 +757,7 @@ void disk_ctl (int ctlr, uint32 cmd) } if (c->format) disk_format (u); - else if (u->capac >= 2<<20 || c->op & DISK_PAGE_MODE) + else if (IS_29MB(u) || c->op & DISK_PAGE_MODE) disk_write (u); else disk_write_track (u); @@ -704,17 +778,25 @@ void disk_ctl (int ctlr, uint32 cmd) else if (cmd & BBIT(3)) c->dev = 2; else if (cmd & BBIT(2)) c->dev = 1; else if (cmd & BBIT(1)) c->dev = 0; - else { + else if (cmd != BBIT(11)) { /* Неверная маска выбора устройства. */ + c->dev = -1; + besm6_debug("Bad unit selection command %o", cmd); + return; + } else { c->dev = -1; return; } c->dev += ctlr * 32 + c->group * 8; + u = &md_unit [c->dev]; + if (IS_29MB(u)) { + c->zone = (c->zone & ~1) | (cmd & BBIT(10) ? 1 : 0); + } u = &md_unit[c->dev]; if (u->dptr->dctrl & DEB_OPS) - besm6_debug ("::: КМД %c: выбор устройства %02o", - ctlr + '3', c->dev); + besm6_debug ("::: КМД %c: cmd = %08o, выбор устройства %02o", + ctlr + '3', cmd, c->dev); if ((u->dptr->flags & DEV_DIS) || ! (u->flags & UNIT_ATT)) { /* Device not attached. */ @@ -733,12 +815,10 @@ void disk_ctl (int ctlr, uint32 cmd) besm6_debug ("::: КМД %c: selected group %d", ctlr + '3', c->group); } - c->track = cmd & BBIT(13) ? 1 : 0; - if (u->dptr->dctrl & DEB_OPS && cmd & BBIT(13)) - besm6_debug ("::: КМД %c: set track# LSB", - ctlr + '3'); - GRP |= c->mask_grp; + } else if (cmd & BBIT(8)) { + besm6_debug ("::: КМД %c: cmd = %08o\n", + ctlr + '3', cmd); } else { /* Команда, выдаваемая в КМД. */ @@ -802,10 +882,9 @@ void disk_ctl (int ctlr, uint32 cmd) c->status = 0; break; case 011: /* опрос 1÷12 разрядов PC */ + c->status = 0; if (md_unit[c->dev].flags & UNIT_ATT) - c->status = STATUS_GOOD & BITS(12); - else - c->status = 0; + c->status = STATUS_READY; #if 1 if (u->dptr->dctrl & DEB_STA) besm6_debug ("::: КМД %c: опрос младших разрядов состояния - %04o", @@ -813,10 +892,14 @@ void disk_ctl (int ctlr, uint32 cmd) #endif break; case 031: /* опрос 13÷24 разрядов РС */ - if (md_unit[c->dev].flags & UNIT_ATT) - c->status = (STATUS_GOOD >> 12) & BITS(12); - else - c->status = 0; + c->status = 0; + if (md_unit[c->dev].flags & UNIT_DISABLE) + c->status |= STATUS_ABSENT; + else if (md_unit[c->dev].flags & UNIT_ATT) + c->status |= STATUS_POWERUP; + if (md_unit[c->dev].flags & UNIT_RO) + c->status |= STATUS_READONLY; + c->status >>= 12; #if 1 if (u->dptr->dctrl & DEB_STA) besm6_debug ("::: КМД %c: опрос старших разрядов состояния - %04o",